| 1 | <?php
 | 
  
    | 2 | 
 | 
  
    | 3 | /**
 | 
  
    | 4 |  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 | 
  
    | 5 |  *
 | 
  
    | 6 |  * This program is free software: you can redistribute it and/or modify
 | 
  
    | 7 |  * it under the terms of the GNU General Public License as published by
 | 
  
    | 8 |  * the Free Software Foundation, either version 3 of the License, or
 | 
  
    | 9 |  * (at your option) any later version.
 | 
  
    | 10 |  *
 | 
  
    | 11 |  * This program is distributed in the hope that it will be useful,
 | 
  
    | 12 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
  
    | 13 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
  
    | 14 |  * GNU General Public License for more details.
 | 
  
    | 15 |  *
 | 
  
    | 16 |  * You should have received a copy of the GNU General Public License
 | 
  
    | 17 |  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
  
    | 18 |  */
 | 
  
    | 19 | 
 | 
  
    | 20 | /**
 | 
  
    | 21 |  * Description of Translate
 | 
  
    | 22 |  *
 | 
  
    | 23 |  * @category     Core
 | 
  
    | 24 |  * @package      Core_Security
 | 
  
    | 25 |  * @copyright    Manuela v.d.Decken <manuela@isteam.de>
 | 
  
    | 26 |  * @author       Manuela v.d.Decken <manuela@isteam.de>
 | 
  
    | 27 |  * @license      GNU General Public License 3.0
 | 
  
    | 28 |  * @version      0.0.2
 | 
  
    | 29 |  * @revision     $Revision: 2 $
 | 
  
    | 30 |  * @lastmodified $Date: 2017-07-02 17:14:29 +0200 (Sun, 02 Jul 2017) $
 | 
  
    | 31 |  * @since        File available since 23.05.2016
 | 
  
    | 32 |  * @deprecated   no / since 0000/00/00
 | 
  
    | 33 |  * @description  handling of security tokens to prevent cross side scripting on manipulating requests
 | 
  
    | 34 |  */
 | 
  
    | 35 | class Translate
 | 
  
    | 36 | {
 | 
  
    | 37 | /** holds the active singleton instance */
 | 
  
    | 38 |     private static $oInstance      = null;
 | 
  
    | 39 | /** translations of the core */
 | 
  
    | 40 |     protected $aTranslations       = array();
 | 
  
    | 41 | /** translations of current module */
 | 
  
    | 42 |     protected $aAddonTranslations  = array();
 | 
  
    | 43 | /** path to the cache files */
 | 
  
    | 44 |     protected $sCachePath          = '';
 | 
  
    | 45 | /** switch the cache on/off */
 | 
  
    | 46 |     protected $bUseCache           = false;
 | 
  
    | 47 | /** list of languages to load */
 | 
  
    | 48 |     protected $aLanguages          = array('EN');
 | 
  
    | 49 | /** stack of loaded addons */
 | 
  
    | 50 |     protected $aAddonStack         = array();
 | 
  
    | 51 | // -----------------------------------------------------------------------------
 | 
  
    | 52 | /** prevent class from public instancing and get an object to hold extensions */
 | 
  
    | 53 |     protected function  __construct() {}
 | 
  
    | 54 | // -----------------------------------------------------------------------------
 | 
  
    | 55 | /** prevent from cloning existing instance */
 | 
  
    | 56 |     private function __clone() {}
 | 
  
    | 57 | // -----------------------------------------------------------------------------
 | 
  
    | 58 | /**
 | 
  
    | 59 |  * get a valid instance of this class
 | 
  
    | 60 |  * @return object
 | 
  
    | 61 |  */
 | 
  
    | 62 |     static public function getInstance() {
 | 
  
    | 63 |         if( is_null(self::$oInstance) ) {
 | 
  
    | 64 |             $c = __CLASS__;
 | 
  
    | 65 |             self::$oInstance = new $c;
 | 
  
    | 66 |         }
 | 
  
    | 67 |         return self::$oInstance;
 | 
  
    | 68 |     }
 | 
  
    | 69 | // -----------------------------------------------------------------------------
 | 
  
    | 70 | /**
 | 
  
    | 71 |  * initialize class and load core translations
 | 
  
    | 72 |  * @param string $sCachePath
 | 
  
    | 73 |  */
 | 
  
    | 74 |     public function initialize($mLanguages, $sCachePath = '')
 | 
  
    | 75 |     {
 | 
  
    | 76 |         if ($this->sCachePath == '') {
 | 
  
    | 77 |             if ($sCachePath == '') {
 | 
  
    | 78 |                 $sCachePath = dirname(__DIR__).'/temp/';
 | 
  
    | 79 |             }
 | 
  
    | 80 |             $sCachePath = rtrim(str_replace('\\', '/', $sCachePath), '/').'/';
 | 
  
    | 81 |             $this->bUseCache = (is_writeable($sCachePath));
 | 
  
    | 82 |             $this->sCachePath = $sCachePath;
 | 
  
    | 83 |             if (!is_array($mLanguages)) {
 | 
  
    | 84 |                 $mLanguages = preg_split('/\s*?[,;|\s]\s*?/', $mLanguages);
 | 
  
    | 85 |             }
 | 
  
    | 86 |             $this->aLanguages = $mLanguages;
 | 
  
    | 87 |             $this->aTranslations = array();
 | 
  
    | 88 |             $this->aTranslations = $this->readFiles('core');
 | 
  
    | 89 |         }
 | 
  
    | 90 |     }
 | 
  
    | 91 | // -----------------------------------------------------------------------------
 | 
  
    | 92 | /**
 | 
  
    | 93 |  * load translations of an addon
 | 
  
    | 94 |  * @param string $sDomain   i.e 'modules\\news' or 'admin\\pages'
 | 
  
    | 95 |  */
 | 
  
    | 96 |     public function addAddon($sDomain)
 | 
  
    | 97 |     {
 | 
  
    | 98 |         if ($sDomain) {
 | 
  
    | 99 |             $this->aAddonTranslations = array();
 | 
  
    | 100 |             $this->aAddonTranslations = $this->readFiles($sDomain);
 | 
  
    | 101 |         }
 | 
  
    | 102 |     }
 | 
  
    | 103 | // -----------------------------------------------------------------------------
 | 
  
    | 104 | /**
 | 
  
    | 105 |  * ALIAS for addAddon()
 | 
  
    | 106 |  * @param string $sDomain   i.e 'modules\\news' or 'admin\\pages'
 | 
  
    | 107 |  */
 | 
  
    | 108 |     public function enableAddon($sDomain)
 | 
  
    | 109 |     {
 | 
  
    | 110 |         $this->addAddon($sDomain);
 | 
  
    | 111 |         array_push($this->aAddonStack, $sDomain);
 | 
  
    | 112 |     }
 | 
  
    | 113 | // -----------------------------------------------------------------------------
 | 
  
    | 114 | /**
 | 
  
    | 115 |  * remove translations of an addon
 | 
  
    | 116 |  */
 | 
  
    | 117 |     public function disableAddon()
 | 
  
    | 118 |     {
 | 
  
    | 119 |         if (isset($this->aAddonTranslations)) {
 | 
  
    | 120 |             $this->aAddonTranslations = array();
 | 
  
    | 121 |             if (($sDomain = array_pop($this->aAddonStack)) != null) {
 | 
  
    | 122 |                 $this->addAddon($sDomain);
 | 
  
    | 123 |             }
 | 
  
    | 124 |         }
 | 
  
    | 125 |     }
 | 
  
    | 126 | // -----------------------------------------------------------------------------
 | 
  
    | 127 | /**
 | 
  
    | 128 |  * clear all translation cache files
 | 
  
    | 129 |  */
 | 
  
    | 130 |    public function clearCache()
 | 
  
    | 131 |     {
 | 
  
    | 132 |         $sMask = $this->sCachePath.'*.transcache';
 | 
  
    | 133 |         $aFiles = glob($sMask, GLOB_NOSORT);
 | 
  
    | 134 |         foreach ($aFiles as $sFile) {
 | 
  
    | 135 |             if (is_writable($sFile)) {
 | 
  
    | 136 |               unlink($sFile);
 | 
  
    | 137 |             }
 | 
  
    | 138 |         }
 | 
  
    | 139 |     }// -----------------------------------------------------------------------------
 | 
  
    | 140 | /**
 | 
  
    | 141 |  * Return complete table of translations
 | 
  
    | 142 |  * @return array containing all loaded translations
 | 
  
    | 143 |  * @deprecated for backward compatibility to PHPLIB only. Will be removed shortly
 | 
  
    | 144 |  */
 | 
  
    | 145 |     public function getLangArray()
 | 
  
    | 146 |     {
 | 
  
    | 147 |         $aRetval = array_merge($this->aTranslations, $this->aAddonTranslations);
 | 
  
    | 148 |         return $aRetval;
 | 
  
    | 149 |     }
 | 
  
    | 150 | // -----------------------------------------------------------------------------
 | 
  
    | 151 | /* *** method group used by Twig ******************************************** */
 | 
  
    | 152 | /**
 | 
  
    | 153 |  * check if a entry exists
 | 
  
    | 154 |  * @param string $sKeyword
 | 
  
    | 155 |  * @return boolean
 | 
  
    | 156 |  */
 | 
  
    | 157 |     public function __isset($sKeyword)
 | 
  
    | 158 |     {
 | 
  
    | 159 |         return (
 | 
  
    | 160 |             isset($this->aAddonTranslations[$sKeyword]) ||
 | 
  
    | 161 |             isset($this->aTranslations[$sKeyword])
 | 
  
    | 162 |         );
 | 
  
    | 163 |     }
 | 
  
    | 164 | // -----------------------------------------------------------------------------
 | 
  
    | 165 | /**
 | 
  
    | 166 |  * return value of an existing entry
 | 
  
    | 167 |  * @param string $sKeyword
 | 
  
    | 168 |  * @return string
 | 
  
    | 169 |  */
 | 
  
    | 170 |     public function __get($sKeyword)
 | 
  
    | 171 |     {
 | 
  
    | 172 |         if (isset($this->aAddonTranslations[$sKeyword])) {
 | 
  
    | 173 |             $sRetval = $this->aAddonTranslations[$sKeyword];
 | 
  
    | 174 |         } elseif (isset($this->aTranslations[$sKeyword])) {
 | 
  
    | 175 |             $sRetval = $this->aTranslations[$sKeyword];
 | 
  
    | 176 |         } else {
 | 
  
    | 177 |             $sRetval = '#'.$sKeyword.'#';
 | 
  
    | 178 |         }
 | 
  
    | 179 |         return $sRetval;
 | 
  
    | 180 |     }
 | 
  
    | 181 | // -----------------------------------------------------------------------------
 | 
  
    | 182 | /**
 | 
  
    | 183 |  * try to set a new entry
 | 
  
    | 184 |  * @param string $sKeyword
 | 
  
    | 185 |  * @param string $value
 | 
  
    | 186 |  */
 | 
  
    | 187 |     public function __set($sKeyword, $value)
 | 
  
    | 188 |     {
 | 
  
    | 189 |         throw new RuntimeException('illegal action ['.__CLASS__.'::__set(\''.$sKeyword.'\', \''.$value.'\')]!! ');
 | 
  
    | 190 |     }
 | 
  
    | 191 | // -----------------------------------------------------------------------------
 | 
  
    | 192 | /**
 | 
  
    | 193 |  * read translation files of given domain
 | 
  
    | 194 |  * @param string $sDomain
 | 
  
    | 195 |  * @return array of translations
 | 
  
    | 196 |  */
 | 
  
    | 197 |     protected function readFiles($sDomain)
 | 
  
    | 198 |     {
 | 
  
    | 199 |         $aTranslations = array();
 | 
  
    | 200 |         $sSourcePath = str_replace('\\', '/', dirname(__DIR__).'/'.($sDomain == 'core' ? '' : $sDomain.'/'));
 | 
  
    | 201 |         $sCacheFile = $this->sCachePath.md5($sDomain.implode('', $this->aLanguages)).'.transcache';
 | 
  
    | 202 |         if (!is_readable($sCacheFile)) {
 | 
  
    | 203 |             $sLoadedLanguages = '';
 | 
  
    | 204 |             $sCurrentLang = '';
 | 
  
    | 205 |             foreach ($this->aLanguages as $sLanguage) {
 | 
  
    | 206 |                 // Avoid that a language is proceeded several times in a row
 | 
  
    | 207 |                 if ($sCurrentLang == $sLanguage) { continue; }
 | 
  
    | 208 |                 $sCurrentLang = $sLanguage;
 | 
  
    | 209 |                 $sLoadedLanguages .= $sLanguage.', ';
 | 
  
    | 210 |                 $sFile = $sSourcePath.'languages/'.$sLanguage.'.php';
 | 
  
    | 211 |                 if (is_readable($sFile)) {
 | 
  
    | 212 |                     $aTranslations = array_merge($aTranslations, $this->importArrays($sFile));
 | 
  
    | 213 |                 }
 | 
  
    | 214 |                 reset($aTranslations);
 | 
  
    | 215 |             }
 | 
  
    | 216 |             // create cache file
 | 
  
    | 217 |             $sOutput = '<?php'.PHP_EOL.'// *** autogenerated cachefile '.PHP_EOL
 | 
  
    | 218 |                      . '// *** Domain:    '.$sDomain.PHP_EOL
 | 
  
    | 219 |                      . '// *** Languages: '.rtrim($sLoadedLanguages, ' ,').PHP_EOL
 | 
  
    | 220 |                      . '// ***************************'.PHP_EOL;
 | 
  
    | 221 |             while (list($key, $value) = each($aTranslations)) {
 | 
  
    | 222 |                 $sOutput .= '$aTranslations[\''.$key.'\']=\''.str_replace("'", "\'", $value).'\';'.PHP_EOL;
 | 
  
    | 223 |             }
 | 
  
    | 224 |             $sOutput .= PHP_EOL;
 | 
  
    | 225 |             // save cache file
 | 
  
    | 226 |             if ($this->bUseCache && is_writeable($this->sCachePath)) {
 | 
  
    | 227 |                 file_put_contents($sCacheFile, $sOutput); //, LOCK_EX);
 | 
  
    | 228 |             }
 | 
  
    | 229 |         } else {
 | 
  
    | 230 |             // include chache file
 | 
  
    | 231 |             include($sCacheFile);
 | 
  
    | 232 |         }
 | 
  
    | 233 |         return $aTranslations;
 | 
  
    | 234 |     }
 | 
  
    | 235 | // -----------------------------------------------------------------------------
 | 
  
    | 236 | /**
 | 
  
    | 237 |  * Import language definitions into array
 | 
  
    | 238 |  * @param string load language from filename
 | 
  
    | 239 |  * @return array contains all found translations
 | 
  
    | 240 |  */
 | 
  
    | 241 |     protected function importArrays($sLanguageFile)
 | 
  
    | 242 |     {
 | 
  
    | 243 |         // get all available loaded vars of this method
 | 
  
    | 244 |         $aOldVarlist = array();
 | 
  
    | 245 |         $aOldVarlist = get_defined_vars();
 | 
  
    | 246 |         // include the file
 | 
  
    | 247 |         include $sLanguageFile;
 | 
  
    | 248 |         $aCurrVarlist = array_diff_key(get_defined_vars(), $aOldVarlist);
 | 
  
    | 249 |         $aLangSections = array();
 | 
  
    | 250 |         $aLanguageTable = array();
 | 
  
    | 251 |         foreach ($aCurrVarlist as $key=>$value) {
 | 
  
    | 252 |         // extract the names of arrays from language file
 | 
  
    | 253 |             if (is_array($value)) {
 | 
  
    | 254 |                 $aLangSections[] = $key;
 | 
  
    | 255 |             }
 | 
  
    | 256 |         }
 | 
  
    | 257 |         foreach ($aLangSections as $sSection) {
 | 
  
    | 258 |         // walk through all arrays
 | 
  
    | 259 |             foreach (${$sSection} as $key => $value) {
 | 
  
    | 260 |             // and import all found translations
 | 
  
    | 261 |                 if (!is_array($value)) {
 | 
  
    | 262 |                 // skip all multiarray definitions from compatibility mode
 | 
  
    | 263 |                     $aLanguageTable[$sSection.'_'.$key] = $value;
 | 
  
    | 264 |                 }
 | 
  
    | 265 |             }
 | 
  
    | 266 |         }
 | 
  
    | 267 |         return $aLanguageTable;
 | 
  
    | 268 |     }
 | 
  
    | 269 | // -----------------------------------------------------------------------------
 | 
  
    | 270 | } // end of class Translation()
 |