From 2ec5595277eb0e3c5a4a3e042b5ffac04fa4d065 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur <eldy@destailleur.fr> Date: Sat, 4 Apr 2015 00:19:03 +0200 Subject: [PATCH] NEW Can install an external module from admin pages, if web server has permission for and if setup is ok for. --- htdocs/admin/tools/update.php | 164 +++++++++++++++--- htdocs/core/lib/functions.lib.php | 7 +- .../modules/syslog/mod_syslog_chromephp.php | 2 +- htdocs/langs/en_US/admin.lang | 7 +- 4 files changed, 150 insertions(+), 30 deletions(-) diff --git a/htdocs/admin/tools/update.php b/htdocs/admin/tools/update.php index 7c85f820eab..27799ff1e93 100644 --- a/htdocs/admin/tools/update.php +++ b/htdocs/admin/tools/update.php @@ -29,6 +29,8 @@ include_once DOL_DOCUMENT_ROOT . '/core/lib/geturl.lib.php'; $langs->load("admin"); $langs->load("other"); +$action=GETPOST('action','alpha'); + if (! $user->admin) accessforbidden(); if (GETPOST('msg','alpha')) { @@ -43,14 +45,18 @@ $dolibarrroot=preg_replace('/([\\/]+)$/i','',DOL_DOCUMENT_ROOT); $dolibarrroot=preg_replace('/([^\\/]+)$/i','',$dolibarrroot); $dolibarrdataroot=preg_replace('/([\\/]+)$/i','',DOL_DATA_ROOT); +$dirins=DOL_DOCUMENT_ROOT.'/custom'; + + /* * Actions */ -if (GETPOST('action','alpha')=='install') +if ($action=='install') { $error=0; + // $original_file should match format module_modulename-x.y[.z].zip $original_file=basename($_FILES["fileinstall"]["name"]); $newfile=$conf->admin->dir_temp.'/'.$original_file.'/'.$original_file; @@ -72,33 +78,87 @@ if (GETPOST('action','alpha')=='install') if (! $error) { - @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$original_file); - dol_mkdir($conf->admin->dir_temp.'/'.$original_file); + if ($original_file) + { + @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$original_file); + dol_mkdir($conf->admin->dir_temp.'/'.$original_file); + } + + $tmpdir=preg_replace('/\.zip$/','',$original_file).'.dir'; + if ($tmpdir) + { + @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$tmpdir); + dol_mkdir($conf->admin->dir_temp.'/'.$tmpdir); + } $result=dol_move_uploaded_file($_FILES['fileinstall']['tmp_name'],$newfile,1,0,$_FILES['fileinstall']['error']); if ($result > 0) { - $documentrootalt=DOL_DOCUMENT_ROOT.'/extensions'; - $result=dol_uncompress($newfile,$documentrootalt); + $result=dol_uncompress($newfile,$conf->admin->dir_temp.'/'.$tmpdir); + if (! empty($result['error'])) { $langs->load("errors"); setEventMessage($langs->trans($result['error'],$original_file), 'errors'); + $error++; } else { - setEventMessage($langs->trans("SetupIsReadyForUse")); + // Now we move the dir of the module + $modulename=preg_replace('/module_/', '', $original_file); + $modulename=preg_replace('/\-[\d]+\.[\d]+.*$/', '', $modulename); + // Search dir $modulename + $modulenamedir=$conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulename; + //var_dump($modulenamedir); + if (! dol_is_dir($modulenamedir)) + { + $modulenamedir=$conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulename; + //var_dump($modulenamedir); + if (! dol_is_dir($modulenamedir)) + { + setEventMessage($langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat"), 'errors'); + $error++; + } + } + + if (! $error) + { + //var_dump($dirins); + @dol_delete_dir_recursive($dirins.'/'.$modulename); + $result=dolCopyDir($modulenamedir, $dirins.'/'.$modulename, '0444', 1); + if ($result <= 0) + { + setEventMessage($langs->trans("ErrorFailedToCopy"), 'errors'); + $error++; + } + } } } + else + { + $error++; + } + } + + if (! $error) + { + setEventMessage($langs->trans("SetupIsReadyForUse")); } } + /* * View */ -$dirins=DOL_DOCUMENT_ROOT.'/extensions'; -$dirins_ok=(is_dir($dirins)); + + +// Set dir where external modules are installed +if (! dol_is_dir($dirins)) +{ + dol_mkdir($dirins); +} +$dirins_ok=(dol_is_dir($dirins)); $wikihelp='EN:Installation_-_Upgrade|FR:Installation_-_Mise_à_jour|ES:Instalación_-_Actualización'; llxHeader('',$langs->trans("Upgrade"),$wikihelp); @@ -143,6 +203,8 @@ else } print '<br>'; + +// Upgrade print $langs->trans("Upgrade").'<br>'; print '<hr>'; print $langs->trans("ThisIsProcessToFollow").'<br>'; @@ -162,20 +224,76 @@ print $langs->trans("RestoreLock",$dolibarrdataroot.'/install.lock').'<br>'; print '<br>'; print '<br>'; + +// Install external module + +$allowonlineinstall=true; +$allowfromweb=1; +if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) $allowonlineinstall=false; + $fullurl='<a href="'.$urldolibarrmodules.'" target="_blank">'.$urldolibarrmodules.'</a>'; +$message=''; +if (! empty($allowonlineinstall)) +{ + if (! in_array('/custom',explode(',',$dolibarr_main_url_root_alt))) + { + $message=info_admin($langs->trans("ConfFileMuseContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT)); + $allowfromweb=-1; + } + else + { + if ($dirins_ok) + { + if (! is_writable(dol_osencode($dirins))) + { + $langs->load("errors"); + $message=info_admin($langs->trans("ErrorFailedToWriteInDir",$dirins)); + $allowfromweb=0; + } + } + else + { + + $message=info_admin($langs->trans("NotExistsDirect",$dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample")); + $allowfromweb=0; + } + } +} +else +{ + $message=info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile",$dolibarrdataroot.'/installmodules.lock')); + $allowfromweb=0; +} + + + + + print $langs->trans("AddExtensionThemeModuleOrOther").'<br>'; print '<hr>'; -print $langs->trans("ThisIsProcessToFollow").'<br>'; -print '<b>'.$langs->trans("StepNb",1).'</b>: '; -print $langs->trans("FindPackageFromWebSite",$fullurl).'<br>'; -print '<b>'.$langs->trans("StepNb",2).'</b>: '; -print $langs->trans("DownloadPackageFromWebSite",$fullurl).'<br>'; -print '<b>'.$langs->trans("StepNb",3).'</b>: '; -print $langs->trans("UnpackPackageInDolibarrRoot",$dolibarrroot).'<br>'; -if (! empty($conf->global->MAIN_ONLINE_INSTALL_MODULE)) + +if ($allowfromweb < 1) +{ + print $langs->trans("SomethingMakeInstallFromWebNotPossible"); + print $message; + //print $langs->trans("SomethingMakeInstallFromWebNotPossible2"); + print '<br>'; +} + + +if ($allowfromweb >= 0) { - if ($dirins_ok) + if ($allowfromweb == 1) print $langs->trans("ThisIsProcessToFollow").'<br>'; + else print $langs->trans("ThisIsAlternativeProcessToFollow").'<br>'; + print '<b>'.$langs->trans("StepNb",1).'</b>: '; + print $langs->trans("FindPackageFromWebSite",$fullurl).'<br>'; + print '<b>'.$langs->trans("StepNb",2).'</b>: '; + print $langs->trans("DownloadPackageFromWebSite",$fullurl).'<br>'; + print '<b>'.$langs->trans("StepNb",3).'</b>: '; + + if ($allowfromweb == 1) { + print $langs->trans("UnpackPackageInDolibarrRoot",$dirins).'<br>'; print '<form enctype="multipart/form-data" method="POST" class="noborder" action="'.$_SERVER["PHP_SELF"].'" name="forminstall">'; print '<input type="hidden" name="action" value="install">'; print $langs->trans("YouCanSubmitFile").' <input type="file" name="fileinstall"> '; @@ -184,16 +302,12 @@ if (! empty($conf->global->MAIN_ONLINE_INSTALL_MODULE)) } else { - $message=info_admin($langs->trans("NotExistsDirect",$dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample")); - setEventMessage($message, 'warnings'); + print $langs->trans("UnpackPackageInDolibarrRoot",$dirins).'<br>'; + print '<b>'.$langs->trans("StepNb",4).'</b>: '; + print $langs->trans("SetupIsReadyForUse").'<br>'; } } -else -{ - print '<b>'.$langs->trans("StepNb",4).'</b>: '; - print $langs->trans("SetupIsReadyForUse").'<br>'; -} -print '</form>'; + if (! empty($result['return'])) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index f687d79bcd1..d2465afff22 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -3728,9 +3728,10 @@ function get_exdir($num,$level=3,$alpha=0,$withoutslash=0) * * @param string $dir Directory to create (Separator must be '/'. Example: '/mydir/mysubdir') * @param string $dataroot Data root directory (To avoid having the data root in the loop. Using this will also lost the warning on first dir PHP has no permission when open_basedir is used) + * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0444' * @return int < 0 if KO, 0 = already exists, > 0 if OK */ -function dol_mkdir($dir, $dataroot='') +function dol_mkdir($dir, $dataroot='', $newmask=0) { global $conf; @@ -3767,8 +3768,8 @@ function dol_mkdir($dir, $dataroot='') dol_syslog("functions.lib::dol_mkdir: Directory '".$ccdir."' does not exists or is outside open_basedir PHP setting.",LOG_DEBUG); umask(0); - $dirmaskdec=octdec('0755'); - if (! empty($conf->global->MAIN_UMASK)) $dirmaskdec=octdec($conf->global->MAIN_UMASK); + $dirmaskdec=octdec($newmask); + if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $dirmaskdec=octdec($conf->global->MAIN_UMASK); $dirmaskdec |= octdec('0111'); // Set x bit required for directories if (! @mkdir($ccdir_osencoded, $dirmaskdec)) { diff --git a/htdocs/core/modules/syslog/mod_syslog_chromephp.php b/htdocs/core/modules/syslog/mod_syslog_chromephp.php index 3e24901f5af..9ea39caaf50 100644 --- a/htdocs/core/modules/syslog/mod_syslog_chromephp.php +++ b/htdocs/core/modules/syslog/mod_syslog_chromephp.php @@ -55,7 +55,7 @@ class mod_syslog_chromephp extends LogHandler implements LogHandlerInterface set_include_path($conf->global->SYSLOG_CHROMEPHP_INCLUDEPATH); //print 'rrrrr'.get_include_path(); - $res = include_once('ChromePhp.php'); + $res = @include_once('ChromePhp.php'); if (! $res) $res=@include_once('ChromePhp.class.php'); restore_include_path(); diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index b24e108c80f..984b9717dab 100755 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -297,10 +297,11 @@ MenuHandlers=Menu handlers MenuAdmin=Menu editor DoNotUseInProduction=Do not use in production ThisIsProcessToFollow=This is setup to process: +ThisIsAlternativeProcessToFollow=This is an alternative setup to process: StepNb=Step %s FindPackageFromWebSite=Find a package that provides feature you want (for example on official web site %s). DownloadPackageFromWebSite=Download package %s. -UnpackPackageInDolibarrRoot=Unpack package file into Dolibarr's root directory <b>%s</b> +UnpackPackageInDolibarrRoot=Unpack package file into directory dedicated to external modules: <b>%s</b> SetupIsReadyForUse=Install is finished and Dolibarr is ready to use with this new component. NotExistsDirect=The alternative root directory is not defined.<br> InfDirAlt=Since version 3 it is possible to define an alternative root directory.This allows you to store, same place, plug-ins and custom templates.<br>Just create a directory at the root of Dolibarr (eg: custom).<br> @@ -1617,3 +1618,7 @@ ListOfFixedNotifications=List of fixed notifications GoOntoContactCardToAddMore=Go on the tab "Notifications" of a thirdparty contact to add or remove notifications for contacts/addresses Threshold=Threshold BackupDumpWizard=Wizard to build database backup dump file +SomethingMakeInstallFromWebNotPossible=Installation of external module is not possible from the web interface for the following reason: +SomethingMakeInstallFromWebNotPossible2=For this reason, process to upgrade described here is only manual steps a privileged user can do. +InstallModuleFromWebHasBeenDisabledByFile=Install of external module from application has been disabled by your administrator. You must ask him to remove the file <strong>%s</strong> to allow this feature. +ConfFileMuseContainCustom=Installing an external module from application save the module files into directory <strong>%s</strong>. To have this directory processed by Dolibarr, you must setup your <strong>conf/conf.php</strong> to have option<br>- <strong>$dolibarr_main_url_root_alt</strong> enabled to value <strong>$dolibarr_main_url_root_alt="/custom"</strong><br>- <strong>$dolibarr_main_document_root_alt</strong> enabled to value <strong>"%s/custom"</strong> \ No newline at end of file -- GitLab