dolSavePageContent()   F
last analyzed

Complexity

Conditions 35
Paths > 20000

Size

Total Lines 150
Code Lines 100

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 35
eloc 100
nc 1014745
nop 4
dl 0
loc 150
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/* Copyright (C) 2017 Laurent Destailleur   <[email protected]>
4
 * Copyright (C) 2024       Rafael San José             <[email protected]>
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
use Dolibarr\Lib\ViewMain;
21
22
/**
23
 *      \file       htdocs/core/lib/website2.lib.php
24
 *      \ingroup    website
25
 *      \brief      Library for website module (rare functions not required for execution of website)
26
 */
27
28
29
/**
30
 * Save content of a page on disk
31
 *
32
 * @param string $filemaster Full path of filename master.inc.php for website to generate
33
 * @return  boolean                         True if OK
34
 */
35
function dolSaveMasterFile($filemaster)
36
{
37
    // Now generate the master.inc.php page
38
    dol_syslog("We regenerate the master.inc.php file");
39
40
    dol_delete_file($filemaster);
41
42
    $mastercontent = '<?php' . "\n";
43
    $mastercontent .= '// File generated to link to the master file - DO NOT MODIFY - It is just an include' . "\n";
44
    $mastercontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) {\n";
45
    $mastercontent .= "    if (! defined('USEEXTERNALSERVER')) define('USEEXTERNALSERVER', 1);\n";
46
    $mastercontent .= "    require_once '" . DOL_DOCUMENT_ROOT . "/master.inc.php';\n";
47
    $mastercontent .= "}\n";
48
    $mastercontent .= '?>' . "\n";
49
    $result = file_put_contents($filemaster, $mastercontent);
50
    dolChmod($filemaster);
51
52
    return $result;
53
}
54
55
/**
56
 * Save an alias page on disk (A page that include the reference page).
57
 * It saves file into the root directory but also into language subdirectory.
58
 *
59
 * @param string $filealias Full path of filename to generate
60
 * @param Website $object Object website
61
 * @param WebsitePage $objectpage Object websitepage
62
 * @return  boolean                         True if OK
63
 * @see dolSavePageContent()
64
 */
65
function dolSavePageAlias($filealias, $object, $objectpage)
66
{
67
    // Now create the .tpl file
68
    dol_syslog("dolSavePageAlias We regenerate the alias page filealias=" . $filealias . " and a wrapper into all language subdirectories");
69
70
    $aliascontent = '<?php' . "\n";
71
    $aliascontent .= "// File generated to wrap the alias page - DO NOT MODIFY - It is just a wrapper to real page\n";
72
    $aliascontent .= 'global $dolibarr_main_data_root;' . "\n";
73
    $aliascontent .= 'if (empty($dolibarr_main_data_root)) require \'./page' . $objectpage->id . '.tpl.php\'; ';
74
    $aliascontent .= 'else require $dolibarr_main_data_root.\'/website/\'.$website->ref.\'/page' . $objectpage->id . '.tpl.php\';' . "\n";
75
    $aliascontent .= '?>' . "\n";
76
    $result = file_put_contents($filealias, $aliascontent);
77
    if ($result === false) {
78
        dol_syslog("Failed to write file " . $filealias, LOG_WARNING);
79
    }
80
    dolChmod($filealias);
81
82
    // Save also alias into language subdirectory if it is not a main language
83
    if ($objectpage->lang && in_array($objectpage->lang, explode(',', $object->otherlang))) {
84
        $dirname = dirname($filealias);
85
        $filename = basename($filealias);
86
        $filealiassub = $dirname . '/' . $objectpage->lang . '/' . $filename;
87
88
        dol_mkdir($dirname . '/' . $objectpage->lang, DOL_DATA_ROOT);
89
90
        $aliascontent = '<?php' . "\n";
91
        $aliascontent .= "// File generated to wrap the alias page - DO NOT MODIFY - It is just a wrapper to real page\n";
92
        $aliascontent .= 'global $dolibarr_main_data_root;' . "\n";
93
        $aliascontent .= 'if (empty($dolibarr_main_data_root)) require \'../page' . $objectpage->id . '.tpl.php\'; ';
94
        $aliascontent .= 'else require $dolibarr_main_data_root.\'/website/\'.$website->ref.\'/page' . $objectpage->id . '.tpl.php\';' . "\n";
95
        $aliascontent .= '?>' . "\n";
96
        $result = file_put_contents($filealiassub, $aliascontent);
97
        if ($result === false) {
98
            dol_syslog("Failed to write file " . $filealiassub, LOG_WARNING);
99
        }
100
        dolChmod($filealiassub);
101
    } elseif (empty($objectpage->lang) || !in_array($objectpage->lang, explode(',', $object->otherlang))) {
102
        // Save also alias into all language subdirectories if it is a main language
103
        if (!getDolGlobalString('WEBSITE_DISABLE_MAIN_LANGUAGE_INTO_LANGSUBDIR') && !empty($object->otherlang)) {
104
            $dirname = dirname($filealias);
105
            $filename = basename($filealias);
106
            foreach (explode(',', $object->otherlang) as $sublang) {
107
                // Avoid to erase main alias file if $sublang is empty string
108
                if (empty(trim($sublang))) {
109
                    continue;
110
                }
111
                $filealiassub = $dirname . '/' . $sublang . '/' . $filename;
112
113
                $aliascontent = '<?php' . "\n";
114
                $aliascontent .= "// File generated to wrap the alias page - DO NOT MODIFY - It is just a wrapper to real page\n";
115
                $aliascontent .= 'global $dolibarr_main_data_root;' . "\n";
116
                $aliascontent .= 'if (empty($dolibarr_main_data_root)) require \'../page' . $objectpage->id . '.tpl.php\'; ';
117
                $aliascontent .= 'else require $dolibarr_main_data_root.\'/website/\'.$website->ref.\'/page' . $objectpage->id . '.tpl.php\';' . "\n";
118
                $aliascontent .= '?>' . "\n";
119
120
                dol_mkdir($dirname . '/' . $sublang);
121
                $result = file_put_contents($filealiassub, $aliascontent);
122
                if ($result === false) {
123
                    dol_syslog("Failed to write file " . $filealiassub, LOG_WARNING);
124
                }
125
                dolChmod($filealiassub);
126
            }
127
        }
128
    }
129
130
    return ($result ? true : false);
131
}
132
133
134
/**
135
 * Save content of a page on disk (page name is generally ID_of_page.php).
136
 * Page contents are always saved into "root" directory. Only aliases pages saved with dolSavePageAlias() can be in root or language subdir.
137
 *
138
 * @param string $filetpl Full path of filename to generate
139
 * @param Website $object Object website
140
 * @param WebsitePage $objectpage Object websitepage
141
 * @param int $backupold 1=Make a backup of old page
142
 * @return  boolean                         True if OK
143
 * @see dolSavePageAlias()
144
 */
145
function dolSavePageContent($filetpl, Website $object, WebsitePage $objectpage, $backupold = 0)
146
{
147
    global $db;
148
149
    // Now create the .tpl file (duplicate code with actions updatesource or updatecontent but we need this to save new header)
150
    dol_syslog("dolSavePageContent We regenerate the tpl page filetpl=" . $filetpl);
151
152
    include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
153
154
    if (dol_is_file($filetpl)) {
155
        if ($backupold) {
156
            $result = archiveOrBackupFile($filetpl);
157
            if (!$result) {
158
                return false;
159
            }
160
        } else {
161
            dol_delete_file($filetpl);
162
        }
163
    }
164
165
    $shortlangcode = '';
166
    if ($objectpage->lang) {
167
        $shortlangcode = substr($objectpage->lang, 0, 2); // en_US or en-US -> en
168
    }
169
    if (empty($shortlangcode)) {
170
        $shortlangcode = substr($object->lang, 0, 2); // en_US or en-US -> en
171
    }
172
173
    if (!empty($objectpage->type_container) && in_array($objectpage->type_container, array('library', 'service'))) {
174
        $originalcontentonly = 1;
175
    }
176
177
    $tplcontent = '';
178
    if (!isset($originalcontentonly)) {
179
        $tplcontent .= "<?php // BEGIN PHP\n";
180
        $tplcontent .= '$websitekey=basename(__DIR__); if (empty($websitepagefile)) $websitepagefile=__FILE__;' . "\n";
181
        $tplcontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) {\n";
182
        $tplcontent .= '	$pathdepth = count(explode(\'/\', $_SERVER[\'SCRIPT_NAME\'])) - 2;' . "\n";
183
        $tplcontent .= '	require_once ($pathdepth ? str_repeat(\'../\', $pathdepth) : \'./\').\'master.inc.php\';' . "\n";
184
        $tplcontent .= "} // Not already loaded\n";
185
        $tplcontent .= "require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
186
        $tplcontent .= "require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
187
        $tplcontent .= "ob_start();\n";
188
        $tplcontent .= "// END PHP ?>\n";
189
        if (getDolGlobalString('WEBSITE_FORCE_DOCTYPE_HTML5')) {
190
            $tplcontent .= "<!DOCTYPE html>\n";
191
        }
192
        $tplcontent .= '<html' . ($shortlangcode ? ' lang="' . $shortlangcode . '"' : '') . '>' . "\n";
193
        $tplcontent .= '<head>' . "\n";
194
        $tplcontent .= '<title>' . dol_string_nohtmltag($objectpage->title, 0, 'UTF-8') . '</title>' . "\n";
195
        $tplcontent .= '<meta charset="utf-8">' . "\n";
196
        $tplcontent .= '<meta http-equiv="content-type" content="text/html; charset=utf-8" />' . "\n";
197
        $tplcontent .= '<meta name="robots" content="index, follow" />' . "\n";
198
        $tplcontent .= '<meta name="viewport" content="width=device-width, initial-scale=1.0">' . "\n";
199
        $tplcontent .= '<meta name="keywords" content="' . dol_string_nohtmltag($objectpage->keywords) . '" />' . "\n";
200
        $tplcontent .= '<meta name="title" content="' . dol_string_nohtmltag($objectpage->title, 0, 'UTF-8') . '" />' . "\n";
201
        $tplcontent .= '<meta name="description" content="' . dol_string_nohtmltag($objectpage->description, 0, 'UTF-8') . '" />' . "\n";
202
        $tplcontent .= '<meta name="generator" content="' . DOL_APPLICATION_TITLE . ' ' . DOL_VERSION . ' (https://www.dolibarr.org)" />' . "\n";
203
        $tplcontent .= '<meta name="dolibarr:pageid" content="' . dol_string_nohtmltag($objectpage->id) . '" />' . "\n";
204
205
        // Add favicon
206
        if ($objectpage->id == $object->fk_default_home) {
207
            $tplcontent .= '<link rel="icon" type="image/png" href="/favicon.png" />' . "\n";
208
        }
209
210
        // Add canonical reference
211
        if ($object->virtualhost) {
212
            $tplcontent .= '<link rel="canonical" href="' . (($objectpage->id == $object->fk_default_home) ? '/' : (($shortlangcode != substr($object->lang, 0, 2) ? '/' . $shortlangcode : '') . '/' . $objectpage->pageurl . '.php')) . '" />' . "\n";
213
        }
214
        // Add translation reference (main language)
215
        if ($object->isMultiLang()) {
216
            // Add page "translation of"
217
            $translationof = $objectpage->fk_page;
218
            if ($translationof) {
219
                $tmppage = new WebsitePage($db);
220
                $tmppage->fetch($translationof);
221
                if ($tmppage->id > 0) {
222
                    $tmpshortlangcode = '';
223
                    if ($tmppage->lang) {
224
                        $tmpshortlangcode = preg_replace('/[_-].*$/', '', $tmppage->lang); // en_US or en-US -> en
225
                    }
226
                    if (empty($tmpshortlangcode)) {
227
                        $tmpshortlangcode = preg_replace('/[_-].*$/', '', $object->lang); // en_US or en-US -> en
228
                    }
229
                    if ($tmpshortlangcode != $shortlangcode) {
230
                        $tplcontent .= '<link rel="alternate" hreflang="' . $tmpshortlangcode . '" href="<?php echo $website->virtualhost; ?>' . ($object->fk_default_home == $tmppage->id ? '/' : (($tmpshortlangcode != substr($object->lang, 0, 2)) ? '/' . $tmpshortlangcode : '') . '/' . $tmppage->pageurl . '.php') . '" />' . "\n";
231
                    }
232
                }
233
            }
234
235
            // Add "has translation pages"
236
            $sql = "SELECT rowid as id, lang, pageurl from " . MAIN_DB_PREFIX . 'website_page where fk_page IN (' . $db->sanitize($objectpage->id . ($translationof ? ", " . $translationof : '')) . ")";
237
            $resql = $db->query($sql);
238
            if ($resql) {
239
                $num_rows = $db->num_rows($resql);
240
                if ($num_rows > 0) {
241
                    while ($obj = $db->fetch_object($resql)) {
242
                        $tmpshortlangcode = '';
243
                        if ($obj->lang) {
244
                            $tmpshortlangcode = preg_replace('/[_-].*$/', '', $obj->lang); // en_US or en-US -> en
245
                        }
246
                        if ($tmpshortlangcode != $shortlangcode) {
247
                            $tplcontent .= '<link rel="alternate" hreflang="' . $tmpshortlangcode . '" href="<?php echo $website->virtualhost; ?>' . ($object->fk_default_home == $obj->id ? '/' : (($tmpshortlangcode != substr($object->lang, 0, 2) ? '/' . $tmpshortlangcode : '')) . '/' . $obj->pageurl . '.php') . '" />' . "\n";
248
                        }
249
                    }
250
                }
251
            } else {
252
                dol_print_error($db);
253
            }
254
255
            // Add myself
256
            $tplcontent .= '<?php if ($_SERVER["PHP_SELF"] == "' . (($object->fk_default_home == $objectpage->id) ? '/' : (($shortlangcode != substr($object->lang, 0, 2)) ? '/' . $shortlangcode : '')) . '/' . $objectpage->pageurl . '.php") { ?>' . "\n";
257
            $tplcontent .= '<link rel="alternate" hreflang="' . $shortlangcode . '" href="<?php echo $website->virtualhost; ?>' . (($object->fk_default_home == $objectpage->id) ? '/' : (($shortlangcode != substr($object->lang, 0, 2)) ? '/' . $shortlangcode : '') . '/' . $objectpage->pageurl . '.php') . '" />' . "\n";
258
259
            $tplcontent .= '<?php } ?>' . "\n";
260
        }
261
        // Add manifest.json. Do we have to add it only on home page ?
262
        $tplcontent .= '<?php if ($website->use_manifest) { print \'<link rel="manifest" href="/manifest.json.php" />\'."\n"; } ?>' . "\n";
263
        $tplcontent .= '<!-- Include link to CSS file -->' . "\n";
264
        // Add js
265
        $tplcontent .= '<link rel="stylesheet" href="/styles.css.php?website=<?php echo $websitekey; ?>" type="text/css" />' . "\n";
266
        $tplcontent .= '<!-- Include link to JS file -->' . "\n";
267
        $tplcontent .= '<script nonce="' . getNonce() . '" async src="/javascript.js.php?website=<?php echo $websitekey; ?>"></script>' . "\n";
268
        // Add headers
269
        $tplcontent .= '<!-- Include HTML header from common file -->' . "\n";
270
        $tplcontent .= '<?php if (file_exists(DOL_DATA_ROOT."/website/".$websitekey."/htmlheader.html")) include DOL_DATA_ROOT."/website/".$websitekey."/htmlheader.html"; ?>' . "\n";
271
        $tplcontent .= '<!-- Include HTML header from page header block -->' . "\n";
272
        $tplcontent .= preg_replace('/<\/?html>/ims', '', $objectpage->htmlheader) . "\n";
273
        $tplcontent .= '</head>' . "\n";
274
275
        $tplcontent .= '<!-- File generated by Dolibarr website module editor -->' . "\n";
276
        $tplcontent .= '<body id="bodywebsite" class="bodywebsite bodywebpage-' . $objectpage->ref . '">' . "\n";
277
        $tplcontent .= $objectpage->content . "\n";
278
        $tplcontent .= '</body>' . "\n";
279
        $tplcontent .= '</html>' . "\n";
280
281
        $tplcontent .= '<?php // BEGIN PHP' . "\n";
282
        $tplcontent .= '$tmp = ob_get_contents(); ob_end_clean(); dolWebsiteOutput($tmp, "html", ' . $objectpage->id . '); dolWebsiteIncrementCounter(' . $object->id . ', "' . $objectpage->type_container . '", ' . $objectpage->id . ');' . "\n";
283
        $tplcontent .= "// END PHP ?>\n";
284
    } else {
285
        $tplcontent .= "<?php\n// This is a library page.\n?>\n";
286
        $tplcontent .= $objectpage->content;
287
    }
288
289
    //var_dump($filetpl);exit;
290
    $result = file_put_contents($filetpl, $tplcontent);
291
292
    dolChmod($filetpl);
293
294
    return $result;
295
}
296
297
298
/**
299
 * Save content of the index.php and/or the wrapper.php page
300
 *
301
 * @param string $pathofwebsite Path of website root
302
 * @param string $fileindex Full path of file index.php
303
 * @param string $filetpl File tpl the index.php page redirect to (used only if $fileindex is provided)
304
 * @param string $filewrapper Full path of file wrapper.php
305
 * @param Website $object Object website
306
 * @return  boolean                             True if OK
307
 */
308
function dolSaveIndexPage($pathofwebsite, $fileindex, $filetpl, $filewrapper, $object = null)
309
{
310
    global $db;
311
312
    $result1 = false;
313
    $result2 = false;
314
315
    dol_mkdir($pathofwebsite);
316
317
    if ($fileindex) {
318
        dol_delete_file($fileindex);
319
        $indexcontent = '<?php' . "\n";
320
        $indexcontent .= "// BEGIN PHP File generated to provide an index.php as Home Page or alias redirector - DO NOT MODIFY - It is just a generated wrapper.\n";
321
        $indexcontent .= '$websitekey=basename(__DIR__); if (empty($websitepagefile)) $websitepagefile=__FILE__;' . "\n";
322
        $indexcontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once './master.inc.php'; } // Load master if not already loaded\n";
323
        $indexcontent .= 'if (!empty($_GET[\'pageref\']) || !empty($_GET[\'pagealiasalt\']) || !empty($_GET[\'pageid\'])) {' . "\n";
324
        $indexcontent .= "	require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
325
        $indexcontent .= "	require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
326
        $indexcontent .= '	redirectToContainer($_GET[\'pageref\'], $_GET[\'pagealiasalt\'], $_GET[\'pageid\']);' . "\n";
327
        $indexcontent .= "}\n";
328
        $indexcontent .= "include_once './" . basename($filetpl) . "'\n";
329
        $indexcontent .= '// END PHP ?>' . "\n";
330
331
        $result1 = file_put_contents($fileindex, $indexcontent);
332
333
        dolChmod($fileindex);
334
335
        if (is_object($object) && $object->fk_default_home > 0) {
336
            $objectpage = new WebsitePage($db);
337
            $objectpage->fetch($object->fk_default_home);
338
339
            // Create a version for sublanguages
340
            if (empty($objectpage->lang) || !in_array($objectpage->lang, explode(',', $object->otherlang))) {
341
                if (!getDolGlobalString('WEBSITE_DISABLE_MAIN_LANGUAGE_INTO_LANGSUBDIR') && is_object($object) && !empty($object->otherlang)) {
342
                    $dirname = dirname($fileindex);
343
                    foreach (explode(',', $object->otherlang) as $sublang) {
344
                        // Avoid to erase main alias file if $sublang is empty string
345
                        if (empty(trim($sublang))) {
346
                            continue;
347
                        }
348
                        $fileindexsub = $dirname . '/' . $sublang . '/index.php';
349
350
                        // Same indexcontent than previously but with ../ instead of ./ for master and tpl file include/require_once.
351
                        $relpath = '..';
352
                        $indexcontent = '<?php' . "\n";
353
                        $indexcontent .= "// BEGIN PHP File generated to provide an index.php as Home Page or alias redirector - DO NOT MODIFY - It is just a generated wrapper.\n";
354
                        $indexcontent .= '$websitekey=basename(__DIR__); if (empty($websitepagefile)) $websitepagefile=__FILE__;' . "\n";
355
                        $indexcontent .= "if (! defined('USEDOLIBARRSERVER') && ! defined('USEDOLIBARREDITOR')) { require_once '" . $relpath . "/master.inc.php'; } // Load master if not already loaded\n";
356
                        $indexcontent .= 'if (!empty($_GET[\'pageref\']) || !empty($_GET[\'pagealiasalt\']) || !empty($_GET[\'pageid\'])) {' . "\n";
357
                        $indexcontent .= "	require_once DOL_DOCUMENT_ROOT.'/core/lib/website.lib.php';\n";
358
                        $indexcontent .= "	require_once DOL_DOCUMENT_ROOT.'/core/website.inc.php';\n";
359
                        $indexcontent .= '	redirectToContainer($_GET[\'pageref\'], $_GET[\'pagealiasalt\'], $_GET[\'pageid\']);' . "\n";
360
                        $indexcontent .= "}\n";
361
                        $indexcontent .= "include_once '" . $relpath . "/" . basename($filetpl) . "'\n";    // use .. instead of .
362
                        $indexcontent .= '// END PHP ?>' . "\n";
363
                        $result = file_put_contents($fileindexsub, $indexcontent);
364
                        if ($result === false) {
365
                            dol_syslog("Failed to write file " . $fileindexsub, LOG_WARNING);
366
                        }
367
                        dolChmod($fileindexsub);
368
                    }
369
                }
370
            }
371
        }
372
    } else {
373
        $result1 = true;
374
    }
375
376
    if ($filewrapper) {
377
        dol_delete_file($filewrapper);
378
        $wrappercontent = file_get_contents(DOL_DOCUMENT_ROOT . '/website/samples/wrapper.php');
379
380
        $result2 = file_put_contents($filewrapper, $wrappercontent);
381
        dolChmod($filewrapper);
382
    } else {
383
        $result2 = true;
384
    }
385
386
    return ($result1 && $result2);
387
}
388
389
390
/**
391
 * Save content of a page on disk
392
 *
393
 * @param string $filehtmlheader Full path of filename to generate
394
 * @param string $htmlheadercontent Content of file
395
 * @return  boolean                         True if OK
396
 */
397
function dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent)
398
{
399
    global $pathofwebsite;
400
401
    dol_syslog("Save html header into " . $filehtmlheader);
402
403
    dol_mkdir($pathofwebsite);
404
    $result = file_put_contents($filehtmlheader, $htmlheadercontent);
405
    dolChmod($filehtmlheader);
406
407
    return $result;
408
}
409
410
/**
411
 * Save content of a page on disk
412
 *
413
 * @param string $filecss Full path of filename to generate
414
 * @param string $csscontent Content of file
415
 * @return  boolean                         True if OK
416
 */
417
function dolSaveCssFile($filecss, $csscontent)
418
{
419
    global $pathofwebsite;
420
421
    dol_syslog("Save css file into " . $filecss);
422
423
    dol_mkdir($pathofwebsite);
424
    $result = file_put_contents($filecss, $csscontent);
425
    dolChmod($filecss);
426
427
    return $result;
428
}
429
430
/**
431
 * Save content of a page on disk. For example into documents/website/mywebsite/javascript.js.php file.
432
 *
433
 * @param string $filejs Full path of filename to generate
434
 * @param string $jscontent Content of file
435
 * @return  boolean                         True if OK
436
 */
437
function dolSaveJsFile($filejs, $jscontent)
438
{
439
    global $pathofwebsite;
440
441
    dol_syslog("Save js file into " . $filejs);
442
443
    dol_mkdir($pathofwebsite);
444
    $result = file_put_contents($filejs, $jscontent);
445
    dolChmod($filejs);
446
447
    return $result;
448
}
449
450
/**
451
 * Save content of a page on disk
452
 *
453
 * @param string $filerobot Full path of filename to generate
454
 * @param string $robotcontent Content of file
455
 * @return  boolean                         True if OK
456
 */
457
function dolSaveRobotFile($filerobot, $robotcontent)
458
{
459
    global $pathofwebsite;
460
461
    dol_syslog("Save robot file into " . $filerobot);
462
463
    dol_mkdir($pathofwebsite);
464
    $result = file_put_contents($filerobot, $robotcontent);
465
    dolChmod($filerobot);
466
467
    return $result;
468
}
469
470
/**
471
 * Save content of a page on disk
472
 *
473
 * @param string $filehtaccess Full path of filename to generate
474
 * @param string $htaccess Content of file
475
 * @return  boolean                         True if OK
476
 */
477
function dolSaveHtaccessFile($filehtaccess, $htaccess)
478
{
479
    global $pathofwebsite;
480
481
    dol_syslog("Save htaccess file into " . $filehtaccess);
482
483
    dol_mkdir($pathofwebsite);
484
    $result = file_put_contents($filehtaccess, $htaccess);
485
    dolChmod($filehtaccess);
486
487
    return $result;
488
}
489
490
/**
491
 * Save content of a page on disk
492
 *
493
 * @param string $file Full path of filename to generate
494
 * @param string $content Content of file
495
 * @return  boolean                         True if OK
496
 */
497
function dolSaveManifestJson($file, $content)
498
{
499
    global $pathofwebsite;
500
501
    dol_syslog("Save manifest.js.php file into " . $file);
502
503
    dol_mkdir($pathofwebsite);
504
    $result = file_put_contents($file, $content);
505
    dolChmod($file);
506
507
    return $result;
508
}
509
510
/**
511
 * Save content of a page on disk
512
 *
513
 * @param string $file Full path of filename to generate
514
 * @param string $content Content of file
515
 * @return  boolean                         True if OK
516
 */
517
function dolSaveReadme($file, $content)
518
{
519
    global $pathofwebsite;
520
521
    dol_syslog("Save README.md file into " . $file);
522
523
    dol_mkdir($pathofwebsite);
524
    $result = file_put_contents($file, $content);
525
    dolChmod($file);
526
527
    return $result;
528
}
529
530
/**
531
 * Save content of a page on disk
532
 *
533
 * @param string $file Full path of filename to generate
534
 * @param string $content Content of file
535
 * @return  boolean                         True if OK
536
 */
537
function dolSaveLicense($file, $content)
538
{
539
    global $pathofwebsite;
540
541
    dol_syslog("Save LICENSE file into " . $file);
542
543
    dol_mkdir($pathofwebsite);
544
    $result = file_put_contents($file, $content);
545
    dolChmod($file);
546
547
    return $result;
548
}
549
550
/**
551
 *  Show list of themes. Show all thumbs of themes/skins
552
 *
553
 * @param Website $website Object website to load the template into
554
 * @return void
555
 */
556
function showWebsiteTemplates(Website $website)
557
{
558
    global $conf, $langs, $form, $user;
559
560
    $dirthemes = array('/doctemplates/websites');
561
    /*
562
    if (!empty($conf->modules_parts['websitetemplates'])) {
563
        foreach ($conf->modules_parts['websitetemplates'] as $reldir) {
564
            $dirthemes = array_merge($dirthemes, (array) ($reldir.'doctemplates/websites'));
565
        }
566
    }
567
    */
568
    $dirthemes = array_unique($dirthemes);
569
    // Now dir_themes=array('/themes') or dir_themes=array('/theme','/mymodule/theme')
570
571
    $colspan = 2;
572
573
    print '<!-- For website template import -->' . "\n";
574
    print '<table class="noborder centpercent">';
575
576
    // Title
577
    print '<tr class="liste_titre"><th class="titlefield">';
578
    print $form->textwithpicto($langs->trans("Templates"), $langs->trans("ThemeDir") . ' : ' . implode(", ", $dirthemes));
579
    print ' ';
580
    print '<a href="' . $_SERVER["PHP_SELF"] . '?website=' . urlencode($website->ref) . '&importsite=1" rel="noopener noreferrer external">';
581
    print img_picto('', 'refresh');
582
    print '</a>';
583
    print '</th>';
584
    print '<th class="right">';
585
    $url = 'https://www.dolistore.com/43-web-site-templates';
586
    print '<a href="' . $url . '" target="_blank" rel="noopener noreferrer external">';
587
    print img_picto('', 'globe', 'class="pictofixedwidth"') . $langs->trans('DownloadMoreSkins');
588
    print '</a>';
589
    print '</th></tr>';
590
591
    print '<tr><td colspan="' . $colspan . '">';
592
593
    print '<table class="nobordernopadding centpercent"><tr><td><div class="display-flex">';
594
595
    if (count($dirthemes)) {
596
        $i = 0;
597
        foreach ($dirthemes as $dir) {
598
            if (preg_match('/^\/doctemplates\//', $dir)) {
599
                $dirtheme = DOL_DATA_ROOT . $dir; // This include loop on $conf->file->dol_document_root
600
            } else {
601
                $dirtheme = dol_buildpath($dir); // This include loop on $conf->file->dol_document_root
602
            }
603
            if (is_dir($dirtheme)) {
604
                $handle = opendir($dirtheme);
605
                if (is_resource($handle)) {
606
                    while (($subdir = readdir($handle)) !== false) {
607
                        //var_dump($dirtheme.'/'.$subdir);
608
                        if (is_file($dirtheme . "/" . $subdir) && substr($subdir, 0, 1) != '.' && substr($subdir, 0, 3) != 'CVS' && preg_match('/\.zip$/i', $subdir)) {
609
                            $subdirwithoutzip = preg_replace('/\.zip$/i', '', $subdir);
610
611
                            // Disable not stable themes (dir ends with _exp or _dev)
612
                            if (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2 && preg_match('/_dev$/i', $subdir)) {
613
                                continue;
614
                            }
615
                            if (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1 && preg_match('/_exp$/i', $subdir)) {
616
                                continue;
617
                            }
618
619
                            print '<div class="inline-block center flex-item" style="min-width: 250px; max-width: 400px; margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;">';
620
621
                            $templatedir = $dirtheme . "/" . $subdir;
622
                            $file = $dirtheme . "/" . $subdirwithoutzip . ".jpg";
623
                            $url = constant('BASE_URL') . '/viewimage.php?modulepart=doctemplateswebsite&file=' . $subdirwithoutzip . ".jpg";
624
625
                            if (!file_exists($file)) {
626
                                $url = constant('BASE_URL') . '/public/theme/common/nophoto.png';
627
                            }
628
629
                            $originalfile = basename($file);
630
                            $entity = $conf->entity;
631
                            $modulepart = 'doctemplateswebsite';
632
                            $cache = '';
633
                            $title = $file;
634
635
                            $ret = '';
636
                            $urladvanced = getAdvancedPreviewUrl($modulepart, $originalfile, 1, '&entity=' . $entity);
637
                            if (!empty($urladvanced)) {
638
                                $ret .= '<a class="' . $urladvanced['css'] . '" target="' . $urladvanced['target'] . '" mime="' . $urladvanced['mime'] . '" href="' . $urladvanced['url'] . '">';
639
                            } else {
640
                                $ret .= '<a href="' . constant('BASE_URL') . '/viewimage.php?modulepart=' . urlencode($modulepart) . '&entity=' . ((int)$entity) . '&file=' . urlencode($originalfile) . '&cache=' . ((int)$cache) . '">';
641
                            }
642
                            print $ret;
643
                            print '<img class="img-skinthumb shadow" src="' . $url . '" border="0" alt="' . $title . '" title="' . $title . '" style="margin-bottom: 5px;">';
644
                            print '</a>';
645
646
                            print '<br>';
647
                            print $subdir;
648
                            print '<br>';
649
                            print '<span class="opacitymedium">' . dol_print_size(dol_filesize($dirtheme . "/" . $subdir), 1, 1) . ' - ' . dol_print_date(dol_filemtime($templatedir), 'dayhour', 'tzuserrel') . '</span>';
650
                            if ($user->hasRight('website', 'delete')) {
651
                                print ' <a href="' . $_SERVER["PHP_SELF"] . '?action=deletetemplate&token=' . newToken() . '&website=' . urlencode($website->ref) . '&templateuserfile=' . urlencode($subdir) . '">' . img_picto('', 'delete') . '</a>';
652
                            }
653
                            print '<br><a href="' . $_SERVER["PHP_SELF"] . '?action=importsiteconfirm&token=' . newToken() . '&website=' . urlencode($website->ref) . '&templateuserfile=' . urlencode($subdir) . '" class="button">' . $langs->trans("Load") . '</a>';
654
                            print '</div>';
655
656
                            $i++;
657
                        }
658
                    }
659
                    print '<div class="inline-block center flex-item" style="min-width: 250px; max-width: 400px;margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;"></div>';
660
                    print '<div class="inline-block center flex-item" style="min-width: 250px; max-width: 400px;margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;"></div>';
661
                    print '<div class="inline-block center flex-item" style="min-width: 250px; max-width: 400px;margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;"></div>';
662
                    print '<div class="inline-block center flex-item" style="min-width: 250px; max-width: 400px;margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;"></div>';
663
                    print '<div class="inline-block center flex-item" style="min-width: 250px; max-width: 400px;margin-top: 10px; margin-bottom: 10px; margin-right: 20px; margin-left: 20px;"></div>';
664
                }
665
            }
666
        }
667
    } else {
668
        print '<span class="opacitymedium">' . $langs->trans("None") . '</span>';
669
    }
670
671
    print '</div></td></tr></table>';
672
673
    print '</td></tr>';
674
    print '</table>';
675
}
676
677
678
/**
679
 * Check a new string containing only php code (including <php tag)
680
 * - Block if bad code in the new string.
681
 * - Block also if user has no permission to change PHP code.
682
 *
683
 * @param string $phpfullcodestringold PHP old string (before the change). For example "<?php echo 'a' ?><php echo 'b' ?>"
684
 * @param string $phpfullcodestring PHP new string. For example "<?php echo 'a' ?><php echo 'c' ?>"
685
 * @return  int                                     Error or not
686
 * @see dolKeepOnlyPhpCode()
687
 */
688
function checkPHPCode(&$phpfullcodestringold, &$phpfullcodestring)
689
{
690
    global $langs, $user;
691
692
    $error = 0;
693
694
    if (empty($phpfullcodestringold) && empty($phpfullcodestring)) {
695
        return 0;
696
    }
697
698
    // First check permission
699
    if ($phpfullcodestringold != $phpfullcodestring) {
700
        if (!$error && !$user->hasRight('website', 'writephp')) {
701
            $error++;
702
            setEventMessages($langs->trans("NotAllowedToAddDynamicContent"), null, 'errors');
703
        }
704
    }
705
706
    // Then check forbidden commands
707
    if (!$error) {
708
        $forbiddenphpcommands = array("override_function", "session_id", "session_create_id", "session_regenerate_id");
709
        if (!getDolGlobalString('WEBSITE_PHP_ALLOW_EXEC')) {    // If option is not on, we disallow functions to execute commands
710
            $forbiddenphpcommands = array_merge($forbiddenphpcommands, array("exec", "passthru", "shell_exec", "system", "proc_open", "popen", "eval", "dol_eval", "executeCLI"));
711
        }
712
        if (!getDolGlobalString('WEBSITE_PHP_ALLOW_WRITE')) {    // If option is not on, we disallow functions to write files
713
            $forbiddenphpcommands = array_merge($forbiddenphpcommands, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "unlink", "mkdir", "rmdir", "symlink", "touch", "umask"));
714
        }
715
        foreach ($forbiddenphpcommands as $forbiddenphpcommand) {
716
            if (preg_match('/' . $forbiddenphpcommand . '\s*\(/ms', $phpfullcodestring)) {
717
                $error++;
718
                setEventMessages($langs->trans("DynamicPHPCodeContainsAForbiddenInstruction", $forbiddenphpcommand), null, 'errors');
719
                break;
720
            }
721
        }
722
        // This char can be used to execute RCE for example using with echo `ls`
723
        $forbiddenphpchars = array();
724
        if (!getDolGlobalString('WEBSITE_PHP_ALLOW_DANGEROUS_CHARS')) {    // If option is not on, we disallow functions to execute commands
725
            $forbiddenphpchars = array("`");
726
        }
727
        foreach ($forbiddenphpchars as $forbiddenphpchar) {
728
            if (preg_match('/' . $forbiddenphpchar . '/ms', $phpfullcodestring)) {
729
                $error++;
730
                setEventMessages($langs->trans("DynamicPHPCodeContainsAForbiddenInstruction", $forbiddenphpchar), null, 'errors');
731
                break;
732
            }
733
        }
734
        // Deny dynamic functions '${a}('  or  '$a[b]('  or  '$a->b('  => So we refuse '}('  and  ']('
735
        if (preg_match('/[}\]]\(/ims', $phpfullcodestring)) {
736
            $error++;
737
            setEventMessages($langs->trans("DynamicPHPCodeContainsAForbiddenInstruction", ']('), null, 'errors');
738
        }
739
        // Deny dynamic functions '$xxx(' or '$a->b('
740
        if (preg_match('/\$[a-z0-9_\-\>\/\*]+\(/ims', $phpfullcodestring)) {
741
            $error++;
742
            setEventMessages($langs->trans("DynamicPHPCodeContainsAForbiddenInstruction", '$...('), null, 'errors');
743
        }
744
    }
745
746
    if ($phpfullcodestringold != $phpfullcodestring) {
747
        if (!$error) {
748
            $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
749
            $allowimportsite = true;
750
            include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
751
            if (dol_is_file($dolibarrdataroot . '/installmodules.lock')) {
752
                $allowimportsite = false;
753
            }
754
755
            if (!$allowimportsite) {
756
                $error++;
757
                // Blocked by installmodules.lock
758
                if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
759
                    // Show clean corporate message
760
                    $message = $langs->trans('InstallModuleFromWebHasBeenDisabledContactUs');
761
                } else {
762
                    // Show technical generic message
763
                    $message = $langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot . '/installmodules.lock');
764
                }
765
                setEventMessages($message, null, 'errors');
766
            }
767
        }
768
    }
769
770
    return $error;
771
}
772