diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 0e7203ba748..884dbaa120c 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -108,27 +108,36 @@ function versiondolibarrarray() /** - * Launch a sql file. Function used by: + * Launch a sql file. Function is used by: * - Migrate process (dolibarr-xyz-abc.sql) * - Loading sql menus (auguria) * - Running specific Sql by a module init + * - Loading sql file of website import package * Install process however does not use it. - * Note that Sql files must have all comments at start of line. + * Note that Sql files must have all comments at start of line. Also this function take ';' as the char to detect end of sql request * - * @param string $sqlfile Full path to sql file - * @param int $silent 1=Do not output anything, 0=Output line for update page - * @param int $entity Entity targeted for multicompany module - * @param int $usesavepoint 1=Run a savepoint before each request and a rollback to savepoint if error (this allow to have some request with errors inside global transactions). - * @param string $handler Handler targeted for menu - * @param string $okerror Family of errors we accept ('default', 'none') - * @return int <=0 if KO, >0 if OK + * @param string $sqlfile Full path to sql file + * @param int $silent 1=Do not output anything, 0=Output line for update page + * @param int $entity Entity targeted for multicompany module + * @param int $usesavepoint 1=Run a savepoint before each request and a rollback to savepoint if error (this allow to have some request with errors inside global transactions). + * @param string $handler Handler targeted for menu (replace __HANDLER__ with this value) + * @param string $okerror Family of errors we accept ('default', 'none') + * @param int $linelengthlimit Limit for length of each line (Use 0 if unknown, may be faster if defined) + * @param int $nocommentremoval Do no try to remove comments (in such a case, we consider that each line is a request, so use also $linelengthlimit=0) + * @return int <=0 if KO, >0 if OK */ -function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$okerror='default') +function run_sql($sqlfile, $silent=1, $entity='', $usesavepoint=1, $handler='', $okerror='default', $linelengthlimit=32768, $nocommentremoval=0) { global $db, $conf, $langs, $user; dol_syslog("Admin.lib::run_sql run sql file ".$sqlfile." silent=".$silent." entity=".$entity." usesavepoint=".$usesavepoint." handler=".$handler." okerror=".$okerror, LOG_DEBUG); + if (! is_numeric($linelengthlimit)) + { + dol_syslog("Admin.lib::run_sql param linelengthlimit is not a numeric", LOG_ERR); + return -1; + } + $ok=0; $error=0; $i=0; @@ -143,7 +152,9 @@ function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$oker { while (! feof($fp)) { - $buf = fgets($fp, 32768); + // Warning fgets with second parameter that is null or 0 hang. + if ($linelengthlimit > 0) $buf = fgets($fp, $linelengthlimit); + else $buf = fgets($fp); // Test if request must be ran only for particular database or version (if yes, we must remove the -- comment) if (preg_match('/^--\sV(MYSQL|PGSQL)([^\s]*)/i',$buf,$reg)) @@ -191,13 +202,13 @@ function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$oker } // Add line buf to buffer if not a comment - if (! preg_match('/^\s*--/',$buf)) + if ($nocommentremoval || ! preg_match('/^\s*--/',$buf)) { - $buf=preg_replace('/([,;ERLT\)])\s*--.*$/i','\1',$buf); //remove comment from a line that not start with -- before add it to the buffer + if (empty($nocommentremoval)) $buf=preg_replace('/([,;ERLT\)])\s*--.*$/i','\1',$buf); //remove comment from a line that not start with -- before add it to the buffer $buffer .= trim($buf); } - // print $buf.'
'; + //print $buf.'
';exit; if (preg_match('/;/',$buffer)) // If string contains ';', it's end of a request string, we save it in arraysql. { @@ -229,7 +240,7 @@ function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$oker if (! isset($listofmaxrowid[$table])) { //var_dump($db); - $sqlgetrowid='SELECT MAX(rowid) as max from '.$table; + $sqlgetrowid='SELECT MAX(rowid) as max from '.preg_replace('/^llx_/', MAIN_DB_PREFIX, $table); $resql=$db->query($sqlgetrowid); if ($resql) { @@ -246,9 +257,10 @@ function run_sql($sqlfile,$silent=1,$entity='',$usesavepoint=1,$handler='',$oker break; } } + // Replace __+MAX_llx_table__ with +999 $from='__+MAX_'.$table.'__'; $to='+'.$listofmaxrowid[$table]; - $newsql=str_replace($from,$to,$newsql); + $newsql=str_replace($from, $to, $newsql); dol_syslog('Admin.lib::run_sql New Request '.($i+1).' (replacing '.$from.' to '.$to.')', LOG_DEBUG); $arraysql[$i]=$newsql; diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 15e8c003417..a7001d357b8 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -574,7 +574,7 @@ function dol_filemtime($pathoffile) * @param array $arrayreplacement Array with strings to replace. Example: array('valuebefore'=>'valueafter', ...) * @param string $destfile Destination file (can't be a directory). If empty, will be same than source file. * @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666' - * @param int $indexdatabase Index new file into database. + * @param int $indexdatabase 1=index new file into database. * @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK * @see dol_copy dolReplaceRegExInFile */ @@ -611,7 +611,7 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, dol_delete_file($tmpdestfile); // Create $newpathoftmpdestfile from $newpathofsrcfile - $content=file_get_contents($newpathofsrcfile, 'r'); + $content = file_get_contents($newpathofsrcfile, 'r'); $content = make_substitutions($content, $arrayreplacement, null); @@ -1509,7 +1509,7 @@ function dol_init_file_process($pathtoscan='', $trackid='') * * @param string $upload_dir Directory where to store uploaded file (note: used to forge $destpath = $upload_dir + filename) * @param int $allowoverwrite 1=Allow overwrite existing file - * @param int $donotupdatesession 1=Do no edit _SESSION variable but update database index. 0=Update _SESSION and not database index. + * @param int $donotupdatesession 1=Do no edit _SESSION variable but update database index. 0=Update _SESSION and not database index. -1=Do not update SESSION neither db. * @param string $varfiles _FILES var name * @param string $savingdocmask Mask to use to define output filename. For example 'XXXXX-__YYYYMMDD__-__file__' * @param string $link Link to add (to add a link instead of a file) @@ -1591,7 +1591,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio } // Update table of files - if ($donotupdatesession) + if ($donotupdatesession == 1) { $result = addFileIntoDatabaseIndex($upload_dir, basename($destfile), $TFile['name'][$i], 'uploaded', 0); if ($result < 0) @@ -1656,7 +1656,7 @@ function dol_add_file_process($upload_dir, $allowoverwrite=0, $donotupdatesessio * All information used are in db, conf, langs, user and _FILES. * * @param int $filenb File nb to delete - * @param int $donotupdatesession 1=Do not edit _SESSION variable + * @param int $donotupdatesession -1 or 1 = Do not update _SESSION variable * @param int $donotdeletefile 1=Do not delete physically file * @param string $trackid Track id (used to prefix name of session vars to avoid conflict) * @return void diff --git a/htdocs/langs/en_US/website.lang b/htdocs/langs/en_US/website.lang index fe3a4b7cf92..ef2b70b685a 100644 --- a/htdocs/langs/en_US/website.lang +++ b/htdocs/langs/en_US/website.lang @@ -47,6 +47,7 @@ PreviewSiteServedByWebServer=Preview %s in a new tab.

The %s will PreviewSiteServedByDolibarr=Preview %s in a new tab.

The %s will be served by Dolibarr server so it does not need any extra web server (like Apache, Nginx, IIS) to be installed.
The inconvenient is that URL of pages are not user friendly and start with path of your Dolibarr.
URL served by Dolibarr:
%s

To use your own external web server to serve this web site, create a virtual host on your web server that point on directory
%s
then enter the name of this virtual server and click on the other preview button. VirtualHostUrlNotDefined=URL of the virtual host served by external web server not defined NoPageYet=No pages yet +YouCanCreatePageOrImportTemplate=You can create a new page or import a full website template SyntaxHelp=Help on specific syntax tips YouCanEditHtmlSourceckeditor=You can edit HTML source code using the "Source" button in editor. YouCanEditHtmlSource=
You can include PHP code into this source using tags <?php ?>. The following global variables are available: $conf, $langs, $db, $mysoc, $user, $website.

You can also include content of another Page/Container with the following syntax:
<?php includeContainer('alias_of_container_to_include'); ?>

You can make a redirect to another Page/Container with the following syntax:
<?php redirectToContainer('alias_of_container_to_redirect_to'); ?>

To include a link to download a file stored into the documents directory, use the document.php wrapper:
Example, for a file into documents/ecm (need to be logged), syntax is:
<a href="/document.php?modulepart=ecm&file=[relative_dir/]filename.ext">
For a file into documents/medias (open directory for public access), syntax is:
<a href="/document.php?modulepart=medias&file=[relative_dir/]filename.ext">
For a file shared with a share link (open access using the sharing hash key of file), syntax is:
<a href="/document.php?hashp=publicsharekeyoffile">

To include an image stored into the documents directory, use the viewimage.php wrapper:
Example, for an image into documents/medias (open access), syntax is:
<a href="/viewimage.php?modulepart=medias&file=[relative_dir/]filename.ext">
diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index 9e128329cad..1f7a8bf90a8 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -853,10 +853,11 @@ class Website extends CommonObject } foreach($listofpages as $pageid => $objectpageold) { - $line = 'INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, title, description, keyword, status, date_creation, tms, lang, import_key, grabbed_from, content)'; + // Warning: We must keep llx_ here. It is a generic SQL. + $line = 'INSERT INTO llx_website_page(rowid, fk_page, fk_website, pageurl, title, description, keywords, status, date_creation, tms, lang, import_key, grabbed_from, content)'; $line.= " VALUES("; - $line.= $objectpageold->newid."+__MAXROWID__, "; - $line.= ($objectpageold->newfk_page ? $this->db->escape($objectpageold->newfk_page)."+__MAXROWID__" : "null").", "; + $line.= $objectpageold->newid."__+MAX_llx_website_page__, "; + $line.= ($objectpageold->newfk_page ? $this->db->escape($objectpageold->newfk_page)."__+MAX_llx_website_page__" : "null").", "; $line.= "__WEBSITE_ID__, "; $line.= "'".$this->db->escape($objectpageold->pageurl)."', "; $line.= "'".$this->db->escape($objectpageold->title)."', "; @@ -879,7 +880,7 @@ class Website extends CommonObject @chmod($filesql, octdec($conf->global->MAIN_UMASK)); // Build zip file - $filedir = $conf->website->dir_temp.'/'.$website->ref; + $filedir = $conf->website->dir_temp.'/'.$website->ref.'/.'; $fileglob = $conf->website->dir_temp.'/'.$website->ref.'/website_'.$website->ref.'-*.zip'; $filename = $conf->website->dir_temp.'/'.$website->ref.'/website_'.$website->ref.'-'.dol_print_date(dol_now(),'dayhourlog').'.zip'; @@ -900,9 +901,17 @@ class Website extends CommonObject { global $conf; - $result = 0; + $error = 0; - $object = new Website($this->db); + $object = $this; + if (empty($object->ref)) + { + $this->error = 'Function importWebSite called on object not loaded (object->ref is empty)'; + return -1; + } + + dol_delete_dir_recursive(dirname($pathtofile).'/'.$object->ref); + dol_mkdir(dirname($pathtofile).'/'.$object->ref); $filename = basename($pathtofile); if (! preg_match('/^website_(.*)-(.*)$/', $filename, $reg)) @@ -911,13 +920,43 @@ class Website extends CommonObject return -1; } - $websitecode = $reg[1]; - - $sql = "INSERT INTO ".MAIN_DB_PREFIX."website(ref, entity, description, status) values('".$websitecode."', ".$conf->entity.", 'Portal to sell your SaaS. Do not remove this entry.', 1)"; - $resql = $this->db->query($sql); + $result = dol_uncompress($pathtofile, $conf->website->dir_temp.'/'.$object->ref); + if (! empty($result['error'])) + { + $this->errors[]='Failed to unzip file '.$pathtofile.'.'; + return -1; + } - return $result; + dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/containers', $conf->website->dir_output.'/'.$object->ref, 0, 1); // Overwrite if exists + + dolCopyDir($conf->website->dir_temp.'/'.$object->ref.'/medias', $conf->website->dir_output.'/'.$object->ref.'/medias', 0, 1); // Medias can be shared, do not overwrite if exists + + $sqlfile = $conf->website->dir_temp.'/'.$object->ref.'/website_pages.sql'; + + $arrayreplacement = array('__WEBSITE_ID__' => $object->id); + $result = dolReplaceInFile($sqlfile, $arrayreplacement); + + $this->db->begin(); + + $runsql = run_sql($sqlfile, 1, '', 0, '', 'none', 0, 1); + if ($runsql <= 0) + { + $this->errors[]='Failed to load sql file '.$sqlfile.'.'; + $error++; + } + + + if ($error) + { + $this->db->rollback(); + return -1; + } + else + { + $this->db->commit(); + return $object->id; + } } } diff --git a/htdocs/website/index.php b/htdocs/website/index.php index af6b1312cbc..3297d63366b 100644 --- a/htdocs/website/index.php +++ b/htdocs/website/index.php @@ -1276,7 +1276,11 @@ if (($action == 'updatesource' || $action == 'updatecontent' || $action == 'conf } else { - if (! $error) setEventMessages($langs->trans("NoPageYet"), null, 'warnings'); + if (! $error) + { + setEventMessages($langs->trans("NoPageYet"), null, 'warnings'); + setEventMessages($langs->trans("YouCanCreatePageOrImportTemplate"), null, 'warnings'); + } } } @@ -1301,28 +1305,63 @@ if ($action == 'exportsite') // Import site if ($action == 'importsiteconfirm') { - $fileofzip = GETPOST('userfile'); - if (empty($fileofzip)) + if (empty($_FILES)) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("File")), null, 'errors'); $action = 'importsite'; } else { - // TODO - - - $result = $object->importWebSite($fileofzip); - if ($result < 0) + if (! empty($_FILES)) { - setEventMessages($object->error, $object->errors, 'errors'); - $action = 'importsite'; - } - else - { - header("Location: aaaaa"); - exit(); + if (is_array($_FILES['userfile']['tmp_name'])) $userfiles=$_FILES['userfile']['tmp_name']; + else $userfiles=array($_FILES['userfile']['tmp_name']); + + foreach($userfiles as $key => $userfile) + { + if (empty($_FILES['userfile']['tmp_name'][$key])) + { + $error++; + if ($_FILES['userfile']['error'][$key] == 1 || $_FILES['userfile']['error'][$key] == 2){ + setEventMessages($langs->trans('ErrorFileSizeTooLarge'), null, 'errors'); + $action = 'importsite'; + } + else { + setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("File")), null, 'errors'); + $action = 'importsite'; + } + } + } + + if (! $error) + { + $upload_dir = $conf->website->dir_temp; + $result = dol_add_file_process($upload_dir, 1, -1, 'userfile', ''); + + // Get name of file (take last one if several name provided) + $fileofzip = $upload_dir.'/unknown'; + foreach($_FILES as $key => $ifile) + { + foreach($ifile['name'] as $key2 => $ifile2) + { + $fileofzip = $upload_dir . '/' .$ifile2; + } + } + + $result = $object->importWebSite($fileofzip); + if ($result < 0) + { + setEventMessages($object->error, $object->errors, 'errors'); + $action = 'importsite'; + } + else + { + header("Location: ".$_SERVER["PHP_SELF"].'?website='.$object->ref); + exit(); + } + } } + } }