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 18/** 19 * \file htdocs/core/lib/website.lib.php 20 * \ingroup website 21 * \brief Library for website module 22 */ 23 24/** 25 * Remove PHP code part from a string. 26 * 27 * @param string $str String to clean 28 * @param string $replacewith String to use as replacement 29 * @return string Result string without php code 30 * @see dolKeepOnlyPhpCode() 31 */ 32function dolStripPhpCode($str, $replacewith = '') 33{ 34 $newstr = ''; 35 36 //split on each opening tag 37 $parts = explode('<?php', $str); 38 if (!empty($parts)) 39 { 40 $i = 0; 41 foreach ($parts as $part) 42 { 43 if ($i == 0) // The first part is never php code 44 { 45 $i++; 46 $newstr .= $part; 47 continue; 48 } 49 // The second part is the php code. We split on closing tag 50 $partlings = explode('?>', $part); 51 if (!empty($partlings)) 52 { 53 //$phppart = $partlings[0]; 54 //remove content before closing tag 55 if (count($partlings) > 1) $partlings[0] = ''; // Todo why a count > 1 and not >= 1 ? 56 //append to out string 57 //$newstr .= '<span class="phptag" class="tooltip" title="'.dol_escape_htmltag(dolGetFirstLineOfText($phppart).'...').'">'.$replacewith.'<!-- '.$phppart.' --></span>'.implode('', $partlings); 58 //$newstr .= '<span>'.$replacewith.'<!-- '.$phppart.' --></span>'.implode('', $partlings); 59 $newstr .= '<span phptag>'.$replacewith.'</span>'.implode('', $partlings); 60 //$newstr .= $replacewith.implode('', $partlings); 61 } 62 } 63 } 64 return $newstr; 65} 66 67/** 68 * Keep only PHP code part from a HTML string page. 69 * 70 * @param string $str String to clean 71 * @return string Result string with php code only 72 * @see dolStripPhpCode() 73 */ 74function dolKeepOnlyPhpCode($str) 75{ 76 $newstr = ''; 77 78 //split on each opening tag 79 $parts = explode('<?php', $str); 80 if (!empty($parts)) 81 { 82 $i = 0; 83 foreach ($parts as $part) 84 { 85 if ($i == 0) // The first part is never php code 86 { 87 $i++; 88 continue; 89 } 90 $newstr .= '<?php'; 91 //split on closing tag 92 $partlings = explode('?>', $part, 2); 93 if (!empty($partlings)) 94 { 95 $newstr .= $partlings[0].'?>'; 96 } else { 97 $newstr .= $part.'?>'; 98 } 99 } 100 } 101 return $newstr; 102} 103 104/** 105 * Convert a page content to have correct links (based on DOL_URL_ROOT) into an html content. It replaces also dynamic content with '...php...' 106 * Used to ouput the page on the Preview from backoffice. 107 * 108 * @param Website $website Web site object 109 * @param string $content Content to replace 110 * @param int $removephppart 0=Replace PHP sections with a PHP badge. 1=Remove completely PHP sections. 111 * @param string $contenttype Content type 112 * @param int $containerid Contenair id 113 * @return boolean True if OK 114 * @see dolWebsiteOutput() for function used to replace content in a web server context 115 */ 116function dolWebsiteReplacementOfLinks($website, $content, $removephppart = 0, $contenttype = 'html', $containerid = '') 117{ 118 $nbrep = 0; 119 120 dol_syslog('dolWebsiteReplacementOfLinks start (contenttype='.$contenttype." containerid=".$containerid." USEDOLIBARREDITOR=".(defined('USEDOLIBARREDITOR') ? '1' : '')." USEDOLIBARRSERVER=".(defined('USEDOLIBARRSERVER') ? '1' : '').')', LOG_DEBUG); 121 //if ($contenttype == 'html') { print $content;exit; } 122 123 // Replace php code. Note $content may come from database and does not contains body tags. 124 $replacewith = '...php...'; 125 if ($removephppart) $replacewith = ''; 126 $content = preg_replace('/value="<\?php((?!\?>).)*\?>\n*/ims', 'value="'.$replacewith.'"', $content); 127 128 $replacewith = '"callto=#'; 129 if ($removephppart) $replacewith = ''; 130 $content = preg_replace('/"callto:<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content); 131 132 $replacewith = '"mailto=#'; 133 if ($removephppart) $replacewith = ''; 134 $content = preg_replace('/"mailto:<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content); 135 136 $replacewith = 'src="php'; 137 if ($removephppart) $replacewith = ''; 138 $content = preg_replace('/src="<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content); 139 140 $replacewith = 'href="php'; 141 if ($removephppart) $replacewith = ''; 142 $content = preg_replace('/href="<\?php((?!\?>).)*\?>\n*/ims', $replacewith, $content); 143 144 //$replacewith='<span class="phptag">...php...</span>'; 145 $replacewith = '...php...'; 146 if ($removephppart) $replacewith = ''; 147 //$content = preg_replace('/<\?php((?!\?toremove>).)*\?toremove>\n*/ims', $replacewith, $content); 148 /*if ($content === null) { 149 if (preg_last_error() == PREG_JIT_STACKLIMIT_ERROR) $content = 'preg_replace error (when removing php tags) PREG_JIT_STACKLIMIT_ERROR'; 150 }*/ 151 $content = dolStripPhpCode($content, $replacewith); 152 //var_dump($content); 153 154 // Protect the link styles.css.php to any replacement that we make after. 155 $content = str_replace('href="styles.css.php', 'href="!~!~!~styles.css.php', $content); 156 $content = str_replace('href="http', 'href="!~!~!~http', $content); 157 $content = str_replace('href="//', 'href="!~!~!~//', $content); 158 $content = str_replace('src="viewimage.php', 'src="!~!~!~/viewimage.php', $content); 159 $content = str_replace('src="/viewimage.php', 'src="!~!~!~/viewimage.php', $content); 160 $content = str_replace('src="'.DOL_URL_ROOT.'/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content); 161 $content = str_replace('href="document.php', 'href="!~!~!~/document.php', $content); 162 $content = str_replace('href="/document.php', 'href="!~!~!~/document.php', $content); 163 $content = str_replace('href="'.DOL_URL_ROOT.'/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content); 164 165 // Replace relative link '/' with dolibarr URL 166 $content = preg_replace('/(href=")\/(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageid='.$website->fk_default_home.'\2"', $content, -1, $nbrep); 167 // Replace relative link /xxx.php#aaa or /xxx.php with dolibarr URL (we discard param ?...) 168 $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageref=\2\3"', $content, -1, $nbrep); 169 // Replace relative link /xxx.php?a=b&c=d#aaa or /xxx.php?a=b&c=d with dolibarr URL 170 $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php\?([^#\"<>]*)(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageref=\2&\3\4"', $content, -1, $nbrep); 171 172 // Fix relative link into medias with correct URL after the DOL_URL_ROOT: ../url("medias/ 173 $content = preg_replace('/url\((["\']?)\/?medias\//', 'url(\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 174 $content = preg_replace('/data-slide-bg=(["\']?)\/?medias\//', 'data-slide-bg=\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 175 176 // <img src="medias/...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png... 177 // <img src="...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png... 178 $content = preg_replace('/(<img[^>]*src=")\/?medias\//', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 179 // <img src="image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png... 180 $content = preg_replace('/(<img[^>]*src=")\/?([^:\"\!]+)\"/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=\2"', $content, -1, $nbrep); 181 // <img src="viewimage.php/modulepart=medias&file=image.png" => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png" 182 $content = preg_replace('/(<img[^>]*src=")(\/?viewimage\.php)/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content, -1, $nbrep); 183 184 // action="newpage.php" => action="dolibarr/website/index.php?website=...&pageref=newpage 185 $content = preg_replace('/(action=")\/?([^:\"]*)(\.php\")/', '\1!~!~!~'.DOL_URL_ROOT.'/website/index.php?website='.$website->ref.'&pageref=\2"', $content, -1, $nbrep); 186 187 // Fix relative link /document.php with correct URL after the DOL_URL_ROOT: ...href="/document.php?modulepart=" 188 $content = preg_replace('/(href=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 189 $content = preg_replace('/(src=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 190 191 // Fix relative link /viewimage.php with correct URL after the DOL_URL_ROOT: ...href="/viewimage.php?modulepart=" 192 $content = preg_replace('/(url\(")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 193 194 // Fix relative URL 195 $content = str_replace('src="!~!~!~/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content); 196 $content = str_replace('href="!~!~!~/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content); 197 // Remove the protection tag !~!~!~ 198 $content = str_replace('!~!~!~', '', $content); 199 200 dol_syslog('dolWebsiteReplacementOfLinks end', LOG_DEBUG); 201 //if ($contenttype == 'html') { print $content;exit; } 202 203 return $content; 204} 205 206/** 207 * Render a string of an HTML content and output it. 208 * Used to ouput the page when viewed from server (Dolibarr or Apache). 209 * 210 * @param string $content Content string 211 * @param string $contenttype Content type 212 * @param int $containerid Contenair id 213 * @return void 214 * @see dolWebsiteReplacementOfLinks() for function used to replace content in the backoffice context. 215 */ 216function dolWebsiteOutput($content, $contenttype = 'html', $containerid = '') 217{ 218 global $db, $langs, $conf, $user; 219 global $dolibarr_main_url_root, $dolibarr_main_data_root; 220 global $website; 221 global $includehtmlcontentopened; 222 223 $nbrep = 0; 224 225 dol_syslog("dolWebsiteOutput start - contenttype=".$contenttype." containerid=".$containerid." USEDOLIBARREDITOR=".(defined('USEDOLIBARREDITOR') ? '1' : '')." USEDOLIBARRSERVER=".(defined('USEDOLIBARRSERVER') ? '1' : '').' includehtmlcontentopened='.$includehtmlcontentopened); 226 227 //print $containerid.' '.$content; 228 229 // Define $urlwithroot 230 $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root)); 231 $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file 232 //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current 233 234 if (defined('USEDOLIBARREDITOR')) // REPLACEMENT OF LINKS When page called from Dolibarr editor 235 { 236 // We remove the <head> part of content 237 if ($contenttype == 'html') 238 { 239 $content = preg_replace('/<head>.*<\/head>/ims', '', $content); 240 $content = preg_replace('/^.*<body(\s[^>]*)*>/ims', '', $content); 241 $content = preg_replace('/<\/body(\s[^>]*)*>.*$/ims', '', $content); 242 } 243 } elseif (defined('USEDOLIBARRSERVER')) // REPLACEMENT OF LINKS When page called from Dolibarr server 244 { 245 $content = str_replace('<link rel="stylesheet" href="/styles.css', '<link rel="stylesheet" href="styles.css', $content); 246 247 // Protect the link styles.css.php to any replacement that we make after. 248 $content = str_replace('href="styles.css.php', 'href="!~!~!~styles.css.php', $content); 249 $content = str_replace('href="http', 'href="!~!~!~http', $content); 250 $content = str_replace('href="//', 'href="!~!~!~//', $content); 251 $content = str_replace(array('src="viewimage.php', 'src="/viewimage.php'), 'src="!~!~!~/viewimage.php', $content); 252 $content = str_replace('src="'.DOL_URL_ROOT.'/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content); 253 $content = str_replace(array('href="document.php', 'href="/document.php'), 'href="!~!~!~/document.php', $content); 254 $content = str_replace('href="'.DOL_URL_ROOT.'/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content); 255 256 // Replace relative link / with dolibarr URL: ...href="/"... 257 $content = preg_replace('/(href=")\/\"/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'"', $content, -1, $nbrep); 258 // Replace relative link /xxx.php#aaa or /xxx.php with dolibarr URL: ...href="....php" (we discard param ?...) 259 $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2\3"', $content, -1, $nbrep); 260 // Replace relative link /xxx.php?a=b&c=d#aaa or /xxx.php?a=b&c=d with dolibarr URL 261 // Warning: we may replace twice if href="..." was inside an include (dolWebsiteOutput called by include and the by final page), that's why 262 // at end we replace the '!~!~!~' only if we are in final parent page. 263 $content = preg_replace('/(href=")\/?([^:\"\!]*)\.php\?([^#\"<>]*)(#[^\"<>]*)?\"/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2&\3\4"', $content, -1, $nbrep); 264 // Replace relative link without .php like /xxx#aaa or /xxx with dolibarr URL: ...href="....php" 265 $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); 266 267 // Fix relative link /document.php with correct URL after the DOL_URL_ROOT: href="/document.php?modulepart=" => href="/dolibarr/document.php?modulepart=" 268 $content = preg_replace('/(href=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 269 $content = preg_replace('/(src=")(\/?document\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 270 271 // Fix relative link /viewimage.php with correct URL after the DOL_URL_ROOT: href="/viewimage.php?modulepart=" => href="/dolibarr/viewimage.php?modulepart=" 272 $content = preg_replace('/(href=")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 273 $content = preg_replace('/(src=")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 274 $content = preg_replace('/(url\(")(\/?viewimage\.php\?[^\"]*modulepart=[^\"]*)(\")/', '\1!~!~!~'.DOL_URL_ROOT.'\2\3', $content, -1, $nbrep); 275 276 // Fix relative link into medias with correct URL after the DOL_URL_ROOT: ../url("medias/ 277 $content = preg_replace('/url\((["\']?)\/?medias\//', 'url(\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 278 $content = preg_replace('/data-slide-bg=(["\']?)\/?medias\//', 'data-slide-bg=\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 279 280 // <img src="medias/...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png... 281 // <img src="...image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png... 282 $content = preg_replace('/(<img[^>]*src=")\/?medias\//', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 283 // <img src="image.png... => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png... 284 $content = preg_replace('/(<img[^>]*src=")\/?([^:\"\!]+)\"/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=\2"', $content, -1, $nbrep); 285 // <img src="viewimage.php/modulepart=medias&file=image.png" => <img src="dolibarr/viewimage.php/modulepart=medias&file=image.png" 286 $content = preg_replace('/(<img[^>]*src=")(\/?viewimage\.php)/', '\1!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content, -1, $nbrep); 287 288 // action="newpage.php" => action="dolibarr/website/index.php?website=...&pageref=newpage 289 $content = preg_replace('/(action=")\/?([^:\"]*)(\.php\")/', '\1!~!~!~'.DOL_URL_ROOT.'/public/website/index.php?website='.$website->ref.'&pageref=\2"', $content, -1, $nbrep); 290 291 // Fix relative URL 292 $content = str_replace('src="!~!~!~/viewimage.php', 'src="!~!~!~'.DOL_URL_ROOT.'/viewimage.php', $content); 293 $content = str_replace('href="!~!~!~/document.php', 'href="!~!~!~'.DOL_URL_ROOT.'/document.php', $content); 294 295 // Remove the protection tag !~!~!~, but only if this is the parent page and not an include 296 if (empty($includehtmlcontentopened)) { 297 $content = str_replace('!~!~!~', '', $content); 298 } 299 } else // REPLACEMENT OF LINKS When page called from virtual host 300 { 301 $symlinktomediaexists = 1; 302 if ($website->virtualhost) { 303 $content = preg_replace('/^(<link[^>]*rel="canonical" href=")\//m', '\1'.$website->virtualhost.'/', $content, -1, $nbrep); 304 } 305 //print 'rrrrrrrrr'.$website->virtualhost.$content; 306 307 308 // Make a change into HTML code to allow to include images from medias directory correct with direct link for virtual server 309 // <img alt="" src="/dolibarr_dev/htdocs/viewimage.php?modulepart=medias&entity=1&file=image/ldestailleur_166x166.jpg" style="height:166px; width:166px" /> 310 // become 311 // <img alt="" src="'.$urlwithroot.'/medias/image/ldestailleur_166x166.jpg" style="height:166px; width:166px" /> 312 if (!$symlinktomediaexists) 313 { 314 // <img src="image.png... => <img src="medias/image.png... 315 $content = preg_replace('/(<img[^>]*src=")\/?image\//', '\1/wrapper.php?modulepart=medias&file=medias/image/', $content, -1, $nbrep); 316 $content = preg_replace('/(url\(["\']?)\/?image\//', '\1/wrapper.php?modulepart=medias&file=medias/image/', $content, -1, $nbrep); 317 318 $content = preg_replace('/(<script[^>]*src=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep); 319 $content = preg_replace('/(<a[^>]*href=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep); 320 321 $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep); 322 $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep); 323 $content = preg_replace('/(url\(["\']?)[^\)]*viewimage\.php([^\)]*)modulepart=medias([^\)]*)file=([^\)]*)(["\']?\))/', '\1/wrapper.php\2modulepart=medias\3file=\4\5', $content, -1, $nbrep); 324 325 $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep); 326 $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep); 327 $content = preg_replace('/(url\(["\']?)[^\)]*viewimage\.php([^\)]*)hashp=([^\)]*)(["\']?\))/', '\1/wrapper.php\2hashp\3\4', $content, -1, $nbrep); 328 329 $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=mycompany([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=mycompany\3file=\4\5', $content, -1, $nbrep); 330 331 // If some links to documents or viewimage remains, we replace with wrapper 332 $content = preg_replace('/(<img[^>]*src=")\/?viewimage\.php/', '\1/wrapper.php', $content, -1, $nbrep); 333 $content = preg_replace('/(<a[^>]*href=")\/?documents\.php/', '\1/wrapper.php', $content, -1, $nbrep); 334 } else { 335 // <img src="image.png... => <img src="medias/image.png... 336 $content = preg_replace('/(<img[^>]*src=")\/?image\//', '\1/medias/image/', $content, -1, $nbrep); 337 $content = preg_replace('/(url\(["\']?)\/?image\//', '\1/medias/image/', $content, -1, $nbrep); 338 339 $content = preg_replace('/(<script[^>]*src=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep); 340 $content = preg_replace('/(<a[^>]*href=")[^\"]*document\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep); 341 342 $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep); 343 $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=medias([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/medias/\4\5', $content, -1, $nbrep); 344 $content = preg_replace('/(url\(["\']?)[^\)]*viewimage\.php([^\)]*)modulepart=medias([^\)]*)file=([^\)]*)(["\']?\))/', '\1/medias/\4\5', $content, -1, $nbrep); 345 346 $content = preg_replace('/(<a[^>]*href=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep); 347 $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)hashp=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep); 348 $content = preg_replace('/(url\(["\']?)[^\)]*viewimage\.php([^\)]*)hashp=([^\)]*)(["\']?\))/', '\1/wrapper.php\2hashp=\3\4', $content, -1, $nbrep); 349 350 $content = preg_replace('/(<img[^>]*src=")[^\"]*viewimage\.php([^\"]*)modulepart=mycompany([^\"]*)file=([^\"]*)("[^>]*>)/', '\1/wrapper.php\2modulepart=mycompany\3file=\4\5', $content, -1, $nbrep); 351 352 // If some links to documents or viewimage remains, we replace with wrapper 353 $content = preg_replace('/(<img[^>]*src=")\/?viewimage\.php/', '\1/wrapper.php', $content, -1, $nbrep); 354 $content = preg_replace('/(<a[^>]*href=")\/?document\.php/', '\1/wrapper.php', $content, -1, $nbrep); 355 } 356 } 357 358 $content = str_replace(' contenteditable="true"', ' contenteditable="false"', $content); 359 360 if (!empty($conf->global->WEBSITE_ADD_CSS_TO_BODY)) { 361 $content = str_replace('<body id="bodywebsite" class="bodywebsite', '<body id="bodywebsite" class="bodywebsite '.$conf->global->WEBSITE_ADD_CSS_TO_BODY, $content); 362 } 363 364 dol_syslog("dolWebsiteOutput end"); 365 366 print $content; 367} 368 369 370/** 371 * Format img tags to introduce viewimage on img src. 372 * 373 * @param string $content Content string 374 * @return void 375 * @see dolWebsiteOutput() 376 */ 377/* 378function dolWebsiteSaveContent($content) 379{ 380 global $db, $langs, $conf, $user; 381 global $dolibarr_main_url_root, $dolibarr_main_data_root; 382 383 //dol_syslog("dolWebsiteSaveContent start (mode=".(defined('USEDOLIBARRSERVER')?'USEDOLIBARRSERVER':'').')'); 384 385 // Define $urlwithroot 386 $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); 387 $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file 388 //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current 389 390 //$content = preg_replace('/(<img.*src=")(?!(http|'.preg_quote(DOL_URL_ROOT,'/').'\/viewimage))/', '\1'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file=', $content, -1, $nbrep); 391 392 return $content; 393} 394*/ 395 396 397/** 398 * Make a redirect to another container. 399 * 400 * @param string $containerref Ref of container to redirect to (Example: 'mypage' or 'mypage.php'). 401 * @param string $containeraliasalt Ref of alternative aliases to redirect to. 402 * @param int $containerid Id of container. 403 * @param int $permanent 0=Use temporary redirect 302, 1=Use permanent redirect 301 404 * @return void 405 */ 406function redirectToContainer($containerref, $containeraliasalt = '', $containerid = 0, $permanent = 0) 407{ 408 global $db, $website; 409 410 $newurl = ''; 411 $result = 0; 412 413 // We make redirect using the alternative alias, we must find the real $containerref 414 if ($containeraliasalt) 415 { 416 include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; 417 $tmpwebsitepage = new WebsitePage($db); 418 $result = $tmpwebsitepage->fetch(0, $website->id, '', $containeraliasalt); 419 if ($result > 0) 420 { 421 $containerref = $tmpwebsitepage->pageurl; 422 } else { 423 print "Error, page contains a redirect to the alternative alias '".$containeraliasalt."' that does not exists in web site (".$website->id." / ".$website->ref.")"; 424 exit; 425 } 426 } 427 428 if (defined('USEDOLIBARREDITOR')) 429 { 430 /*print '<div class="margintoponly marginleftonly">'; 431 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."; 432 print '</div>';*/ 433 $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."; 434 setEventMessages($text, null, 'warnings', 'WEBSITEREDIRECTDISABLED'.$containerref); 435 return; 436 } 437 438 if (defined('USEDOLIBARRSERVER')) // When page called from Dolibarr server 439 { 440 // Check new container exists 441 if (!$containeraliasalt) // If containeraliasalt set, we already did the test 442 { 443 include_once DOL_DOCUMENT_ROOT.'/website/class/websitepage.class.php'; 444 $tmpwebsitepage = new WebsitePage($db); 445 $result = $tmpwebsitepage->fetch(0, $website->id, $containerref); 446 unset($tmpwebsitepage); 447 } 448 if ($result > 0) 449 { 450 $currenturi = $_SERVER["REQUEST_URI"]; 451 $regtmp = array(); 452 if (preg_match('/&pageref=([^&]+)/', $currenturi, $regtmp)) 453 { 454 if ($regtmp[0] == $containerref) 455 { 456 print "Error, page with uri '.$currenturi.' try a redirect to the same alias page '".$containerref."' in web site '".$website->ref."'"; 457 exit; 458 } else { 459 $newurl = preg_replace('/&pageref=([^&]+)/', '&pageref='.$containerref, $currenturi); 460 } 461 } else { 462 $newurl = $currenturi.'&pageref='.urlencode($containerref); 463 } 464 } 465 } else // When page called from virtual host server 466 { 467 $newurl = '/'.$containerref.'.php'; 468 } 469 470 if ($newurl) 471 { 472 if ($permanent) { 473 header("Status: 301 Moved Permanently", false, 301); 474 } 475 header("Location: ".$newurl); 476 exit; 477 } else { 478 print "Error, page contains a redirect to the alias page '".$containerref."' that does not exists in web site (".$website->id." / ".$website->ref.")"; 479 exit; 480 } 481} 482 483 484/** 485 * Clean an HTML page to report only content, so we can include it into another page. 486 * It outputs content of file sanitized from html and body part. 487 * 488 * @param string $containerref Path to file to include (must be a page from website root. Example: 'mypage.php' means 'mywebsite/mypage.php') 489 * @return void 490 */ 491function includeContainer($containerref) 492{ 493 global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running included containers. 494 global $includehtmlcontentopened; 495 global $websitekey, $websitepagefile; 496 497 $MAXLEVEL = 20; 498 499 if (!preg_match('/\.php$/i', $containerref)) $containerref .= '.php'; 500 501 $fullpathfile = DOL_DATA_ROOT.'/website/'.$websitekey.'/'.$containerref; 502 503 if (empty($includehtmlcontentopened)) $includehtmlcontentopened = 0; 504 $includehtmlcontentopened++; 505 if ($includehtmlcontentopened > $MAXLEVEL) 506 { 507 print 'ERROR: RECURSIVE CONTENT LEVEL. Depth of recursive call is more than the limit of '.$MAXLEVEL.".\n"; 508 return; 509 } 510 511 //dol_syslog("Include container ".$containerref.' includehtmlcontentopened='.$includehtmlcontentopened); 512 513 // file_get_contents is not possible. We must execute code with include 514 //$content = file_get_contents($fullpathfile); 515 //print preg_replace(array('/^.*<body[^>]*>/ims','/<\/body>.*$/ims'), array('', ''), $content);*/ 516 517 ob_start(); 518 $res = include $fullpathfile; // Include because we want to execute code content 519 $tmpoutput = ob_get_contents(); 520 ob_end_clean(); 521 522 print "\n".'<!-- include '.$websitekey.'/'.$containerref.(is_object($websitepage) ? ' parent id='.$websitepage->id : '').' level = '.$includehtmlcontentopened.' -->'."\n"; 523 print preg_replace(array('/^.*<body[^>]*>/ims', '/<\/body>.*$/ims'), array('', ''), $tmpoutput); 524 525 if (!$res) 526 { 527 print 'ERROR: FAILED TO INCLUDE PAGE '.$containerref.".\n"; 528 } 529 530 $includehtmlcontentopened--; 531} 532 533/** 534 * Return HTML content to add structured data for an article, news or Blog Post. 535 * Use the json-ld format. 536 * 537 * @param string $type 'blogpost', 'product', 'software', 'organization', 'qa', ... 538 * @param array $data Array of data parameters for structured data 539 * @return string HTML content 540 */ 541function getStructuredData($type, $data = array()) 542{ 543 global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs, $pagelangs; // Very important. Required to have var available when running inluded containers. 544 545 $type = strtolower($type); 546 547 if ($type == 'software') 548 { 549 $ret = '<!-- Add structured data for entry in a software annuary -->'."\n"; 550 $ret .= '<script type="application/ld+json">'."\n"; 551 $ret .= '{ 552 "@context": "https://schema.org", 553 "@type": "SoftwareApplication", 554 "name": "'.dol_escape_json($data['name']).'", 555 "operatingSystem": "'.dol_escape_json($data['os']).'", 556 "applicationCategory": "https://schema.org/'.$data['applicationCategory'].'",'; 557 if (!empty($data['ratingcount'])) { 558 $ret .= ' 559 "aggregateRating": { 560 "@type": "AggregateRating", 561 "ratingValue": "'.$data['ratingvalue'].'", 562 "ratingCount": "'.$data['ratingcount'].'" 563 },'; 564 } 565 $ret .= ' 566 "offers": { 567 "@type": "Offer", 568 "price": "'.$data['price'].'", 569 "priceCurrency": "'.($data['currency'] ? $data['currency'] : $conf->currency).'" 570 } 571 }'."\n"; 572 $ret .= '</script>'."\n"; 573 } elseif ($type == 'organization') 574 { 575 $companyname = $mysoc->name; 576 $url = $mysoc->url; 577 578 $ret = '<!-- Add structured data for organization -->'."\n"; 579 $ret .= '<script type="application/ld+json">'."\n"; 580 $ret .= '{ 581 "@context": "https://schema.org", 582 "@type": "Organization", 583 "name": "'.dol_escape_json($data['name'] ? $data['name'] : $companyname).'", 584 "url": "'.dol_escape_json($data['url'] ? $data['url'] : $url).'", 585 "logo": "'.($data['logo'] ? dol_escape_json($data['logo']) : '/wrapper.php?modulepart=mycompany&file=logos%2F'.urlencode($mysoc->logo)).'", 586 "contactPoint": { 587 "@type": "ContactPoint", 588 "contactType": "Contact", 589 "email": "'.dol_escape_json($data['email'] ? $data['email'] : $mysoc->email).'" 590 }'."\n"; 591 if (is_array($mysoc->socialnetworks) && count($mysoc->socialnetworks) > 0) { 592 $ret .= ",\n"; 593 $ret .= '"sameAs": ['; 594 $i = 0; 595 foreach ($mysoc->socialnetworks as $key => $value) { 596 if ($key == 'linkedin') { 597 $ret .= '"https://www.'.$key.'.com/company/'.dol_escape_json($value).'"'; 598 } elseif ($key == 'youtube') { 599 $ret .= '"https://www.'.$key.'.com/user/'.dol_escape_json($value).'"'; 600 } else { 601 $ret .= '"https://www.'.$key.'.com/'.dol_escape_json($value).'"'; 602 } 603 $i++; 604 if ($i < count($mysoc->socialnetworks)) $ret .= ', '; 605 } 606 $ret .= ']'."\n"; 607 } 608 $ret .= '}'."\n"; 609 $ret .= '</script>'."\n"; 610 } elseif ($type == 'blogpost') 611 { 612 if (!empty($websitepage->author_alias)) 613 { 614 //include_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; 615 //$tmpuser = new User($db); 616 //$restmpuser = $tmpuser->fetch($websitepage->fk_user_creat); 617 618 $pageurl = $websitepage->pageurl; 619 $title = $websitepage->title; 620 $image = $websitepage->image; 621 $companyname = $mysoc->name; 622 $description = $websitepage->description; 623 624 $pageurl = str_replace('__WEBSITE_KEY__', $website->ref, $pageurl); 625 $title = str_replace('__WEBSITE_KEY__', $website->ref, $title); 626 $image = '/medias/'.str_replace('__WEBSITE_KEY__', $website->ref, $image); 627 $companyname = str_replace('__WEBSITE_KEY__', $website->ref, $companyname); 628 $description = str_replace('__WEBSITE_KEY__', $website->ref, $description); 629 630 $ret = '<!-- Add structured data for blog post -->'."\n"; 631 $ret .= '<script type="application/ld+json">'."\n"; 632 $ret .= '{ 633 "@context": "https://schema.org", 634 "@type": "NewsArticle", 635 "mainEntityOfPage": { 636 "@type": "WebPage", 637 "@id": "'.dol_escape_json($pageurl).'" 638 }, 639 "headline": "'.dol_escape_json($title).'", 640 "image": [ 641 "'.dol_escape_json($image).'" 642 ], 643 "dateCreated": "'.dol_print_date($websitepage->date_creation, 'dayhourrfc').'", 644 "datePublished": "'.dol_print_date($websitepage->date_creation, 'dayhourrfc').'", 645 "dateModified": "'.dol_print_date($websitepage->date_modification, 'dayhourrfc').'", 646 "author": { 647 "@type": "Person", 648 "name": "'.dol_escape_json($websitepage->author_alias).'" 649 }, 650 "publisher": { 651 "@type": "Organization", 652 "name": "'.dol_escape_json($companyname).'", 653 "logo": { 654 "@type": "ImageObject", 655 "url": "/wrapper.php?modulepart=mycompany&file=logos%2F'.urlencode($mysoc->logo).'" 656 } 657 },'."\n"; 658 if ($websitepage->keywords) { 659 $ret .= '"keywords": ['; 660 $i = 0; 661 $arrayofkeywords = explode(',', $websitepage->keywords); 662 foreach ($arrayofkeywords as $keyword) { 663 $ret .= '"'.dol_escape_json($keyword).'"'; 664 $i++; 665 if ($i < count($arrayofkeywords)) $ret .= ', '; 666 } 667 $ret .= '],'."\n"; 668 } 669 $ret .= '"description": "'.dol_escape_json($description).'"'; 670 $ret .= "\n".'}'."\n"; 671 $ret .= '</script>'."\n"; 672 } 673 } elseif ($type == 'product') 674 { 675 $ret = '<!-- Add structured data for product -->'."\n"; 676 $ret .= '<script type="application/ld+json">'."\n"; 677 $ret .= '{ 678 "@context": "https://schema.org/", 679 "@type": "Product", 680 "name": "'.dol_escape_json($data['label']).'", 681 "image": [ 682 "'.dol_escape_json($data['image']).'", 683 ], 684 "description": "'.dol_escape_json($data['description']).'", 685 "sku": "'.dol_escape_json($data['ref']).'", 686 "brand": { 687 "@type": "Thing", 688 "name": "'.dol_escape_json($data['brand']).'" 689 }, 690 "author": { 691 "@type": "Person", 692 "name": "'.dol_escape_json($data['author']).'" 693 } 694 }, 695 "offers": { 696 "@type": "Offer", 697 "url": "https://example.com/anvil", 698 "priceCurrency": "'.($data['currency'] ? $data['currency'] : $conf->currency).'", 699 "price": "'.$data['price'].'", 700 "itemCondition": "https://schema.org/UsedCondition", 701 "availability": "https://schema.org/InStock", 702 "seller": { 703 "@type": "Organization", 704 "name": "'.dol_escape_json($mysoc->name).'" 705 } 706 } 707 }'."\n"; 708 $ret .= '</script>'."\n"; 709 } elseif ($type == 'qa') 710 { 711 $ret = '<!-- Add structured data for QA -->'."\n"; 712 $ret .= '<script type="application/ld+json">'."\n"; 713 $ret .= '{ 714 "@context": "https://schema.org/", 715 "@type": "QAPage", 716 "mainEntity": { 717 "@type": "Question", 718 "name": "'.dol_escape_json($data['name']).'", 719 "text": "'.dol_escape_json($data['name']).'", 720 "answerCount": 1, 721 "author": { 722 "@type": "Person", 723 "name": "'.dol_escape_json($data['author']).'" 724 } 725 "acceptedAnswer": { 726 "@type": "Answer", 727 "text": "'.dol_escape_json(dol_string_nohtmltag(dolStripPhpCode($data['description']))).'", 728 "author": { 729 "@type": "Person", 730 "name": "'.dol_escape_json($data['author']).'" 731 } 732 } 733 } 734 }'."\n"; 735 $ret .= '</script>'."\n"; 736 } 737 return $ret; 738} 739 740/** 741 * Return HTML content to add structured data for an article, news or Blog Post. 742 * 743 * @return string HTML content 744 */ 745function getSocialNetworkSharingLinks() 746{ 747 global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers. 748 749 $out = '<!-- section for social network sharing of page -->'."\n"; 750 751 if ($website->virtualhost) { 752 $fullurl = $website->virtualhost.'/'.$websitepage->pageurl.'.php'; 753 $hashtags = trim(join(' #', array_map('trim', explode(',', $websitepage->keywords)))); 754 755 $out .= '<div class="dol-social-share">'."\n"; 756 757 // Twitter 758 $out .= '<div class="dol-social-share-tw">'."\n"; 759 $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>'; 760 $out .= '<script>!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>'; 761 $out .= '</div>'."\n"; 762 763 // Reddit 764 $out .= '<div class="dol-social-share-reddit">'."\n"; 765 $out .= '<a href="https://www.reddit.com/submit" target="_blank" onclick="window.location = \'https://www.reddit.com/submit?url='.$fullurl.'\'; return false">'; 766 $out .= '<span class="dol-social-share-reddit-span">Reddit</span>'; 767 $out .= '</a>'; 768 $out .= '</div>'."\n"; 769 770 // Facebook 771 $out .= '<div class="dol-social-share-fbl">'."\n"; 772 $out .= '<div id="fb-root"></div>'."\n"; 773 $out .= '<script>(function(d, s, id) { 774 var js, fjs = d.getElementsByTagName(s)[0]; 775 if (d.getElementById(id)) return; 776 js = d.createElement(s); js.id = id; 777 js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.0&appId=dolibarr.org"; 778 fjs.parentNode.insertBefore(js, fjs); 779 }(document, \'script\', \'facebook-jssdk\'));</script> 780 <fb:like 781 href="'.$fullurl.'" 782 layout="button_count" 783 show_faces="false" 784 width="90" 785 colorscheme="light" 786 share="1" 787 action="like" ></fb:like>'."\n"; 788 $out .= '</div>'."\n"; 789 790 $out .= "\n</div>\n"; 791 } 792 else { 793 $out .= '<!-- virtual host not defined in CMS. No way to add sharing buttons -->'."\n"; 794 } 795 $out .= '<!-- section end for social network sharing of page -->'."\n"; 796 797 return $out; 798} 799 800/** 801 * Return list of containers object that match a criteria. 802 * WARNING: This function can be used by websites. 803 * 804 * @param string $type Type of container to search into (Example: '', 'page', 'blogpost', 'page,blogpost', ...) 805 * @param string $algo Algorithm used for search (Example: 'meta' is searching into meta information like title and description, 'content', 'sitefiles', or any combination 'meta,content,...') 806 * @param string $searchstring Search string 807 * @param int $max Max number of answers 808 * @param string $sortfield Sort Fields 809 * @param string $sortorder Sort order ('DESC' or 'ASC') 810 * @param string $langcode Language code ('' or 'en', 'fr', 'es', ...) 811 * @param array $otherfilters Other filters 812 * @param int $status 0 or 1, or -1 for both 813 * @return string HTML content 814 */ 815function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $sortfield = 'date_creation', $sortorder = 'DESC', $langcode = '', $otherfilters = 'null', $status = 1) 816{ 817 global $conf, $db, $hookmanager, $langs, $mysoc, $user, $website, $websitepage, $weblangs; // Very important. Required to have var available when running inluded containers. 818 819 $error = 0; 820 $arrayresult = array('code'=>'', 'list'=>array()); 821 822 if (!is_object($weblangs)) $weblangs = $langs; 823 824 if (empty($searchstring) && empty($type) && empty($langcode) && empty($otherfilters)) 825 { 826 $error++; 827 $arrayresult['code'] = 'KO'; 828 $arrayresult['message'] = $weblangs->trans("EmptySearchString"); 829 } elseif ($searchstring && dol_strlen($searchstring) < 2) { 830 $weblangs->load("errors"); 831 $error++; 832 $arrayresult['code'] = 'KO'; 833 $arrayresult['message'] = $weblangs->trans("ErrorSearchCriteriaTooSmall"); 834 } else { 835 $tmparrayoftype = explode(',', $type); 836 /*foreach ($tmparrayoftype as $tmptype) { 837 if (!in_array($tmptype, array('', 'page', 'blogpost'))) { 838 $error++; 839 $arrayresult['code'] = 'KO'; 840 $arrayresult['message'] = 'Bad value for parameter type'; 841 break; 842 } 843 }*/ 844 } 845 846 $searchdone = 0; 847 $found = 0; 848 849 if (!$error && (empty($max) || ($found < $max)) && (preg_match('/meta/', $algo) || preg_match('/content/', $algo))) 850 { 851 $sql = 'SELECT wp.rowid FROM '.MAIN_DB_PREFIX.'website_page as wp'; 852 if (is_array($otherfilters) && !empty($otherfilters['category'])) { 853 $sql .= ', '.MAIN_DB_PREFIX.'categorie_website_page as cwp'; 854 } 855 $sql .= " WHERE wp.fk_website = ".$website->id; 856 if ($status >= 0) { 857 $sql .= " AND wp.status = ".$status; 858 } 859 if ($langcode) { 860 $sql .= " AND wp.lang ='".$db->escape($langcode)."'"; 861 } 862 if ($type) { 863 $tmparrayoftype = explode(',', $type); 864 $typestring = ''; 865 foreach ($tmparrayoftype as $tmptype) { 866 $typestring .= ($typestring ? ", " : "")."'".$db->escape(trim($tmptype))."'"; 867 } 868 $sql .= " AND wp.type_container IN (".$typestring.")"; 869 } 870 $sql .= " AND ("; 871 $searchalgo = ''; 872 if (preg_match('/meta/', $algo)) 873 { 874 $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.title LIKE '%".$db->escape($searchstring)."%' OR wp.description LIKE '%".$db->escape($searchstring)."%'"; 875 $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.keywords LIKE '".$db->escape($searchstring).",%' OR wp.keywords LIKE '% ".$db->escape($searchstring)."%'"; // TODO Use a better way to scan keywords 876 } 877 if (preg_match('/content/', $algo)) 878 { 879 $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.content LIKE '%".$db->escape($searchstring)."%'"; 880 } 881 $sql .= $searchalgo; 882 if (is_array($otherfilters) && !empty($otherfilters['category'])) { 883 $sql .= ' AND cwp.fk_website_page = wp.rowid AND cwp.fk_categorie = '.((int) $otherfilters['category']); 884 } 885 $sql .= ")"; 886 $sql .= $db->order($sortfield, $sortorder); 887 $sql .= $db->plimit($max); 888 889 $resql = $db->query($sql); 890 if ($resql) 891 { 892 $i = 0; 893 while (($obj = $db->fetch_object($resql)) && ($i < $max || $max == 0)) 894 { 895 if ($obj->rowid > 0) 896 { 897 $tmpwebsitepage = new WebsitePage($db); 898 $tmpwebsitepage->fetch($obj->rowid); 899 if ($tmpwebsitepage->id > 0) $arrayresult['list'][$obj->rowid] = $tmpwebsitepage; 900 $found++; 901 } 902 $i++; 903 } 904 } else { 905 $error++; 906 $arrayresult['code'] = $db->lasterrno(); 907 $arrayresult['message'] = $db->lasterror(); 908 } 909 910 $searchdone = 1; 911 } 912 913 if (!$error && (empty($max) || ($found < $max)) && (preg_match('/sitefiles/', $algo))) 914 { 915 global $dolibarr_main_data_root; 916 917 $pathofwebsite = $dolibarr_main_data_root.'/website/'.$website->ref; 918 $filehtmlheader = $pathofwebsite.'/htmlheader.html'; 919 $filecss = $pathofwebsite.'/styles.css.php'; 920 $filejs = $pathofwebsite.'/javascript.js.php'; 921 $filerobot = $pathofwebsite.'/robots.txt'; 922 $filehtaccess = $pathofwebsite.'/.htaccess'; 923 $filemanifestjson = $pathofwebsite.'/manifest.json.php'; 924 $filereadme = $pathofwebsite.'/README.md'; 925 926 $filecontent = file_get_contents($filehtmlheader); 927 if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) 928 { 929 $arrayresult['list'][] = array('type'=>'website_htmlheadercontent'); 930 } 931 932 $filecontent = file_get_contents($filecss); 933 if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) 934 { 935 $arrayresult['list'][] = array('type'=>'website_csscontent'); 936 } 937 938 $filecontent = file_get_contents($filejs); 939 if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) 940 { 941 $arrayresult['list'][] = array('type'=>'website_jscontent'); 942 } 943 944 $filerobot = file_get_contents($filerobot); 945 if ((empty($max) || ($found < $max)) && preg_match('/'.preg_quote($searchstring, '/').'/', $filecontent)) 946 { 947 $arrayresult['list'][] = array('type'=>'website_robotcontent'); 948 } 949 950 $searchdone = 1; 951 } 952 953 if (!$error) 954 { 955 if ($searchdone) 956 { 957 $arrayresult['code'] = 'OK'; 958 if (empty($arrayresult['list'])) 959 { 960 $arrayresult['code'] = 'KO'; 961 $arrayresult['message'] = $weblangs->trans("NoRecordFound"); 962 } 963 } else { 964 $error++; 965 $arrayresult['code'] = 'KO'; 966 $arrayresult['message'] = 'No supported algorithm found'; 967 } 968 } 969 970 return $arrayresult; 971} 972 973/** 974 * Download all images found into page content $tmp. 975 * If $modifylinks is set, links to images will be replace with a link to viewimage wrapper. 976 * 977 * @param Website $object Object website 978 * @param WebsitePage $objectpage Object website page 979 * @param string $urltograb URL to grab (exemple: http://www.nltechno.com/ or http://www.nltechno.com/dir1/ or http://www.nltechno.com/dir1/mapage1) 980 * @param string $tmp Content to parse 981 * @param string $action Var $action 982 * @param string $modifylinks 0=Do not modify content, 1=Replace links with a link to viewimage 983 * @param int $grabimages 0=Do not grab images, 1=Grab images 984 * @param string $grabimagesinto 'root' or 'subpage' 985 * @return void 986 */ 987function getAllImages($object, $objectpage, $urltograb, &$tmp, &$action, $modifylinks = 0, $grabimages = 1, $grabimagesinto = 'subpage') 988{ 989 global $conf; 990 991 $error = 0; 992 993 dol_syslog("Call getAllImages with grabimagesinto=".$grabimagesinto); 994 995 $alreadygrabbed = array(); 996 997 if (preg_match('/\/$/', $urltograb)) $urltograb .= '.'; 998 $urltograb = dirname($urltograb); // So urltograb is now http://www.nltechno.com or http://www.nltechno.com/dir1 999 1000 // Search X in "img...src=X" 1001 $regs = array(); 1002 preg_match_all('/<img([^\.\/]+)src="([^>"]+)"([^>]*)>/i', $tmp, $regs); 1003 1004 foreach ($regs[0] as $key => $val) 1005 { 1006 if (preg_match('/^data:image/i', $regs[2][$key])) continue; // We do nothing for such images 1007 1008 if (preg_match('/^\//', $regs[2][$key])) 1009 { 1010 $urltograbdirrootwithoutslash = getRootURLFromURL($urltograb); 1011 $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot 1012 } else { 1013 $urltograbbis = $urltograb.'/'.$regs[2][$key]; // We use dir of grabbed file 1014 } 1015 1016 $linkwithoutdomain = $regs[2][$key]; 1017 $dirforimages = '/'.$objectpage->pageurl; 1018 if ($grabimagesinto == 'root') $dirforimages = ''; 1019 1020 // Define $filetosave and $filename 1021 $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $regs[2][$key]) ? '' : '/').$regs[2][$key]; 1022 if (preg_match('/^http/', $regs[2][$key])) 1023 { 1024 $urltograbbis = $regs[2][$key]; 1025 $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]); 1026 $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain; 1027 } 1028 $filename = 'image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain; 1029 1030 // Clean the aa/bb/../cc into aa/cc 1031 $filetosave = preg_replace('/\/[^\/]+\/\.\./', '', $filetosave); 1032 $filename = preg_replace('/\/[^\/]+\/\.\./', '', $filename); 1033 1034 //var_dump($filetosave); 1035 //var_dump($filename); 1036 //exit; 1037 1038 if (empty($alreadygrabbed[$urltograbbis])) 1039 { 1040 if ($grabimages) 1041 { 1042 $tmpgeturl = getURLContent($urltograbbis); 1043 if ($tmpgeturl['curl_error_no']) 1044 { 1045 $error++; 1046 setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors'); 1047 $action = 'create'; 1048 } elseif ($tmpgeturl['http_code'] != '200') 1049 { 1050 $error++; 1051 setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors'); 1052 $action = 'create'; 1053 } else { 1054 $alreadygrabbed[$urltograbbis] = 1; // Track that file was alreay grabbed. 1055 1056 dol_mkdir(dirname($filetosave)); 1057 1058 $fp = fopen($filetosave, "w"); 1059 fputs($fp, $tmpgeturl['content']); 1060 fclose($fp); 1061 if (!empty($conf->global->MAIN_UMASK)) 1062 @chmod($filetosave, octdec($conf->global->MAIN_UMASK)); 1063 } 1064 } 1065 } 1066 1067 if ($modifylinks) 1068 { 1069 $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); 1070 } 1071 } 1072 1073 // Search X in "background...url(X)" 1074 preg_match_all('/background([^\.\/\(;]+)url\([\"\']?([^\)\"\']*)[\"\']?\)/i', $tmp, $regs); 1075 1076 foreach ($regs[0] as $key => $val) 1077 { 1078 if (preg_match('/^data:image/i', $regs[2][$key])) continue; // We do nothing for such images 1079 1080 if (preg_match('/^\//', $regs[2][$key])) 1081 { 1082 $urltograbdirrootwithoutslash = getRootURLFromURL($urltograb); 1083 $urltograbbis = $urltograbdirrootwithoutslash.$regs[2][$key]; // We use dirroot 1084 } else { 1085 $urltograbbis = $urltograb.'/'.$regs[2][$key]; // We use dir of grabbed file 1086 } 1087 1088 $linkwithoutdomain = $regs[2][$key]; 1089 1090 $dirforimages = '/'.$objectpage->pageurl; 1091 if ($grabimagesinto == 'root') $dirforimages = ''; 1092 1093 $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $regs[2][$key]) ? '' : '/').$regs[2][$key]; 1094 1095 if (preg_match('/^http/', $regs[2][$key])) 1096 { 1097 $urltograbbis = $regs[2][$key]; 1098 $linkwithoutdomain = preg_replace('/^https?:\/\/[^\/]+\//i', '', $regs[2][$key]); 1099 $filetosave = $conf->medias->multidir_output[$conf->entity].'/image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain; 1100 } 1101 1102 $filename = 'image/'.$object->ref.$dirforimages.(preg_match('/^\//', $linkwithoutdomain) ? '' : '/').$linkwithoutdomain; 1103 1104 // Clean the aa/bb/../cc into aa/cc 1105 $filetosave = preg_replace('/\/[^\/]+\/\.\./', '', $filetosave); 1106 $filename = preg_replace('/\/[^\/]+\/\.\./', '', $filename); 1107 1108 //var_dump($filetosave); 1109 //var_dump($filename); 1110 //exit; 1111 1112 if (empty($alreadygrabbed[$urltograbbis])) 1113 { 1114 if ($grabimages) 1115 { 1116 $tmpgeturl = getURLContent($urltograbbis); 1117 if ($tmpgeturl['curl_error_no']) 1118 { 1119 $error++; 1120 setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['curl_error_msg'], null, 'errors'); 1121 $action = 'create'; 1122 } elseif ($tmpgeturl['http_code'] != '200') 1123 { 1124 $error++; 1125 setEventMessages('Error getting '.$urltograbbis.': '.$tmpgeturl['http_code'], null, 'errors'); 1126 $action = 'create'; 1127 } else { 1128 $alreadygrabbed[$urltograbbis] = 1; // Track that file was alreay grabbed. 1129 1130 dol_mkdir(dirname($filetosave)); 1131 1132 $fp = fopen($filetosave, "w"); 1133 fputs($fp, $tmpgeturl['content']); 1134 fclose($fp); 1135 if (!empty($conf->global->MAIN_UMASK)) 1136 @chmod($filetosave, octdec($conf->global->MAIN_UMASK)); 1137 } 1138 } 1139 } 1140 1141 if ($modifylinks) 1142 { 1143 $tmp = preg_replace('/'.preg_quote($regs[0][$key], '/').'/i', 'background'.$regs[1][$key].'url("'.DOL_URL_ROOT.'/viewimage.php?modulepart=medias&file='.$filename.'")', $tmp); 1144 } 1145 } 1146} 1147