Zoals wellicht bekend/ondervonden kunnen bij een update van de firmware de 3rd party applicaties worden gewist... Om dat nu te voorkomen deze 3rd party manager. Ik heb het Duitse origineel aangepast naar het Nederlands en hier en daar een tikje verbeterd.
Naast de mogelijkheid van backup en restore is er de mogelijkheid om via de interface een 3rd party applicatie aan te maken en te wissen.
Enige verduidelijkende tekst over de werking staat onder de afbeelding.
application.cfg
text = 3rd party manager
description = 3rd party manager
type=embedded
path = /phpsrc/manager/manager.php
manager.php
NB. Bijgewerkt met de beveiliging van Merty. Zie
http://synology.nl/forum/viewtopic.php?f=83&t=2274.
<?php
putenv('HTTP_COOKIE='.$_SERVER['HTTP_COOKIE']);
putenv('REMOTE_ADDR='.$_SERVER['REMOTE_ADDR']);
$user=exec('/usr/syno/synoman/webman/modules/authenticate.cgi');
if($user != 'admin'){
header("HTTP/1.0 403 Forbidden");
exit;
}
ini_set('session.use_cookies','0');
session_start();
/**
* Setting some "global" Vars
*/
$appl_names = array();
$path_3rdparty = '/usr/syno/synoman/webman/3rdparty';
$path_phpsrc = '/usr/syno/synoman/phpsrc';
$backup_dir = '/volume1/tmp';
$backup_name = 'backupSynology';
$dh = opendir($path_3rdparty);
while(($res=readdir($dh))!==false){
if($res != '.' && $res != '..' && is_dir($path_3rdparty.'/'.$res)){
$appl_names[] = $res;
}
}
if(isset($_POST['delete']) && isset($_POST['del']) && count($_POST['del']) > 0){
foreach ($_POST['del'] as $wert){
(file_exists($path_3rdparty.'/'.$wert.'/application.cfg') ? $res=file_get_contents($path_3rdparty.'/'.$wert.'/application.cfg') :$res=0);
if($res===0){
continue;
}
preg_match('/path.*?=.*?/phpsrc(/.*?)/.*?.[^s]*/i',$res,$ret);
$tt = array();
exec('rm -r '.$path_3rdparty.'/'.$wert,$tt);
if(isset($ret[1]) && is_dir($path_phpsrc.$ret[1])){
exec('rm -r '.$path_phpsrc.$ret[1],$tt);
}
if(count($tt) == 0){
echo 'Entry deleted';
}else{
echo '<pre>'.implode("rn",$tt).'</pre>';
}
exit;
}
}elseif(isset($_POST['senden']) && !empty($_POST['Linktext']) && !empty($_POST['Description']) && !empty($_POST['Dir']) && !empty($_POST['type']) && (!empty($_POST['fname']) || !empty($_FILES['file']['name'][0]))){
$att = array();
$strr = '<strong>Please check the data below carefully as after your confirmation application directories will be created with the parameters given<br />*** No operation will be executed <u>before</u> you confirm by clicking below ***</strong>';
$strr .= '<br /><br />First the content of <strong>application.cfg</strong> that will be created in <strong>'.$path_3rdparty.'/'.preg_replace('/s+|/+/','',strtolower($_POST['Dir'])).'</strong><br />';
$str = '';
$str .= 'text = '.$_POST['Linktext']."rn";
$str .= 'description = '.$_POST['Description']."rn";
$str .= 'type = ';
($_POST['type'] == 'embedded') ? $str .= 'embedded' : $str .= 'standalone';
$str .= "rn";
$str .= 'path = /phpsrc/'.preg_replace('/s+|/+/','',strtolower($_POST['Dir'])).'/'.preg_replace('/s+|/+/','',strtolower($_POST['fname']))."rn";
$_SESSION['appl.cfg'] = $str;
$_SESSION['appl.dir'] = preg_replace('/s+|/+/','',strtolower($_POST['Dir']));
for($i=0;$i<count($_FILES['file']['name']);$i++){
if($_FILES['file']['name'][$i] == '' || $_FILES['file']['size'][$i] == 0){
continue;
}
$f = file_get_contents($_FILES['file']['tmp_name'][$i]);
$att[] = array('path'=>$path_phpsrc.'/'.$_SESSION['appl.dir'].'/'.$_FILES['file']['name'][$i],'content'=>$f);
}
if(isset($_POST['file_content']) && trim($_POST['file_content']) != ''){
$att[] = array('path'=>$path_phpsrc.'/'.preg_replace('/s+|/+/','',strtolower($_POST['Dir'])).'/'.preg_replace('/s+|/+/','',strtolower($_POST['fname'])),'content'=>str_replace(chr(13),'',stripslashes($_POST['file_content'])));
}
$_SESSION['appl.att'] = $att;
echo $strr;
echo '<pre>'.$str.'</pre>';
echo '<br />';
echo 'The following files from your upload will be created:<br /><br />';
foreach($_SESSION['appl.att'] as $wert){
echo '<strong>'.$wert['path'].'</strong><br />';
}
echo '<br />By clicking <a href="'.$_SERVER['PHP_SELF'].'?'.strip_tags(SID).'">this link</a> all the necessary files and settings will be written to disk!!!<br />You can abort the operation by <a href="https://'.$_SERVER['SERVER_ADDR'].':5001/webman/index.cgi">clicking this link</a>';
}elseif(isset($_POST['backup'])){
if(!is_dir($backup_dir.'/'.$backup_name)){
mkdir($backup_dir.'/'.$backup_name);
}
$t = time();
mkdir($backup_dir.'/'.$backup_name.'/3rdparty_'.$t);
mkdir($backup_dir.'/'.$backup_name.'/phpsrc_'.$t);
foreach($appl_names as $wert){
(file_exists($path_3rdparty.'/'.$wert.'/application.cfg') ? $res=file_get_contents($path_3rdparty.'/'.$wert.'/application.cfg') :$res=0);
if($res===0){
continue;
}
preg_match('/path.*?=.*?/phpsrc(/.*?)/.*?.[^s]*/i',$res,$ret);
exec('cp -R '.$path_3rdparty.'/'.$wert.' '.$backup_dir.'/'.$backup_name.'/3rdparty_'.$t);
exec('cp -R '.$path_phpsrc.$ret[1].' '.$backup_dir.'/'.$backup_name.'/phpsrc_'.$t);
}
die('Data succesfully written to backup directory');
}elseif(isset($_POST['restore']) && isset($_POST['path']) && !empty($_POST['path'])){
if(!is_dir($_POST['path']) || !is_dir($_POST['path'].'/phpsrc_'.$_POST['time']) || !is_dir($_POST['path'].'/3rdparty_'.$_POST['time'])){
die('Data could not be restored because eihter BackupPath was not given OR the subdirectories (3rdparty phpsrc) do not exist in given path');
}
exec('cp -Rf '.$_POST['path'].'/phpsrc_'.$_POST['time'].'/* '.$path_phpsrc);
exec('cp -Rf '.$_POST['path'].'/3rdparty_'.$_POST['time'].'/* '.$path_3rdparty);
die('Data succesfully restored');
}elseif(isset($_SESSION['appl.cfg']) && isset($_SESSION['appl.dir'])){
exec('mkdir '.$path_3rdparty.'/'.$_SESSION['appl.dir']);
exec('mkdir '.$path_phpsrc.'/'.$_SESSION['appl.dir']);
$fp = fopen($path_3rdparty.'/'.$_SESSION['appl.dir'].'/application.cfg','w');
fwrite($fp,$_SESSION['appl.cfg']);
fclose($fp);
foreach($_SESSION['appl.att'] as $wert){
$fp = fopen($wert['path'],'w');
fwrite($fp,$wert['content']);
fclose($fp);
}
unset($_SESSION);
session_destroy();
echo '<a href="https://'.$_SERVER['SERVER_ADDR'].':5001/webman/index.cgi">Operation successfull: return</a>';
exit;
}else{
?>
<html>
<head>
<title>3rd Party Application Manager</title>
</head>
<body>
<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
<?php
/**
* Build up a table with checkboxes and names of the installed application
*/
echo '<font size=10; face="Arial">3rd-Party Manager';
echo '<table border="0">';
echo '<tr><td colspan=2><font size="4">Remove a 3rd-Party application</font></td></tr>';
foreach ($appl_names as $wert){
echo '<tr><td><input type="checkbox" name="del[]" value="'.$wert.'" /></td><td><input disabled="disabled" type="text" value="'.$wert.'" /></td></tr>';
}
echo '<tr colspan="4" style="text-align:center;"><td><input type="submit" name="delete" value="Delete" /></td>';
echo '<td><input type="reset" value="Reset selection" /></td></tr></table>';
?>
</form>
<?php
/**
* Form for adding a new application by user
*/
?>
<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post" enctype="multipart/form-data">
<table border="0">
<tr><td colspan="3"><font size="4">Create a 3rd-Party application for Diskstation</font></td></tr>
</th>
<tr>
<td>Text for the Link</td><td><input name="Linktext" type="text" size="40" /></td><td></td>
</tr>
<tr>
<td>Text for the Tooltip</td><td><input name="Description" type="text" size="40" /></td>
</tr>
<tr>
<td>Application Directory</td><td><input name="Dir" type="text" size="40" /></td>
</tr>
<tr>
<td>Application Type</td><td><select name="type">
<option value="embedded" selected="selected">Embedded</option>
<option value="standalone">Standalone</option>
</select>
</td>
</tr>
<tr><td>Filename</td><td><input name="fname" type="text" size="40" /></td><td width="340">This is the file that will initially be called by DSM;</br>if this is an uploaded file (see below) please repeat its name here without a path;</br>otherwise enter the file contents below.</td></tr>
<tr>
<tr>
<td colspan=2>Contents of file:</td>
</tr>
<td colspan="20"><textarea name="file_content" rows="40" cols="80"></textarea></td>
</tr>
<tr><td>File(s) to upload</td><td colspan=2><input name="file[]" type="file" size="40" /></td></tr>
<tr><td> </td><td colspan=2><input name="file[]" type="file" size="40" /></td></tr>
<tr><td> </td><td colspan=2><input name="file[]" type="file" size="40" /></td></tr>
<tr><td> </td><td colspan=2><input name="file[]" type="file" size="40" /></td></tr>
<tr><td> </td><td colspan=2><input name="file[]" type="file" size="40" /></td></tr>
<tr>
<td colspan=2><input type="submit" name="senden" value="Create" /> <input type="reset" value="Reset Form" /></td>
</tr>
</table>
</form>
<form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
<font size="4">Backup / Restore 3rd-Party applications</font></br>
<select name="time">
<?php
$path = $backup_dir.'/'.$backup_name;
$dh = opendir($path);
while(($res=readdir($dh))!==false){
if($res != '.' && $res != '..' && is_dir($path.'/'.$res)){
$t = substr($res,strpos($res,'_')+1);
$arr[] = $t;
}
}
$arr = array_unique($arr);
rsort($arr);
foreach($arr as $wert){
if(!empty($wert)){
echo '<option value="'.$wert.'">'.date('d.m.y H:i:s',$wert).'</option>';
}
}
?>
</select>
<input type="text" name="path" />
<input type="submit" name="backup" value="Backup" /> <input type="submit" name="restore" value="Restore" />
</font>
</form>
</body>
</html>
<?php
}
?>
Werking:
1) Verwijderen (Remove a 3rd-Party application)
Er wordt een lijst getoond van alle aanwezige 3rd-Party applicaties. Aanvinken van de te verwijderen applicatie(s) en klikken op 'Delete'. Met 'Reset selection' worden alle applicaties uitgevinkt.
2) Aanmaken (Create a 3rd-Party-Application)
Dit volgt de globale opbouw van application.cfg (zie evt. hierboven)
- 'Text for the link' is de tekst die getoond wordt in het 3rd-Party menu in de DSM
- 'Text for the Tooltip' is de tekst die in de tooltip staat die in het 3rd-Party menu bij deze applicatie getoond wordt
- 'Application Directory' is de directory onder /usr/syno/synoman/phpsrc die aangemaakt zal worden om de applicatie in onder te brengen
- 'Application Type': Embedded of Standalone
- 'Filename' is de bestandsnaam die in de link van de DSM wordt aangeroepen. Ter vergelijk, dit is dus de bestandsnaam die helemaal op het eind van de 'Path' waarde in application.cfg staat (bij deze 3rd-Party manager is dat dus 'manager.php'
- 'Contents of file' geeft de mogelijkheid om het bij filename genoemde bestand te voorzien van inhoud (dus bv. in dit geval de hele lap code die in manager.php staat. Dit betekent dat je dus niet eerst het bestand hoeft aan te maken, te vullen en op te slaan.
- 'File(s) to upload' zijn eventuele extra te plaatsen bestanden in de 'application directory'
Met de knop 'Create' geef je opdracht om de applicatie te maken/installeren. Er verschijnt dan een bevestigingsscherm waarop je e.e.a. nog eens kunt overzien, alsvorens definitief te bevestigen
De knop 'Reset form' wist alle invoer.
LET OP!Als je enkel bestanden te uploaden hebt en één daarvan is het bestand dat aangeroepen gaat worden vanuit de DSM (en je hoeft dus niet een bestand te vullen met gegevens in ''Contents of file'), dan dien je dit te uploaden bestand nogmaals te benoemen bij 'Filename'.
Anders zou je weliswaar de bestanden uploaden, maar heb je de DSM niet duidelijk gemaakt wélke van de ge-uploade bestanden je als startbestand wilt zien.
Er vindt een controle plaats of alle benodigde velden zijn ingevoerd.
De enige adder die ik onder het gras zie zitten is bij het 'inplakken' van een .cgi bestand in het 'Contents of file' venster. Zoals ik in eerdere posts al heb geschreven heb je grote kans dat een vanuit Windows geplakt .cgi script niet goed uitgevoerd wordt omdat Windows ^M-tekens aan het einde van een regel plakt. Je kan dus wél op deze manier een .cgi script naar de Syno uploaden, je zal alleen wél naderhand de ^M tekens uit het bestand moeten vissen.
PHP bestanden hebben er veel minder moeite mee. Ik studeer nog op een mogelijkheid om ook die ^M's er uit te filteren.... (als iemand nog suggesties heeft....)
3) Backup en restore
Initieel is de drop-down links leeg; pas als er één of meer backups gemaakt zijn komen hier de diverse gemaakte backups te staan, gesorteerd op datum; de nieuwste eerst.
Als je klikt op 'Backup' wordt de gehele 3rd-party directorystructuur gekopiëerd. Waarheen is instelbaar in het script. Standaard is dit '/volume1/tmp/backupSynology'.
Restore werkt uiteraard enkel ná een eerste backup. Je kiest uit de dropdown lijst de backup die je wilt restoren en klikt op 'Restore'.
Veel plezier er mee!
Wizjos