Better support of SFTP for the FTP module

This commit is contained in:
Laurent Destailleur 2020-09-18 00:36:24 +02:00
parent 57ff4784b1
commit 27d03a2034
2 changed files with 91 additions and 48 deletions

View File

@ -87,7 +87,7 @@ if (GETPOST("sendit") && !empty($conf->global->MAIN_UPLOAD_DOC))
{ {
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$result = $ecmdir->fetch($_REQUEST["section"]); $result = $ecmdir->fetch(GETPOST("section", 'int'));
if (!$result > 0) if (!$result > 0)
{ {
dol_print_error($db, $ecmdir->error); dol_print_error($db, $ecmdir->error);
@ -125,9 +125,9 @@ if (GETPOST("sendit") && !empty($conf->global->MAIN_UPLOAD_DOC))
// Action ajout d'un rep // Action ajout d'un rep
if ($action == 'add' && $user->rights->ftp->setup) if ($action == 'add' && $user->rights->ftp->setup)
{ {
$ecmdir->ref = $_POST["ref"]; $ecmdir->ref = GETPOST("ref");
$ecmdir->label = $_POST["label"]; $ecmdir->label = GETPOST("label");
$ecmdir->description = $_POST["desc"]; $ecmdir->description = GETPOST("desc");
$id = $ecmdir->create($user); $id = $ecmdir->create($user);
if ($id > 0) if ($id > 0)
@ -140,8 +140,8 @@ if ($action == 'add' && $user->rights->ftp->setup)
} }
} }
// Remove file // Remove 1 file
if ($action == 'confirm_deletefile' && $_REQUEST['confirm'] == 'yes') if ($action == 'confirm_deletefile' && GETPOST('confirm') == 'yes')
{ {
// set up a connection or die // set up a connection or die
if (!$conn_id) if (!$conn_id)
@ -155,16 +155,26 @@ if ($action == 'confirm_deletefile' && $_REQUEST['confirm'] == 'yes')
if ($conn_id && $ok && !$mesg) if ($conn_id && $ok && !$mesg)
{ {
$newsection = $section;
if (!empty($conf->global->FTP_CONNECT_WITH_SFTP))
{
$newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169
}
$langs->load("other"); $langs->load("other");
// Remote file // Remote file
$filename = $file; $filename = $file;
$remotefile = $section.(preg_match('@[\\\/]$@', $section) ? '' : '/').$file; $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file;
$newremotefileiso = utf8_decode($remotefile); $newremotefileiso = utf8_decode($remotefile);
//print "x".$newremotefileiso; //print "x".$newremotefileiso;
dol_syslog("ftp/index.php ftp_delete ".$newremotefileiso); dol_syslog("ftp/index.php ftp_delete ".$newremotefileiso);
$result = @ftp_delete($conn_id, $newremotefileiso); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) {
$result = ssh2_sftp_unlink($conn_id, $newremotefileiso);
} else {
$result = @ftp_delete($conn_id, $newremotefileiso);
}
if ($result) if ($result)
{ {
setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs'); setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs');
@ -182,7 +192,7 @@ if ($action == 'confirm_deletefile' && $_REQUEST['confirm'] == 'yes')
} }
// Delete several lines at once // Delete several lines at once
if ($_POST["const"] && $_POST["delete"] && $_POST["delete"] == $langs->trans("Delete")) if (GETPOST("const", 'array') && GETPOST("delete") && GETPOST("delete") == $langs->trans("Delete"))
{ {
// set up a connection or die // set up a connection or die
if (!$conn_id) if (!$conn_id)
@ -196,7 +206,7 @@ if ($_POST["const"] && $_POST["delete"] && $_POST["delete"] == $langs->trans("De
if ($conn_id && $ok && !$mesg) if ($conn_id && $ok && !$mesg)
{ {
foreach ($_POST["const"] as $const) foreach (GETPOST('const', 'array') as $const)
{ {
if ($const["check"]) // Is checkbox checked if ($const["check"]) // Is checkbox checked
{ {
@ -204,18 +214,26 @@ if ($_POST["const"] && $_POST["delete"] && $_POST["delete"] == $langs->trans("De
// Remote file // Remote file
$file = $const["file"]; $file = $const["file"];
$section = $const["section"]; $newsection = $const["section"];
$remotefile = $section.(preg_match('@[\\\/]$@', $section) ? '' : '/').$file; if (!empty($conf->global->FTP_CONNECT_WITH_SFTP))
{
$newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169
}
$remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file;
$newremotefileiso = utf8_decode($remotefile); $newremotefileiso = utf8_decode($remotefile);
//print "x".$newremotefileiso; //print "x".$newremotefileiso;
dol_syslog("ftp/index.php ftp_delete ".$newremotefileiso); dol_syslog("ftp/index.php ftp_delete n files for ".$newremotefileiso);
$result = @ftp_delete($conn_id, $newremotefileiso); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) {
$result = ssh2_sftp_unlink($conn_id, $newremotefileiso);
} else {
$result = @ftp_delete($conn_id, $newremotefileiso);
}
if ($result) if ($result)
{ {
setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs'); setEventMessages($langs->trans("FileWasRemoved", $file), null, 'mesgs');
} else { } else {
dol_syslog("ftp/index.php ftp_delete", LOG_ERR); dol_syslog("ftp/index.php ftp_delete n files", LOG_ERR);
setEventMessages($langs->trans("FTPFailedToRemoveFile", $file), null, 'errors'); setEventMessages($langs->trans("FTPFailedToRemoveFile", $file), null, 'errors');
} }
@ -244,12 +262,22 @@ if ($action == 'confirm_deletesection' && $confirm == 'yes')
if ($conn_id && $ok && !$mesg) if ($conn_id && $ok && !$mesg)
{ {
$newsection = $section;
if (!empty($conf->global->FTP_CONNECT_WITH_SFTP))
{
$newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169
}
// Remote file // Remote file
$filename = $file; $filename = $file;
$remotefile = $section.(preg_match('@[\\\/]$@', $section) ? '' : '/').$file; $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file;
$newremotefileiso = utf8_decode($remotefile); $newremotefileiso = utf8_decode($remotefile);
$result = @ftp_rmdir($conn_id, $newremotefileiso); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) {
$result = ssh2_sftp_rmdir($conn_id, $newremotefileiso);
} else {
$result = @ftp_rmdir($conn_id, $newremotefileiso);
}
if ($result) if ($result)
{ {
setEventMessages($langs->trans("DirWasRemoved", $file), null, 'mesgs'); setEventMessages($langs->trans("DirWasRemoved", $file), null, 'mesgs');
@ -283,12 +311,22 @@ if ($action == 'download')
// Local file // Local file
$localfile = tempnam($download_dir, 'dol_'); $localfile = tempnam($download_dir, 'dol_');
$newsection = $section;
if (!empty($conf->global->FTP_CONNECT_WITH_SFTP))
{
$newsection = ssh2_sftp_realpath($conn_id, ".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169
}
// Remote file // Remote file
$filename = $file; $filename = $file;
$remotefile = $section.(preg_match('@[\\\/]$@', $section) ? '' : '/').$file; $remotefile = $newsection.(preg_match('@[\\\/]$@', $newsection) ? '' : '/').$file;
$newremotefileiso = utf8_decode($remotefile); $newremotefileiso = utf8_decode($remotefile);
$result = ftp_get($conn_id, $localfile, $newremotefileiso, FTP_BINARY); if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) {
$result = fopen('ssh2.sftp://' . intval($conn_id) . $newremotefileiso, 'r');
} else {
$result = ftp_get($conn_id, $localfile, $newremotefileiso, FTP_BINARY);
}
if ($result) if ($result)
{ {
if (!empty($conf->global->MAIN_UMASK)) if (!empty($conf->global->MAIN_UMASK))
@ -296,13 +334,13 @@ if ($action == 'download')
// Define mime type // Define mime type
$type = 'application/octet-stream'; $type = 'application/octet-stream';
if (!empty($_GET["type"])) $type = $_GET["type"]; if (GETPOSTISSET("type")) $type = GETPOST("type");
else $type = dol_mimetype($original_file); else $type = dol_mimetype($file);
// Define attachment (attachment=true to force choice popup 'open'/'save as') // Define attachment (attachment=true to force choice popup 'open'/'save as')
$attachment = true; $attachment = true;
if ($encoding) header('Content-Encoding: '.$encoding); //if ($encoding) header('Content-Encoding: '.$encoding);
if ($type) header('Content-Type: '.$type); if ($type) header('Content-Type: '.$type);
if ($attachment) header('Content-Disposition: attachment; filename="'.$filename.'"'); if ($attachment) header('Content-Disposition: attachment; filename="'.$filename.'"');
else header('Content-Disposition: inline; filename="'.$filename.'"'); else header('Content-Disposition: inline; filename="'.$filename.'"');
@ -382,13 +420,13 @@ if (!function_exists('ftp_connect'))
// Confirm remove file // Confirm remove file
if ($action == 'delete') if ($action == 'delete')
{ {
print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'&section='.urlencode($_REQUEST["section"]).'&file='.urlencode($_GET["file"]), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', '', 1); print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'&section='.urlencode(GETPOST('section')).'&file='.urlencode(GETPOST('file')), $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', '', 1);
} }
// Confirmation de la suppression d'une ligne categorie // Confirmation de la suppression d'une ligne categorie
if ($action == 'delete_section') if ($action == 'delete_section')
{ {
print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'&section='.urlencode($_REQUEST["section"]).'&file='.urlencode($_GET["file"]), $langs->trans('DeleteSection'), $langs->trans('ConfirmDeleteSection', $ecmdir->label), 'confirm_deletesection', '', '', 1); print $form->formconfirm($_SERVER["PHP_SELF"].'?numero_ftp='.$numero_ftp.'&section='.urlencode(GETPOST('section')).'&file='.urlencode(GETPOST('file')), $langs->trans('DeleteSection'), $langs->trans('ConfirmDeleteSection', $ecmdir->label), 'confirm_deletesection', '', '', 1);
} }
print $langs->trans("Server").': <b>'.$ftp_server.'</b><br>'; print $langs->trans("Server").': <b>'.$ftp_server.'</b><br>';
@ -431,12 +469,12 @@ if (!function_exists('ftp_connect'))
print '<table width="100%" class="noborder">'."\n"; print '<table width="100%" class="noborder">'."\n";
print '<tr class="liste_titre">'."\n"; print '<tr class="liste_titre">'."\n";
print '<td class="liste_titre" class="left">'.$langs->trans("Content").'</td>'."\n"; print '<td class="liste_titre left">'.$langs->trans("Content").'</td>'."\n";
print '<td class="liste_titre" class="center">'.$langs->trans("Size").'</td>'."\n"; print '<td class="liste_titre center">'.$langs->trans("Size").'</td>'."\n";
print '<td class="liste_titre" class="center">'.$langs->trans("Date").'</td>'."\n"; print '<td class="liste_titre center">'.$langs->trans("Date").'</td>'."\n";
print '<td class="liste_titre" class="center">'.$langs->trans("Owner").'</td>'."\n"; print '<td class="liste_titre center">'.$langs->trans("Owner").'</td>'."\n";
print '<td class="liste_titre" class="center">'.$langs->trans("Group").'</td>'."\n"; print '<td class="liste_titre center">'.$langs->trans("Group").'</td>'."\n";
print '<td class="liste_titre" class="center">'.$langs->trans("Permissions").'</td>'."\n"; print '<td class="liste_titre center">'.$langs->trans("Permissions").'</td>'."\n";
print '<td class="liste_titre nowrap right">'; print '<td class="liste_titre nowrap right">';
if ($conf->use_javascript_ajax) print '<a href="#" id="checkall">'.$langs->trans("All").'</a> / <a href="#" id="checknone">'.$langs->trans("None").'</a> '; if ($conf->use_javascript_ajax) print '<a href="#" id="checkall">'.$langs->trans("All").'</a> / <a href="#" id="checknone">'.$langs->trans("None").'</a> ';
print '<a href="'.$_SERVER["PHP_SELF"].'?action=refreshmanual&numero_ftp='.$numero_ftp.($section ? '&section='.urlencode($section) : '').'">'.img_picto($langs->trans("Refresh"), 'refresh').'</a>&nbsp;'; print '<a href="'.$_SERVER["PHP_SELF"].'?action=refreshmanual&numero_ftp='.$numero_ftp.($section ? '&section='.urlencode($section) : '').'">'.img_picto($langs->trans("Refresh"), 'refresh').'</a>&nbsp;';
@ -464,10 +502,14 @@ if (!function_exists('ftp_connect'))
// List content of directory ($newsection = '/', '/home', ...) // List content of directory ($newsection = '/', '/home', ...)
if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) if (!empty($conf->global->FTP_CONNECT_WITH_SFTP))
{ {
if ($newsection == '/') $newsection = '/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169 if ($newsection == '/') {
//$newsection = '/./';
$newsection = ssh2_sftp_realpath($conn_id,".").'/./'; // workaround for bug https://bugs.php.net/bug.php?id=64169
}
//$newsection='/';
//$dirHandle = opendir("ssh2.sftp://$conn_id".$newsection); //$dirHandle = opendir("ssh2.sftp://$conn_id".$newsection);
//var_dump($dirHandle); //$dirHandle = opendir("ssh2.sftp://".intval($conn_id).ssh2_sftp_realpath($conn_id,".").'/./');
$contents = scandir('ssh2.sftp://'.$conn_id.$newsection); $contents = scandir('ssh2.sftp://'.intval($conn_id).$newsection);
$buff = array(); $buff = array();
foreach ($contents as $i => $key) foreach ($contents as $i => $key)
{ {
@ -528,7 +570,7 @@ if (!function_exists('ftp_connect'))
$newsection = $section.(preg_match('@[\\\/]$@', $section) ? '' : '/').$file; $newsection = $section.(preg_match('@[\\\/]$@', $section) ? '' : '/').$file;
$newsection = preg_replace('@[\\\/][^\\\/]+[\\\/]\.\.$@', '/', $newsection); // Change aaa/xxx/.. to new aaa $newsection = preg_replace('@[\\\/][^\\\/]+[\\\/]\.\.$@', '/', $newsection); // Change aaa/xxx/.. to new aaa
if ($is_directory) print '<a href="'.$_SERVER["PHP_SELF"].'?section='.urlencode($newsection).'&numero_ftp='.$numero_ftp.'">'; if ($is_directory) print '<a href="'.$_SERVER["PHP_SELF"].'?section='.urlencode($newsection).'&numero_ftp='.$numero_ftp.'">';
print $file; print dol_escape_htmltag($file);
if ($is_directory) print '</a>'; if ($is_directory) print '</a>';
print '</td>'; print '</td>';
// Size // Size
@ -553,7 +595,7 @@ if (!function_exists('ftp_connect'))
print $vals[0]; print $vals[0];
print '</td>'; print '</td>';
// Action // Action
print '<td class="right" width="64" class="nowrap">'; print '<td class="right nowrap" width="64">';
if ($is_directory) if ($is_directory)
{ {
if ($file != '..') print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete_section&numero_ftp='.$numero_ftp.'&section='.urlencode($section).'&file='.urlencode($file).'">'.img_delete().'</a>'; if ($file != '..') print '<a href="'.$_SERVER["PHP_SELF"].'?action=delete_section&numero_ftp='.$numero_ftp.'&section='.urlencode($section).'&file='.urlencode($file).'">'.img_delete().'</a>';
@ -676,12 +718,10 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect
if ($ok) if ($ok)
{ {
$connecttimeout = (empty($conf->global->FTP_CONNECT_TIMEOUT) ? 40 : $conf->global->FTP_CONNECT_TIMEOUT); $connecttimeout = (empty($conf->global->FTP_CONNECT_TIMEOUT) ? 40 : $conf->global->FTP_CONNECT_TIMEOUT);
if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) {
{
dol_syslog('Try to connect with ssh2_ftp'); dol_syslog('Try to connect with ssh2_ftp');
$tmp_conn_id = ssh2_connect($ftp_server, $ftp_port); $tmp_conn_id = ssh2_connect($ftp_server, $ftp_port);
} elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) } elseif (!empty($conf->global->FTP_CONNECT_WITH_SSL)) {
{
dol_syslog('Try to connect with ftp_ssl_connect'); dol_syslog('Try to connect with ftp_ssl_connect');
$conn_id = ftp_ssl_connect($ftp_server, $ftp_port, $connecttimeout); $conn_id = ftp_ssl_connect($ftp_server, $ftp_port, $connecttimeout);
} else { } else {
@ -694,6 +734,7 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect
{ {
if (!empty($conf->global->FTP_CONNECT_WITH_SFTP)) if (!empty($conf->global->FTP_CONNECT_WITH_SFTP))
{ {
dol_syslog('Try to authenticate with ssh2_auth_password');
if (ssh2_auth_password($tmp_conn_id, $ftp_user, $ftp_password)) if (ssh2_auth_password($tmp_conn_id, $ftp_user, $ftp_password))
{ {
// Turn on passive mode transfers (must be after a successful login // Turn on passive mode transfers (must be after a successful login
@ -705,11 +746,13 @@ function dol_ftp_connect($ftp_server, $ftp_port, $ftp_user, $ftp_password, $sect
$conn_id = ssh2_sftp($tmp_conn_id); $conn_id = ssh2_sftp($tmp_conn_id);
if (!$conn_id) if (!$conn_id)
{ {
dol_syslog('Failed to connect to SFTP after sssh authentication', LOG_DEBUG);
$mesg = $langs->transnoentitiesnoconv("FailedToConnectToSFTPAfterSSHAuthentication"); $mesg = $langs->transnoentitiesnoconv("FailedToConnectToSFTPAfterSSHAuthentication");
$ok = 0; $ok = 0;
$error++; $error++;
} }
} else { } else {
dol_syslog('Failed to connect to FTP with login '.$ftp_user, LOG_DEBUG);
$mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials"); $mesg = $langs->transnoentitiesnoconv("FailedToConnectToFTPServerWithCredentials");
$ok = 0; $ok = 0;
$error++; $error++;

View File

@ -1,14 +1,14 @@
# Dolibarr language file - Source file is en_US - ftp # Dolibarr language file - Source file is en_US - ftp
FTPClientSetup=FTP Client module setup FTPClientSetup=FTP or SFTP Client module setup
NewFTPClient=New FTP connection setup NewFTPClient=New FTP/FTPS connection setup
FTPArea=FTP Area FTPArea=FTP/FTPS Area
FTPAreaDesc=This screen shows a view of an FTP server. FTPAreaDesc=This screen shows a view of an FTP et SFTP server.
SetupOfFTPClientModuleNotComplete=The setup of the FTP client module seems to be incomplete SetupOfFTPClientModuleNotComplete=The setup of the FTP or SFTP client module seems to be incomplete
FTPFeatureNotSupportedByYourPHP=Your PHP does not support FTP functions FTPFeatureNotSupportedByYourPHP=Your PHP does not support FTP or SFTP functions
FailedToConnectToFTPServer=Failed to connect to FTP server (server %s, port %s) FailedToConnectToFTPServer=Failed to connect to server (server %s, port %s)
FailedToConnectToFTPServerWithCredentials=Failed to login to FTP server with defined login/password FailedToConnectToFTPServerWithCredentials=Failed to login to server with defined login/password
FTPFailedToRemoveFile=Failed to remove file <b>%s</b>. FTPFailedToRemoveFile=Failed to remove file <b>%s</b>.
FTPFailedToRemoveDir=Failed to remove directory <b>%s</b>: check permissions and that the directory is empty. FTPFailedToRemoveDir=Failed to remove directory <b>%s</b>: check permissions and that the directory is empty.
FTPPassiveMode=Passive mode FTPPassiveMode=Passive mode
ChooseAFTPEntryIntoMenu=Choose a FTP site from the menu... ChooseAFTPEntryIntoMenu=Choose a FTP/SFTP site from the menu...
FailedToGetFile=Failed to get files %s FailedToGetFile=Failed to get files %s