<?php
/**
 * Joom!Fish - Multi Lingual extention and translation manager for Joomla!
 * Copyright (C) 2003-2009 Think Network GmbH, Munich
 * 
 * All rights reserved.  The Joom!Fish project is a set of extentions for 
 * the content management system Joomla!. It enables Joomla! 
 * to manage multi lingual sites especially in all dynamic information 
 * which are stored in the database.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
 *
 * The "GNU General Public License" (GPL) is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * -----------------------------------------------------------------------------
 * $Id: jfrouter.php 1395 2009-08-20 09:21:32Z geraint $
 * @package joomfish
 * @subpackage jfrouter
 * @version 2.0
 *
*/

/** ensure this file is being included by a parent file */
defined( '_JEXEC' ) or die( 'Restricted access' );

// In PHP5 this should be a instance_of check
// Currently Joom!Fish does not need to be active in Administrator
// This might be an extended version
if($mainframe->isAdmin()) {
	return;
}
jimport('joomla.filesystem.file');
// Joom!Fish router only gets activated if essential files are missing
//if ( !file_exists( JPATH_PLUGINS .DS. 'system' .DS. 'jfdatabase' .DS. 'jfdatabase.class.php' )) {
if ( !JFile::exists( dirname(__FILE__) .DS. 'jfrouter' .DS. 'contact.php' )) {
	JError::raiseNotice('no_jf_plugin', JText::_('Joom!Fish router plugin not installed correctly. Plugin not executed'));
	return;
}
if(JFile::exists(JPATH_SITE .DS. 'components' .DS. 'com_joomfish' .DS. 'helpers' .DS. 'defines.php')) {
	require_once( JPATH_SITE .DS. 'components' .DS. 'com_joomfish' .DS. 'helpers' .DS. 'defines.php' );
	JLoader::register('JoomfishManager', JOOMFISH_ADMINPATH .DS. 'classes' .DS. 'JoomfishManager.class.php' );
	JLoader::register('JoomFishVersion', JOOMFISH_ADMINPATH .DS. 'version.php' );
	JLoader::register('JoomFish', JOOMFISH_PATH .DS. 'helpers' .DS. 'joomfish.class.php' );	
} else {
	JError::raiseNotice('no_jf_extension', JText::_('Joom!Fish extension not installed correctly. Plugin not executed'));
	return;
}
/**
* Language Determination and basic routing for Joomfish
*/
class plgSystemJFRouter extends JPlugin{

	/**
	 * stored configuration from plugin
	 *
	 * @var object configuration information
	 */
	var $_config = null;

	function plgSystemJFRouter(& $subject, $config)
	{
		global $mainframe;
		if ($mainframe->isAdmin()) {
			// This plugin is only relevant for use within the frontend!
			return;
		}
		parent::__construct($subject, $config);

		// put params in registry so I have easy access to them later
		$conf =& JFactory::getConfig();
		$conf->setValue("jfrouter.params",$this->params);

		// Must do this here in case other plugins instantiate language!
		// Get the router
		$app	= &JFactory::getApplication();
		$router = &$app->getRouter();

		// atttach build rules for language
		$router->attachBuildRule("routeJFRule");

		// This gets the language from the router before any other part of Joomla can load the language !!
		$uri = &JURI::getInstance();
		$this->parseJFRule($router, $uri);
	}

	function _discoverJFLanguage ( ) {

		static $discovered;
		if (isset($discovered) && $discovered){
			return;
		}
		$discovered=true;

		$registry =& JFactory::getConfig();

		// Find language without loading strings		
		$locale	= $registry->getValue('config.language');
		
		// Attention - we need to access the site default values
		// #12943 explains that a user might overwrite the orignial settings based on his own profile
		$langparams = JComponentHelper::getParams('com_languages');
		$registry->setValue("config.defaultlang",$langparams->get("site"));

		// get params from registry in case function called statically
		$params = $registry->getValue("jfrouter.params");

		$determitLanguage 		= $params->get( 'determitLanguage', 1 );
		$newVisitorAction		= $params->get( 'newVisitorAction', 'browser' );
		$use302redirect			= $params->get( 'use302redirect', 0 );
		$enableCookie			= $params->get( 'enableCookie', 1 );

		// get instance of JoomFishManager to obtain active language list and config values
		$jfm =&  JoomFishManager::getInstance();
	
		$client_lang = '';
		$lang_known = false;
		$jfcookie = JRequest::getVar('jfcookie', null ,"COOKIE");
		if (isset($jfcookie["lang"]) && $jfcookie["lang"] != "") {
			$client_lang = $jfcookie["lang"];
			$lang_known = true;
		}

		$uri =& JURI::getInstance();
		if ($requestlang = JRequest::getVar('lang', null ,"REQUEST")){
			if( $requestlang != '' ) {
				$client_lang = $requestlang;
				$lang_known = true;
			}
		}

		// no language choosen - Test plugin e.g. IP lookup tool
		if ( !$lang_known)	{
			// setup Joomfish pluginds
			$dispatcher	   =& JDispatcher::getInstance();
			$iplang="";
			JPluginHelper::importPlugin('joomfish');
			$dispatcher->trigger('onDiscoverLanguage', array (& $iplang));
			if ($iplang!=""){
				$client_lang = $iplang;
				$lang_known = true;
			}
		}
		if ( !$lang_known && $determitLanguage &&
		key_exists( 'HTTP_ACCEPT_LANGUAGE', $_SERVER ) && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) ) {

			switch ($newVisitorAction) {
				// usesing the first defined Joom!Fish language
				case 'joomfish':
					$activeLanguages = $jfm->getActiveLanguages();
					reset($activeLanguages);
					$first = key($activeLanguages);
					$client_lang = $activeLanguages[$first]->getLanguageCode();
					break;

				case 'site':
					// We accept that this default locale might be overwritten by user settings!
					$jfLang = TableJFLanguage::createByJoomla( $locale );
					$client_lang = $jfLang->getLanguageCode();
					break;

					// no language chooses - assume from browser configuration
				case 'browser':
				default:
					// language negotiation by Kochin Chang, June 16, 2004
					// retrieve active languages from database
					$active_iso = array();
					$active_isocountry = array();
					$active_code = array();
					$activeLanguages = $jfm->getActiveLanguages();
					if( count( $activeLanguages ) == 0 ) {
						return;
					}

					foreach ($activeLanguages as $alang) {
						$active_iso[] = $alang->iso;
						if( eregi('[_-]', $alang->iso) ) {
							$isocountry = split('[_-]',$alang->iso);
							$active_isocountry[] = $isocountry[0];
						}
						$active_code[] = $alang->shortcode;
					}

					// figure out which language to use - browser languages are based on ISO codes
					$browserLang = explode(',', $_SERVER["HTTP_ACCEPT_LANGUAGE"]);

					foreach( $browserLang as $blang ) {
						if( in_array($blang, $active_iso) ) {
							$client_lang = $blang;
							break;
						}
						$shortLang = substr( $blang, 0, 2 );
						if( in_array($shortLang, $active_isocountry) ) {
							$client_lang = $shortLang;
							break;
						}

						// compare with code
						if ( in_array($shortLang, $active_code) ) {
							$client_lang = $shortLang;
							break;
						}
					}
					break;
			}
		}

		// get the name of the language file for joomla
		$jfLang = TableJFLanguage::createByShortcode($client_lang, false);
		if( $jfLang === null && $client_lang!="") {
			$jfLang = TableJFLanguage::createByISO( $client_lang, false );
		}
		else if( $jfLang === null) {
			$jfLang = TableJFLanguage::createByJoomla( $locale );
		}

		if( !$lang_known && $use302redirect ) {
			// using a 302 redirect means that we do not change the language on the fly the first time, but with a clean reload of the page

			$href= "index.php";
			$hrefVars = '';
			$queryString = JRequest::getVar('QUERY_STRING', null ,"SERVER");
			if( !empty($queryString) ) {
				$vars = explode( "&", $queryString );
				if( count($vars) > 0 && $queryString) {
					foreach ($vars as $var) {
						if( eregi('=', $var ) ) {
							list($key, $value) = explode( "=", $var);
							if( $key != "lang" ) {
								if( $hrefVars != "" ) {
									$hrefVars .= "&amp;";
								}
								// ignore mosmsg to ensure it is visible in frontend
								if( $key != 'mosmsg' ) {
									$hrefVars .= "$key=$value";
								}
							}
						}
					}
				}
			}

			// Add the existing variables
			if( $hrefVars != "" ) {
				$href .= '?' .$hrefVars;
			}

			if( $jfLang->getLanguageCode() != null ) {
				$ulang = 'lang=' .$jfLang->getLanguageCode();
			} else {
				// it's important that we add at least the basic parameter - as of the sef is adding the actual otherwise!
				$ulang = 'lang=';
			}

			// if there are other vars we need to add a & otherwiese ?
			if( $hrefVars == '' ) {
				$href .= '?' . $ulang;
			} else {
				$href .= '&amp;' . $ulang;
			}

			$registry->setValue("config.multilingual_support", true);
			global $mainframe;

			$mainframe->setUserState('application.lang',$jfLang->code);
			$registry->setValue("config.jflang", $jfLang->code);
			$registry->setValue("config.lang_site",$jfLang->code);
			$registry->setValue("config.language",$jfLang->code);
			$registry->setValue("joomfish.language",$jfLang);

			$href = JRoute::_($href,false);
			
			header( 'HTTP/1.1 303 See Other' );
			header( "Location: ". $href );
			exit();
		}

		if( isset($jfLang) && $jfLang->code != "" && ($jfLang->active  || $jfm->getCfg("frontEndPreview") )) {
			$locale = $jfLang->code;
		} else {
			$jfLang = TableJFLanguage::createByJoomla( $locale );
		if( !$jfLang->active ) {
			?>
			<div style="background-color: #c00; color: #fff">
				<p style="font-size: 1.5em; font-weight: bold; padding: 10px 0px 10px 0px; text-align: center; font-family: Arial, Helvetica, sans-serif;">
				Joom!Fish config error: Default language is inactive!<br />&nbsp;<br />
				Please check configuration, try to use first active language</p>
			</div>
			<?php
			$activeLanguages = $jfm->getActiveLanguages();
			if( count($activeLanguages) > 0 ) {
				$jfLang = $activeLanguages[0];
				$locale = $jfLang->code;
			}
			else {
				// No active language defined - using system default is only alternative!
			}
			}
			$client_lang = ($jfLang->shortcode!='') ? $jfLang->shortcode : $jfLang->iso;
		}

		// TODO set the cookie domain so that it works for all subdomains
		if ($enableCookie){
			setcookie( "lang", "", time() - 1800, "/" );
			setcookie( "jfcookie", "", time() - 1800, "/" );
			setcookie( "jfcookie[lang]", $client_lang, time()+24*3600, '/' );
		}
		
		if( defined("_JLEGACY") ) {
			$GLOBALS['iso_client_lang'] = $client_lang;
			$GLOBALS['mosConfig_lang'] = $jfLang->code;
		}

		$registry->setValue("config.multilingual_support", true);

		global $mainframe;

		$mainframe->setUserState('application.lang',$jfLang->code);
		$registry->setValue("config.jflang", $jfLang->code);
		$registry->setValue("config.lang_site",$jfLang->code);
		$registry->setValue("config.language",$jfLang->code);
		$registry->setValue("joomfish.language",$jfLang);

		// Force factory static instance to be updated if necessary
		$lang =& JFactory::getLanguage();
		if ($jfLang->code != $lang->getTag()){
			// Must not assign by reference in order to overwrite the existing reference to the static instance of the language
			$lang = JFactory::_createLanguage();
		}
		// no need to set locale for this ISO code its done by JLanguage
		
		// overwrite with the valued from $jfLang
		$jfparams = JComponentHelper::getParams("com_joomfish");
		$overwriteGlobalConfig =  $jfparams->get( 'overwriteGlobalConfig', 0 );
		if($overwriteGlobalConfig ) {
			// We should overwrite additional global variables based on the language parameter configuration
			$params = new JParameter($jfLang->params);
			$paramarray = $params->toArray();
			foreach ($paramarray as $key=>$val) {
				$registry->setValue("config.".$key,$val);
	
				if (defined("_JLEGACY")){
					$name = 'mosConfig_'.$key;
					$GLOBALS[$name] = $val;
				}
			}
		}
	}

	/**
	 * Custom handlers to deal with bad component routers e.g. for contact
	 */ 
	function procesCustomBuildRule($router, &$uri){
		$option = $uri->getVar("option","");
		if (strpos($option,"com_")!==0) return;
		$option = substr($option,4);
		$customFile = dirname(__FILE__).DS."jfrouter".DS.$option.".php";
		if (file_exists($customFile)){
			include_once($customFile);
			if (function_exists("JFRouterHelper".ucfirst($option))){
				$function = "JFRouterHelper".ucfirst($option);
				$function ($router, $uri);
			}
		}
	}
	
	function parseJFRule($router, &$uri){
		//echo "got here too lang = ".$uri->getVar("lang","")."<br/>";
		$route = $uri->getPath();

		$conf =& JFactory::getConfig();
		$params = $conf->getValue("jfrouter.params");

		$sefordomain = $params->get("sefordomain","sefprefix");

		if ($sefordomain == "subdomain"){
			$host = $uri->getHost();
			// TODO cache the indexed array
			$rawsubdomains = $params->getValue("sefsubdomain",array());
			$subdomains = array();
			$jfm =&  JoomFishManager::getInstance();
			$langs = $jfm->getLanguagesIndexedById();
			foreach ($rawsubdomains as $domain) {
				list($langid,$domain) = split("::",$domain,2);
				// if you have inactive languages and are not logged in then skip inactive language
				if (!array_key_exists($langid, $langs)) continue;
				$domain = strtolower(str_replace("http://","",$domain));
				$domain = str_replace("https://","",$domain);
				$domain = preg_replace("#/$#","",$domain);
				//$domain = str_replace("/","",$domain);
				$subdomains[$domain]=$langs[$langid]->shortcode;
			}
			if (array_key_exists($host, $subdomains)){
				$lang = $subdomains[$host];
				// This get over written later - really stupid !!!
				$uri->setVar("lang",$lang);
				JRequest::setVar('lang', $lang );
				// I need to discover language here since menu is loaded in router
				plgSystemJFRouter::_discoverJFLanguage();
				$config =& JFactory::getConfig();
				// TODO fix this for HTTPS
				$config->setValue('config.live_site',"http://".$host);
				$config->setValue("joomfish.current_host",$host);
				return array("lang"=>$lang);
			}
		}

		else {
			// Consider stripping base path from URI
			/*
			$live_site = JURI::base();
			$livesite_uri = new JURI($live_site);
			$livesite_path = $livesite_uri->getPath();
			$route = str_replace($livesite_path,"",$route);
			*/

			$jfm =&  JoomFishManager::getInstance();
			$langs = $jfm->getLanguagesIndexedById();

			$sefprefixes = $params->getValue("sefprefixes",array());

			// Workaround if some language prefixes are missing
			if (!is_array($sefprefixes)){
				$sefprefixes = array();
			}
			if (count($sefprefixes)<count($langs)){
				foreach ($sefprefixes as $prefix) {
					list($langid,$prefix) = split("::",$prefix,2);
					if (array_key_exists($langid,$langs)){
						$langs[$langid]->hasprefix = true;
					}
				}
				foreach ($langs as $lang) {
					if (!isset($lang->hasprefix)){
						$sefprefixes[] = $lang->id."::".$lang->shortcode;
					}
				}
			}

			$segments = explode('/', $route);
			$seg=0;
			while ($seg<count($segments)){
				if (strlen($segments[$seg])==0) {
					$seg++;
					continue;
				}
				foreach ($sefprefixes as $prefix) {
					list($langid,$prefix) = split("::",$prefix,2);
					// split off any suffix
					if (strpos($segments[$seg],".")>0){
						$segcompare = substr($segments[$seg],0, strpos($segments[$seg],"."));
						// Trap for pdf, feed of html info in the extension
						if (strpos($segments[$seg],$prefix.".")===0){
							$format = str_replace($prefix.".","",$segments[$seg]);
							//$uri->setVar("format",$format);
							//JRequest::setVar('format', $format);
						}
					}
					else {
						$segcompare = $segments[$seg];
					}
					// does the segment match the prefix
					if ($segcompare==$prefix){
																				
						// This section forces the current url static to include the language string which means the base tag is correct - but ONLY on the home page
						// restricting this to the homepage means no risk for image paths etc.
						$homepage = true;
						for ($seg2=$seg+1;$seg2<count($segments);$seg2++) {
							$segment = $segments[$seg2];
							if (strlen($segment)>0) $homepage = false;
						}
						if ($homepage){
							$current =& JURI::current();
							$uri	 = & JURI::getInstance();
							$current = $uri->toString( array('scheme', 'host', 'port', 'path'));
						}

						unset($segments[$seg]);//array_shift($segments);
						$uri->setPath(implode("/",$segments));

						$lang = $langs[$langid]->shortcode;
						// This get over written later - really stupid !!!
						$uri->setVar("lang",$lang);

						JRequest::setVar('lang', $lang);
						// I need to discover language here since menu is loaded in router
						plgSystemJFRouter::_discoverJFLanguage();
						return array("lang"=>$lang);
					}
				}

				$seg++;
			}
		}
		plgSystemJFRouter::_discoverJFLanguage();
		return array();
	}

}

function routeJFRule($router, &$uri){
	$registry =& JFactory::getConfig();
	$multilingual_support= $registry->getValue("config.multilingual_support",false);
	$jfLang = $registry->getValue("joomfish.language", false);
	if ($multilingual_support && $jfLang){
		if ($uri->getVar("lang","")==""){
			$uri->setVar("lang",($jfLang->shortcode!='') ? $jfLang->shortcode : $jfLang->iso);
		}
		// this is dependent on Joomfish router being first!!
		$lang=$uri->getVar("lang","");

		$conf =& JFactory::getConfig();

		// This may not ready at this stage
		$params = $conf->getValue("jfrouter.params");

		// so load plugin parameters directly
		if (is_null($params)){
			$params =& JPluginHelper::getPlugin("system", "jfrouter");
			$params = new JParameter($params->params);
		}
		
		$sefordomain = $params->get("sefordomain","sefprefix");

		if ($sefordomain == "subdomain"){
			// If I set config_live_site I actually don't need this function at all let alone this logic ?  Apart from language switcher.
			// TODO cache the indexed array
			$rawsubdomains = $params->getValue("sefsubdomain",array());
			$subdomains = array();
			$jfm =&  JoomFishManager::getInstance();
			$langs = $jfm->getLanguagesIndexedById();
			foreach ($rawsubdomains as $domain) {
				list($langid,$domain) = split("::",$domain,2);
				$domain = strtolower(str_replace("http://","",$domain));
				$domain = str_replace("https://","",$domain);
				$domain = preg_replace("#/$#","",$domain);
				//$domain = str_replace("/","",$domain);
				$subdomains[$langs[$langid]->shortcode]=$domain;
			}

			if (array_key_exists($lang,$subdomains)) {
				$uri->setHost($subdomains[$lang]);
				$uri->delVar("lang");
				$registry->setValue("joomfish.sef_host",$subdomains[$lang]);
				
				plgSystemJFRouter::procesCustomBuildRule($router, $uri);
				return;
			}
		}
		else {
			// Get the path data
			$route = $uri->getPath();

			//Add the suffix to the uri
			if($router->_mode == JROUTER_MODE_SEF && $route && !$lang!==""){

				$jfm =&  JoomFishManager::getInstance();
				$jfLang = $jfm->getLanguageByShortcode($lang);
				if (!$jfLang) return;

				$sefprefixes = $params->getValue("sefprefixes",array());

				// Workaround if some language prefixes are missing
				$langs = $jfm->getLanguagesIndexedById();
				if (!is_array($sefprefixes)){
					$sefprefixes = array();
				}
				if (count($sefprefixes)<count($langs)){
					foreach ($sefprefixes as $prefix) {
						list($langid,$prefix) = split("::",$prefix,2);
						if (array_key_exists($langid,$langs)){
							$langs[$langid]->hasprefix = true;
						}
					}
					foreach ($langs as $lang) {
						if (!isset($lang->hasprefix)){
							$sefprefixes[] = $lang->id."::".$lang->shortcode;
						}
					}
				}

				foreach ($sefprefixes as $prefix) {
					list($langid,$prefix) = split("::",$prefix,2);
					if ($jfLang->id == $langid){
						$uri->setPath($uri->getPath()."/".$prefix);
						$uri->delVar("lang");
						plgSystemJFRouter::procesCustomBuildRule($router, $uri);
						return;
					}
				}
			}
		}
		
	}
	return;
}
