PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/ww.admin/admin_libs.php

http://kv-webme.googlecode.com/
PHP | 654 lines | 516 code | 18 blank | 120 comment | 35 complexity | 2537544a8a98572a54e436212971bccb MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, BSD-3-Clause, BSD-2-Clause, Apache-2.0, MIT, LGPL-2.1
  1. <?php
  2. /**
  3. * admin libs
  4. *
  5. * PHP version 5.2
  6. *
  7. * @category None
  8. * @package None
  9. * @author Kae Verens <kae@kvsites.ie>
  10. * @license GPL 2.0
  11. * @link http://kvsites.ie/
  12. */
  13. $scripts=array();
  14. $scripts_inline=array();
  15. // { built-in page types
  16. $pagetypes=array(
  17. array(0, 'normal'),
  18. array(1, 'redirect'),
  19. array(9, 'table of contents'),
  20. array(5, 'search results'),
  21. array(4, 'page summaries')
  22. );
  23. // }
  24. // { function Core_adminSideMenu
  25. /**
  26. * generate HTML for a menu
  27. *
  28. * @param array $list the list of pages to link to
  29. * @param string $this the current page
  30. *
  31. * @return null
  32. */
  33. function Core_adminSideMenu($list, $this='') {
  34. $arr=array();
  35. foreach ($list as $key=>$val) {
  36. if ($val==$this) {
  37. $arr[]='<a href="'.$val.'" class="thispage">'.__($key, 'menu').'</a>';
  38. }
  39. else {
  40. $arr[]='<a href="'.$val.'">'.__($key, 'menu').'</a>';
  41. }
  42. }
  43. return '<div class="sub-nav">'.join('', $arr).'</div>';
  44. }
  45. // }
  46. // { Core_fixImageResizes
  47. /**
  48. * check images to see if they are really as large as the HTML says
  49. *
  50. * @param string $src the HTML source to check
  51. *
  52. * @return string the "fixed" source
  53. */
  54. function Core_fixImageResizes($src) {
  55. // checks for image resizes done with HTML parameters or inline CSS
  56. // and redirects those images to pre-resized versions held elsewhere
  57. preg_match_all('/<img [^>]*>/im', $src, $matches);
  58. if (!count($matches)) {
  59. return $src;
  60. }
  61. foreach ($matches[0] as $match) {
  62. $width=0;
  63. $height=0;
  64. if (preg_match('#width="[0-9]*"#i', $match)
  65. && preg_match('/height="[0-9]*"/i', $match)
  66. ) {
  67. $width=preg_replace('#.*width="([0-9]*)".*#i', '\1', $match);
  68. $height=preg_replace('#.*height="([0-9]*)".*#i', '\1', $match);
  69. }
  70. else if (preg_match('/style="[^"]*width: *[0-9]*px/i', $match)
  71. && preg_match('/style="[^"]*height: *[0-9]*px/i', $match)
  72. ) {
  73. $width= preg_replace(
  74. '#.*style="([^"]*[^-]width|width): *([0-9]*)px.*#i',
  75. '\2',
  76. $match
  77. );
  78. $height=preg_replace(
  79. '#.*style="([^"]*[^-]height|height): *([0-9]*)px.*#i',
  80. '\2',
  81. $match
  82. );
  83. }
  84. if (!$width || !$height) {
  85. continue;
  86. }
  87. $imgsrc=preg_replace('#.*src="([^"]*)".*#i', '\1', $match);
  88. $dir=str_replace('/', '@_@', $imgsrc);
  89. // get absolute address of img (naive, but will work for most cases)
  90. if (!preg_match('/^http/i', $imgsrc)) {
  91. $imgsrc=USERBASE.'/'.$imgsrc;
  92. }
  93. if (!file_exists($imgsrc)) {
  94. continue;
  95. }
  96. list($x, $y)=getimagesize($imgsrc);
  97. if (!$x || !$y || ($x==$width && $y==$height)) {
  98. continue;
  99. }
  100. // create address of resized image and update HTML
  101. $ext=strtolower(preg_replace('/.*\./', '', $imgsrc));
  102. $newURL=WORKURL_IMAGERESIZES.$dir.'/'.$width.'x'.$height
  103. .($ext=='png'||$ext=='gif'?'.png':'.jpg');
  104. $newImgHTML=preg_replace('/(.*src=")[^"]*(".*)/i', "$1$newURL$2", $match);
  105. $src=str_replace($match, $newImgHTML, $src);
  106. // create cached image
  107. $imgdir=WORKDIR_IMAGERESIZES.$dir;
  108. if (!file_exists(WORKDIR_IMAGERESIZES)) {
  109. mkdir(WORKDIR_IMAGERESIZES);
  110. }
  111. if (!file_exists($imgdir)) {
  112. mkdir($imgdir);
  113. }
  114. $imgfile=$imgdir.'/'.$width.'x'.$height
  115. .($ext=='png'||$ext=='gif'?'.png':'.jpg');
  116. if (file_exists($imgfile)) {
  117. continue;
  118. }
  119. $str='convert "'.addslashes($imgsrc).'" -geometry '.$width.'x'.$height
  120. .' "'.$imgfile.'"';
  121. exec($str);
  122. }
  123. return $src;
  124. }
  125. // }
  126. // { Core_unfixImageResizes
  127. /**
  128. * replace any "fixed" images with the original image's src
  129. *
  130. * @param string $src the HTML to check
  131. *
  132. * @return string "unfixed" HTML
  133. */
  134. function Core_unfixImageResizes($src) {
  135. // replace resized images with their originals
  136. $count=preg_match_all(
  137. '#/f/.files/image_resizes/(@_@[^"]*)(/[^"]*)"#',
  138. $src,
  139. $matches
  140. );
  141. if (!$count) {
  142. return $src;
  143. }
  144. foreach ($matches[1] as $key=>$match) {
  145. $src=str_replace(
  146. '/f/.files/image_resizes/'.$match.$matches[2][$key],
  147. str_replace('@_@', '/', $match),
  148. $src
  149. );
  150. }
  151. return $src;
  152. }
  153. // }
  154. // { WW_getCSS
  155. /**
  156. * generate a list of external CSS scripts and build a <style> tag
  157. *
  158. * @return string the HTML
  159. */
  160. function WW_getCSS() {
  161. global $css_urls;
  162. $url='/css/';
  163. foreach ($css_urls as $s) {
  164. $url.='|'.$s;
  165. }
  166. $css_urls=array();
  167. return '<link rel="stylesheet" href="'.htmlspecialchars($url).'" />';
  168. }
  169. // }
  170. // { WW_getScripts
  171. /**
  172. * generate a list of external JS scripts and build a <script> tag
  173. *
  174. * @return string the HTML
  175. */
  176. function WW_getScripts() {
  177. global $scripts, $scripts_inline;
  178. if (!count($scripts)) {
  179. return '';
  180. }
  181. // { set up inline scripts
  182. // { set up admin vars
  183. $adminVars=(object)null;
  184. $rs=dbAll(
  185. 'select * from admin_vars where admin_id='.((int)$_SESSION['userdata']['id'])
  186. );
  187. if ($rs) {
  188. foreach ($rs as $r) {
  189. $adminVars->{$r['varname']}=$r['varvalue'];
  190. }
  191. }
  192. $scripts_inline[]='this.adminVars='.json_encode(
  193. $adminVars
  194. );
  195. // }
  196. // { list plugins
  197. $scripts_inline[]='this.webmePlugins='.json_encode(array_keys($GLOBALS['PLUGINS']));
  198. // }
  199. $scripts_inline[]='userdata={wasAdmin:1}'; // for translations
  200. $inline='<script>'.join(';', $scripts_inline).';</script>';
  201. // }
  202. // { set up external scripts
  203. $external=array();
  204. $local=array();
  205. $latest=0;
  206. foreach ($scripts as $script) {
  207. if (strpos($script, '//')!==false) {
  208. $external[]=$script;
  209. }
  210. else {
  211. if (strpos($script, '/')===false) {
  212. $script='/ww.plugins/'.$script.'/js.js';
  213. }
  214. elseif ($script{0}!='/') { // {
  215. $script='/ww.plugins/'.$script;
  216. }
  217. $local[]=$script;
  218. if (filemtime($_SERVER['DOCUMENT_ROOT'].$script)>$latest) {
  219. $latest=filemtime($_SERVER['DOCUMENT_ROOT'].$script);
  220. }
  221. }
  222. }
  223. $md5=md5(join('|', $local).'|'.$latest);
  224. if (!file_exists(USERBASE.'/ww.cache/admin/'.$md5)) {
  225. @mkdir(USERBASE.'/ww.cache/admin');
  226. foreach ($local as $file) {
  227. file_put_contents(
  228. USERBASE.'/ww.cache/admin/'.$md5,
  229. file_get_contents($_SERVER['DOCUMENT_ROOT'].$file).';',
  230. FILE_APPEND
  231. );
  232. }
  233. }
  234. $external=count($external)
  235. ?'<script src="'
  236. .join('"></script><script src="', $external).'"></script>'
  237. :'';
  238. // }
  239. return $external
  240. .'<script src="/ww.admin/js.php/'.$md5.'"></script>'
  241. .$inline;
  242. }
  243. // }
  244. // { ckeditor
  245. /**
  246. * output an RTE's HTML
  247. *
  248. * @param string $name name of the textarea to replace
  249. * @param string $value prefill the textarea with this value
  250. * @param int $height the height of the RTE to show
  251. * @param int $translatable is this editor a multi-lingual one
  252. *
  253. * @return string the HTML of the RTE
  254. */
  255. function ckeditor($name, $value='', $height=250, $translatable=0) {
  256. if (!$translatable) {
  257. return '<textarea style="width:100%;height:'.$height.'px" name="'
  258. .addslashes($name).'">'.htmlspecialchars($value).'</textarea>'
  259. ."<script>//<![CDATA[\n"
  260. .'$(function(){window.ckeditor_'.preg_replace('/[^a-zA-Z_]/', '', $name)
  261. .'=CKEDITOR.replace("'
  262. .str_replace(array('[',']'), array('\[','\]'), addslashes($name))
  263. .'",CKEditor_config);});'
  264. ."//]]></script>";
  265. }
  266. global $langs, $tabindex;
  267. if (count($langs)<2) {
  268. $lang=$langs[0];
  269. $v2=__FromJson($value, true, $lang['code']);
  270. return '<textarea style="width:100%;height:'.$height.'px" name="'
  271. .addslashes($name).'['.$lang['code'].']">'
  272. .htmlspecialchars($v2).'</textarea>'
  273. ."<script>//<![CDATA[\n".'$(function(){window.ckeditor_'
  274. .preg_replace('/[^a-zA-Z_]/', '', $name.'_'.$lang['code'])
  275. .'=CKEDITOR.replace("'
  276. .str_replace(
  277. array('[',']'),
  278. array('\[','\]'),
  279. addslashes($name.'['.$lang['code'].']')
  280. )
  281. .'",CKEditor_config);});'
  282. ."//]]></script>";
  283. }
  284. if (!$tabindex) {
  285. $tabindex=time();
  286. }
  287. $html='<div class="tabs mini-tabs"><ul>';
  288. foreach ($langs as $lang) {
  289. $html.='<li><a href="#tab-'.$tabindex.'-'.$lang['code'].'">'
  290. .$lang['name'].'</a></li>';
  291. }
  292. $html.='</ul>';
  293. foreach ($langs as $lang) {
  294. $v2=__FromJson($value, true, $lang['code']);
  295. $html.='<div id="tab-'.$tabindex.'-'.$lang['code'].'">'
  296. .'<textarea style="width:100%;height:'.$height.'px" name="'
  297. .addslashes($name).'['.$lang['code'].']">'.htmlspecialchars($v2).'</textarea>'
  298. ."<script>//<![CDATA[\n"
  299. .'$(function(){window.ckeditor_'
  300. .preg_replace('/[^a-zA-Z_]/', '', $name.'_'.$lang['code'])
  301. .'=CKEDITOR.replace("'
  302. .str_replace(
  303. array('[',']'),
  304. array('\[','\]'),
  305. addslashes($name.'['.$lang['code'].']')
  306. )
  307. .'",CKEditor_config);});'
  308. ."//]]></script>"
  309. .'</div>';
  310. }
  311. $html.='</div>';
  312. $tabindex++;
  313. return $html;
  314. }
  315. // }
  316. // { Core_sanitiseHtmlEssential
  317. /**
  318. * basically clean up HTML
  319. *
  320. * @param string $original_html the original HTML
  321. *
  322. * @return string sanitised HTML
  323. */
  324. function Core_sanitiseHtmlEssential($original_html) {
  325. $original_html = str_replace("\n", '{{N}}', $original_html);
  326. $original_html = str_replace("\r", '{{R}}', $original_html);
  327. do {
  328. $html = $original_html;
  329. // { clean old fckeditor stuff
  330. $html = preg_replace(
  331. '#<link href="[^"]*editor/css/fck_editorarea.css" rel="stylesheet" ty'
  332. .'pe="text/css" />#',
  333. '',
  334. $html
  335. );
  336. $html = preg_replace(
  337. '#<style _fcktemp="true" type="text/css">[^<]*</style>#',
  338. '',
  339. $html
  340. );
  341. $html = preg_replace(
  342. '#<link _fcktemp="true" href="[^"]*editor/editor/css/fck_internal.css'
  343. .'" rel="stylesheet" type="text/css" />#',
  344. '',
  345. $html
  346. );
  347. $html = preg_replace('#_fcksavedurl="[^"]*"#', '', $html);
  348. $html = str_replace('class="FCK__ShowTableBorders"', '', $html);
  349. // }
  350. // { clean skype crap from page
  351. $html = str_replace(
  352. '<span class="skype_pnh_left_span" skypeaction="skype_dropdown">&nbsp'
  353. .';&nbsp;</span>',
  354. '',
  355. $html
  356. );
  357. $html = str_replace(
  358. '<span class="skype_pnh_dropart_flag_span" skypeaction="skype_dropdow'
  359. .'n" style="background-position: -1999px 1px ! important;">&nbsp;&nbs'
  360. .'p;&nbsp;&nbsp;&nbsp;&nbsp;</span>',
  361. '',
  362. $html
  363. );
  364. $html = str_replace(
  365. '<span class="skype_pnh_dropart_span" skypeaction="skype_dropdown" '
  366. .'title="Skype actions">&nbsp;&nbsp;&nbsp;</span>',
  367. '',
  368. $html
  369. );
  370. $html = str_replace(
  371. '<span class="skype_pnh_right_span">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'
  372. .'</span>',
  373. '',
  374. $html
  375. );
  376. $html = preg_replace(
  377. '#<span class="skype_pnh_print_container">([^<]*)</span>#',
  378. '\1',
  379. $html
  380. );
  381. $html = preg_replace(
  382. '#<span class="skype_pnh_text_span">([^<]*)</span>#',
  383. '\1',
  384. $html
  385. );
  386. $html = preg_replace(
  387. '#<span class="skype_pnh_mark">[^<]*</span>#',
  388. '',
  389. $html
  390. );
  391. $html = preg_replace(
  392. '#<span class="skype_pnh_textarea_span">([^<]*)</span>#',
  393. '\1',
  394. $html
  395. );
  396. $html = preg_replace(
  397. '#<span class="skype_pnh_highlighting_inactive_common" dir="ltr"[^>'
  398. .']*>([^<]*)</span>#',
  399. '\1',
  400. $html
  401. );
  402. $html = preg_replace(
  403. '#<span class="skype_pnh_container"[^>]*>([^<]*)</span>#',
  404. '\1',
  405. $html
  406. );
  407. $html = preg_replace(
  408. '#<span class="skype_pnh_text_span">([^<]*)</span>#',
  409. '\1',
  410. $html
  411. );
  412. $html = preg_replace(
  413. '#<span class="skype_pnh_print_container">([^<]*)</span>#',
  414. '\1',
  415. $html
  416. );
  417. // }
  418. // { remove empty elements and parameters
  419. $html = preg_replace('#<style[^>]*>\s*</style>#', '', $html);
  420. $html = preg_replace('#<span>\s*</span>#', '', $html);
  421. $html = preg_replace('#<meta[^>]*>\s*</meta>#', '', $html);
  422. $html = str_replace(' alt=""', '', $html);
  423. // }
  424. // { clean up Word crap
  425. $html = preg_replace('#<link [^>]*href="file[^>]*>#', '', $html);
  426. $html = preg_replace('#<m:[^>]*/>#', '', $html);
  427. $html = preg_replace('#<m:mathPr>\s*</m:mathPr>#', '', $html);
  428. $html = preg_replace('#<xml>.*?</xml>#', '', $html);
  429. $html = preg_replace('#<!--\[if gte mso 10\].*?<!\[endif\]-->#', '', $html);
  430. $html = preg_replace('#<!--\[if gte mso 9\].*?<!\[endif\]-->#', '', $html);
  431. $html = preg_replace('#<!--\[if gte vml 1\]>.*?<!\[endif\]-->#', '', $html);
  432. $html = preg_replace(
  433. '#<object classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id=[^>'
  434. .']*></object>#',
  435. '',
  436. $html
  437. );
  438. $html = preg_replace('#<style>\s[a-z0-9]*.:[^<]*</style>#', '', $html);
  439. $html = preg_replace('#<!--\[if !mso\][^<]*<!\[endif\]-->#', '', $html);
  440. // }
  441. if (strpos($html, '{')===0) {
  442. $html=str_replace('&quot;', '\\"', $html);
  443. } // }
  444. else {
  445. $html=str_replace('&quot;', '"', $html);
  446. }
  447. $html=str_replace('&#39;', "'", $html);
  448. $has_changed=$html!=$original_html;
  449. $original_html=$html;
  450. } while ($has_changed);
  451. $html = str_replace('{{N}}', "\n", $html);
  452. $html = str_replace('{{R}}', "\r", $html);
  453. return $html;
  454. }
  455. // }
  456. // { Core_sanitiseHtml
  457. /**
  458. * thoroughly clean up HTML
  459. *
  460. * @param string $original_html the original HTML
  461. *
  462. * @return string sanitised HTML
  463. */
  464. function Core_sanitiseHtml($original_html) {
  465. $original_html = Core_sanitiseHtmlEssential($original_html);
  466. $original_html = Core_fixImageResizes($original_html);
  467. $original_html = str_replace("\n", '{{N}}', $original_html);
  468. $original_html = str_replace("\r", '{{R}}', $original_html);
  469. do {
  470. $html = $original_html;
  471. // { clean white-space
  472. $html = str_replace(
  473. '{{R}}{{N}}',
  474. "{{N}}",
  475. $html
  476. );
  477. $html = str_replace('>{{N}}', '>', $html);
  478. $html = str_replace(
  479. '{{N}}{{N}}',
  480. '{{N}}',
  481. $html
  482. );
  483. $html = preg_replace("/<p>\s*/", '<p>', $html);
  484. $html = preg_replace("#\s*<br( ?/)?>\s*#", '<br />', $html);
  485. $html = preg_replace("#\s*<li>\s*#", '<li>', $html);
  486. $html = str_replace(">\t", '>', $html);
  487. $html = preg_replace('#<p([^>]*)>\s*\&nbsp;\s*</p>#', '<p\1></p>', $html);
  488. // }
  489. // { remove empty elements and parameters
  490. $html = preg_replace('/<!--[^>]*-->/', '', $html);
  491. // }
  492. // { combine nested elements
  493. $html = preg_replace(
  494. '#<span style="([^"]*?);?">(\s*)<span style="([^"]*)">([^<]*|<img[^>]'
  495. .'*>)</span>(\s*)</span>#',
  496. '\2<span style="\1;\3">\4</span>\5',
  497. $html
  498. );
  499. $html = preg_replace(
  500. '#<a href="([^"]*)">(\s*)<span style="([^"]*)">([^<]*|<img[^>]*>)</sp'
  501. .'an>(\s*)</a>#',
  502. '\2<a href="\1" style="\3">\4</a>\5',
  503. $html
  504. );
  505. $html = preg_replace(
  506. '#<strong>(\s*)<span style="([^"]*)">([^<]*)</span>(\s*)</strong>#',
  507. '<strong style="\2">\1\3\4</strong>',
  508. $html
  509. );
  510. $html = preg_replace(
  511. '#<b>(\s*)<span style="([^"]*)">([^<]*)</span>(\s*)</b>#',
  512. '<b style="\2">\1\3\4</b>',
  513. $html
  514. );
  515. $html = preg_replace(
  516. '#<li>(\s*)<span style="([^"]*)">([^<]*)</span>(\s*)</li>#',
  517. '<li style="\2">\1\3\4</li>',
  518. $html
  519. );
  520. $html = preg_replace(
  521. '#<p>(\s*)<span style="([^"]*)">([^<]*)</span>(\s*)</p>#',
  522. '<p style="\2">\1\3\4</p>',
  523. $html
  524. );
  525. $html = preg_replace(
  526. '#<span style="([^"]*)">(\s*)<strong>([^<]*)</strong>(\s*)</span>#',
  527. '\2<strong style="\1">\3</strong>\4',
  528. $html
  529. );
  530. $html = preg_replace(
  531. '#<span style="([^"]*?);?">(\s*)<strong style="([^"]*)">([^<]*)</stro'
  532. .'ng>(\s*)</span>#',
  533. '\2<strong style="\1;\3">\4</strong>\5',
  534. $html
  535. );
  536. $html = preg_replace("/<p>\s*(<img[^>]*>)\s*<\/p>/", '\1', $html);
  537. $html = preg_replace(
  538. '/<span( style="font-[^:]*:[^"]*")?>\s*(<img[^>]*>)\s*<\/span>/',
  539. '\2',
  540. $html
  541. );
  542. $html = preg_replace("/<strong>\s*(<img[^>]*>)\s*<\/strong>/", '\1', $html);
  543. // }
  544. // { remove unnecessary elements
  545. $html = preg_replace('#<meta [^>]*>(.*?)</meta>#', '\1', $html);
  546. // }
  547. // { strip repeated CSS inline elements (TODO: make this more efficient...)
  548. $html=str_replace(
  549. 'font-size: large;font-size: large',
  550. 'font-size: large',
  551. $html
  552. );
  553. // }
  554. // { strip useless CSS
  555. $sillystuff=' style="([^"]*)(color:[^;"]*|font-size:[^;"]*|font-family:'
  556. .'[^;"]*|line-height:[^;"]*);([^"]*)"';
  557. $html=preg_replace(
  558. '#\s*<span'.$sillystuff.'>\s*</span>\s*#',
  559. '<span style="\1\3"></span>',
  560. $html
  561. );
  562. $html=str_replace(
  563. '<span style=""></span>',
  564. '<span></span>',
  565. $html
  566. );
  567. $html=preg_replace(
  568. '#\s*<p'.$sillystuff.'>\s*</p>\s*#',
  569. '<p style="\1\3"></p>',
  570. $html
  571. );
  572. $html=str_replace('<p style=""></p>', '<p></p>', $html);
  573. // }
  574. $has_changed=$html!=$original_html;
  575. $original_html=$html;
  576. } while ($has_changed);
  577. // { old-style tabs
  578. if (strpos($html, '%TABPAGE%')) {
  579. $rand=md5(mt_rand());
  580. $test=preg_replace('/<p>[^<]*(%TAB[^%]*%)[^<]*<\/p>/', '\1', $html);
  581. $test=str_replace(
  582. '%TABEND%',
  583. '</div></div><script>$(function(){$("#'.$rand.'").tabs();});</script>',
  584. $test
  585. );
  586. $parts=preg_split('/%TAB[^%]*%/', $test);
  587. $headings=array();
  588. for ($i=1; $i<count($parts); ++$i) {
  589. $headings[]=preg_replace(
  590. '/<[^>]*>/',
  591. '',
  592. preg_replace('/^[^<]*<h2[^>]*>(.*?)<\/h2>.*/', '\1', $parts[$i])
  593. );
  594. $replacement=($i>1?'</div>':'').'<div id="'.$rand.'-'.strtolower(
  595. preg_replace('/[^a-zA-Z0-9]/', '', $headings[$i-1])
  596. ).'">';
  597. $parts[$i]=preg_replace(
  598. '/^[^<]*<h2[^>]*>(.*?)<\/h2>/',
  599. $replacement,
  600. $parts[$i]
  601. );
  602. }
  603. $menu='<div id="'.$rand.'" class="tabs"><ul>';
  604. foreach ($headings as $h) {
  605. $menu.='<li><a href="#'.$rand.'-'.strtolower(
  606. preg_replace('/[^a-zA-Z0-9]/', '', $h)
  607. ).'">'.htmlspecialchars($h).'</a></li>';
  608. }
  609. $parts[0].=$menu.'</ul>';
  610. $html=join('', $parts);
  611. }
  612. // }
  613. $html = str_replace('{{N}}', "\n", $html);
  614. $html = str_replace('{{R}}', "\r", $html);
  615. return $html;
  616. }
  617. // }
  618. // { Core_getExternalFile
  619. /**
  620. * retrieve an external file and return its contents
  621. *
  622. * @param string $url URL of the external file
  623. *
  624. * @return string contents of the file
  625. */
  626. function Core_getExternalFile($url) {
  627. $ch = curl_init();
  628. curl_setopt($ch, CURLOPT_URL, $url);
  629. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  630. $response = curl_exec($ch);
  631. curl_close($ch);
  632. return $response;
  633. }
  634. // }