dolibarr  18.0.6
website.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <https://www.gnu.org/licenses/>.
16  */
17 
32 function dolStripPhpCode($str, $replacewith = '')
33 {
34  $str = str_replace('<?=', '<?php', $str);
35 
36  $newstr = '';
37 
38  // Split on each opening tag
39  //$parts = explode('<?php', $str);
40  $parts = preg_split('/'.preg_quote('<?php', '/').'/i', $str);
41 
42  if (!empty($parts)) {
43  $i = 0;
44  foreach ($parts as $part) {
45  if ($i == 0) { // The first part is never php code
46  $i++;
47  $newstr .= $part;
48  continue;
49  }
50  // The second part is the php code. We split on closing tag
51  $partlings = explode('?>', $part);
52  if (!empty($partlings)) {
53  //$phppart = $partlings[0];
54  //remove content before closing tag
55  if (count($partlings) > 1) {
56  $partlings[0] = ''; // Todo why a count > 1 and not >= 1 ?
57  }
58  //append to out string
59  //$newstr .= '<span class="phptag" class="tooltip" title="'.dol_escape_htmltag(dolGetFirstLineOfText($phppart).'...').'">'.$replacewith.'<!-- '.$phppart.' --></span>'.implode('', $partlings);
60  //$newstr .= '<span>'.$replacewith.'<!-- '.$phppart.' --></span>'.implode('', $partlings);
61  $newstr .= '<span phptag>'.$replacewith.'</span>'.implode('', $partlings);
62  //$newstr .= $replacewith.implode('', $partlings);
63  }
64  }
65  }
66  return $newstr;
67 }
68 
76 function dolKeepOnlyPhpCode($str)
77 {
78  $str = str_replace('<?=', '<?php', $str);
79  $str = str_replace('<?php', '__LTINTPHP__', $str);
80  $str = str_replace('<?', '<?php', $str); // replace the short_open_tag. It is recommended to set this is Off in php.ini
81  $str = str_replace('__LTINTPHP__', '<?php', $str);
82 
83  $newstr = '';
84 
85  // Split on each opening tag
86  //$parts = explode('<?php', $str);
87  $parts = preg_split('/'.preg_quote('<?php', '/').'/i', $str);
88 
89  if (!empty($parts)) {
90  $i = 0;
91  foreach ($parts as $part) {
92  if ($i == 0) { // The first part is never php code
93  $i++;
94  continue;
95  }
96  $newstr .= '<?php';
97  //split on closing tag
98  $partlings = explode('?>', $part, 2);
99  if (!empty($partlings)) {
100  $newstr .= $partlings[0].'?>';
101  } else {
102  $newstr .= $part.'?>';
103  }
104  }
105  }
106  return $newstr;
107 }
108 
121 function dolWebsiteReplacementOfLinks($website, $content, $removephppart = 0, $contenttype = 'html', $containerid = '')
122 {
123  $nbrep = 0;
124 
125  dol_syslog('dolWebsiteReplacementOfLinks start (contenttype='.$contenttype." containerid=".$containerid." USEDOLIBARREDITOR=".(defined('USEDOLIBARREDITOR') ? '1' : '')." USEDOLIBARRSERVER=".(defined('USEDOLIBARRSERVER') ? '1' : '').')', LOG_DEBUG);
126  //if ($contenttype == 'html') { print $content;exit; }
127 
128  // Replace php code. Note $content may come from database and does not contain body tags.
129  $replacewith = '...php...';
130  if ($removephppart) {
131  $replacewith = '';
132  }
133  $content = preg_replace('/value="<\?php((?!\?>).)*\?>\n*/ims', 'value="'.$replacewith.'"', $content);
134 
135  $replacewith = '"callto=#';
136  if ($removephppart) {
137  $replacewith = '';
138  }
139  $content = preg_replace('/"callto:<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content);
140 
141  $replacewith = '"mailto=#';
142  if ($removephppart) {
143  $replacewith = '';
144  }
145  $content = preg_replace('/"mailto:<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content);
146 
147  $replacewith = 'src="php';
148  if ($removephppart) {
149  $replacewith = '';
150  }
151  $content = preg_replace('/src="<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content);
152 
153  $replacewith = 'href="php';
154  if ($removephppart) {
155  $replacewith = '';
156  }
157  $content = preg_replace('/href="<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content);
158 
159  //$replacewith='<span class="phptag">...php...</span>';
160  $replacewith = '...php...';
161  if ($removephppart) {
162  $replacewith = '';
163  }
164  //$content = preg_replace('/<\?php((?!\?toremove>).)*\?toremove>\n*/ims', $replacewith, $content);
165  /*if ($content === null) {
166  if (preg_last_error() == PREG_JIT_STACKLIMIT_ERROR) $content = 'preg_replace error (when removing php tags) PREG_JIT_STACKLIMIT_ERROR';
167  }*/
168  $content = dolStripPhpCode($content, $replacewith);
169  //var_dump($content);
170 
171  // Protect the link styles.css.php to any replacement that we make after.
172  $content = str_replace('href="styles.css.php', 'href="!~!~!~styles.css.php', $content);
173  $content = str_replace('href="http', 'href="!~!~!~http', $content);
174  $content = str_replace('href="//', 'href="!~!~!~//', $content);
175  $content = str_replace('src="viewimage.php', 'src="!~!~!~/viewimage.php', $content);
176  $content = str_replace('src="/viewimage.php', 'src="!~!~!~/viewimage.php', $content);
177  $content = str_replace('src="'.DOL_URL_ROOT.'/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content);
178  $content = str_replace('href="document.php', 'href="!~!~!~/document.php', $content);
179  $content = str_replace('href="/document.php', 'href="!~!~!~/document.php', $content);
180  $content = str_replace('href="'.DOL_URL_ROOT.'/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content);
181 
182  // Replace relative link '/' with dolibarr URL
183  $content = preg_replace('/(href=")\/(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageid='.$website->fk_default_home.'\2"', $content, -1, $nbrep);
184  // Replace relative link /xxx.php#aaa or /xxx.php with dolibarr URL (we discard param ?...)
185  $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageref=\2\3"', $content, -1, $nbrep);
186  // Replace relative link /xxx.php?a=b&c=d#aaa or /xxx.php?a=b&c=d with dolibarr URL
187  $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php\?([^#\"<>]*)(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageref=\2&\3\4"', $content, -1, $nbrep);
188 
189  // Fix relative link into medias with correct URL after the DOL_URL_ROOT: ../url("medias/
190  $content = preg_replace('/url\‍((["\']?)\/?medias\//', 'url(\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
191  $content = preg_replace('/data-slide-bg=(["\']?)\/?medias\//', 'data-slide-bg=\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
192 
193  // <img src="medias/...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png...
194  // <img src="...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png...
195  $content = preg_replace('/(<img[^>]*src=")\/?medias\//', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
196  // <img src="image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png...
197  $content = preg_replace('/(<img[^>]*src=")\/?([^:\"\!]+)\"/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=\2"', $content, -1, $nbrep);
198  // <img src="viewimage.php/modulepart=medias&file=image.png" => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png"
199  $content = preg_replace('/(<img[^>]*src=")(\/?viewimage\.php)/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content, -1, $nbrep);
200 
201  // action="newpage.php" => action="dolibarr/website/index.php?website=...&pageref=newpage
202  $content = preg_replace('/(action=")\/?([^:\"]*)(\.php\")/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageref=\2"', $content, -1, $nbrep);
203 
204  // Fix relative link /document.php with correct URL after the DOL_URL_ROOT: ...href="/document.php?modulepart="
205  $content = preg_replace('/(href=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
206  $content = preg_replace('/(src=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
207 
208  // Fix relative link /viewimage.php with correct URL after the DOL_URL_ROOT: ...href="/viewimage.php?modulepart="
209  $content = preg_replace('/(url\‍(")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
210 
211  // Fix relative URL
212  $content = str_replace('src="!~!~!~/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content);
213  $content = str_replace('href="!~!~!~/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content);
214  // Remove the protection tag !~!~!~
215  $content = str_replace('!~!~!~', '', $content);
216 
217  dol_syslog('dolWebsiteReplacementOfLinks end', LOG_DEBUG);
218  //if ($contenttype == 'html') { print $content;exit; }
219 
220  return $content;
221 }
222 
230 {
231  $map = array(
232  ":face_with_tears_of_joy:" => "\xF0\x9F\x98\x82",
233  ":grinning_face_with_smiling_eyes:" => "\xF0\x9F\x98\x81",
234  ":smiling_face_with_open_mouth:" => "\xF0\x9F\x98\x83",
235  ":smiling_face_with_open_mouth_and_cold_sweat:" => "\xF0\x9F\x98\x85",
236  ":smiling_face_with_open_mouth_and_tightly_closed_eyes:" => "\xF0\x9F\x98\x86",
237  ":winking_face:" => "\xF0\x9F\x98\x89",
238  ":smiling_face_with_smiling_eyes:" => "\xF0\x9F\x98\x8A",
239  ":face_savouring_delicious_food:" => "\xF0\x9F\x98\x8B",
240  ":relieved_face:" => "\xF0\x9F\x98\x8C",
241  ":smiling_face_with_heart_shaped_eyes:" => "\xF0\x9F\x98\x8D",
242  ":smiling_face_with_sunglasses:" => "\xF0\x9F\x98\x8E",
243  ":smirking_face:" => "\xF0\x9F\x98\x8F",
244  ":neutral_face:" => "\xF0\x9F\x98\x90",
245  ":expressionless_face:" => "\xF0\x9F\x98\x91",
246  ":unamused_face:" => "\xF0\x9F\x98\x92",
247  ":face_with_cold_sweat:" => "\xF0\x9F\x98\x93",
248  ":pensive_face:" => "\xF0\x9F\x98\x94",
249  ":confused_face:" => "\xF0\x9F\x98\x95",
250  ":confounded_face:" => "\xF0\x9F\x98\x96",
251  ":kissing_face:" => "\xF0\x9F\x98\x97",
252  ":face_throwing_a_kiss:" => "\xF0\x9F\x98\x98",
253  ":kissing_face_with_smiling_eyes:" => "\xF0\x9F\x98\x99",
254  ":kissing_face_with_closed_eyes:" => "\xF0\x9F\x98\x9A",
255  ":face_with_stuck_out_tongue:" => "\xF0\x9F\x98\x9B",
256  ":face_with_stuck_out_tongue_and_winking_eye:" => "\xF0\x9F\x98\x9C",
257  ":face_with_stuck_out_tongue_and_tightly_closed_eyes:" => "\xF0\x9F\x98\x9D",
258  ":disappointed_face:" => "\xF0\x9F\x98\x9E",
259  ":worried_face:" => "\xF0\x9F\x98\x9F",
260  ":angry_face:" => "\xF0\x9F\x98\xA0",
261  ":face_with_symbols_on_mouth:" => "\xF0\x9F\x98\xA1",
262  );
263  foreach ($map as $key => $value) {
264  $content = str_replace($key, $value, $content);
265  }
266  return $content;
267 }
268 
269 
280 function dolWebsiteOutput($content, $contenttype = 'html', $containerid = '')
281 {
282  global $db, $langs, $conf, $user;
283  global $dolibarr_main_url_root, $dolibarr_main_data_root;
284  global $website;
285  global $includehtmlcontentopened;
286 
287  $nbrep = 0;
288 
289  dol_syslog("dolWebsiteOutput start - contenttype=".$contenttype." containerid=".$containerid." USEDOLIBARREDITOR=".(defined('USEDOLIBARREDITOR') ? '1' : '')." USEDOLIBARRSERVER=".(defined('USEDOLIBARRSERVER') ? '1' : '').' includehtmlcontentopened='.$includehtmlcontentopened);
290 
291  //print $containerid.' '.$content;
292 
293  // Define $urlwithroot
294  $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
295  $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
296  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
297 
298  if (defined('USEDOLIBARREDITOR')) { // REPLACEMENT OF LINKS When page called from Dolibarr editor
299  // We remove the <head> part of content
300  if ($contenttype == 'html') {
301  $content = preg_replace('/<head>.*<\/head>/ims', '', $content);
302  $content = preg_replace('/^.*<body(\s[^>]*)*>/ims', '', $content);
303  $content = preg_replace('/<\/body(\s[^>]*)*>.*$/ims', '', $content);
304  }
305  } elseif (defined('USEDOLIBARRSERVER')) { // REPLACEMENT OF LINKS When page called from Dolibarr server
306  $content = str_replace('<link rel="stylesheet" href="/styles.css', '<link rel="stylesheet" href="styles.css', $content);
307 
308  // Protect the link styles.css.php to any replacement that we make after.
309  $content = str_replace('href="styles.css.php', 'href="!~!~!~styles.css.php', $content);
310  $content = str_replace('href="http', 'href="!~!~!~http', $content);
311  $content = str_replace('href="//', 'href="!~!~!~//', $content);
312  $content = str_replace(array('src="viewimage.php', 'src="/viewimage.php'), 'src="!~!~!~/viewimage.php', $content);
313  $content = str_replace('src="'.DOL_URL_ROOT.'/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content);
314  $content = str_replace(array('href="document.php', 'href="/document.php'), 'href="!~!~!~/document.php', $content);
315  $content = str_replace('href="'.DOL_URL_ROOT.'/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content);
316 
317  // Replace relative link / with dolibarr URL: ...href="/"...
318  $content = preg_replace('/(href=")\/\"/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'"', $content, -1, $nbrep);
319  // Replace relative link /xxx.php#aaa or /xxx.php with dolibarr URL: ...href="....php" (we discard param ?...)
320  $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2\3"', $content, -1, $nbrep);
321  // Replace relative link /xxx.php?a=b&c=d#aaa or /xxx.php?a=b&c=d with dolibarr URL
322  // Warning: we may replace twice if href="..." was inside an include (dolWebsiteOutput called by include and the by final page), that's why
323  // at end we replace the '!~!~!~' only if we are in final parent page.
324  $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php\?([^#\"<>]*)(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2&\3\4"', $content, -1, $nbrep);
325  // Replace relative link without .php like /xxx#aaa or /xxx with dolibarr URL: ...href="....php"
326  $content = preg_replace('/(href=")\/?([a-zA-Z0-9\-_#]+)(\"|\?)/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2\3', $content, -1, $nbrep);
327 
328  // Fix relative link /document.php with correct URL after the DOL_URL_ROOT: href="/document.php?modulepart=" => href="/dolibarr/document.php?modulepart="
329  $content = preg_replace('/(href=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
330  $content = preg_replace('/(src=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
331 
332  // Fix relative link /viewimage.php with correct URL after the DOL_URL_ROOT: href="/viewimage.php?modulepart=" => href="/dolibarr/viewimage.php?modulepart="
333  $content = preg_replace('/(href=")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
334  $content = preg_replace('/(src=")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
335  $content = preg_replace('/(url\‍(")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep);
336 
337  // Fix relative link into medias with correct URL after the DOL_URL_ROOT: ../url("medias/
338  $content = preg_replace('/url\‍((["\']?)\/?medias\//', 'url(\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
339  $content = preg_replace('/data-slide-bg=(["\']?)\/?medias\//', 'data-slide-bg=\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
340 
341  // <img src="medias/...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png...
342  // <img src="...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png...
343  $content = preg_replace('/(<img[^>]*src=")\/?medias\//', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
344  // <img src="image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png...
345  $content = preg_replace('/(<img[^>]*src=")\/?([^:\"\!]+)\"/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=\2"', $content, -1, $nbrep);
346  // <img src="viewimage.php/modulepart=medias&file=image.png" => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png"
347  $content = preg_replace('/(<img[^>]*src=")(\/?viewimage\.php)/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content, -1, $nbrep);
348 
349  // action="newpage.php" => action="dolibarr/website/index.php?website=...&pageref=newpage
350  $content = preg_replace('/(action=")\/?([^:\"]*)(\.php\")/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2"', $content, -1, $nbrep);
351 
352  // Fix relative URL
353  $content = str_replace('src="!~!~!~/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content);
354  $content = str_replace('href="!~!~!~/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content);
355 
356  // Remove the protection tag !~!~!~, but only if this is the parent page and not an include
357  if (empty($includehtmlcontentopened)) {
358  $content = str_replace('!~!~!~', '', $content);
359  }
360  } else // REPLACEMENT OF LINKS When page called from virtual host web server
361  {
362  $symlinktomediaexists = 1;
363  if ($website->virtualhost) {
364  $content = preg_replace('/^(<link[^>]*rel="canonical" href=")\//m', '\1'.$website->virtualhost.'/', $content, -1, $nbrep);
365  }
366  //print 'rrrrrrrrr'.$website->virtualhost.$content;
367 
368 
369  // Make a change into HTML code to allow to include images from medias directory correct with direct link for virtual server
370  // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&amp;entity=1&amp;file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
371  // become
372  // <img alt="" src="'.$urlwithroot.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" />
373  if (!$symlinktomediaexists) {
374  // <img src="image.png... => <img src="medias/image.png...
375  $content = preg_replace('/(<img[^>]*src=")\/?image\//', '\1/wrapper.php?modulepart=medias&file=medias/image/', $content, -1, $nbrep);
376  $content = preg_replace('/(url\‍(["\']?)\/?image\//', '\1/wrapper.php?modulepart=medias&file=medias/image/', $content, -1, $nbrep);
377 
378  $content = preg_replace('/(<script[^>]*src=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep);
379  $content = preg_replace('/(<a[^>]*href=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep);
380 
381  $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep);
382  $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep);
383  $content = preg_replace('/(url\‍(["\']?)[^\‍)]*viewimage\.php([^\‍)]*)modulepart=medias([^\‍)]*)file=([^\‍)]*)(["\']?\‍))/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep);
384 
385  $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep);
386  $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep);
387  $content = preg_replace('/(url\‍(["\']?)[^\‍)]*viewimage\.php([^\‍)]*)hashp=([^\‍)]*)(["\']?\‍))/', '\1/wrapper.php\2hashp\3\4', $content, -1, $nbrep);
388 
389  $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=mycompany([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=mycompany\3file=\4\5', $content, -1, $nbrep);
390 
391  // If some links to documents or viewimage remains, we replace with wrapper
392  $content = preg_replace('/(<img[^>]*src=")\/?viewimage\.php/', '\1/wrapper.php', $content, -1, $nbrep);
393  $content = preg_replace('/(<a[^>]*href=")\/?documents\.php/', '\1/wrapper.php', $content, -1, $nbrep);
394  } else {
395  // <img src="image.png... => <img src="medias/image.png...
396  $content = preg_replace('/(<img[^>]*src=")\/?image\//', '\1/medias/image/', $content, -1, $nbrep);
397  $content = preg_replace('/(url\‍(["\']?)\/?image\//', '\1/medias/image/', $content, -1, $nbrep);
398 
399  $content = preg_replace('/(<script[^>]*src=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep);
400  $content = preg_replace('/(<a[^>]*href=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep);
401 
402  $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep);
403  $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep);
404  $content = preg_replace('/(url\‍(["\']?)[^\‍)]*viewimage\.php([^\‍)]*)modulepart=medias([^\‍)]*)file=([^\‍)]*)(["\']?\‍))/', '\1/medias/\4\5', $content, -1, $nbrep);
405 
406  $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep);
407  $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep);
408  $content = preg_replace('/(url\‍(["\']?)[^\‍)]*viewimage\.php([^\‍)]*)hashp=([^\‍)]*)(["\']?\‍))/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep);
409 
410  $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=mycompany([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=mycompany\3file=\4\5', $content, -1, $nbrep);
411 
412  // If some links to documents or viewimage remains, we replace with wrapper
413  $content = preg_replace('/(<img[^>]*src=")\/?viewimage\.php/', '\1/wrapper.php', $content, -1, $nbrep);
414  $content = preg_replace('/(<a[^>]*href=")\/?document\.php/', '\1/wrapper.php', $content, -1, $nbrep);
415  }
416  }
417 
418  if (!defined('USEDOLIBARREDITOR')) {
419  $content = str_replace(' contenteditable="true"', ' contenteditable="false"', $content);
420  }
421 
422  if (!empty($conf->global->WEBSITE_ADD_CSS_TO_BODY)) {
423  $content = str_replace('<body id="bodywebsite" class="bodywebsite', '<body id="bodywebsite" class="bodywebsite '.$conf->global->WEBSITE_ADD_CSS_TO_BODY, $content);
424  }
425 
426  $content = dolReplaceSmileyCodeWithUTF8($content);
427 
428  dol_syslog("dolWebsiteOutput end");
429 
430  print $content;
431 }
432 
441 function dolWebsiteIncrementCounter($websiteid, $websitepagetype, $websitepageid)
442 {
443  if (!getDolGlobalInt('WEBSITE_PERF_DISABLE_COUNTERS')) {
444  //dol_syslog("dolWebsiteIncrementCounter websiteid=".$websiteid." websitepagetype=".$websitepagetype." websitepageid=".$websitepageid);
445  if (in_array($websitepagetype, array('blogpost', 'page'))) {
446  global $db;
447 
448  $tmpnow = dol_getdate(dol_now('gmt'), true, 'gmt');
449 
450  $sql = "UPDATE ".$db->prefix()."website SET ";
451  $sql .= " pageviews_total = pageviews_total + 1,";
452  $sql .= " pageviews_month = pageviews_month + 1,";
453  // if last access was done during previous month, we save pageview_month into pageviews_previous_month
454  $sql .= " pageviews_previous_month = ".$db->ifsql("lastaccess < '".$db->idate(dol_mktime(0, 0, 0, $tmpnow['mon'], 1, $tmpnow['year'], 'gmt', 0), 'gmt')."'", 'pageviews_month', 'pageviews_previous_month').",";
455  $sql .= " lastaccess = '".$db->idate(dol_now('gmt'), 'gmt')."'";
456  $sql .= " WHERE rowid = ".((int) $websiteid);
457  $resql = $db->query($sql);
458  if (! $resql) {
459  return -1;
460  }
461  }
462  }
463 
464  return 1;
465 }
466 
467 
475 /*
476 function dolWebsiteSaveContent($content)
477 {
478  global $db, $langs, $conf, $user;
479  global $dolibarr_main_url_root, $dolibarr_main_data_root;
480 
481  //dol_syslog("dolWebsiteSaveContent start (mode=".(defined('USEDOLIBARRSERVER')?'USEDOLIBARRSERVER':'').')');
482 
483  // Define $urlwithroot
484  $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
485  $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
486  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
487 
488  //$content = preg_replace('/(<img.*src=")(?!(http|'.preg_quote(DOL_URL_ROOT,'/').'\/viewimage))/', '\1'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep);
489 
490  return $content;
491 }
492 */
493 
494 
504 function redirectToContainer($containerref, $containeraliasalt = '', $containerid = 0, $permanent = 0)
505 {
506  global $db, $website;
507 
508  $newurl = '';
509  $result = 0;
510 
511  // We make redirect using the alternative alias, we must find the real $containerref
512  if ($containeraliasalt) {
513  include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
514  $tmpwebsitepage = new WebsitePage($db);
515  $result = $tmpwebsitepage->fetch(0, $website->id, '', $containeraliasalt);
516  if ($result > 0) {
517  $containerref = $tmpwebsitepage->pageurl;
518  } else {
519  print "Error, page contains a redirect to the alternative alias '".$containeraliasalt."' that does not exists in web site (".$website->id." / ".$website->ref.")";
520  exit;
521  }
522  }
523 
524  if (defined('USEDOLIBARREDITOR')) {
525  /*print '<div class="margintoponly marginleftonly">';
526  print "This page contains dynamic code that make a redirect to '".$containerref."' in your current context. Redirect has been canceled as it is not supported in edition mode.";
527  print '</div>';*/
528  $text = "This page contains dynamic code that make a redirect to '".$containerref."' in your current context. Redirect has been canceled as it is not supported in edition mode.";
529  setEventMessages($text, null, 'warnings', 'WEBSITEREDIRECTDISABLED'.$containerref);
530  return;
531  }
532 
533  if (defined('USEDOLIBARRSERVER')) { // When page called from Dolibarr server
534  // Check new container exists
535  if (!$containeraliasalt) { // If containeraliasalt set, we already did the test
536  include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
537  $tmpwebsitepage = new WebsitePage($db);
538  $result = $tmpwebsitepage->fetch(0, $website->id, $containerref);
539  unset($tmpwebsitepage);
540  }
541  if ($result > 0) {
542  $currenturi = $_SERVER["REQUEST_URI"];
543  $regtmp = array();
544  if (preg_match('/&pageref=([^&]+)/', $currenturi, $regtmp)) {
545  if ($regtmp[0] == $containerref) {
546  print "Error, page with uri '.$currenturi.' try a redirect to the same alias page '".$containerref."' in web site '".$website->ref."'";
547  exit;
548  } else {
549  $newurl = preg_replace('/&pageref=([^&]+)/', '&pageref='.$containerref, $currenturi);
550  }
551  } else {
552  $newurl = $currenturi.'&pageref='.urlencode($containerref);
553  }
554  }
555  } else // When page called from virtual host server
556  {
557  $newurl = '/'.$containerref.'.php';
558  }
559 
560  if ($newurl) {
561  if ($permanent) {
562  header("Status: 301 Moved Permanently", false, 301);
563  }
564  header("Location: ".$newurl.(empty($_SERVER["QUERY_STRING"]) ? '' : '?'.$_SERVER["QUERY_STRING"]));
565  exit;
566  } else {
567  print "Error, page contains a redirect to the alias page '".$containerref."' that does not exists in web site (".$website->id." / ".$website->ref.")";
568  exit;
569  }
570 }
571 
572 
580 function includeContainer($containerref)
581 {
582  global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running included containers.
583  global $includehtmlcontentopened;
584  global $websitekey, $websitepagefile;
585 
586  $MAXLEVEL = 20;
587 
588  if (!preg_match('/\.php$/i', $containerref)) {
589  $containerref .= '.php';
590  }
591 
592  $fullpathfile = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$websitekey.'/'.$containerref;
593 
594  if (empty($includehtmlcontentopened)) {
595  $includehtmlcontentopened = 0;
596  }
597  $includehtmlcontentopened++;
598  if ($includehtmlcontentopened > $MAXLEVEL) {
599  print 'ERROR: RECURSIVE CONTENT LEVEL. Depth of recursive call is more than the limit of '.((int) $MAXLEVEL).".\n";
600  return;
601  }
602 
603  //dol_syslog("Include container ".$containerref.' includehtmlcontentopened='.$includehtmlcontentopened);
604 
605  // file_get_contents is not possible. We must execute code with include
606  //$content = file_get_contents($fullpathfile);
607  //print preg_replace(array('/^.*<body[^>]*>/ims','/<\/body>.*$/ims'), array('', ''), $content);*/
608 
609  ob_start();
610  $res = include $fullpathfile; // Include because we want to execute code content
611  $tmpoutput = ob_get_contents();
612  ob_end_clean();
613 
614  print "\n".'<!-- include '.$websitekey.'/'.$containerref.(is_object($websitepage) ? ' parent id='.$websitepage->id : '').' level = '.$includehtmlcontentopened.' -->'."\n";
615  print preg_replace(array('/^.*<body[^>]*>/ims', '/<\/body>.*$/ims'), array('', ''), $tmpoutput);
616 
617  if (!$res) {
618  print 'ERROR: FAILED TO INCLUDE PAGE '.$containerref.".\n";
619  }
620 
621  $includehtmlcontentopened--;
622 }
623 
634 function getStructuredData($type, $data = array())
635 {
636  global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs, $pagelangs; // Very important. Required to have var available when running inluded containers.
637 
638  $type = strtolower($type);
639 
640  if ($type == 'software') {
641  $ret = '<!-- Add structured data for entry in a software annuary -->'."\n";
642  $ret .= '<script nonce="'.getNonce().'" type="application/ld+json">'."\n";
643  $ret .= '{
644  "@context": "https://schema.org",
645  "@type": "SoftwareApplication",
646  "name": "'.dol_escape_json($data['name']).'",
647  "operatingSystem": "'.dol_escape_json($data['os']).'",
648  "applicationCategory": "https://schema.org/'.dol_escape_json($data['applicationCategory']).'",';
649  if (!empty($data['ratingcount'])) {
650  $ret .= '
651  "aggregateRating": {
652  "@type": "AggregateRating",
653  "ratingValue": "'.dol_escape_json($data['ratingvalue']).'",
654  "ratingCount": "'.dol_escape_json($data['ratingcount']).'"
655  },';
656  }
657  $ret .= '
658  "offers": {
659  "@type": "Offer",
660  "price": "'.dol_escape_json($data['price']).'",
661  "priceCurrency": "'.dol_escape_json($data['currency'] ? $data['currency'] : $conf->currency).'"
662  }
663  }'."\n";
664  $ret .= '</script>'."\n";
665  } elseif ($type == 'organization') {
666  $companyname = $mysoc->name;
667  $url = $mysoc->url;
668 
669  $ret = '<!-- Add structured data for organization -->'."\n";
670  $ret .= '<script nonce="'.getNonce().'" type="application/ld+json">'."\n";
671  $ret .= '{
672  "@context": "https://schema.org",
673  "@type": "Organization",
674  "name": "'.dol_escape_json($data['name'] ? $data['name'] : $companyname).'",
675  "url": "'.dol_escape_json($data['url'] ? $data['url'] : $url).'",
676  "logo": "'.($data['logo'] ? dol_escape_json($data['logo']) : '/wrapper.php?modulepart=mycompany&file=logos%2F'.urlencode($mysoc->logo)).'",
677  "contactPoint": {
678  "@type": "ContactPoint",
679  "contactType": "Contact",
680  "email": "'.dol_escape_json($data['email'] ? $data['email'] : $mysoc->email).'"
681  }'."\n";
682  if (is_array($mysoc->socialnetworks) && count($mysoc->socialnetworks) > 0) {
683  $ret .= ",\n";
684  $ret .= '"sameAs": [';
685  $i = 0;
686  foreach ($mysoc->socialnetworks as $key => $value) {
687  if ($key == 'linkedin') {
688  $ret .= '"https://www.'.$key.'.com/company/'.dol_escape_json($value).'"';
689  } elseif ($key == 'youtube') {
690  $ret .= '"https://www.'.$key.'.com/user/'.dol_escape_json($value).'"';
691  } else {
692  $ret .= '"https://www.'.$key.'.com/'.dol_escape_json($value).'"';
693  }
694  $i++;
695  if ($i < count($mysoc->socialnetworks)) {
696  $ret .= ', ';
697  }
698  }
699  $ret .= ']'."\n";
700  }
701  $ret .= '}'."\n";
702  $ret .= '</script>'."\n";
703  } elseif ($type == 'blogpost') {
704  if (!empty($websitepage->author_alias)) {
705  //include_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
706  //$tmpuser = new User($db);
707  //$restmpuser = $tmpuser->fetch($websitepage->fk_user_creat);
708 
709  $pageurl = $websitepage->pageurl;
710  $title = $websitepage->title;
711  $image = $websitepage->image;
712  $companyname = $mysoc->name;
713  $description = $websitepage->description;
714 
715  $pageurl = str_replace('__WEBSITE_KEY__', $website->ref, $pageurl);
716  $title = str_replace('__WEBSITE_KEY__', $website->ref, $title);
717  $image = '/medias'.(preg_match('/^\//', $image) ? '' : '/').str_replace('__WEBSITE_KEY__', $website->ref, $image);
718  $companyname = str_replace('__WEBSITE_KEY__', $website->ref, $companyname);
719  $description = str_replace('__WEBSITE_KEY__', $website->ref, $description);
720 
721  $ret = '<!-- Add structured data for blog post -->'."\n";
722  $ret .= '<script nonce="'.getNonce().'" type="application/ld+json">'."\n";
723  $ret .= '{
724  "@context": "https://schema.org",
725  "@type": "NewsArticle",
726  "mainEntityOfPage": {
727  "@type": "WebPage",
728  "@id": "'.dol_escape_json($pageurl).'"
729  },
730  "headline": "'.dol_escape_json($title).'",
731  "image": [
732  "'.dol_escape_json($image).'"
733  ],
734  "dateCreated": "'.dol_print_date($websitepage->date_creation, 'dayhourrfc').'",
735  "datePublished": "'.dol_print_date($websitepage->date_creation, 'dayhourrfc').'",
736  "dateModified": "'.dol_print_date($websitepage->date_modification, 'dayhourrfc').'",
737  "author": {
738  "@type": "Person",
739  "name": "'.dol_escape_json($websitepage->author_alias).'"
740  },
741  "publisher": {
742  "@type": "Organization",
743  "name": "'.dol_escape_json($companyname).'",
744  "logo": {
745  "@type": "ImageObject",
746  "url": "/wrapper.php?modulepart=mycompany&file=logos%2F'.urlencode($mysoc->logo).'"
747  }
748  },'."\n";
749  if ($websitepage->keywords) {
750  $ret .= '"keywords": [';
751  $i = 0;
752  $arrayofkeywords = explode(',', $websitepage->keywords);
753  foreach ($arrayofkeywords as $keyword) {
754  $ret .= '"'.dol_escape_json($keyword).'"';
755  $i++;
756  if ($i < count($arrayofkeywords)) {
757  $ret .= ', ';
758  }
759  }
760  $ret .= '],'."\n";
761  }
762  $ret .= '"description": "'.dol_escape_json($description).'"';
763  $ret .= "\n".'}'."\n";
764  $ret .= '</script>'."\n";
765  } else {
766  $ret = '<!-- no structured data inserted inline inside blogpost because no author_alias defined -->'."\n";
767  }
768  } elseif ($type == 'product') {
769  $ret = '<!-- Add structured data for product -->'."\n";
770  $ret .= '<script nonce="'.getNonce().'" type="application/ld+json">'."\n";
771  $ret .= '{
772  "@context": "https://schema.org/",
773  "@type": "Product",
774  "name": "'.dol_escape_json($data['label']).'",
775  "image": [
776  "'.dol_escape_json($data['image']).'",
777  ],
778  "description": "'.dol_escape_json($data['description']).'",
779  "sku": "'.dol_escape_json($data['ref']).'",
780  "brand": {
781  "@type": "Thing",
782  "name": "'.dol_escape_json($data['brand']).'"
783  },
784  "author": {
785  "@type": "Person",
786  "name": "'.dol_escape_json($data['author']).'"
787  }
788  },
789  "offers": {
790  "@type": "Offer",
791  "url": "https://example.com/anvil",
792  "priceCurrency": "'.dol_escape_json($data['currency'] ? $data['currency'] : $conf->currency).'",
793  "price": "'.dol_escape_json($data['price']).'",
794  "itemCondition": "https://schema.org/UsedCondition",
795  "availability": "https://schema.org/InStock",
796  "seller": {
797  "@type": "Organization",
798  "name": "'.dol_escape_json($mysoc->name).'"
799  }
800  }
801  }'."\n";
802  $ret .= '</script>'."\n";
803  } elseif ($type == 'qa') {
804  $ret = '<!-- Add structured data for QA -->'."\n";
805  $ret .= '<script nonce="'.getNonce().'" type="application/ld+json">'."\n";
806  $ret .= '{
807  "@context": "https://schema.org/",
808  "@type": "QAPage",
809  "mainEntity": {
810  "@type": "Question",
811  "name": "'.dol_escape_json($data['name']).'",
812  "text": "'.dol_escape_json($data['name']).'",
813  "answerCount": 1,
814  "author": {
815  "@type": "Person",
816  "name": "'.dol_escape_json($data['author']).'"
817  }
818  "acceptedAnswer": {
819  "@type": "Answer",
820  "text": "'.dol_escape_json(dol_string_nohtmltag(dolStripPhpCode($data['description']))).'",
821  "author": {
822  "@type": "Person",
823  "name": "'.dol_escape_json($data['author']).'"
824  }
825  }
826  }
827  }'."\n";
828  $ret .= '</script>'."\n";
829  }
830  return $ret;
831 }
832 
839 function getSocialNetworkHeaderCards($params = null)
840 {
841  global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers.
842 
843  $out = '';
844 
845  if ($website->virtualhost) {
846  $pageurl = $websitepage->pageurl;
847  $title = $websitepage->title;
848  $image = $websitepage->image;
849  $companyname = $mysoc->name;
850  $description = $websitepage->description;
851 
852  $pageurl = str_replace('__WEBSITE_KEY__', $website->ref, $pageurl);
853  $title = str_replace('__WEBSITE_KEY__', $website->ref, $title);
854  $image = '/medias'.(preg_match('/^\//', $image) ? '' : '/').str_replace('__WEBSITE_KEY__', $website->ref, $image);
855  $companyname = str_replace('__WEBSITE_KEY__', $website->ref, $companyname);
856  $description = str_replace('__WEBSITE_KEY__', $website->ref, $description);
857 
858  $shortlangcode = '';
859  if ($websitepage->lang) {
860  $shortlangcode = substr($websitepage->lang, 0, 2); // en_US or en-US -> en
861  }
862  if (empty($shortlangcode)) {
863  $shortlangcode = substr($website->lang, 0, 2); // en_US or en-US -> en
864  }
865 
866  $fullurl = $website->virtualhost.'/'.$websitepage->pageurl.'.php';
867  $canonicalurl = $website->virtualhost.(($websitepage->id == $website->fk_default_home) ? '/' : (($shortlangcode != substr($website->lang, 0, 2) ? '/'.$shortlangcode : '').'/'.$websitepage->pageurl.'.php'));
868  $hashtags = trim(join(' #', array_map('trim', explode(',', $websitepage->keywords))));
869 
870  // Open Graph
871  $out .= '<meta name="og:type" content="website">'."\n"; // TODO If blogpost, use type article
872  $out .= '<meta name="og:title" content="'.$websitepage->title.'">'."\n";
873  if ($websitepage->image) {
874  $out .= '<meta name="og:image" content="'.$website->virtualhost.$image.'">'."\n";
875  }
876  $out .= '<meta name="og:url" content="'.$canonicalurl.'">'."\n";
877 
878  // Twitter
879  $out .= '<meta name="twitter:card" content="summary">'."\n";
880  if (!empty($params) && !empty($params['twitter_account'])) {
881  $out .= '<meta name="twitter:site" content="@'.$params['twitter_account'].'">'."\n";
882  $out .= '<meta name="twitter:creator" content="@'.$params['twitter_account'].'">'."\n";
883  }
884  $out .= '<meta name="twitter:title" content="'.$websitepage->title.'">'."\n";
885  if ($websitepage->description) {
886  $out .= '<meta name="twitter:description" content="'.$websitepage->description.'">'."\n";
887  }
888  if ($websitepage->image) {
889  $out .= '<meta name="twitter:image" content="'.$website->virtualhost.$image.'">'."\n";
890  }
891  //$out .= '<meta name="twitter:domain" content="'.getDomainFromURL($website->virtualhost, 1).'">';
892  /*
893  $out .= '<meta name="twitter:app:name:iphone" content="">';
894  $out .= '<meta name="twitter:app:name:ipad" content="">';
895  $out .= '<meta name="twitter:app:name:googleplay" content="">';
896  $out .= '<meta name="twitter:app:url:iphone" content="">';
897  $out .= '<meta name="twitter:app:url:ipad" content="">';
898  $out .= '<meta name="twitter:app:url:googleplay" content="">';
899  $out .= '<meta name="twitter:app:id:iphone" content="">';
900  $out .= '<meta name="twitter:app:id:ipad" content="">';
901  $out .= '<meta name="twitter:app:id:googleplay" content="">';
902  */
903  }
904 
905  return $out;
906 }
907 
914 {
915  global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers.
916 
917  $out = '<!-- section for social network sharing of page -->'."\n";
918 
919  if ($website->virtualhost) {
920  $fullurl = $website->virtualhost.'/'.$websitepage->pageurl.'.php';
921  $hashtags = trim(join(' #', array_map('trim', explode(',', $websitepage->keywords))));
922 
923  $out .= '<div class="dol-social-share">'."\n";
924 
925  // Twitter
926  $out .= '<div class="dol-social-share-tw">'."\n";
927  $out .= '<a href="https://twitter.com/share" class="twitter-share-button" data-url="'.$fullurl.'" data-text="'.dol_escape_htmltag($websitepage->description).'" data-lang="'.$websitepage->lang.'" data-size="small" data-related="" data-hashtags="'.preg_replace('/^#/', '', $hashtags).'" data-count="horizontal">Tweet</a>';
928  $out .= '<script nonce="'.getNonce().'">!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?\'http\':\'https\';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+\'://platform.twitter.com/widgets.js\';fjs.parentNode.insertBefore(js,fjs);}}(document, \'script\', \'twitter-wjs\');</script>';
929  $out .= '</div>'."\n";
930 
931  // Reddit
932  $out .= '<div class="dol-social-share-reddit">'."\n";
933  $out .= '<a href="https://www.reddit.com/submit" target="_blank" rel="noopener noreferrer external" onclick="window.location = \'https://www.reddit.com/submit?url='.$fullurl.'\'; return false">';
934  $out .= '<span class="dol-social-share-reddit-span">Reddit</span>';
935  $out .= '</a>';
936  $out .= '</div>'."\n";
937 
938  // Facebook
939  $out .= '<div class="dol-social-share-fbl">'."\n";
940  $out .= '<div id="fb-root"></div>'."\n";
941  $out .= '<script nonce="'.getNonce().'">(function(d, s, id) {
942  var js, fjs = d.getElementsByTagName(s)[0];
943  if (d.getElementById(id)) return;
944  js = d.createElement(s); js.id = id;
945  js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0&amp;appId=dolibarr.org";
946  fjs.parentNode.insertBefore(js, fjs);
947  }(document, \'script\', \'facebook-jssdk\'));</script>
948  <fb:like
949  href="'.$fullurl.'"
950  layout="button_count"
951  show_faces="false"
952  width="90"
953  colorscheme="light"
954  share="1"
955  action="like" ></fb:like>'."\n";
956  $out .= '</div>'."\n";
957 
958  $out .= "\n</div>\n";
959  } else {
960  $out .= '<!-- virtual host not defined in CMS. No way to add sharing buttons -->'."\n";
961  }
962  $out .= '<!-- section end for social network sharing of page -->'."\n";
963 
964  return $out;
965 }
966 
982 function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $sortfield = 'date_creation', $sortorder = 'DESC', $langcode = '', $otherfilters = 'null', $status = 1)
983 {
984  global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers.
985 
986  $error = 0;
987  $arrayresult = array('code'=>'', 'list'=>array());
988 
989  if (!is_object($weblangs)) {
990  $weblangs = $langs;
991  }
992 
993  if (empty($searchstring) && empty($type) && empty($langcode) && empty($otherfilters)) {
994  $error++;
995  $arrayresult['code'] = 'KO';
996  $arrayresult['message'] = $weblangs->trans("EmptySearchString");
997  } elseif ($searchstring && dol_strlen($searchstring) < 2) {
998  $weblangs->load("errors");
999  $error++;
1000  $arrayresult['code'] = 'KO';
1001  $arrayresult['message'] = $weblangs->trans("ErrorSearchCriteriaTooSmall");
1002  } else {
1003  $tmparrayoftype = explode(',', $type);
1004  /*foreach ($tmparrayoftype as $tmptype) {
1005  if (!in_array($tmptype, array('', 'page', 'blogpost'))) {
1006  $error++;
1007  $arrayresult['code'] = 'KO';
1008  $arrayresult['message'] = 'Bad value for parameter type';
1009  break;
1010  }
1011  }*/
1012  }
1013 
1014  $searchdone = 0;
1015  $found = 0;
1016 
1017  if (!$error && (empty($max) || ($found < $max)) && (preg_match('/meta/', $algo) || preg_match('/content/', $algo))) {
1018  include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php';
1019 
1020  $sql = 'SELECT wp.rowid FROM '.MAIN_DB_PREFIX.'website_page as wp';
1021  if (is_array($otherfilters) && !empty($otherfilters['category'])) {
1022  $sql .= ', '.MAIN_DB_PREFIX.'categorie_website_page as cwp';
1023  }
1024  $sql .= " WHERE wp.fk_website = ".((int) $website->id);
1025  if ($status >= 0) {
1026  $sql .= " AND wp.status = ".((int) $status);
1027  }
1028  if ($langcode) {
1029  $sql .= " AND wp.lang = '".$db->escape($langcode)."'";
1030  }
1031  if ($type) {
1032  $tmparrayoftype = explode(',', $type);
1033  $typestring = '';
1034  foreach ($tmparrayoftype as $tmptype) {
1035  $typestring .= ($typestring ? ", " : "")."'".$db->escape(trim($tmptype))."'";
1036  }
1037  $sql .= " AND wp.type_container IN (".$db->sanitize($typestring, 1).")";
1038  }
1039  $sql .= " AND (";
1040  $searchalgo = '';
1041  if (preg_match('/meta/', $algo)) {
1042  $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.title LIKE '%".$db->escape($db->escapeforlike($searchstring))."%' OR wp.description LIKE '%".$db->escape($db->escapeforlike($searchstring))."%'";
1043  $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.keywords LIKE '".$db->escape($db->escapeforlike($searchstring)).",%' OR wp.keywords LIKE '% ".$db->escape($db->escapeforlike($searchstring))."%'"; // TODO Use a better way to scan keywords
1044  }
1045  if (preg_match('/content/', $algo)) {
1046  $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.content LIKE '%".$db->escape($db->escapeforlike($searchstring))."%'";
1047  }
1048  $sql .= $searchalgo;
1049  if (is_array($otherfilters) && !empty($otherfilters['category'])) {
1050  $sql .= ' AND cwp.fk_website_page = wp.rowid AND cwp.fk_categorie = '.((int) $otherfilters['category']);
1051  }
1052  $sql .= ")";
1053  $sql .= $db->order($sortfield, $sortorder);
1054  $sql .= $db->plimit($max);
1055  //print $sql;
1056 
1057  $resql = $db->query($sql);
1058 
1059  if ($resql) {
1060  $i = 0;
1061  while (($obj = $db->fetch_object($resql)) && ($i < $max || $max == 0)) {
1062  if ($obj->rowid > 0) {
1063  $tmpwebsitepage = new WebsitePage($db);
1064  $tmpwebsitepage->fetch($obj->rowid);
1065  if ($tmpwebsitepage->id > 0) {
1066  $arrayresult['list'][$obj->rowid] = $tmpwebsitepage;
1067  }
1068  $found++;
1069  }
1070  $i++;
1071  }
1072  } else {
1073  $error++;
1074  $arrayresult['code'] = $db->lasterrno();
1075  $arrayresult['message'] = $db->lasterror();
1076  }
1077 
1078  $searchdone = 1;
1079  }
1080 
1081  if (!$error && (empty($max) || ($found < $max)) && (preg_match('/sitefiles/', $algo))) {
1082  global $dolibarr_main_data_root;
1083 
1084  $pathofwebsite = $dolibarr_main_data_root.($conf->entity > 1 ? '/'.$conf->entity : '').'/website/'.$website->ref;
1085  $filehtmlheader = $pathofwebsite.'/htmlheader.html';
1086  $filecss = $pathofwebsite.'/styles.css.php';
1087  $filejs = $pathofwebsite.'/javascript.js.php';
1088  $filerobot = $pathofwebsite.'/robots.txt';
1089  $filehtaccess = $pathofwebsite.'/.htaccess';
1090  $filemanifestjson = $pathofwebsite.'/manifest.json.php';
1091  $filereadme = $pathofwebsite.'/README.md';
1092 
1093  $filecontent = file_get_contents($filehtmlheader);
1094  if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) {
1095  $arrayresult['list'][] = array('type'=>'website_htmlheadercontent');
1096  }
1097 
1098  $filecontent = file_get_contents($filecss);
1099  if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) {
1100  $arrayresult['list'][] = array('type'=>'website_csscontent');
1101  }
1102 
1103  $filecontent = file_get_contents($filejs);
1104  if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) {
1105  $arrayresult['list'][] = array('type'=>'website_jscontent');
1106  }
1107 
1108  $filerobot = file_get_contents($filerobot);
1109  if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) {
1110  $arrayresult['list'][] = array('type'=>'website_robotcontent');
1111  }
1112 
1113  $searchdone = 1;
1114  }
1115 
1116  if (!$error) {
1117  if ($searchdone) {
1118  $arrayresult['code'] = 'OK';
1119  if (empty($arrayresult['list'])) {
1120  $arrayresult['code'] = 'KO';
1121  $arrayresult['message'] = $weblangs->trans("NoRecordFound");
1122  }
1123  } else {
1124  $error++;
1125  $arrayresult['code'] = 'KO';
1126  $arrayresult['message'] = 'No supported algorithm found';
1127  }
1128  }
1129 
1130  return $arrayresult;
1131 }
1132 
1147 function getAllImages($object, $objectpage, $urltograb, &$tmp, &$action, $modifylinks = 0, $grabimages = 1, $grabimagesinto = 'subpage')
1148 {
1149  global $conf;
1150 
1151  $error = 0;
1152 
1153  dol_syslog("Call getAllImages with grabimagesinto=".$grabimagesinto);
1154 
1155  $alreadygrabbed = array();
1156 
1157  if (preg_match('/\/$/', $urltograb)) {
1158  $urltograb .= '.';
1159  }
1160  $urltograb = dirname($urltograb); // So urltograb is now http://www.nltechno.com or http://www.nltechno.com/dir1
1161 
1162  // Search X in "img...src=X"
1163  $regs = array();
1164  preg_match_all('/<img([^\.\/]+)src="([^>"]+)"([^>]*)>/i', $tmp, $regs);
1165 
1166  foreach ($regs[0] as $key => $val) {
1167  if (preg_match('/^data:image/i', $regs[2][$key])) {
1168  continue; // We do nothing for such images
1169  }
1170 
1171  if (preg_match('/^\//', $regs[2][$key])) {
1172  $urltograbdirrootwithoutslash = getRootURLFromURL($urltograb);
1173  $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot
1174  } else {
1175  $urltograbbis = $urltograb.'/'.$regs[2][$key]; // We use dir of grabbed file
1176  }
1177 
1178  $linkwithoutdomain = $regs[2][$key];
1179  $dirforimages = '/'.$objectpage->pageurl;
1180  if ($grabimagesinto == 'root') {
1181  $dirforimages = '';
1182  }
1183 
1184  // Define $filetosave and $filename
1185  $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $regs[2][$key]) ? '' : '/').$regs[2][$key];
1186  if (preg_match('/^http/', $regs[2][$key])) {
1187  $urltograbbis = $regs[2][$key];
1188  $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]);
1189  $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain;
1190  }
1191  $filename = 'image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain;
1192 
1193  // Clean the aa/bb/../cc into aa/cc
1194  $filetosave = preg_replace('/\/[^\/]+\/\.\./', '', $filetosave);
1195  $filename = preg_replace('/\/[^\/]+\/\.\./', '', $filename);
1196 
1197  //var_dump($filetosave);
1198  //var_dump($filename);
1199  //exit;
1200 
1201  if (empty($alreadygrabbed[$urltograbbis])) {
1202  if ($grabimages) {
1203  $tmpgeturl = getURLContent($urltograbbis, 'GET', '', 1, array(), array('http', 'https'), 0);
1204  if ($tmpgeturl['curl_error_no']) {
1205  $error++;
1206  setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors');
1207  $action = 'create';
1208  } elseif ($tmpgeturl['http_code'] != '200') {
1209  $error++;
1210  setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors');
1211  $action = 'create';
1212  } else {
1213  $alreadygrabbed[$urltograbbis] = 1; // Track that file was alreay grabbed.
1214 
1215  dol_mkdir(dirname($filetosave));
1216 
1217  $fp = fopen($filetosave, "w");
1218  fputs($fp, $tmpgeturl['content']);
1219  fclose($fp);
1220  dolChmod($filetosave);
1221  }
1222  }
1223  }
1224 
1225  if ($modifylinks) {
1226  $tmp = preg_replace('/'.preg_quote($regs[0][$key], '/').'/i', '<img'.$regs[1][$key].'src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file='.$filename.'"'.$regs[3][$key].'>', $tmp);
1227  }
1228  }
1229 
1230  // Search X in "background...url(X)"
1231  preg_match_all('/background([^\.\/\‍(;]+)url\‍([\"\']?([^\‍)\"\']*)[\"\']?\‍)/i', $tmp, $regs);
1232 
1233  foreach ($regs[0] as $key => $val) {
1234  if (preg_match('/^data:image/i', $regs[2][$key])) {
1235  continue; // We do nothing for such images
1236  }
1237 
1238  if (preg_match('/^\//', $regs[2][$key])) {
1239  $urltograbdirrootwithoutslash = getRootURLFromURL($urltograb);
1240  $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot
1241  } else {
1242  $urltograbbis = $urltograb.'/'.$regs[2][$key]; // We use dir of grabbed file
1243  }
1244 
1245  $linkwithoutdomain = $regs[2][$key];
1246 
1247  $dirforimages = '/'.$objectpage->pageurl;
1248  if ($grabimagesinto == 'root') {
1249  $dirforimages = '';
1250  }
1251 
1252  $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $regs[2][$key]) ? '' : '/').$regs[2][$key];
1253 
1254  if (preg_match('/^http/', $regs[2][$key])) {
1255  $urltograbbis = $regs[2][$key];
1256  $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]);
1257  $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain;
1258  }
1259 
1260  $filename = 'image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain;
1261 
1262  // Clean the aa/bb/../cc into aa/cc
1263  $filetosave = preg_replace('/\/[^\/]+\/\.\./', '', $filetosave);
1264  $filename = preg_replace('/\/[^\/]+\/\.\./', '', $filename);
1265 
1266  //var_dump($filetosave);
1267  //var_dump($filename);
1268  //exit;
1269 
1270  if (empty($alreadygrabbed[$urltograbbis])) {
1271  if ($grabimages) {
1272  $tmpgeturl = getURLContent($urltograbbis, 'GET', '', 1, array(), array('http', 'https'), 0);
1273  if ($tmpgeturl['curl_error_no']) {
1274  $error++;
1275  setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors');
1276  $action = 'create';
1277  } elseif ($tmpgeturl['http_code'] != '200') {
1278  $error++;
1279  setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors');
1280  $action = 'create';
1281  } else {
1282  $alreadygrabbed[$urltograbbis] = 1; // Track that file was alreay grabbed.
1283 
1284  dol_mkdir(dirname($filetosave));
1285 
1286  $fp = fopen($filetosave, "w");
1287  fputs($fp, $tmpgeturl['content']);
1288  fclose($fp);
1289  dolChmod($filetosave);
1290  }
1291  }
1292  }
1293 
1294  if ($modifylinks) {
1295  $tmp = preg_replace('/'.preg_quote($regs[0][$key], '/').'/i', 'background'.$regs[1][$key].'url("'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file='.$filename.'")', $tmp);
1296  }
1297  }
1298 }
Class Websitepage.
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dolChmod($filepath, $newmask='')
Change mod of a file.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_escape_json($stringtoescape)
Returns text escaped for inclusion into javascript code.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
getRootURLFromURL($url)
Function root url from a long url For example: https://www.abc.mydomain.com/dir/page....
Definition: geturl.lib.php:370
getURLContent($url, $postorget='GET', $param='', $followlocation=1, $addheaders=array(), $allowedschemes=array('http', 'https'), $localurl=0, $ssl_verifypeer=-1)
Function to get a content from an URL (use proxy if proxy defined).
Definition: geturl.lib.php:41
if(!defined( 'CSRFCHECK_WITH_TOKEN'))
getAllImages($object, $objectpage, $urltograb, &$tmp, &$action, $modifylinks=0, $grabimages=1, $grabimagesinto='subpage')
Download all images found into page content $tmp.
getPagesFromSearchCriterias($type, $algo, $searchstring, $max=25, $sortfield='date_creation', $sortorder='DESC', $langcode='', $otherfilters='null', $status=1)
Return list of containers object that match a criteria.
dolWebsiteReplacementOfLinks($website, $content, $removephppart=0, $contenttype='html', $containerid='')
Convert a page content to have correct links (based on DOL_URL_ROOT) into an html content.
dolStripPhpCode($str, $replacewith='')
Remove PHP code part from a string.
Definition: website.lib.php:32
getStructuredData($type, $data=array())
Return HTML content to add structured data for an article, news or Blog Post.
dolWebsiteIncrementCounter($websiteid, $websitepagetype, $websitepageid)
Increase the website counter of page access.
dolReplaceSmileyCodeWithUTF8($content)
Converts smiley string into the utf8 sequence.
includeContainer($containerref)
Clean an HTML page to report only content, so we can include it into another page.
dolKeepOnlyPhpCode($str)
Keep only PHP code part from a HTML string page.
Definition: website.lib.php:76
getSocialNetworkSharingLinks()
Return HTML content to add structured data for an article, news or Blog Post.
redirectToContainer($containerref, $containeraliasalt='', $containerid=0, $permanent=0)
Format img tags to introduce viewimage on img src.
dolWebsiteOutput($content, $contenttype='html', $containerid='')
Render a string of an HTML content and output it.
getSocialNetworkHeaderCards($params=null)
Return HTML content to add as header card for an article, news or Blog Post or home page.