PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/components/com_sef/joomsef.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 1030 lines | 637 code | 137 blank | 256 comment | 229 complexity | 309f796a4df6b42312f0a76ea7d92a04 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')) die('Direct Access to this location is not allowed.');
  12. global $database, $URI, $my, $option, $index, $base;
  13. // debugging on/off
  14. $debug = (bool) @$_REQUEST['debugSEF'];
  15. // hack in mos database as required
  16. if (!is_object(@$database)) {
  17. $database = new database($GLOBALS['mosConfig_host'], $GLOBALS['mosConfig_user'], $GLOBALS['mosConfig_password'], $GLOBALS['mosConfig_db'], $GLOBALS['mosConfig_dbprefix']);
  18. }
  19. $REQUEST = $SRU = $_SERVER['REQUEST_URI'];
  20. if ($debug) {
  21. $GLOBALS['JOOMSEF_DEBUG']['INDEX'] = $index;
  22. $GLOBALS['JOOMSEF_DEBUG']['BASE'] = $base;
  23. $GLOBALS['JOOMSEF_DEBUG']['QUERY_STRING'] = $_SERVER['QUERY_STRING'];
  24. $GLOBALS['JOOMSEF_DEBUG']['REQUEST'] = $REQUEST;
  25. $GLOBALS['JOOMSEF_DEBUG']['URI'] = $URI;
  26. }
  27. // Redirection check for nonSEF URLs
  28. if ($sefConfig->nonSefRedirect && // nonSefRedirect is ON
  29. (strpos($_SERVER['REQUEST_URI'], $base.$index.'?') !== false) && // request uri has ?
  30. ($index != 'index2.php') && // site isn't index2.php
  31. (count($_POST) == 0)) // POST is empty
  32. {
  33. // Try to find the non-SEF URL in the database - don't create new!
  34. $oldDisable = $sefConfig->disableNewSEF;
  35. $sefConfig->disableNewSEF = true;
  36. $lnk = sefRelToAbs(str_replace($base, '', $_SERVER['REQUEST_URI']));
  37. // Restore the configuration
  38. $sefConfig->disableNewSEF = $oldDisable;
  39. if( strpos($lnk, 'index.php?') === false ) {
  40. // Seems the URL is SEF, let's redirect
  41. $f = $l = '';
  42. if (!headers_sent($f, $l)) {
  43. header("HTTP/1.1 301 Moved Permanently");
  44. header("Location: ".$lnk);
  45. header("Connection: close");
  46. exit();
  47. } else headers_sent_error($f, $l, $GLOBALS['mosConfig_live_site'].$_SERVER['QUERY_STRING'], @$option);
  48. }
  49. }
  50. // check the URL nesting
  51. switch ($URI->path) {
  52. case $base:
  53. case $base.$index: {
  54. $option = isset($_GET['option']) ? $_GET['option'] : isset($_REQUEST['option']) ? $_REQUEST['option'] : null;
  55. if (is_null($option)) {
  56. $GLOBALS['JOOMSEF_DEBUG']['REDIRECT_INDEX'] = 0;
  57. // fix those funky polls by ensuring we have an Itemid for the homepage
  58. /*$query = "SELECT `id`,`link` FROM #__menu WHERE `menutype` = 'mainmenu' AND `published` > 0 AND `link` LIKE '%com_frontpage%' LIMIT 1";
  59. $database->setQuery($query);
  60. if (($row = $database->loadRow())) {
  61. $GLOBALS['JOOMSEF_DEBUG']['REDIRECT_INDEX'] = 1;
  62. $_GET['Itemid'] = $_REQUEST['Itemid'] = $Itemid = $row[0];
  63. $_SERVER['QUERY_STRING'] = $QUERY_STRING = str_replace('index.php?', '', $row[1])."&Itemid=$Itemid";
  64. $REQUEST_URI = $GLOBALS['mosConfig_live_site'].'/index.php?'.$QUERY_STRING;
  65. $_SERVER['REQUEST_URI'] = $REQUEST_URI;
  66. $matches = array();
  67. if (preg_match("/option=([a-zA-Z_0-9]+)/", $QUERY_STRING, $matches)) {
  68. $_GET['option'] = $_REQUEST['option'] = $option = $matches[1];
  69. }
  70. if (preg_match("/id=([0-9]+)/", $QUERY_STRING, $matches)) {
  71. $_GET['id'] = $_REQUEST['id'] = $id = $matches[1];
  72. }
  73. if (preg_match("/task=([a-zA-Z_0-9]+)/", $QUERY_STRING, $matches)) {
  74. $_GET['task'] = $_REQUEST['task'] = $task = $matches[1];
  75. }
  76. unset($matches);
  77. $GLOBALS['JOOMSEF_DEBUG']['ROW'] = $row;
  78. $GLOBALS['JOOMSEF_DEBUG']['QUERY_STRING'] = $QUERY_STRING;
  79. $GLOBALS['JOOMSEF_DEBUG']['REQUEST_URI'] = $REQUEST_URI;
  80. $f = $l = '';
  81. if (!headers_sent($f, $l)) {
  82. header('HTTP/1.0 200 OK');
  83. }
  84. else headers_sent_error($f, $l, $GLOBALS['mosConfig_live_site'].$_SERVER['QUERY_STRING'], @$option);
  85. }*/
  86. // if MetaBot is installed ...
  87. $database->setQuery("SELECT id FROM #__mambots WHERE element = 'joomsef_metabot' AND folder = 'system' AND published = 1");
  88. if ($database->loadResult()) {
  89. // ... and frontpage has meta tags
  90. $database->setQuery("SELECT * FROM #__redirection WHERE oldurl = '' OR oldurl = '$index' LIMIT 1");
  91. if (!is_null($database->loadObject($sefRow))) {
  92. if (@$sefRow->metatitle) $GLOBALS['sefMetaTags']['title'] = $sefRow->metatitle;
  93. if (@$sefRow->metadesc) $GLOBALS['sefMetaTags']['metadesc'] = $sefRow->metadesc;
  94. if (@$sefRow->metakey) $GLOBALS['sefMetaTags']['metakey'] = $sefRow->metakey;
  95. if (@$sefRow->metalang) $GLOBALS['sefMetaTags']['lang'] = $sefRow->metalang;
  96. if (@$sefRow->metarobots) $GLOBALS['sefMetaTags']['robots'] = $sefRow->metarobots;
  97. if (@$sefRow->metagoogle) $GLOBALS['sefMetaTags']['googlebot'] = $sefRow->metagoogle;
  98. }
  99. }
  100. }
  101. break;
  102. }
  103. case '': {
  104. die(_COM_SEF_STRANGE.' URI->path='.$URI->path.":<br />".basename(__FILE__)."-".__LINE__);
  105. }
  106. default: {
  107. // lets process the URL
  108. // strip out the base
  109. $path = preg_replace('/^'.preg_quote($base, '/').'/', '', $URI->path);
  110. // path should never start with /
  111. $path = preg_replace('/^'.preg_quote('/', '/').'/', '', $path);
  112. // split path into array
  113. $path_array = explode('/', $path);
  114. // find appropriate extension handler
  115. $ext = getExt($path_array);
  116. $sef_ext_class = 'sef_'.$ext['name'];
  117. if ($sef_ext_class != 'sef_joomsef') {
  118. // do our space conversion
  119. // then find our suffix (.html) and strip it off,
  120. // SEF Advance extensions don't want the suffix
  121. // and some them require the spaces
  122. foreach ($path_array as $i => $pathdata) {
  123. //$path_array[$i] = $pathdata = str_replace($sefConfig->replacement, ' ', $pathdata);
  124. if ($sefConfig->suffix && strpos($pathdata, $sefConfig->suffix) !== false) {
  125. $path_array[$i] = str_replace($sefConfig->suffix, '', $pathdata);
  126. }
  127. }
  128. }
  129. if ($debug) {
  130. $GLOBALS['JOOMSEF_DEBUG']['EXT'] = $ext;
  131. $GLOBALS['JOOMSEF_DEBUG']['SEF_EXT'] = $sef_ext_class;
  132. $GLOBALS['JOOMSEF_DEBUG']['PATH'] = $path;
  133. }
  134. // set php show_error settings to prevent notices breaking headers
  135. // Dave: removed, caused fatal errors on servers where ini_set disabled
  136. //$displayErrors = @ini_get('display_errors');
  137. //@ini_set('display_errors', 0);
  138. // instantiate class that will take care about URL conversion
  139. if($ext['path'] != $GLOBALS['mosConfig_absolute_path'].'/components/com_sef/sef_ext.php') {
  140. require_once($ext['path']);
  141. }
  142. // also instantiate our own - always
  143. include_once ($GLOBALS['mosConfig_absolute_path'] . '/components/com_sef/sef_ext.php');
  144. eval("\$sef_ext = new $sef_ext_class;");
  145. $pos = 0;
  146. if (isset($_REQUEST['option'])) {
  147. $pos = array_search($_REQUEST['option'], $path_array);
  148. if ($pos === false) $pos = 0;
  149. }
  150. if ($sef_ext_class != 'sef_content'
  151. && $sef_ext_class != 'sef_component'
  152. && $pos == 0) {
  153. array_unshift($path_array, 'option');
  154. }
  155. if ($debug) {
  156. $GLOBALS['JOOMSEF_DEBUG']['POS'] = $pos;
  157. $GLOBALS['JOOMSEF_DEBUG']['PATH_ARRAY'] = $path_array;
  158. }
  159. // Revert the SEF url to non-SEF
  160. $_SEF_SPACE = $sefConfig->replacement;
  161. $QUERY_STRING = $sef_ext->revert($path_array, $pos);
  162. // Dave: removed, caused fatal errors on servers where ini_set disabled
  163. //@ini_set('display_errors', $displayErrors);
  164. if ($debug) {
  165. $GLOBALS['JOOMSEF_DEBUG']['REVERTED'] = $QUERY_STRING;
  166. }
  167. // append the original query string because some components
  168. // (like SMF Bridge and SOBI2) use it
  169. if (!empty($URI->querystring)) {
  170. foreach($URI->querystring as $name => $value) {
  171. if (empty($QUERY_STRING)) {
  172. $QUERY_STRING = $name.'='.$value;
  173. }
  174. else {
  175. $QUERY_STRING .= '&'.$name.'='.$value;
  176. }
  177. }
  178. // Let's save the variables from query string, we'll use them later
  179. // in sefRelToAbs as nonSefVars (because JoomFish's language
  180. // selection module creates duplicates without this)
  181. $GLOBALS['JOOMSEF_NONSEFVARS'] = $URI->querystring;
  182. }
  183. if ($debug) var_dump($GLOBALS['JOOMSEF_DEBUG']);
  184. if (is_valid($QUERY_STRING)) {
  185. // Set anchor without extras.
  186. $anchor = ($URI->anchor) ? '#'.$URI->anchor : '';
  187. $_SERVER['QUERY_STRING'] = $QUERY_STRING = str_replace('&?', '&', $QUERY_STRING./*(isset($QS) ? $QS : '').*/$anchor);
  188. $REQUEST_URI = $GLOBALS['mosConfig_live_site'].'/index.php?'.$QUERY_STRING;
  189. $_SERVER['REQUEST_URI'] = $REQUEST_URI;
  190. // Make sure to set option variable.
  191. $matches = array();
  192. if (preg_match("/option=([a-zA-Z_0-9]+)/", $QUERY_STRING, $matches)) {
  193. $_GET['option'] = $_REQUEST['option'] = $option = $matches[1];
  194. }
  195. unset($matches);
  196. // Add variables to GLOBALS only if RG_EMULATION is set to 1
  197. if( RG_EMULATION == 1 ) {
  198. while (list($key, $value) = each($_REQUEST)) {
  199. // Since this is very dangerous operation, let's set only those variables
  200. // that doesn't begin with mosConfig_
  201. if( (substr($key, 0, 10) != 'mosConfig_') ) {
  202. $GLOBALS[$key] = $value;
  203. }
  204. }
  205. }
  206. $f = $l = '';
  207. if (!headers_sent($f, $l)) {
  208. header('HTTP/1.0 200 OK');
  209. }
  210. else headers_sent_error($f, $l, $GLOBALS['mosConfig_live_site']."/index.php?".$_SERVER['QUERY_STRING'], @$option);
  211. }
  212. // bad URL, so check to see if we've seen it before
  213. else {
  214. // Maybe we need to redirect to index2.php
  215. if( substr($QUERY_STRING, 0, 10) == 'index2.php' ) {
  216. mosRedirect($mosConfig_live_site.'/'.$QUERY_STRING);
  217. exit();
  218. }
  219. // 404 recording (only if enabled)
  220. if ($sefConfig->record404) {
  221. $query = "SELECT * FROM #__redirection WHERE oldurl = '".$path."'";
  222. $database->setQuery($query);
  223. $results = $database->loadObjectList();
  224. if ($results) {
  225. // we have it, so update counter
  226. $database->setQuery("UPDATE #__redirection SET cpt=(cpt+1) WHERE oldurl = '".$path."'");
  227. $database->query();
  228. }
  229. else {
  230. // record the bad URL
  231. $query = 'INSERT INTO `#__redirection` (`cpt`, `oldurl`, `newurl`, `dateadd`) '
  232. . ' VALUES ( \'1\', \''.$path.'\', \'\', CURDATE() );'
  233. . ' ';
  234. $database->setQuery($query);
  235. $database->query();
  236. }
  237. }
  238. // redirect to the error page
  239. // you MUST create a static content page with the title 404 for this to work properly
  240. $mosmsg = 'FILE NOT FOUND: '.$path;
  241. $_GET['mosmsg'] = $_REQUEST['mosmsg'] = $mosmsg;
  242. $option = 'com_content';
  243. $task = 'view';
  244. if ($sefConfig->page404 == '0') {
  245. $sql='SELECT id FROM #__content WHERE `title`="404"';
  246. $database->setQuery($sql);
  247. if (($id = $database->loadResult())) {
  248. $Itemid = null; /*Beat: was wrong: =$id : the $Itemid represents the menuId, and $id the contentId ! */
  249. if( $sefConfig->itemid404 != '' ) {
  250. $Itemid = $sefConfig->itemid404;
  251. }
  252. $_SERVER['QUERY_STRING'] = "option=com_content&task=view&id=$id&Itemid=$id&mosmsg=$mosmsg";
  253. $_SERVER['REQUEST_URI'] = $GLOBALS['mosConfig_live_site']."/index.php?".$_SERVER['QUERY_STRING'];
  254. $_GET['option'] = $_REQUEST['option'] = $option;
  255. $_GET['task'] = $_REQUEST['task'] = $task;
  256. /*Beat: was wrong: $_GET['Itemid'] = $_REQUEST['Itemid'] = $Itemid; */
  257. unset($_GET['Itemid']);
  258. unset($_REQUEST['Itemid']);
  259. $_GET['id'] = $_REQUEST['id'] = $id;
  260. if( !is_null($Itemid) ) {
  261. $_GET['Itemid'] = $_REQUEST['Itemid'] = $Itemid;
  262. }
  263. }
  264. else {
  265. die(_COM_SEF_DEF_404_MSG.$mosmsg."<br>URI:".$_SERVER['REQUEST_URI']);
  266. }
  267. }
  268. elseif ($sefConfig->page404 == '9999999') {
  269. //redirect to frontpage
  270. $front404 = 1;
  271. }
  272. else{
  273. $id = $Itemid = $sefConfig->page404;
  274. $_SERVER['QUERY_STRING'] = "option=com_content&task=view&id=$id&Itemid=$id&mosmsg=$mosmsg";
  275. $_SERVER['REQUEST_URI'] = $GLOBALS['mosConfig_live_site'].'/index.php?'.$_SERVER['QUERY_STRING'];
  276. $_GET['option'] = $_REQUEST['option'] = $option;
  277. $_GET['task'] = $_REQUEST['task'] = $task;
  278. $_GET['Itemid'] = $_REQUEST['Itemid'] = $Itemid;
  279. $_GET['id'] = $_REQUEST['id'] = $id;
  280. }
  281. $f = $l = '';
  282. if (!headers_sent($f, $l)) {
  283. header('HTTP/1.0 404 NOT FOUND');
  284. if (isset($front404) && $front404) mosRedirect( $GLOBALS['mosConfig_live_site'] );
  285. }
  286. else headers_sent_error($f, $l, sefRelToAbs($GLOBALS['mosConfig_live_site'].'/index.php?'.$_SERVER['QUERY_STRING']), @$option);
  287. } // end bad url
  288. } //
  289. }
  290. if ($debug) {
  291. $GLOBALS['JOOMSEF_DEBUG']['SERVER_QUERY_STRING'] = $_SERVER['QUERY_STRING'];
  292. $GLOBALS['JOOMSEF_DEBUG']['SERVER_REQUEST_URI'] = $_SERVER['REQUEST_URI'];
  293. }
  294. /**
  295. * Check if own extension exists for a component.
  296. * This can be either db or nodb version.
  297. *
  298. * @param string $component Component name
  299. * @param bool $noDB Testing for non-db version?
  300. * @return object
  301. */
  302. function existOwnExt($option, $noDB = false)
  303. {
  304. if (!$noDB) {
  305. return is_readable($GLOBALS['mosConfig_absolute_path'].'/components/com_sef/sef_ext/'.$option.'.php');
  306. }
  307. else {
  308. $path = $GLOBALS['mosConfig_absolute_path'].'/components/com_sef/sef_ext_nodb/'.$option.'.php';
  309. return is_readable($path) ? $path : false;
  310. }
  311. }
  312. /**
  313. * Does the component in question has own (3rd party) sef extension?
  314. * Returns DB select result if found or null.
  315. *
  316. * @param string $component Component name
  317. * @return object
  318. */
  319. function exist3rdExt($option)
  320. {
  321. $path = $GLOBALS['mosConfig_absolute_path']."/components/$option/sef_ext.php";
  322. return is_readable($path) ? $path : false;
  323. }
  324. /**
  325. * Tries to find the component from first URL part
  326. *
  327. * @param string $component
  328. * @return string
  329. */
  330. function testComponent($component)
  331. {
  332. global $database, $sefConfig;
  333. $debug = 0;
  334. // Try to find the component in user defined extension titles
  335. // Load the list of titles (original language)
  336. $database->setQuery("SELECT file, title FROM #__sefexts WHERE title != ''");
  337. $rows = $database->loadObjectList('title');
  338. // Load the list of titles (JoomFish translations)
  339. if( !is_null($rows) && class_exists('JoomFish') ) {
  340. $database->setQuery("SELECT l.value AS title, s.file AS file FROM #__jf_content AS l INNER JOIN #__sefexts AS s ON s.id = l.reference_id WHERE l.reference_table = 'sefexts' AND l.reference_field = 'title' AND l.published > 0");
  341. $rows2 = $database->loadObjectList('title');
  342. if( !is_null($rows2) ) $rows = array_merge($rows, $rows2);
  343. }
  344. // Remove special characters from titles
  345. if( !is_null($rows) ) {
  346. foreach($rows as $k => $v) {
  347. $k2 = titleToLocation($k);
  348. if( !isset($rows[$k2]) ) $rows[$k2] = $v;
  349. }
  350. }
  351. // If component is found, return it
  352. if( isset($rows[$component]) ) {
  353. $result = new stdClass();
  354. $result->name = str_replace('.xml', '', $rows[$component]->file);
  355. $database->setQuery("SELECT id FROM #__menu WHERE link LIKE 'index.php?option={$result->name}%' AND published > 0");
  356. $result->id = $database->loadResult();
  357. return $result;
  358. }
  359. // Component not found in custom titles, let's search through the menu
  360. // Load the list of menu items
  361. $database->setQuery("SELECT name, link, id FROM #__menu WHERE published > 0 AND link LIKE 'index.php?option=com_%'");
  362. $rows = $database->loadObjectList('name');
  363. // Load the list of translated menu items, if JoomFish is present
  364. if( !is_null($rows) && class_exists('JoomFish') ) {
  365. $database->setQuery("SELECT l.value AS name, m.link AS link, m.id as id FROM #__jf_content AS l INNER JOIN #__menu AS m ON m.id = l.reference_id WHERE l.reference_table = 'menu' AND l.reference_field = 'name' AND l.published > 0 AND m.published > 0 AND m.link LIKE 'index.php?option=com_%'");
  366. $rows2 = $database->loadObjectList('name');
  367. if( !is_null($rows2) ) $rows = array_merge($rows, $rows2);
  368. }
  369. // Remove special characters from titles
  370. if( !is_null($rows) ) {
  371. foreach($rows as $k => $v) {
  372. $k2 = titleToLocation($k);
  373. if( !isset($rows[$k2]) ) $rows[$k2] = $v;
  374. }
  375. }
  376. // If component is found, return it
  377. if( isset($rows[$component]) ) {
  378. $name = str_replace('index.php?option=', '', $rows[$component]->link);
  379. $pos = strpos($name, '&');
  380. if( $pos > 0 ) $name = substr($name, 0, $pos);
  381. $rows[$component]->name = $name;
  382. return $rows[$component];
  383. }
  384. // Component not found
  385. $componentObj = new stdClass();
  386. $componentObj->name = $component;
  387. return $componentObj;
  388. }
  389. /**
  390. * Determine what class use to convert URLs.
  391. *
  392. * @param array $urlArray
  393. * @return string
  394. */
  395. function getExt($urlArray)
  396. {
  397. global $database, $sefConfig;
  398. $ext = array();
  399. $ext['path'] = $GLOBALS['mosConfig_absolute_path'].'/components/com_sef/sef_ext.php';
  400. // test if component with given name can be found
  401. $component = testComponent($urlArray[0]);
  402. // if found our own plug-in, use it
  403. // 1st test for nodb version
  404. if (($path = existOwnExt($component->name, true))) {
  405. $_GET['option'] = $_REQUEST['option'] = $option = $component->name;
  406. $_GET['Itemid'] = $_REQUEST['Itemid'] = $Itemid = $component->id;
  407. $ext['path'] = $path;
  408. }
  409. // then test db version
  410. elseif (existOwnExt($component->name, false)) {
  411. $option = 'com_joomsef';
  412. }
  413. // otherwise try to find 3rd party sef_ext
  414. elseif (($path = exist3rdExt($component->name))) {
  415. $_GET['option'] = $_REQUEST['option'] = $option = $component->name;
  416. $_GET['Itemid'] = $_REQUEST['Itemid'] = $Itemid = $component->id;
  417. $ext['path'] = $path;
  418. }
  419. // built-in component ext
  420. elseif ((strpos($urlArray[0], 'com_') !== false) or ($urlArray[0] == 'component')) {
  421. $_GET['option'] = $_REQUEST['option'] = $option = 'com_component';
  422. }
  423. // built-in content ext
  424. elseif($urlArray[0] == 'content') {
  425. $_GET['option'] = $_REQUEST['option'] = $option = 'com_content';
  426. }
  427. // otherwise use default handler
  428. else $option = 'com_joomsef';
  429. $ext['name'] = str_replace('com_', '', $option);
  430. return $ext;
  431. }
  432. /**
  433. * Validates the query string
  434. *
  435. * @param string $string
  436. * @return bool
  437. */
  438. function is_valid($string)
  439. {
  440. global $base, $index;
  441. // David: removed || $string == '' in revision 281, was causing problems with 404 page
  442. if (strcmp($string, $index) == 0 || strcmp($string, $base.$index) == 0) {
  443. $state = true;
  444. }
  445. else {
  446. $state = false;
  447. include_once ($GLOBALS['mosConfig_absolute_path'] . '/components/com_sef/sef_ext.php');
  448. $sef_ext = new sef_joomsef();
  449. $option = (isset($_GET['option'])) ? $_GET['option'] : (isset($_REQUEST['option'])) ? $_REQUEST['option'] : null;
  450. $vars = array();
  451. if (is_null($option)) {
  452. parse_str($string, $vars);
  453. if (isset($vars['option'])) {
  454. $option = $vars['option'];
  455. }
  456. }
  457. switch ($option) {
  458. case is_null($option): break;
  459. case 'login': /*Beat: makes this also compatible with CommunityBuilder login module*/
  460. case 'logout': {
  461. $state = true;
  462. break;
  463. }
  464. default: {
  465. if (is_valid_component($option)){
  466. if ($option != 'com_content' | $option != 'content') {
  467. $state = true;
  468. }
  469. else {
  470. $title = $sef_ext->getContentTitles($_REQUEST['task'], $_REQUEST['id']);
  471. //die(count($title));
  472. if (count($title) > 0) $state = true;
  473. }
  474. }
  475. }
  476. }
  477. }
  478. return $state;
  479. }
  480. /**
  481. * Check whether object is a valid component.
  482. *
  483. * @param object $this
  484. * @return bool
  485. */
  486. function is_valid_component($this)
  487. {
  488. $state = false;
  489. $path = $GLOBALS['mosConfig_absolute_path'] .'/components/';
  490. if (is_dir($path) && $contents = opendir($path)) {
  491. while (($node = readdir($contents)) !== false) {
  492. if ($node != '.' && $node != '..'
  493. && is_dir($path.'/'.$node) && $this == $node) {
  494. $state = true;
  495. break;
  496. }
  497. }
  498. }
  499. return $state;
  500. }
  501. /**
  502. * Rewrite relative URL to absolute.
  503. *
  504. * @param string $string
  505. * @return string
  506. */
  507. function sefRelToAbs($string)
  508. {
  509. global $database, $sefConfig, $_SEF_SPACE, $mosConfig_db, $mainframe, $mosConfig_lang, $_MAMBOTS, $jsCache;
  510. // Trigger onSefStart patches
  511. $_MAMBOTS->trigger('onSefStart');
  512. $debug = 0;
  513. $prevLang = ''; // For correct title translations
  514. // Check if this is site root.
  515. if ($string == $GLOBALS['mosConfig_live_site']
  516. || $string == $GLOBALS['mosConfig_live_site'].'/'
  517. || $string == $GLOBALS['mosConfig_live_site'].'/index.php') {
  518. // Trigger onSefEnd patches
  519. $_MAMBOTS->trigger('onSefEnd');
  520. return $GLOBALS['mosConfig_live_site'];
  521. }
  522. $newstring = str_replace($GLOBALS['mosConfig_live_site'].'/', '', $string);
  523. $newstring = ltrim($newstring, '/');
  524. // If this appears to be SEO-able URL, work with it.
  525. if (((strcasecmp(substr($newstring, 0, 9), 'index.php') == 0) || (strcasecmp(substr($newstring, 0, 10), 'index2.php') == 0))
  526. && !eregi('^(([^:/?#]+):)', $newstring)
  527. && !eregi('this\.options\[selectedIndex\]\.value', $newstring))
  528. {
  529. // if newstring is just anchor, prepend current query string
  530. if ($newstring[0] == '#') $newstring = 'index.php?' . $_SERVER['QUERY_STRING'] . $newstring;
  531. // Replace & character variations.
  532. $string = str_replace(array('&amp;', '&#38;'), array('&', '&'), $newstring);
  533. // Remove bad characters at the end (just for sure)
  534. $string = trim($string, '?&');
  535. if (class_exists('JoomFish')) {
  536. // add lang if configured to and it is missing
  537. if ($sefConfig->alwaysUseLang && strpos($string, 'lang=') === false && SEFTools::getLangCode() != 'en') { //Organic mod, added && SEFTools::getLangCode() != 'en' to stop en being aded to urls
  538. // handle the anchor
  539. $matches = array();
  540. if( preg_match('/(#.*)$/', $string, $matches) ) {
  541. $anchor = $matches[1];
  542. $string = str_replace($anchor, '', $string);
  543. }
  544. unset($matches);
  545. // add the lang variable
  546. $string .= ((strpos($string, '?') !== false) ? '&' : '?');
  547. $string .= 'lang='.SEFTools::getLangCode();
  548. if (isset($anchor)) {
  549. $string .= $anchor;
  550. unset($anchor);
  551. }
  552. }
  553. // Handle URLs with empty lang variable
  554. if (eregi('lang=(&|$)', $string) && SEFTools::getLangCode() != 'en') { //Organic mod, added && SEFTools::getLangCode() != 'en' to stop en being aded to urls
  555. if($sefConfig->alwaysUseLang) {
  556. $string = str_replace('lang=', 'lang='.SEFTools::getLangCode(), $string);
  557. } else {
  558. $string = SEFTools::RemoveVariable($string, 'lang');
  559. }
  560. }
  561. // Get the URL's language and set it as mosConfig_lang (for correct translation)
  562. $matches = array();
  563. $iso = '';
  564. if (preg_match('/lang=([^&]*)/', $string, $matches)) {
  565. $iso = $matches[1];
  566. $urlLang = SEFTools::getLangName($iso);
  567. if ($mosConfig_lang != $urlLang) {
  568. $prevLang = $mosConfig_lang;
  569. $mosConfig_lang = $urlLang;
  570. }
  571. }
  572. // Set the live_site according to language
  573. if ($sefConfig->langPlacement == _COM_SEF_LANG_DOMAIN) {
  574. if( $iso != '' ) {
  575. $langId = SEFTools::getLangId($iso);
  576. if( isset($sefConfig->langDomain[$langId]) )
  577. $langOverride = $sefConfig->langDomain[$langId];
  578. }
  579. }
  580. }
  581. $URI = new Net_URL($string);
  582. if (count($URI->querystring) > 0) {
  583. // Import new vars here.
  584. $option = null;
  585. $task = null;
  586. $sid = null;
  587. extract($URI->querystring, EXTR_REFS);
  588. }
  589. else {
  590. // Trigger onSefEnd patches
  591. $_MAMBOTS->trigger('onSefEnd');
  592. restoreLang($prevLang);
  593. return $URI->url;
  594. }
  595. // Check URLs for junk if set to
  596. if( $sefConfig->checkJunkUrls ) {
  597. $junkWords = array( 'http://', 'https://', 'www.', '@' );
  598. $seferr = false;
  599. if (isset($option) && (substr($option, 0, 4) !== 'com_')) {
  600. $seferr = true;
  601. } else {
  602. foreach ($junkWords as $word ) {
  603. if ((isset($task) && (strpos($task, $word) !== false)) || (isset($id) && (strpos($id, $word) !== false))) {
  604. $seferr = true;
  605. break;
  606. }
  607. }
  608. }
  609. if ($seferr) {
  610. // Trigger onSefEnd patches
  611. $_MAMBOTS->trigger('onSefEnd');
  612. restoreLang($prevLang);
  613. return $URI->url;
  614. }
  615. }
  616. // is there a named anchor attached to $string? If so, strip it off, we'll put it back later.
  617. if ($URI->anchor) $string = str_replace('#'.$URI->anchor, '', $string);
  618. if ($debug) {
  619. $GLOBALS['JOOMSEF_DEBUG']['sefRelToAbs'][$string]= $URI;
  620. $debugString = $string;
  621. }
  622. //if (!((isset($task) ? ((@$task == "new") | (@$task == "edit")) : false)) && isset($option) ) {
  623. if (isset($option) && @$task != 'edit') {
  624. /*Beat: sometimes task is not set, e.g. when $string = "index.php?option=com_frontpage&Itemid=1" */
  625. switch ($option) {
  626. // skipped extensions
  627. case (in_array($option, $sefConfig->skip)): {
  628. $sefstring = str_replace('&', '&amp;', $string);
  629. //$skipThis = true;
  630. break;
  631. }
  632. // Non-cached extensions.
  633. case (in_array($option, $sefConfig->nocache)): {
  634. $sefstring = 'component/';
  635. foreach($URI->querystring as $key => $value) {
  636. $sefstring .= "$key,$value/";
  637. }
  638. $sefstring = str_replace('option/', '', $sefstring);
  639. break;
  640. }
  641. // Default handler.
  642. default: {
  643. // If component has its own sef_ext plug-in included.
  644. // However, prefer own plugin if exists (added by Michal, 28.11.2006)
  645. if (file_exists($GLOBALS['mosConfig_absolute_path']."/components/$option/sef_ext.php")
  646. && !file_exists($GLOBALS['mosConfig_absolute_path']."/components/com_sef/sef_ext/$option.php")) {
  647. // Load the plug-in file.
  648. require_once($GLOBALS['mosConfig_absolute_path']."/components/$option/sef_ext.php");
  649. // Load our sef also to provide general functions.
  650. include_once ($GLOBALS['mosConfig_absolute_path'] . '/components/com_sef/sef_ext.php');
  651. $_SEF_SPACE = $sefConfig->replacement;
  652. if( !defined('_SEF_SPACE') ) define('_SEF_SPACE', $sefConfig->replacement);
  653. global $url_replace, $url_exception;
  654. $url_replace = $sefConfig->getReplacements();
  655. $url_exception = explode('|', $sefConfig->stripthese);
  656. //$longurl = ($sefConfig->useAlias == 1);
  657. //$lowerCase = $sefConfig->lowerCase;
  658. $className = str_replace('com_', 'sef_', $option);
  659. eval("\$sef_ext = new $className;");
  660. $title = getMenuTitle($option, null);
  661. $string = str_replace('&', '&amp;', $string);
  662. $sefstring = $sef_ext->create($string);
  663. if ($sefstring == $string) {
  664. // Trigger onSefEnd patches
  665. $_MAMBOTS->trigger('onSefEnd');
  666. restoreLang($prevLang);
  667. return $string;
  668. }
  669. else {
  670. $sefstring = str_replace(' ', $_SEF_SPACE, $sefstring);
  671. $sefstring = str_replace(' ', '', titleToLocation($title).'/'.$sefstring.(($sefstring != '') ? $sefConfig->suffix : ''));
  672. $sefstring = str_replace('/'.$sefConfig->suffix, $sefConfig->suffix, $sefstring);
  673. }
  674. }
  675. // Component has no own sef extension.
  676. else {
  677. include_once ($GLOBALS['mosConfig_absolute_path'] . '/components/com_sef/sef_ext.php');
  678. // Try to load the extension class
  679. if (file_exists($GLOBALS['mosConfig_absolute_path'].'/components/com_sef/sef_ext/'.$option.'.php')) {
  680. require_once($GLOBALS['mosConfig_absolute_path'].'/components/com_sef/sef_ext/'.$option.'.php');
  681. $class = 'sefext_'.$option;
  682. } else {
  683. $class = 'sef_joomsef';
  684. }
  685. $sef_ext = new $class();
  686. // Let the extension change the url and options
  687. $string = $sef_ext->beforeCreate($string, $URI->querystring);
  688. // Ensure that the session IDs are removed
  689. // If set to
  690. if (isset($sid) && !$sefConfig->dontRemoveSid) $string = SEFTools::RemoveVariable($string, 'sid');
  691. // Ensure that the mosmsg are removed.
  692. if (isset($mosmsg)) $string = SEFTools::RemoveVariable($string, 'mosmsg');
  693. // Override Itemid if set to
  694. $params = SEFTools::getExtParams($option);
  695. $override = $params->get('itemid', '0');
  696. $overrideId = $params->get('overrideId', '');
  697. if (($override != '0') && ($overrideId != '')) {
  698. if (strpos($string, 'Itemid=')) {
  699. $string = eregi_replace('Itemid=[^&]*', 'Itemid='.$overrideId, $string);
  700. } else {
  701. $string .= (strpos($string, '?') ? '&' : '?').'Itemid='.$overrideId;
  702. }
  703. }
  704. // Clean Itemid if desired.
  705. // David: only if overriding is disabled
  706. if (isset($sefConfig->excludeSource) && $sefConfig->excludeSource && ($override == '0') && isset($Itemid)) {
  707. $string = SEFTools::RemoveVariable($string, 'Itemid');
  708. }
  709. // clean remaining characters
  710. $string = trim($string, '&?');
  711. $string = str_replace('&&', '&', $string);
  712. $anchor = (isset($URI->anchor)) ? '#'.$URI->anchor : '';
  713. $URI = new Net_URL($string.$anchor);
  714. extract($URI->querystring, EXTR_REFS);
  715. // Let's reorder the variables in non-sef url first so they
  716. // are in alphabetical order (some components create for
  717. // the same page urls with different variables order)
  718. // -- except option which should be first (changed in 1.3.4)
  719. $string = SEFTools::sortURLvars($string);
  720. // Try to get url from cache
  721. if ($sefConfig->useCache) {
  722. $sefstring = $jsCache->GetSefUrl($string);
  723. }
  724. if (!$sefConfig->useCache || !$sefstring) {
  725. // Check if the url is already saved in the database.
  726. if (!($sefstring = $sef_ext->getSefUrlFromDatabase($string))) {
  727. // Rewrite the URL now.
  728. $sefstring = $sef_ext->create($string, $URI->querystring);
  729. }
  730. }
  731. // Reconnect the sid to the url.
  732. if (isset($sid) && !$sefConfig->dontRemoveSid) $sefstring .= (strpos($sefstring, '?') !== false ? '&amp;' : '?').'sid='.$sid;
  733. // Reconnect mosmsg to the url.
  734. if (isset($mosmsg)) {
  735. // check if the mosmsg isn't already encoded properly
  736. if (urlencode($mosmsg) == urlencode(urldecode($mosmsg))) {
  737. $mosmsg = urlencode($mosmsg);
  738. }
  739. $sefstring .= (strpos($sefstring, '?') !== false ? '&amp;' : '?').'mosmsg='.$mosmsg;
  740. }
  741. // Reconnect ItemID to the url.
  742. // David: only if extension doesn't set its own Itemid through overrideId parameter
  743. if (isset($sefConfig->excludeSource) && $sefConfig->excludeSource && $sefConfig->reappendSource && ($override == '0') && isset($Itemid)) {
  744. $sefstring .= (strpos($sefstring, '?') !== false ? '&amp;' : '?').'Itemid='.urlencode($Itemid);
  745. //$URI->anchor .= (($URI->anchor) ? '-' : '').urlencode('ii'.$Itemid);
  746. }
  747. // Let the extension change the resulting SEF url
  748. $sefstring = $sef_ext->afterCreate($sefstring);
  749. }
  750. }
  751. }
  752. if ($debug){ $GLOBALS['JOOMSEF_DEBUG']['sefRelToAbs']['SEF_EXT'][$debugString] = $sef_ext;}
  753. if (isset($sef_ext)) unset($sef_ext);
  754. $livesite = (isset($langOverride) ? $langOverride : $GLOBALS['mosConfig_live_site']);
  755. $livesite = rtrim($livesite, '/');
  756. $string = $livesite.'/'.$sefstring.(($URI->anchor)? '#'.$URI->anchor : '');
  757. }
  758. //$ret = (!isset($skipThis) || !$skipThis) ? ($sefConfig->lowerCase ? strtolower($string) : $string) : $string;
  759. $ret = $string;
  760. $ret = str_replace('itemid', 'Itemid', $ret);
  761. }
  762. if (!isset($ret)) $ret = $string;
  763. if ($debug) $GLOBALS['JOOMSEF_DEBUG']['sefRelToAbs']['RET'][$debugString] = $ret;
  764. // Trigger onSefEnd patches
  765. $_MAMBOTS->trigger('onSefEnd');
  766. restoreLang($prevLang);
  767. return $ret;
  768. }
  769. /**
  770. * If given language is different from actual joomla's one, select it
  771. *
  772. * @param string $lang
  773. */
  774. function restoreLang($lang)
  775. {
  776. global $mosConfig_lang;
  777. if (($lang != '') && ($lang != $mosConfig_lang)) {
  778. $mosConfig_lang = $lang;
  779. }
  780. }
  781. /**
  782. * Convert title to URL name.
  783. *
  784. * @param string $title
  785. * @return string
  786. */
  787. function titleToLocation(&$title)
  788. {
  789. global $sefConfig;
  790. // remove accented characters
  791. // $title = strtr($title,
  792. //'�������������������������������������ݍ�������������������������������',
  793. //'SOZsozzAuRAAAALCCCEEEEIIDDNNOOOORUUUUYTsraaaalccceeeeiiddnnooooruuuuyt-');
  794. // Replace non-ASCII characters.
  795. $title = strtr($title, $sefConfig->getReplacements());
  796. // remove quotes, spaces, and other illegal characters
  797. $title = preg_replace(array('/\'/', '/[^a-zA-Z0-9\-!.,+]+/', '/(^_|_$)/'), array('', $sefConfig->replacement, ''), $title);
  798. return $sefConfig->lowerCase ? strtolower($title) : $title;
  799. }
  800. /**
  801. * If headers were already sent, output this error message.
  802. *
  803. * @param string $file
  804. * @param int $line
  805. * @param string $url
  806. * @param string $option
  807. */
  808. function headers_sent_error($file, $line, $url, $option)
  809. {
  810. die("<br />Error: headers already sent in ".basename($file)." on line $line.<br />Stopped at line ".__LINE__." in ".basename(__FILE__).": HEADERS ALREADY SENT (200)<br />URL=".@$url.":<br />OPTION=".@$option.":");
  811. }
  812. /**
  813. * Returns the custom menu title for a component
  814. * or null if it's not set
  815. *
  816. * @param string $option
  817. * @return string
  818. */
  819. function getCustomMenuTitle($option) {
  820. global $database, $sefConfig, $mosConfig_lang;
  821. static $titles;
  822. $jfTranslate = $sefConfig->translateNames ? ', id' : '';
  823. if( !isset($titles) ) $titles = array();
  824. if( !isset($titles[$mosConfig_lang]) ) {
  825. $database->setQuery("SELECT file, title$jfTranslate FROM #__sefexts");
  826. $titles[$mosConfig_lang] = $database->loadObjectList('file');
  827. }
  828. $file = $option.'.xml';
  829. if( isset($titles[$mosConfig_lang][$file]->title) ) {
  830. return $titles[$mosConfig_lang][$file]->title;
  831. } else {
  832. return null;
  833. }
  834. }
  835. /**
  836. * Returns the title for a component
  837. *
  838. * @param string $option
  839. * @param string $task
  840. * @param string $id
  841. * @param string $string
  842. * @return string
  843. */
  844. function getMenuTitle($option, $task, $id = null, $string = null)
  845. {
  846. global $database, $sefConfig;
  847. $debug = 0;
  848. // JF translate extension.
  849. $jfTranslate = $sefConfig->translateNames ? ', id' : '';
  850. if( $title = getCustomMenuTitle($option) ) {
  851. return $title;
  852. }
  853. if (isset($string)) {
  854. $sql = "SELECT name$jfTranslate FROM #__menu WHERE `link` = '$string' AND `published` > 0";
  855. }
  856. elseif (isset($id) && $id != 0) {
  857. $sql = "SELECT name$jfTranslate FROM #__menu WHERE `id` = '$id' AND `published` > 0";
  858. }
  859. else {
  860. // Search for direct link to component only
  861. $sql = "SELECT name$jfTranslate FROM #__menu WHERE `link` = 'index.php?option=$option' AND `published` > 0";
  862. }
  863. $database->setQuery($sql);
  864. $rows = @$database->loadObjectList();
  865. if ($debug) {
  866. echo('<pre>');
  867. $GLOBALS['JOOMSEF_DEBUG']['getMenuTitle']['ROWS-'.$option.'-'.$task] = $rows;
  868. echo('</pre>');
  869. }
  870. if ($database->getErrorNum()) die($database->stderr());
  871. elseif (@count($rows) > 0) {
  872. if (!empty($rows[0]->name)) $title = $rows[0]->name;
  873. }
  874. else {
  875. $title = str_replace('com_', '', $option);
  876. if( !isset($string) && !isset($id) ) {
  877. // Try to extend the search for any link to component
  878. $sql = "SELECT name$jfTranslate FROM #__menu WHERE `link` LIKE 'index.php?option=$option%' AND `published` > 0";
  879. $database->setQuery($sql);
  880. $rows = @$database->loadObjectList();
  881. if ($database->getErrorNum()) die($database->stderr());
  882. elseif (@count($rows) > 0) {
  883. if (!empty($rows[0]->name)) $title = $rows[0]->name;
  884. }
  885. }
  886. }
  887. return $title;
  888. }
  889. ?>