"TYPO3 4.0.1: typo3_src-4.0.1/typo3/mod/tools/em/class.em_xmlhandler.php Source File", "datetime" => "Sat Dec 2 19:22:21 2006", "date" => "2 Dec 2006", "doxygenversion" => "1.4.6", "projectname" => "TYPO3 4.0.1", "projectnumber" => "4.0.1" ); get_header($doxygen_vars); ?>

class.em_xmlhandler.php

00001 <?php
00002 /* **************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2006 Karsten Dambekalns <karsten@typo3.org>
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *  A copy is found in the textfile GPL.txt and important notices to the license
00017 *  from the author is found in LICENSE.txt distributed with these scripts.
00018 *
00019 *
00020 *  This script is distributed in the hope that it will be useful,
00021 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023 *  GNU General Public License for more details.
00024 *
00025 *  This copyright notice MUST APPEAR in all copies of the script!
00026 ***************************************************************/
00027 
00038 class SC_mod_tools_em_xmlhandler {
00045         var $emObj;
00046         var $extXMLResult = array();
00047         var $extensionsXML = array();
00048         var $reviewStates = null;
00049         var $useUnchecked = false;
00050         var $useObsolete = false;
00051 
00059         function searchExtensionsXML($search, $owner='') {
00060                 if(!count($this->extensionsXML)) $this->loadExtensionsXML();
00061 
00062                 reset($this->extensionsXML);
00063                 while (list($extkey, $data) = each($this->extensionsXML)) {
00064 
00065                                 // Unset extension key in installed keys array (for tracking)
00066                         if(isset($this->emObj->inst_keys[$extkey])) unset($this->emObj->inst_keys[$extkey]);
00067 
00068                         if(strlen($search) && !stristr($extkey,$search)) {
00069                                 unset($this->extensionsXML[$extkey]);
00070                                 continue;
00071                         }
00072 
00073                         if(strlen($owner) && !$this->checkOwner($extkey, $owner)) {
00074                                 unset($this->extensionsXML[$extkey]);
00075                                 continue;
00076                         }
00077 
00078                         if(!strlen($owner)) {
00079                                 $this->checkReviewState($this->extensionsXML[$extkey]['versions']);     // if showing only own extensions, never hide unreviewed
00080                         }
00081                         $this->removeObsolete($this->extensionsXML[$extkey]['versions']);
00082 
00083                         uksort($data['versions'], array($this->emObj, 'versionDifference')); // needed? or will the extensions always be sorted in the XML anyway? Robert?
00084 
00085                         if(!count($this->extensionsXML[$extkey]['versions'])) {
00086                                 unset($this->extensionsXML[$extkey]);
00087                         }
00088                 }
00089         }
00090 
00098         function checkOwner($extkey, $owner) {
00099                 foreach($this->extensionsXML[$extkey]['versions'] as $ext) {
00100                         if($ext['ownerusername'] == $owner) return true;
00101                 }
00102                 return false;
00103         }
00104 
00110         function loadExtensionsXML() {
00111                 if(is_file(PATH_site.'typo3temp/extensions.bin')) {
00112                         $this->extensionsXML = unserialize(gzuncompress(t3lib_div::getURL(PATH_site.'typo3temp/extensions.bin')));
00113                         return true;
00114                 } else {
00115                         $this->extensionsXML = array();
00116                         return false;
00117                 }
00118         }
00119 
00125         function loadReviewStates() {
00126                 if(is_file(PATH_site.'typo3temp/reviewstates.bin')) {
00127                         $this->reviewStates = unserialize(gzuncompress(t3lib_div::getURL(PATH_site.'typo3temp/reviewstates.bin')));
00128                         return true;
00129                 } else {
00130                         $this->reviewStates = array();
00131                         return false;
00132                 }
00133         }
00134 
00140         function saveExtensionsXML() {
00141                 t3lib_div::writeFile(PATH_site.'typo3temp/extensions.bin',gzcompress(serialize($this->extXMLResult)));
00142                 t3lib_div::writeFile(PATH_site.'typo3temp/reviewstates.bin',gzcompress(serialize($this->reviewStates)));
00143         }
00144 
00150         function freeExtensionsXML() {
00151                 unset($this->extensionsXML);
00152                 $this->extensionsXML = array();
00153         }
00154 
00161         function removeObsolete(&$extensions) {
00162                 if($this->useObsolete) return;
00163 
00164                 reset($extensions);
00165                 while (list($version, $data) = each($extensions)) {
00166                         if($data['state']=='obsolete')
00167                         unset($extensions[$version]);
00168                 }
00169         }
00170 
00178         function getReviewState($extKey, $version) {
00179                 if(!is_array($this->reviewStates)) $this->loadReviewStates();
00180 
00181                 if(isset($this->reviewStates[$extKey])) {
00182                         return (int)$this->reviewStates[$extKey][$version];
00183                 } else {
00184                         return 0;
00185                 }
00186         }
00187 
00194         function checkReviewState(&$extensions) {
00195                 if ($this->useUnchecked) return;
00196 
00197                 reset($extensions);
00198                 while (list($version, $data) = each($extensions))       {
00199                         if($data['reviewstate']<1)
00200                                 unset($extensions[$version]);
00201                 }
00202         }
00203 
00209         function checkReviewStateGlobal() {
00210                 if($this->useUnchecked) return;
00211 
00212                 reset($this->extensionsXML);
00213                 while (list($extkey, $data) = each($this->extensionsXML)) {
00214                         while (list($version, $vdata) = each($data['versions'])) {
00215                                 if($vdata['reviewstate']<1) unset($this->extensionsXML[$extkey]['versions'][$version]);
00216                         }
00217                         if(!count($this->extensionsXML[$extkey]['versions'])) unset($this->extensionsXML[$extkey]);
00218                 }
00219         }
00220 
00221 
00233         function startElement($parser, $name, $attrs) {
00234                 switch($name) {
00235                         case 'extensions':
00236                         break;
00237                         case 'extension':
00238                         $this->currentExt = $attrs['extensionkey'];
00239                         break;
00240                         case 'version':
00241                         $this->currentVersion = $attrs['version'];
00242                         $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion] = array();
00243                         break;
00244                         default:
00245                         $this->currentTag = $name;
00246                 }
00247         }
00248 
00256         function endElement($parser, $name) {
00257                 switch($name) {
00258                         case 'extension':
00259                         unset($this->currentExt);
00260                         break;
00261                         case 'version':
00262                         unset($this->currentVersion);
00263                         break;
00264                         default:
00265                         unset($this->currentTag);
00266                 }
00267         }
00268 
00276         function characterData($parser, $data) {
00277                 if(isset($this->currentTag)) {
00278                         if(!isset($this->currentVersion) && $this->currentTag == 'downloadcounter') {
00279                                 $this->extXMLResult[$this->currentExt]['downloadcounter'] = trim($data);
00280                         } elseif($this->currentTag == 'dependencies') {
00281                                 $data = @unserialize($data);
00282                                 if(is_array($data)) {
00283                                         $dep = array();
00284                                         foreach($data as $v) {
00285                                                 $dep[$v['kind']][$v['extensionKey']] = $v['versionRange'];
00286                                         }
00287                                         $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion]['dependencies'] = $dep;
00288                                 }
00289                         } elseif($this->currentTag == 'reviewstate') {
00290                                         $this->reviewStates[$this->currentExt][$this->currentVersion] = (int)trim($data);
00291                                         $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion]['reviewstate'] = (int)trim($data);
00292                         } else {
00293                                 $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion][$this->currentTag] .= trim($data);
00294                         }
00295                 }
00296         }
00297 
00304         function parseExtensionsXML($string) {
00305                 global $TYPO3_CONF_VARS;
00306 
00307                 $parser = xml_parser_create();
00308                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00309                 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
00310                 xml_set_element_handler($parser, array(&$this,'startElement'), array(&$this,'endElement'));
00311                 xml_set_character_data_handler($parser, array(&$this,'characterData'));
00312 
00313                 if ((double)phpversion()>=5)    {
00314                         $preg_result = array();
00315                         preg_match('/^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/',substr($string,0,200),$preg_result);
00316                         $theCharset = $preg_result[1] ? $preg_result[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
00317                         xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1
00318                 }
00319 
00320                 // Parse content:
00321                 if (!xml_parse($parser, $string)) {
00322                         $content.= 'Error in XML parser while decoding extensions XML file. Line '.xml_get_current_line_number($parser).': '.xml_error_string(xml_get_error_code($parser));
00323                         $error = true;
00324                 }
00325                 xml_parser_free($parser);
00326 
00327                 if(!$error) {
00328                         $content.= '<p>The extensions list has been updated and now contains '.count($this->extXMLResult).' extension entries.</p>';
00329                 }
00330 
00331                 return $content;
00332         }
00333 
00340         function parseMirrorsXML($string) {
00341                 global $TYPO3_CONF_VARS;
00342 
00343                 // Create parser:
00344                 $parser = xml_parser_create();
00345                 $vals = array();
00346                 $index = array();
00347 
00348                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00349                 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
00350 
00351                 if ((double)phpversion()>=5)    {
00352                         $preg_result = array();
00353                         preg_match('/^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/',substr($string,0,200),$preg_result);
00354                         $theCharset = $preg_result[1] ? $preg_result[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
00355                         xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1
00356                 }
00357 
00358                 // Parse content:
00359                 xml_parse_into_struct($parser, $string, $vals, $index);
00360 
00361                 // If error, return error message:
00362                 if (xml_get_error_code($parser))        {
00363                         $line = xml_get_current_line_number($parser);
00364                         $error = xml_error_string(xml_get_error_code($parser));
00365                         xml_parser_free($parser);
00366                         return 'Error in XML parser while decoding mirrors XML file. Line '.$line.': '.$error;
00367                 } else  {
00368                         // Init vars:
00369                         $stack = array(array());
00370                         $stacktop = 0;
00371                         $mirrornumber = 0;
00372                         $current=array();
00373                         $tagName = '';
00374                         $documentTag = '';
00375 
00376                         // Traverse the parsed XML structure:
00377                         foreach($vals as $val) {
00378 
00379                                 // First, process the tag-name (which is used in both cases, whether "complete" or "close")
00380                                 $tagName = ($val['tag']=='mirror' && $val['type']=='open') ? '__plh' : $val['tag'];
00381                                 if (!$documentTag)      $documentTag = $tagName;
00382 
00383                                 // Setting tag-values, manage stack:
00384                                 switch($val['type'])    {
00385                                         case 'open':            // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
00386                                                 $current[$tagName] = array();   // Setting blank place holder
00387                                                 $stack[$stacktop++] = $current;
00388                                                 $current = array();
00389                                                 break;
00390                                         case 'close':   // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
00391                                         $oldCurrent = $current;
00392                                         $current = $stack[--$stacktop];
00393                                         end($current);  // Going to the end of array to get placeholder key, key($current), and fill in array next:
00394                                         if($tagName=='mirror') {
00395                                                 unset($current['__plh']);
00396                                                 $current[$oldCurrent['host']] = $oldCurrent;
00397                                         } else {
00398                                                 $current[key($current)] = $oldCurrent;
00399                                         }
00400                                         unset($oldCurrent);
00401                                         break;
00402                                         case 'complete':        // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
00403                                         $current[$tagName] = (string)$val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!
00404                                         break;
00405                                 }
00406                         }
00407                         return $current[$tagName];
00408                 }
00409         }
00410 
00417         function parseL10nXML($string) {
00418                 // Create parser:
00419                 $parser = xml_parser_create();
00420                 $vals = array();
00421                 $index = array();
00422 
00423                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00424                 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
00425 
00426                 // Parse content:
00427                 xml_parse_into_struct($parser, $string, $vals, $index);
00428 
00429                 // If error, return error message:
00430                 if (xml_get_error_code($parser))        {
00431                         $line = xml_get_current_line_number($parser);
00432                         $error = xml_error_string(xml_get_error_code($parser));
00433                         debug($error);
00434                         xml_parser_free($parser);
00435                         return 'Error in XML parser while decoding l10n XML file. Line '.$line.': '.$error;
00436                 } else  {
00437                         // Init vars:
00438                         $stack = array(array());
00439                         $stacktop = 0;
00440                         $mirrornumber = 0;
00441                         $current=array();
00442                         $tagName = '';
00443                         $documentTag = '';
00444 
00445                         // Traverse the parsed XML structure:
00446                         foreach($vals as $val) {
00447 
00448                                 // First, process the tag-name (which is used in both cases, whether "complete" or "close")
00449                                 $tagName = ($val['tag']=='languagepack' && $val['type']=='open') ? $val['attributes']['language'] : $val['tag'];
00450                                 if (!$documentTag)      $documentTag = $tagName;
00451 
00452                                 // Setting tag-values, manage stack:
00453                                 switch($val['type'])    {
00454                                         case 'open':            // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
00455                                                 $current[$tagName] = array();   // Setting blank place holder
00456                                                 $stack[$stacktop++] = $current;
00457                                                 $current = array();
00458                                                 break;
00459                                         case 'close':   // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
00460                                         $oldCurrent = $current;
00461                                         $current = $stack[--$stacktop];
00462                                         end($current);  // Going to the end of array to get placeholder key, key($current), and fill in array next:
00463                                         $current[key($current)] = $oldCurrent;
00464                                         unset($oldCurrent);
00465                                         break;
00466                                         case 'complete':        // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
00467                                         $current[$tagName] = (string)$val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!
00468                                         break;
00469                                 }
00470                         }
00471                         return $current[$tagName];
00472                 }
00473         }
00474 }
00475 ?>