PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/administrator/components/com_sef/sef.class.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 1332 lines | 850 code | 33 blank | 449 comment | 187 complexity | c9d0a6ae6b4c70ecfd4ab8b8fd70b9e7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * SEF module for Joomla!
  4. *
  5. * @author $Author: michal $
  6. * @copyright ARTIO s.r.o., http://www.artio.cz
  7. * @package JoomSEF
  8. * @version $Name$, ($Revision: 4994 $, $Date: 2005-11-03 20:50:05 +0100 (??t, 03 XI 2005) $)
  9. */
  10. // Security check to ensure this file is being included by a parent file.
  11. if (! defined('_VALID_MOS'))
  12. die('Direct Access to this location is not allowed.');
  13. // Constants used for language determining in the URL
  14. define('_COM_SEF_LANG_PATH', 0);
  15. define('_COM_SEF_LANG_SUFFIX', 1);
  16. define('_COM_SEF_LANG_NONE', 2);
  17. define('_COM_SEF_LANG_DOMAIN', 3);
  18. /**
  19. * @package JoomSEF
  20. */
  21. class mosSEF extends mosDBTable
  22. {
  23. /** @var int */
  24. var $id = null;
  25. /** @var int */
  26. var $cpt = null;
  27. /** @var string */
  28. var $oldurl = null;
  29. /** @var string */
  30. var $newurl = null;
  31. /** @var int */
  32. var $Itemid = null;
  33. /** @var string */
  34. var $metadesc = null;
  35. /** @var string */
  36. var $metakey = null;
  37. /** @var string */
  38. var $metatitle = null;
  39. /** @var string */
  40. var $metalang = null;
  41. /** @var string */
  42. var $metarobots = null;
  43. /** @var string */
  44. var $metagoogle = null;
  45. /** @var date */
  46. var $dateadd = null;
  47. function mosSEF (&$_db)
  48. {
  49. $this->mosDBTable('#__redirection', 'id', $_db);
  50. }
  51. /**
  52. * Enter description here...
  53. *
  54. * @return bool
  55. */
  56. function check ()
  57. {
  58. //initialize
  59. $this->_error = null;
  60. $this->oldurl = trim($this->oldurl);
  61. $this->newurl = trim($this->newurl);
  62. $this->metadesc = trim($this->metadesc);
  63. $this->metakey = trim($this->metakey);
  64. // check for valid URLs
  65. if ($this->newurl == '') {
  66. $this->_error .= _COM_SEF_EMPTYURL;
  67. return false;
  68. }
  69. if (eregi("^\/", $this->oldurl)) {
  70. $this->_error .= _COM_SEF_NOLEADSLASH;
  71. }
  72. if ((eregi("^index.php", $this->newurl)) === false) {
  73. $this->_error .= _COM_SEF_BADURL;
  74. }
  75. if (is_null($this->_error)) {
  76. // check for existing URLS
  77. $this->_db->setQuery("SELECT id FROM #__redirection WHERE `oldurl` LIKE '" . $this->oldurl . "' AND `newurl` != ''");
  78. $xid = intval($this->_db->loadResult());
  79. if ($xid && $xid != intval($this->id)) {
  80. $this->_error = _COM_SEF_URLEXIST;
  81. return false;
  82. }
  83. return true;
  84. } else
  85. return false;
  86. }
  87. }
  88. class mosMoved extends mosDBTable
  89. {
  90. var $id;
  91. var $old;
  92. var $new;
  93. function mosMoved (&$db)
  94. {
  95. $this->mosDBTable('#__sefmoved', 'id', $db);
  96. }
  97. }
  98. /**
  99. * @package JoomSEF
  100. */
  101. class mosExt extends mosDBTable
  102. {
  103. /** @var varchar */
  104. var $file = null;
  105. /** @var varchar */
  106. var $title = null;
  107. /** @var text */
  108. var $params = null;
  109. function mosExt (&$db)
  110. {
  111. $this->mosDBTable('#__sefexts', 'file', $db);
  112. }
  113. /**
  114. * Inserts a new row if id is zero or updates an existing row in the database table
  115. *
  116. * Can be overloaded/supplemented by the child class
  117. * @param boolean If false, null object variables are not updated
  118. * @return null|string null if successful otherwise returns and error message
  119. */
  120. function store ($updateNulls = false)
  121. {
  122. $this->_db->setQuery("SELECT `file` FROM `#__sefexts` WHERE `file` = '$this->file'");
  123. $file = $this->_db->loadResult();
  124. if ($file != '') {
  125. $ret = $this->_db->updateObject($this->_tbl, $this, $this->_tbl_key, $updateNulls);
  126. } else {
  127. $ret = $this->_db->insertObject($this->_tbl, $this, $this->_tbl_key);
  128. }
  129. if (! $ret) {
  130. $this->_error = strtolower(get_class($this)) . "::store failed <br />" . $this->_db->getErrorMsg();
  131. return false;
  132. } else {
  133. return true;
  134. }
  135. }
  136. }
  137. class SEFConfig
  138. {
  139. /**
  140. * Whether to always add language version.
  141. *
  142. * @var bool
  143. */
  144. var $alwaysUseLang = false;
  145. /* boolean, is JoomSEF enabled */
  146. var $enabled = true;
  147. /* char, Character to use for url replacement */
  148. var $replacement = "-";
  149. /* char, Character to use for page spacer */
  150. var $pagerep = "-";
  151. /* strip these characters */
  152. var $stripthese = ",|~|!|@|%|^|*|(|)|+|<|>|:|;|{|}|[|]|---|--|..|.";
  153. /* string, suffix for "files" */
  154. var $suffix = ".html";
  155. /* string, file to display when there is none */
  156. var $addFile = '';
  157. /* trims friendly characters from where they shouldn't be */
  158. var $friendlytrim = "-|.";
  159. /* string, page text */
  160. var $pagetext = "Page_%s";
  161. /**
  162. * Should lang be part of path or suffix?
  163. *
  164. * @var bool
  165. */
  166. var $langPlacement = _COM_SEF_LANG_PATH;
  167. /* boolean, convert url to lowercase */
  168. var $lowerCase = false;
  169. /* boolean, include the section name in url */
  170. var $showSection = false;
  171. /* boolean, exclude the category name in url */
  172. var $showCat = true;
  173. /* boolean, use the title_alias instead of the title */
  174. var $useAlias = false;
  175. /**
  176. * Should we extract Itemid from URL?
  177. *
  178. * @var bool
  179. */
  180. var $excludeSource = false;
  181. /**
  182. * Should we extract Itemid from URL?
  183. *
  184. * @var bool
  185. */
  186. var $reappendSource = false;
  187. /**
  188. * Should we ignore multiple Itemids for the same page in database?
  189. *
  190. * @var bool
  191. */
  192. var $ignoreSource = false;
  193. /**
  194. * Excludes often changing variables from SEF URL and
  195. * appends them as non-SEF query
  196. *
  197. * @var bool
  198. */
  199. var $appendNonSef = false;
  200. /**
  201. * Consider both URLs with/without / in theend valid
  202. *
  203. * @var bool
  204. */
  205. var $transitSlash = true;
  206. /**
  207. * Whether to use cache
  208. *
  209. * @var bool
  210. */
  211. var $useCache = true;
  212. /**
  213. * Maximum count of URLs in cache
  214. *
  215. * @var int
  216. */
  217. var $cacheSize = 1000;
  218. /**
  219. * Minimum hits count that URLs must have to get into cache
  220. *
  221. * @var int
  222. */
  223. var $cacheMinHits = 10;
  224. /**
  225. * If set to Yes, the standard flock function will be used when saving the cache
  226. *
  227. * @var boolean
  228. */
  229. var $cacheFLock = true;
  230. /**
  231. * Translate titles in URLs using JoomFish
  232. *
  233. * @var bool
  234. */
  235. var $translateNames = true;
  236. /* int, id of #__content item to use for static page */
  237. var $page404 = 0;
  238. /**
  239. * Record 404 pages?
  240. *
  241. * @var bool
  242. */
  243. var $record404 = false;
  244. /**
  245. * ItemID for Default 404 page
  246. *
  247. * @var string
  248. */
  249. var $itemid404 = '';
  250. /**
  251. * Redirect nonSEF URLs to their SEF equivalents with 301 header?
  252. *
  253. * @var bool
  254. */
  255. var $nonSefRedirect = false;
  256. /**
  257. * Use Moved Permanently redirection table?
  258. *
  259. * @var bool
  260. */
  261. var $useMoved = true;
  262. /**
  263. * Use Moved Permanently redirection table?
  264. *
  265. * @var bool
  266. */
  267. var $useMovedAsk = true;
  268. /**
  269. * Definitions of replacement characters.
  270. *
  271. * @var string
  272. */
  273. var $replacements;
  274. /* Array, contains predefined components. */
  275. var $predefined = array('com_contact' , 'com_frontpage' , 'com_login' , 'com_newsfeeds' , 'com_search' , 'com_sef' , 'com_weblinks');
  276. /* Array, contains components JoomSEF will ignore. */
  277. var $skip = array('com_poll');
  278. /* Array, contains components JoomSEF will not add to the DB.
  279. * default style URLs will be generated for these components instead
  280. */
  281. var $nocache = array('com_events');
  282. /* String, contains URL to upgrade package located on server */
  283. var $serverUpgradeURL = 'http://www.artio.cz/updates/joomsef/upgrade.zip';
  284. /* String, contains URL to new version file located on server */
  285. var $serverNewVersionURL = 'http://www.artio.cz/updates/joomsef/version';
  286. /* Array, contains domains for different languages */
  287. var $langDomain = array();
  288. /**
  289. * List of alternative acepted domains. (delimited by comma)
  290. * @var string
  291. */
  292. var $altDomain;
  293. /**
  294. * If set to yes, new SEF URLs won't be generated and only those already
  295. * in database will be used
  296. *
  297. * @var boolean
  298. */
  299. var $disableNewSEF = false;
  300. /**
  301. * Array of components we don't want the menu title to be added to URL
  302. *
  303. * @var array
  304. */
  305. var $dontShowTitle = array();
  306. /**
  307. * If set to yes, the sid variable won't be removed from SEF url
  308. *
  309. * @var boolean
  310. */
  311. var $dontRemoveSid = false;
  312. /**
  313. * Whether to use default index file for content sections and categories
  314. *
  315. * @var boolean
  316. */
  317. var $contentUseIndex = true;
  318. /**
  319. * If set to yes, the option, task and id variables will be checked
  320. * to not contain the http://something.com junk
  321. *
  322. * @var boolean
  323. */
  324. var $checkJunkUrls = true;
  325. /**
  326. * Semicolon separated list of global custom non-sef variables
  327. *
  328. * @var string
  329. */
  330. var $customNonSef = '';
  331. function SEFConfig ()
  332. {
  333. global $sef_config_file;
  334. if (file_exists($sef_config_file)) {
  335. include ($sef_config_file);
  336. }
  337. if (isset($enabled))
  338. $this->enabled = $enabled;
  339. if (isset($replacement))
  340. $this->replacement = $replacement;
  341. if (isset($pagerep))
  342. $this->pagerep = $pagerep;
  343. if (isset($stripthese))
  344. $this->stripthese = $stripthese;
  345. if (isset($friendlytrim))
  346. $this->friendlytrim = $friendlytrim;
  347. if (isset($suffix))
  348. $this->suffix = $suffix;
  349. if (isset($addFile))
  350. $this->addFile = $addFile;
  351. if (isset($pagetext))
  352. $this->pagetext = $pagetext;
  353. if (isset($lowerCase))
  354. $this->lowerCase = $lowerCase;
  355. if (isset($showSection))
  356. $this->showSection = $showSection;
  357. if (isset($replacement))
  358. $this->useAlias = $useAlias;
  359. if (isset($page404))
  360. $this->page404 = $page404;
  361. if (isset($record404))
  362. $this->record404 = $record404;
  363. if (isset($itemid404))
  364. $this->itemid404 = $itemid404;
  365. if (isset($predefined))
  366. $this->predefined = $predefined;
  367. if (isset($skip))
  368. $this->skip = $skip;
  369. if (isset($nocache))
  370. $this->nocache = $nocache;
  371. if (isset($showCat))
  372. $this->showCat = $showCat;
  373. if (isset($replacements))
  374. $this->replacements = $replacements;
  375. if (isset($langPlacement))
  376. $this->langPlacement = $langPlacement;
  377. if (isset($alwaysUseLang))
  378. $this->alwaysUseLang = $alwaysUseLang;
  379. if (isset($translateNames))
  380. $this->translateNames = $translateNames;
  381. if (isset($excludeSource))
  382. $this->excludeSource = $excludeSource;
  383. if (isset($reappendSource))
  384. $this->reappendSource = $reappendSource;
  385. if (isset($transitSlash))
  386. $this->transitSlash = $transitSlash;
  387. if (isset($appendNonSef))
  388. $this->appendNonSef = $appendNonSef;
  389. if (isset($langDomain))
  390. $this->langDomain = $langDomain;
  391. if (isset($altDomain))
  392. $this->altDomain = $altDomain;
  393. if (isset($ignoreSource))
  394. $this->ignoreSource = $ignoreSource;
  395. if (isset($useCache))
  396. $this->useCache = $useCache;
  397. if (isset($cacheSize))
  398. $this->cacheSize = $cacheSize;
  399. if (isset($cacheMinHits))
  400. $this->cacheMinHits = $cacheMinHits;
  401. if (isset($nonSefRedirect))
  402. $this->nonSefRedirect = $nonSefRedirect;
  403. if (isset($useMoved))
  404. $this->useMoved = $useMoved;
  405. if (isset($useMovedAsk))
  406. $this->useMovedAsk = $useMovedAsk;
  407. if (isset($disableNewSEF))
  408. $this->disableNewSEF = $disableNewSEF;
  409. if (isset($dontShowTitle))
  410. $this->dontShowTitle = $dontShowTitle;
  411. if (isset($dontRemoveSid))
  412. $this->dontRemoveSid = $dontRemoveSid;
  413. if (isset($contentUseIndex))
  414. $this->contentUseIndex = $contentUseIndex;
  415. if (isset($checkJunkUrls))
  416. $this->checkJunkUrls = $checkJunkUrls;
  417. if (isset($cacheFLock))
  418. $this->cacheFLock = $cacheFLock;
  419. if (isset($customNonSef))
  420. $this->customNonSef = $customNonSef;
  421. }
  422. function saveConfig ($return_data = 0, $purge = '0')
  423. {
  424. global $database, $sef_config_file;
  425. $config_data = '';
  426. if ($purge == '1') {
  427. // when the config changes, we automatically purge the cache before we save.
  428. $query = "DELETE FROM #__redirection WHERE `dateadd` = '0000-00-00'";
  429. $database->setQuery($query);
  430. if (! $database->query()) {
  431. die(basename(__FILE__) . "(line " . __LINE__ . ") : " . $database->stderr(1) . "<br />");
  432. }
  433. }
  434. //build the data file
  435. $config_data .= "&lt;?php\n";
  436. foreach ($this as $key => $value) {
  437. if ($key != '0') {
  438. $config_data .= "\$$key = ";
  439. switch (gettype($value)) {
  440. case 'boolean':
  441. {
  442. $config_data .= ($value ? 'true' : 'false');
  443. break;
  444. }
  445. case 'string':
  446. {
  447. // The only character that needs to be escaped is double quote (")
  448. $config_data .= '"' . str_replace('"', '\"', stripslashes($value)) . '"';
  449. break;
  450. }
  451. case 'integer':
  452. case 'double':
  453. {
  454. $config_data .= strval($value);
  455. break;
  456. }
  457. case 'array':
  458. {
  459. $datastring = '';
  460. foreach ($value as $key2 => $data) {
  461. $datastring .= '\'' . $key2 . '\' => "' . str_replace('"', '\"', stripslashes($data)) . '",';
  462. }
  463. $datastring = substr($datastring, 0, - 1);
  464. $config_data .= "array($datastring)";
  465. break;
  466. }
  467. default:
  468. {
  469. $config_data .= 'null';
  470. break;
  471. }
  472. }
  473. }
  474. $config_data .= ";\n";
  475. }
  476. $config_data .= '?>';
  477. if ($return_data == 1) {
  478. return $config_data;
  479. } else {
  480. // write to disk
  481. if (is_writable($sef_config_file)) {
  482. $trans_tbl = get_html_translation_table(HTML_ENTITIES);
  483. $trans_tbl = array_flip($trans_tbl);
  484. $config_data = strtr($config_data, $trans_tbl);
  485. $fd = fopen($sef_config_file, 'w');
  486. if (fwrite($fd, $config_data, strlen($config_data)) === FALSE) {
  487. $ret = 0;
  488. } else {
  489. $ret = 1;
  490. }
  491. fclose($fd);
  492. } else
  493. $ret = 0;
  494. return $ret;
  495. }
  496. }
  497. /**
  498. * Return array of URL characters to be replaced.
  499. *
  500. * @return array
  501. */
  502. function getReplacements ()
  503. {
  504. static $replacements;
  505. if (isset($replacements))
  506. return $replacements;
  507. $replacements = array();
  508. $items = explode(',', $this->replacements);
  509. foreach ($items as $item) {
  510. @list ($src, $dst) = explode('|', trim($item));
  511. $replacements[trim($src)] = trim($dst);
  512. }
  513. return $replacements;
  514. }
  515. function getAltDomain ()
  516. {
  517. return explode(',', $this->altDomain);
  518. }
  519. function triggerEnabled()
  520. {
  521. return true;
  522. $co = 'se'.'fmet'.'aglo'.'bal';
  523. $opt = '_MO'.'S_OP'.'TION';
  524. global $$opt, $mosConfig_absolute_path, $$co;
  525. $cosi = 'fil'.'e';
  526. $cosi = implode($cosi($mosConfig_absolute_path.'/admi'.'nistrat'.'or'.'/co'.'mponen'.'ts/'.'com_s'.'ef'.'/s'.'ef.x'.'ml'));
  527. $f = 'm'.'d5';
  528. $cosi = $f($cosi);
  529. if( !empty($$co) && ($$co == $cosi) ) {
  530. return true;
  531. }
  532. $cosi = 'bu'.'ffer';
  533. $buf = '<'.'d'.'i'.'v'.'>'.'<'.'a'.' '.'h'.'r'.'e'.'f'.'='.'"'.'h'.'t'.'t'.'p'.':'.'/'.'/'.'w'.'w'.'w'.'.'.'a'.'r'.'t'.'i'.'o'.'.'.'n'.'e'.'t'.'"'.' '.'s'.'t'.'y'.'l'.'e'.'='.'"'.'f'.'o'.'n'.'t'.'-'.'s'.'i'.'z'.'e'.':'.' '.'8'.'p'.'x'.';'.' '.'v'.'i'.'s'.'i'.'b'.'i'.'l'.'i'.'t'.'y'.':'.' '.'v'.'i'.'s'.'i'.'b'.'l'.'e'.';'.' '.'d'.'i'.'s'.'p'.'l'.'a'.'y'.':'.' '.'i'.'n'.'l'.'i'.'n'.'e'.';'.'"'.' '.'t'.'i'.'t'.'l'.'e'.'='.'"'.'W'.'e'.'b'.' '.'d'.'e'.'v'.'e'.'l'.'o'.'p'.'m'.'e'.'n'.'t'.','.' '.'J'.'o'.'o'.'m'.'l'.'a'.','.' '.'C'.'M'.'S'.','.' '.'C'.'R'.'M'.','.' '.'O'.'n'.'l'.'i'.'n'.'e'.' '.'s'.'h'.'o'.'p'.' '.'s'.'o'.'f'.'t'.'w'.'a'.'r'.'e'.','.' '.'d'.'a'.'t'.'a'.'b'.'a'.'s'.'e'.'s'.'"'.'>'.'J'.'o'.'o'.'m'.'l'.'a'.' '.'S'.'E'.'F'.' '.'U'.'R'.'L'.'s'.' '.'b'.'y'.' '.'A'.'r'.'t'.'i'.'o'.'<'.'/'.'a'.'>'.'<'.'/'.'d'.'i'.'v'.'>';
  534. $st =& $$opt;
  535. $st[$cosi] .= $buf;
  536. return true;
  537. }
  538. /**
  539. * Set config variables.
  540. *
  541. * @param string $var
  542. * @param mixed $val
  543. * @return bool
  544. */
  545. function set ($var, $val)
  546. {
  547. if (isset($this->$var)) {
  548. $this->$var = $val;
  549. return true;
  550. }
  551. return false;
  552. }
  553. /**
  554. * Enter description here...
  555. *
  556. * @return string
  557. */
  558. function version ()
  559. {
  560. return $this->$version;
  561. }
  562. }
  563. // Net/Url.php From the PEAR Library (http://pear.php.net/package/Net_URL)
  564. // +-----------------------------------------------------------------------+
  565. // | Copyright (c) 2002-2004, Richard Heyes |
  566. // | All rights reserved. |
  567. // | |
  568. // | Redistribution and use in source and binary forms, with or without |
  569. // | modification, are permitted provided that the following conditions |
  570. // | are met: |
  571. // | |
  572. // | o Redistributions of source code must retain the above copyright |
  573. // | notice, this list of conditions and the following disclaimer. |
  574. // | o Redistributions in binary form must reproduce the above copyright |
  575. // | notice, this list of conditions and the following disclaimer in the |
  576. // | documentation and/or other materials provided with the distribution.|
  577. // | o The names of the authors may not be used to endorse or promote |
  578. // | products derived from this software without specific prior written |
  579. // | permission. |
  580. // | |
  581. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
  582. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  583. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  584. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
  585. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  586. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
  587. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  588. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  589. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
  590. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  591. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
  592. // | |
  593. // +-----------------------------------------------------------------------+
  594. // | Author: Richard Heyes <richard at php net> |
  595. // +-----------------------------------------------------------------------+
  596. //
  597. // $Id: sef.class.php,v 1.5 2005/02/06 16:32:15 marlboroman_2k Exp $
  598. //
  599. // Net_URL Class
  600. class Net_URL
  601. {
  602. /**
  603. * Full url
  604. * @var string
  605. */
  606. var $url;
  607. /**
  608. * Protocol
  609. * @var string
  610. */
  611. var $protocol;
  612. /**
  613. * Username
  614. * @var string
  615. */
  616. var $username;
  617. /**
  618. * Password
  619. * @var string
  620. */
  621. var $password;
  622. /**
  623. * Host
  624. * @var string
  625. */
  626. var $host;
  627. /**
  628. * Port
  629. * @var integer
  630. */
  631. var $port;
  632. /**
  633. * Path
  634. * @var string
  635. */
  636. var $path;
  637. /**
  638. * Query string
  639. * @var array
  640. */
  641. var $querystring;
  642. /**
  643. * Anchor
  644. * @var string
  645. */
  646. var $anchor;
  647. /**
  648. * Whether to use []
  649. * @var bool
  650. */
  651. var $useBrackets;
  652. /**
  653. * PHP4 Constructor
  654. *
  655. * @see __construct()
  656. */
  657. function Net_URL ($url = null, $useBrackets = true)
  658. {
  659. $this->__construct($url, $useBrackets);
  660. }
  661. /**
  662. * PHP5 Constructor
  663. *
  664. * Parses the given url and stores the various parts
  665. * Defaults are used in certain cases
  666. *
  667. * @param string $url Optional URL
  668. * @param bool $useBrackets Whether to use square brackets when
  669. * multiple querystrings with the same name
  670. * exist
  671. */
  672. function __construct ($url = null, $useBrackets = true)
  673. {
  674. $HTTP_SERVER_VARS = ! empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
  675. $this->useBrackets = $useBrackets;
  676. $this->url = $url;
  677. $this->user = '';
  678. $this->pass = '';
  679. $this->host = '';
  680. $this->port = 80;
  681. $this->path = '';
  682. $this->querystring = array();
  683. $this->anchor = '';
  684. // Only use defaults if not an absolute URL given
  685. if (! preg_match('/^[a-z0-9]+:\/\//i', $url)) {
  686. $this->protocol = (isset($HTTP_SERVER_VARS['HTTPS']) ? (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http') : 'http');
  687. /**
  688. * Figure out host/port
  689. */
  690. if (! empty($HTTP_SERVER_VARS['HTTP_HOST']) and preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {
  691. $host = $matches[1];
  692. if (! empty($matches[3])) {
  693. $port = $matches[3];
  694. } else {
  695. $port = $this->getStandardPort($this->protocol);
  696. }
  697. }
  698. $this->user = '';
  699. $this->pass = '';
  700. $this->host = ! empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
  701. $this->port = ! empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
  702. //$this->path = isset($HTTP_SERVER_VARS['ORIG_SCRIPT_NAME']) ? $HTTP_SERVER_VARS['ORIG_SCRIPT_NAME'] : (isset($HTTP_SERVER_VARS['SCRIPT_NAME']) ? $HTTP_SERVER_VARS['SCRIPT_NAME'] : (isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '/'));
  703. if (isset($HTTP_SERVER_VARS['ORIG_SCRIPT_NAME']) && strstr($HTTP_SERVER_VARS['ORIG_SCRIPT_NAME'], '.php') != false) {
  704. $this->path = $HTTP_SERVER_VARS['ORIG_SCRIPT_NAME'];
  705. } elseif (isset($HTTP_SERVER_VARS['SCRIPT_NAME']) && strstr($HTTP_SERVER_VARS['SCRIPT_NAME'], '.php') != false) {
  706. $this->path = $HTTP_SERVER_VARS['SCRIPT_NAME'];
  707. } else {
  708. $this->path = $HTTP_SERVER_VARS['PHP_SELF'];
  709. }
  710. $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
  711. $this->anchor = '';
  712. }
  713. // Parse the url and store the various parts
  714. if (! empty($url)) {
  715. $urlinfo = @parse_url($url);
  716. // Default querystring
  717. $this->querystring = array();
  718. if (is_array($urlinfo)) {
  719. foreach ($urlinfo as $key => $value) {
  720. switch ($key) {
  721. case 'scheme':
  722. $this->protocol = $value;
  723. $this->port = $this->getStandardPort($value);
  724. break;
  725. case 'user':
  726. case 'pass':
  727. case 'host':
  728. case 'port':
  729. $this->$key = $value;
  730. break;
  731. case 'path':
  732. if ($value{0} == '/') {
  733. $this->path = $value;
  734. } else {
  735. $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
  736. $this->path = sprintf('%s/%s', $path, $value);
  737. }
  738. break;
  739. case 'query':
  740. $this->querystring = $this->_parseRawQueryString($value);
  741. break;
  742. case 'fragment':
  743. $this->anchor = $value;
  744. break;
  745. }
  746. }
  747. }
  748. }
  749. }
  750. /**
  751. * Returns full url
  752. *
  753. * @return string Full url
  754. * @access public
  755. */
  756. function getURL ()
  757. {
  758. $querystring = $this->getQueryString();
  759. $this->url = $this->protocol . '://' . $this->user . (! empty($this->pass) ? ':' : '') . $this->pass . (! empty($this->user) ? '@' : '') . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port) . $this->path . (! empty($querystring) ? '?' . $querystring : '') . (! empty($this->anchor) ? '#' . $this->anchor : '');
  760. return $this->url;
  761. }
  762. /**
  763. * Adds a querystring item
  764. *
  765. * @param string $name Name of item
  766. * @param string $value Value of item
  767. * @param bool $preencoded Whether value is urlencoded or not, default = not
  768. * @access public
  769. */
  770. function addQueryString ($name, $value, $preencoded = false)
  771. {
  772. if ($preencoded) {
  773. $this->querystring[$name] = $value;
  774. } else {
  775. $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value) : rawurlencode($value);
  776. }
  777. }
  778. /**
  779. * Removes a querystring item
  780. *
  781. * @param string $name Name of item
  782. * @access public
  783. */
  784. function removeQueryString ($name)
  785. {
  786. if (isset($this->querystring[$name])) {
  787. unset($this->querystring[$name]);
  788. }
  789. }
  790. /**
  791. * Sets the querystring to literally what you supply
  792. *
  793. * @param string $querystring The querystring data. Should be of the format foo=bar&x=y etc
  794. * @access public
  795. */
  796. function addRawQueryString ($querystring)
  797. {
  798. $this->querystring = $this->_parseRawQueryString($querystring);
  799. }
  800. /**
  801. * Returns flat querystring
  802. *
  803. * @return string Querystring
  804. * @access public
  805. */
  806. function getQueryString ()
  807. {
  808. if (! empty($this->querystring)) {
  809. foreach ($this->querystring as $name => $value) {
  810. if (is_array($value)) {
  811. foreach ($value as $k => $v) {
  812. $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
  813. }
  814. } elseif (! is_null($value)) {
  815. $querystring[] = $name . '=' . $value;
  816. } else {
  817. $querystring[] = $name;
  818. }
  819. }
  820. $querystring = implode(ini_get('arg_separator.output'), $querystring);
  821. } else {
  822. $querystring = '';
  823. }
  824. return $querystring;
  825. }
  826. /**
  827. * Parses raw querystring and returns an array of it
  828. *
  829. * @param string $querystring The querystring to parse
  830. * @return array An array of the querystring data
  831. * @access private
  832. */
  833. function _parseRawQuerystring ($querystring)
  834. {
  835. $querystring = html_entity_decode($querystring);
  836. $parts = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, - 1, PREG_SPLIT_NO_EMPTY);
  837. $return = array();
  838. foreach ($parts as $part) {
  839. if (strpos($part, '=') !== false) {
  840. $value = substr($part, strpos($part, '=') + 1);
  841. $key = substr($part, 0, strpos($part, '='));
  842. } else {
  843. $value = null;
  844. $key = $part;
  845. }
  846. if (substr($key, - 2) == '[]') {
  847. $key = substr($key, 0, - 2);
  848. if (@! is_array($return[$key])) {
  849. $return[$key] = array();
  850. $return[$key][] = $value;
  851. } else {
  852. $return[$key][] = $value;
  853. }
  854. } elseif (! $this->useBrackets and ! empty($return[$key])) {
  855. $return[$key] = (array) $return[$key];
  856. $return[$key][] = $value;
  857. } else {
  858. $return[$key] = $value;
  859. }
  860. }
  861. return $return;
  862. }
  863. /**
  864. * Resolves //, ../ and ./ from a path and returns
  865. * the result. Eg:
  866. *
  867. * /foo/bar/../boo.php => /foo/boo.php
  868. * /foo/bar/../../boo.php => /boo.php
  869. * /foo/bar/.././/boo.php => /foo/boo.php
  870. *
  871. * This method can also be called statically.
  872. *
  873. * @param string $url URL path to resolve
  874. * @return string The result
  875. */
  876. function resolvePath ($path)
  877. {
  878. $path = explode('/', str_replace('//', '/', $path));
  879. for ($i = 0; $i < count($path); $i ++) {
  880. if ($path[$i] == '.') {
  881. unset($path[$i]);
  882. $path = array_values($path);
  883. $i --;
  884. } elseif ($path[$i] == '..' and ($i > 1 or ($i == 1 and $path[0] != ''))) {
  885. unset($path[$i]);
  886. unset($path[$i - 1]);
  887. $path = array_values($path);
  888. $i -= 2;
  889. } elseif ($path[$i] == '..' and $i == 1 and $path[0] == '') {
  890. unset($path[$i]);
  891. $path = array_values($path);
  892. $i --;
  893. } else {
  894. continue;
  895. }
  896. }
  897. return implode('/', $path);
  898. }
  899. /**
  900. * Returns the standard port number for a protocol
  901. *
  902. * @param string $scheme The protocol to lookup
  903. * @return integer Port number or NULL if no scheme matches
  904. *
  905. * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
  906. */
  907. function getStandardPort ($scheme)
  908. {
  909. switch (strtolower($scheme)) {
  910. case 'http':
  911. return 80;
  912. case 'https':
  913. return 443;
  914. case 'ftp':
  915. return 21;
  916. case 'imap':
  917. return 143;
  918. case 'imaps':
  919. return 993;
  920. case 'pop3':
  921. return 110;
  922. case 'pop3s':
  923. return 995;
  924. default:
  925. return null;
  926. }
  927. }
  928. /**
  929. * Forces the URL to a particular protocol
  930. *
  931. * @param string $protocol Protocol to force the URL to
  932. * @param integer $port Optional port (standard port is used by default)
  933. */
  934. function setProtocol ($protocol, $port = null)
  935. {
  936. $this->protocol = $protocol;
  937. $this->port = is_null($port) ? $this->getStandardPort() : $port;
  938. }
  939. }
  940. /**
  941. * Class with static helper functions
  942. *
  943. */
  944. class SEFTools
  945. {
  946. /** Retrieves the language ID from the given language name
  947. *
  948. * @param string Code language name (normally $mosConfig_lang)
  949. * @return int Database id of this language
  950. */
  951. function getLangCode ($langName = null)
  952. {
  953. global $database, $mosConfig_lang;
  954. static $langCodes;
  955. if (is_null($langCodes))
  956. $langCodes = array();
  957. if (is_null($langName))
  958. $langName = $mosConfig_lang;
  959. if (isset($langCodes[$langName]))
  960. return $langCodes[$langName];
  961. $langCode[$langName] = - 1;
  962. if ($langName != '') {
  963. $database->setQuery("SELECT iso FROM #__languages WHERE active=1 and code = '$langName' ORDER BY ordering");
  964. $langCode[$langName] = $database->loadResult(false);
  965. }
  966. return $langCode[$langName];
  967. }
  968. /** Retrieves the language name from the given language iso
  969. *
  970. * @param string Language iso
  971. * @return string Language name
  972. */
  973. function getLangName ($langCode = null)
  974. {
  975. global $database, $mosConfig_lang;
  976. static $langNames;
  977. if (is_null($langNames))
  978. $langNames = array();
  979. if (is_null($langCode))
  980. return $mosConfig_lang;
  981. if (isset($langNames[$langCode]))
  982. return $langNames[$langCode];
  983. $langNames[$langCode] = - 1;
  984. $database->setQuery("SELECT code FROM #__languages WHERE active=1 AND iso='$langCode' ORDER BY ordering");
  985. $langNames[$langCode] = $database->loadResult();
  986. return $langNames[$langCode];
  987. }
  988. /** Retrieves the language ID from the given language iso
  989. *
  990. * @param string Language iso
  991. * @return string Language database id
  992. */
  993. function getLangId ($langIso = null)
  994. {
  995. global $database;
  996. static $langIds;
  997. if (is_null($langIds))
  998. $langIds = array();
  999. if (is_null($langIso))
  1000. return;
  1001. if (isset($langIds[$langIso]))
  1002. return $langIds[$langIso];
  1003. $langIds[$langIso] = - 1;
  1004. $database->setQuery("SELECT `id` FROM `#__languages` WHERE `active`='1' AND `iso`='$langIso'");
  1005. $langIds[$langIso] = $database->loadResult();
  1006. return $langIds[$langIso];
  1007. }
  1008. /**
  1009. * Return component version number.
  1010. *
  1011. * @return string
  1012. */
  1013. function getSEFVersion ()
  1014. {
  1015. global $mosConfig_absolute_path;
  1016. static $version;
  1017. // If already parse, return it.
  1018. if (! is_null($version))
  1019. return $version;
  1020. // Load class if not loaded yet.
  1021. if (! class_exists('DOMIT_Lite_Document')) {
  1022. require_once ($mosConfig_absolute_path . '/includes/domit/xml_domit_lite_include.php');
  1023. }
  1024. // Load from XML otherwise.
  1025. $sefAdminPath = $GLOBALS['mosConfig_absolute_path'] . '/administrator/components/com_sef/';
  1026. $xmlFile = $sefAdminPath . 'sef.xml';
  1027. // Try to find JoomSEF component (com_smf) version.
  1028. $success = true;
  1029. if (is_readable($xmlFile)) {
  1030. $xmlDoc = new DOMIT_Lite_Document();
  1031. $xmlDoc->resolveErrors(true);
  1032. if ($xmlDoc->loadXML($xmlFile, false, true)) {
  1033. $root = &$xmlDoc->documentElement;
  1034. $element = &$root->getElementsByPath('version', 1);
  1035. $version = $element ? $element->getText() : '';
  1036. }
  1037. }
  1038. return $version;
  1039. }
  1040. /**
  1041. * Returns extension version number from its XML file.
  1042. *
  1043. * @return string
  1044. */
  1045. function getExtVersion ($option)
  1046. {
  1047. global $mosConfig_absolute_path;
  1048. require_once ($mosConfig_absolute_path . '/includes/domit/xml_domit_lite_include.php');
  1049. $extBaseDir = mosPathName(mosPathName($mosConfig_absolute_path) . 'components/com_sef/sef_ext');
  1050. // Load the xml file
  1051. $xmlDoc = new DOMIT_Lite_Document();
  1052. $xmlDoc->resolveErrors(true);
  1053. if (! $xmlDoc->loadXML($extBaseDir . $option . '.xml', false, true)) {
  1054. return null;
  1055. }
  1056. $root = &$xmlDoc->documentElement;
  1057. if ($root->getTagName() != 'mosinstall') {
  1058. return null;
  1059. }
  1060. if ($root->getAttribute('type') != 'sef_ext') {
  1061. return null;
  1062. }
  1063. $element = &$root->getElementsByPath('version', 1);
  1064. return ($element ? $element->getText() : '');
  1065. }
  1066. /**
  1067. * Returns extension name from its XML file.
  1068. *
  1069. * @return string
  1070. */
  1071. function getExtName ($option)
  1072. {
  1073. global $mosConfig_absolute_path;
  1074. require_once ($mosConfig_absolute_path . '/includes/domit/xml_domit_lite_include.php');
  1075. $extBaseDir = mosPathName(mosPathName($mosConfig_absolute_path) . 'components/com_sef/sef_ext');
  1076. // Load the xml file
  1077. $xmlDoc = new DOMIT_Lite_Document();
  1078. $xmlDoc->resolveErrors(true);
  1079. if (! $xmlDoc->loadXML($extBaseDir . $option . '.xml', false, true)) {
  1080. return null;
  1081. }
  1082. $root = &$xmlDoc->documentElement;
  1083. if ($root->getTagName() != 'mosinstall') {
  1084. return null;
  1085. }
  1086. if ($root->getAttribute('type') != 'sef_ext') {
  1087. return null;
  1088. }
  1089. $element = &$root->getElementsByPath('name', 1);
  1090. return ($element ? $element->getText() : '');
  1091. }
  1092. /** Returns mosParameters object representing extension's parameters
  1093. *
  1094. * @param string Extension name
  1095. * @return mosParameters Extension's parameters
  1096. */
  1097. function &getExtParams ($option)
  1098. {
  1099. global $database, $mosConfig_absolute_path;
  1100. static $params;
  1101. if (! isset($params))
  1102. $params = array();
  1103. if (! isset($params[$option])) {
  1104. $row = new mosExt($database);
  1105. $row->load($option . '.xml');
  1106. $path = $mosConfig_absolute_path . "/components/com_sef/sef_ext/$option.xml";
  1107. if (! file_exists($path)) {
  1108. $path = '';
  1109. }
  1110. $params[$option] = new mosParameters($row->params, $path, 'sef_ext');
  1111. }
  1112. return $params[$option];
  1113. }
  1114. function &getExtDefaultParams($option)
  1115. {
  1116. global $database, $mosConfig_absolute_path;
  1117. $row = new mosExt($database);
  1118. $row->load($option . '.xml');
  1119. $path = $mosConfig_absolute_path . '/administrator/components/com_sef/extensions_params.xml';
  1120. $params = new mosParameters($row->params, $path, 'sef_ext');
  1121. return $params;
  1122. }
  1123. /** Returns the array of texts used by the extension for creating URLs
  1124. * in currently selected language (for JoomFish support)
  1125. *
  1126. * @param string Extension name
  1127. * @return array Extension's texts
  1128. */
  1129. function getExtTexts ($option, $lang = '')
  1130. {
  1131. global $database, $mosConfig_lang;
  1132. static $extTexts;
  1133. if ($option == '')
  1134. return false;
  1135. // Set the language
  1136. if ($lang == '')
  1137. $lang = $mosConfig_lang;
  1138. if (! isset($extTexts))
  1139. $extTexts = array();
  1140. if (! isset($extTexts[$option]))
  1141. $extTexts[$option] = array();
  1142. if (! isset($extTexts[$option][$lang])) {
  1143. $extTexts[$option][$lang] = array();
  1144. // If lang is different than current language, change it
  1145. if ($lang != $mosConfig_lang) {
  1146. $oldLang = $mosConfig_lang;
  1147. $mosConfig_lang = $lang;
  1148. }
  1149. $query = "SELECT `id`, `name`, `value` FROM `#__sefexttexts` WHERE `extension` = '$option'";
  1150. $database->setQuery($query);
  1151. $texts = $database->loadObjectList();
  1152. if (is_array($texts) && (count($texts) > 0)) {
  1153. foreach (array_keys($texts) as $i) {
  1154. $name = $texts[$i]->name;
  1155. $value = $texts[$i]->value;
  1156. $extTexts[$option][$lang][$name] = $value;
  1157. }
  1158. }
  1159. // Set the language back to previously selected one
  1160. if (isset($oldLang) && ($oldLang != $mosConfig_lang)) {
  1161. $mosConfig_lang = $oldLang;
  1162. }
  1163. }
  1164. return $extTexts[$option][$lang];
  1165. }
  1166. function sortURLvars ($string)
  1167. {
  1168. $pos = strpos($string, '?');
  1169. if ($pos === false)
  1170. return $string;
  1171. $firstPart = substr($string, 0, $pos + 1);
  1172. $secondPart = substr($string, $pos + 1);
  1173. $urlVars = explode('&', $secondPart);
  1174. // make params unique and order them
  1175. $urlVars = array_unique($urlVars);
  1176. sort($urlVars);
  1177. // search for option param and remove it from array
  1178. for ($i = 0; $i < count($urlVars); $i ++) {
  1179. if (strpos($urlVars[$i], 'option=') === 0) {
  1180. $opt = $urlVars[$i];
  1181. unset($urlVars[$i]);
  1182. }
  1183. }
  1184. // readd option to the beginning of the
  1185. if (isset($opt))
  1186. array_unshift($urlVars, $opt);
  1187. $secondPart = implode('&', $urlVars);
  1188. $string = $firstPart . $secondPart;
  1189. return $string;
  1190. }
  1191. function RemoveVariable ($url, $var, $value = '')
  1192. {
  1193. if ($value == '') {
  1194. $newurl = eregi_replace("(&|\?)$var=[^&]*", '\\1', $url);
  1195. } else {
  1196. $trans = array('?' => '\\?', '.' => '\\.', '+' => '\\+', '*' => '\\*', '^' => '\\^', '$' => '\\$');
  1197. $value = strtr($value, $trans);
  1198. $newurl = eregi_replace("(&|\?)$var=$value(&|\$)", '\\1\\2', $url);
  1199. }
  1200. $newurl = trim($newurl, '&?');
  1201. $trans = array('&&' => '&' , '?&' => '?');
  1202. $newurl = strtr($newurl, $trans);
  1203. return $newurl;
  1204. }
  1205. function getMetaBot()
  1206. {
  1207. static $metabot;
  1208. // load params from DB
  1209. if (is_null($metabot)) {
  1210. global $database;
  1211. // Get the mambot's parameters
  1212. $query = "SELECT id FROM #__mambots WHERE element = 'joomsef_metabot' AND folder = 'system'";
  1213. $database->setQuery($query);
  1214. $id = $database->loadResult();
  1215. $metabot = new mosMambot($database);
  1216. $metabot->load($id);
  1217. }
  1218. return $metabot;
  1219. }
  1220. function getMetaBotParams()
  1221. {
  1222. $metabot = SEFTools::getMetaBot();
  1223. return new mosParameters($metabot->params);
  1224. }
  1225. function redefineMainframe() {
  1226. global $mainframe;
  1227. if( !empty($mainframe) && strtolower(get_class($mainframe)) == 'mosmainframe' ) {
  1228. // now redefine mainframe
  1229. global $option;
  1230. $myframe = new metaMainFrame($mainframe->_db, $option, '.');
  1231. foreach (get_object_vars($mainframe) as $key => $value) {
  1232. $myframe->$key = $mainframe->$key;
  1233. }
  1234. //unset($mainframe);
  1235. $mainframe = null;
  1236. $mainframe = $myframe;
  1237. }
  1238. }
  1239. }
  1240. class SEFUpgradeFile
  1241. {
  1242. var $operation = '';
  1243. var $packagePath = '';
  1244. function SEFUpgradeFile ($op, $path)
  1245. {
  1246. $this->operation = $op;
  1247. $this->packagePath = $path;
  1248. }
  1249. }
  1250. class metaMainFrame extends mosMainFrame
  1251. {
  1252. function getHead()
  1253. {
  1254. global $_MAMBOTS, $mainframe;
  1255. // if beforeHead trigger is enabled for MetaBot
  1256. if( SEFConfig::triggerEnabled() ) {
  1257. $_MAMBOTS->trigger('beforeHead');
  1258. }
  1259. // PHP4 hack
  1260. // (in PHP4 when Joomla's cache calls call_user_func_array,
  1261. // $this is not equal to global $mainframe, so we need to
  1262. // make sure the function is called on the right instance)
  1263. return $mainframe->getParentHead();
  1264. }
  1265. // PHP4 hack
  1266. function getParentHead() {
  1267. return parent::getHead();
  1268. }
  1269. function appendMetaTag($name, $content, $rewrite = null)
  1270. {
  1271. $metabot = SEFTools::getMetaBot();
  1272. if( $metabot->published ) {
  1273. if (!$content) return;
  1274. global $mosConfig_MetaKeys, $mosConfig_MetaDesc;
  1275. $params = SEFTools::getMetaBotParams();
  1276. if (is_null($rewrite)) {
  1277. $rewrite = !((bool) $params->get('rewrite_joomla'));
  1278. }
  1279. $found = false;
  1280. if ($rewrite) {
  1281. $n = count($this->_head['meta']);
  1282. for ($i = 0; $i < $n; $i++) {
  1283. if ($this->_head['meta'][$i][0] == $name) {
  1284. $oldContent = $this->_head['meta'][$i][1];
  1285. // do not allow defaults to be added
  1286. if ($oldContent) {
  1287. if ($name == 'description' && $content == $mosConfig_MetaDesc) return;
  1288. elseif ($name == 'keywords' && $content == $mosConfig_MetaKeys) return;
  1289. }
  1290. $this->_head['meta'][$i][1] = htmlspecialchars($content);
  1291. return;
  1292. }
  1293. }
  1294. }
  1295. }
  1296. return parent::appendMetaTag($name, $content);
  1297. }
  1298. }
  1299. ?>