website.lib.php 56 KB

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