Documentation TYPO3 par Ameos

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 
00064         function searchExtensionsXML($search, $owner='', $order='', $allExt=false, $allVer=false, $offset=0, $limit=500)        {
00065                 $where = '1=1';
00066                 if ($search)    {
00067                         $where.= ' AND extkey LIKE \'%'.$GLOBALS['TYPO3_DB']->quoteStr($GLOBALS['TYPO3_DB']->escapeStrForLike($search, 'cache_extensions'), 'cache_extensions').'%\'';
00068                 }
00069                 if ($owner)     {
00070                         $where.= ' AND ownerusername='.$GLOBALS['TYPO3_DB']->fullQuoteStr($owner, 'cache_extensions');
00071                 }
00072                 if (strlen($owner) || $this->useUnchecked || $allExt)   {
00073                                 // show extensions without review or that have passed review
00074                         $where.= ' AND reviewstate >= 0';
00075                 } else {
00076                                 // only display extensions that have passed review
00077                         $where.= ' AND reviewstate > 0';
00078                 }
00079                 if (!$this->useObsolete && !$allExt)    {
00080                         $where.= ' AND state!=5';               // 5 == obsolete
00081                 }
00082                 switch ($order) {
00083                         case 'author_company':
00084                                 $forder = 'authorname, authorcompany';
00085                         break;
00086                         case 'state':
00087                                 $forder = 'state';
00088                         break;
00089                         case 'cat':
00090                         default:
00091                                 $forder = 'category';
00092                         break;
00093                 }
00094                 $order = $forder.', title';
00095                 if (!$allVer)   {
00096                         if ($this->useUnchecked)        {
00097                                 $where .= ' AND lastversion>0';
00098                         } else  {
00099                                 $where .= ' AND lastreviewedversion>0';
00100                         }
00101                 }
00102                 $this->catArr = array();
00103                 $idx = 0;
00104                 foreach ($this->emObj->defaultCategories['cat'] as $catKey => $tmp)     {
00105                         $this->catArr[$idx] = $catKey;
00106                         $idx++;
00107                 }
00108                 $this->stateArr = array();
00109                 $idx = 0;
00110                 foreach ($this->emObj->states as $state => $tmp)        {
00111                         $this->stateArr[$idx] = $state;
00112                         $idx++;
00113                 }
00114 
00115                         // Fetch count
00116                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('count(*) as cnt', 'cache_extensions', $where);
00117                 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
00118                 $this->matchingCount = $row['cnt'];
00119                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00120 
00121                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'cache_extensions', $where, '', $order, $offset.','.$limit);
00122                 $this->extensionsXML = array();
00123                 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res))      {
00124                         $row['category'] = $this->catArr[$row['category']];
00125                         $row['state'] = $this->stateArr[$row['state']];
00126 
00127                         if (!is_array($this->extensionsXML[$row['extkey']]))    {
00128                                 $this->extensionsXML[$row['extkey']] = array();
00129                                 $this->extensionsXML[$row['extkey']]['downloadcounter'] = $row['alldownloadcounter'];
00130                         }
00131                         if (!is_array($this->extensionsXML[$row['extkey']]['versions']))        {
00132                                 $this->extensionsXML[$row['extkey']]['versions'] = array();
00133                         }
00134                         $row['dependencies'] = unserialize($row['dependencies']);
00135                         $this->extensionsXML[$row['extkey']]['versions'][$row['version']] = $row;
00136                 }
00137                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00138         }
00139 
00140         function countExtensions() {
00141                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('extkey', 'cache_extensions', '1=1', 'extkey');
00142                 $cnt = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
00143                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00144                 return $cnt;
00145         }
00146 
00152         function loadExtensionsXML() {
00153                 $this->searchExtensionsXML('', '', '', true);
00154         }
00155 
00161         function freeExtensionsXML() {
00162                 unset($this->extensionsXML);
00163                 $this->extensionsXML = array();
00164         }
00165 
00172         function removeObsolete(&$extensions) {
00173                 if($this->useObsolete) return;
00174 
00175                 reset($extensions);
00176                 while (list($version, $data) = each($extensions)) {
00177                         if($data['state']=='obsolete')
00178                         unset($extensions[$version]);
00179                 }
00180         }
00181 
00189         function getReviewState($extKey, $version) {
00190                 $where = 'extkey='.$GLOBALS['TYPO3_DB']->fullQuoteStr($extKey, 'cache_extensions').' AND version='.$GLOBALS['TYPO3_DB']->fullQuoteStr($version, 'cache_extensions');
00191                 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('reviewstate', 'cache_extensions', $where);
00192                 if ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
00193                         return $row['reviewstate'];
00194                 }
00195                 $GLOBALS['TYPO3_DB']->sql_free_result($res);
00196                 return 0;
00197         }
00198 
00205         function checkReviewState(&$extensions) {
00206                 if ($this->useUnchecked) return;
00207 
00208                 reset($extensions);
00209                 while (list($version, $data) = each($extensions)) {
00210                         if($data['reviewstate']<1)
00211                                 unset($extensions[$version]);
00212                 }
00213         }
00214 
00220         function checkReviewStateGlobal() {
00221                 if($this->useUnchecked) return;
00222 
00223                 reset($this->extensionsXML);
00224                 while (list($extkey, $data) = each($this->extensionsXML)) {
00225                         while (list($version, $vdata) = each($data['versions'])) {
00226                                 if($vdata['reviewstate']<1) unset($this->extensionsXML[$extkey]['versions'][$version]);
00227                         }
00228                         if(!count($this->extensionsXML[$extkey]['versions'])) unset($this->extensionsXML[$extkey]);
00229                 }
00230         }
00231 
00232 
00244         function startElement($parser, $name, $attrs) {
00245                 switch($name) {
00246                         case 'extensions':
00247                         break;
00248                         case 'extension':
00249                         $this->currentExt = $attrs['extensionkey'];
00250                         break;
00251                         case 'version':
00252                         $this->currentVersion = $attrs['version'];
00253                         $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion] = array();
00254                         break;
00255                         default:
00256                         $this->currentTag = $name;
00257                 }
00258         }
00259 
00267         function endElement($parser, $name) {
00268                 switch($name) {
00269                         case 'extension':
00270                         unset($this->currentExt);
00271                         break;
00272                         case 'version':
00273                         unset($this->currentVersion);
00274                         break;
00275                         default:
00276                         unset($this->currentTag);
00277                 }
00278         }
00279 
00287         function characterData($parser, $data) {
00288                 if(isset($this->currentTag)) {
00289                         if(!isset($this->currentVersion) && $this->currentTag == 'downloadcounter') {
00290                                 $this->extXMLResult[$this->currentExt]['downloadcounter'] = trim($data);
00291                         } elseif($this->currentTag == 'dependencies') {
00292                                 $data = @unserialize($data);
00293                                 if(is_array($data)) {
00294                                         $dep = array();
00295                                         foreach($data as $v) {
00296                                                 $dep[$v['kind']][$v['extensionKey']] = $v['versionRange'];
00297                                         }
00298                                         $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion]['dependencies'] = $dep;
00299                                 }
00300                         } elseif($this->currentTag == 'reviewstate') {
00301                                         $this->reviewStates[$this->currentExt][$this->currentVersion] = (int)trim($data);
00302                                         $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion]['reviewstate'] = (int)trim($data);
00303                         } else {
00304                                 $this->extXMLResult[$this->currentExt]['versions'][$this->currentVersion][$this->currentTag] .= trim($data);
00305                         }
00306                 }
00307         }
00308 
00315         function parseExtensionsXML($filename) {
00316 
00317                 $parser = xml_parser_create();
00318                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00319                 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
00320                 xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, 'utf-8');
00321                 xml_set_element_handler($parser, array(&$this,'startElement'), array(&$this,'endElement'));
00322                 xml_set_character_data_handler($parser, array(&$this,'characterData'));
00323 
00324                 $fp = gzopen($filename, 'rb');
00325                 if (!$fp)       {
00326                         $content.= 'Error opening XML extension file "'.$filename.'"';
00327                         return $content;
00328                 }
00329                 $string = gzread($fp, 0xffff);  // Read 64KB
00330 
00331                 $this->revCatArr = array();
00332                 $idx = 0;
00333                 foreach ($this->emObj->defaultCategories['cat'] as $catKey => $tmp)     {
00334                         $this->revCatArr[$catKey] = $idx++;
00335                 }
00336 
00337                 $this->revStateArr = array();
00338                 $idx = 0;
00339                 foreach ($this->emObj->states as $state => $tmp)        {
00340                         $this->revStateArr[$state] = $idx++;
00341                 }
00342 
00343                 $GLOBALS['TYPO3_DB']->exec_DELETEquery('cache_extensions', '1=1');
00344 
00345                 $extcount = 0;
00346                 @ini_set('pcre.backtrack_limit', 500000);
00347                 do      {
00348                         if (preg_match('/.*(<extension\s+extensionkey="[^"]+">.*<\/extension>)/suU', $string, $match))  {
00349                                 // Parse content:
00350                                 if (!xml_parse($parser, $match[0], 0)) {
00351                                         $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));
00352                                         $error = true;
00353                                         break;
00354                                 }
00355                                 $this->storeXMLResult();
00356                                 $this->extXMLResult = array();
00357                                 $extcount++;
00358                                 $string = substr($string, strlen($match[0]));
00359                         } elseif(function_exists('preg_last_error') && preg_last_error())       {
00360                                 $errorcodes = array(
00361                                         0 => 'PREG_NO_ERROR',
00362                                         1 => 'PREG_INTERNAL_ERROR',
00363                                         2 => 'PREG_BACKTRACK_LIMIT_ERROR',
00364                                         3 => 'PREG_RECURSION_LIMIT_ERROR',
00365                                         4 => 'PREG_BAD_UTF8_ERROR'
00366                                 );
00367                                 $content.= 'Error in regular expression matching, code: '.$errorcodes[preg_last_error()].'<br />See <a href="http://www.php.net/manual/en/function.preg-last-error.php" target="_blank">http://www.php.net/manual/en/function.preg-last-error.php</a>';
00368                                 $error = true;
00369                                 break;
00370                         } else  {
00371                                 if(gzeof($fp)) break; // Nothing more can be read
00372                                 $string .= gzread($fp, 0xffff); // Read another 64KB
00373                         }
00374                 } while (true);
00375 
00376                 xml_parser_free($parser);
00377                 gzclose($fp);
00378 
00379                 if(!$error) {
00380                         $content.= '<p>The extensions list has been updated and now contains '.$extcount.' extension entries.</p>';
00381                 }
00382 
00383                 return $content;
00384         }
00385 
00386         function storeXMLResult()       {
00387                 foreach ($this->extXMLResult as $extkey => $extArr)     {
00388                         $max = -1;
00389                         $maxrev = -1;
00390                         $last = '';
00391                         $lastrev = '';
00392                         $usecat = '';
00393                         $usetitle = '';
00394                         $usestate = '';
00395                         $useauthorcompany = '';
00396                         $useauthorname = '';
00397                         $verArr = array();
00398                         foreach ($extArr['versions'] as $version => $vArr)      {
00399                                 $iv = $this->emObj->makeVersion($version, 'int');
00400                                 if ($vArr['title']&&!$usetitle) {
00401                                         $usetitle = $vArr['title'];
00402                                 }
00403                                 if ($vArr['state']&&!$usestate) {
00404                                         $usestate = $vArr['state'];
00405                                 }
00406                                 if ($vArr['authorcompany']&&!$useauthorcompany) {
00407                                         $useauthorcompany = $vArr['authorcompany'];
00408                                 }
00409                                 if ($vArr['authorname']&&!$useauthorname)       {
00410                                         $useauthorname = $vArr['authorname'];
00411                                 }
00412                                 $verArr[$version] = $iv;
00413                                 if ($iv>$max)   {
00414                                         $max = $iv;
00415                                         $last = $version;
00416                                         if ($vArr['title'])     {
00417                                                 $usetitle = $vArr['title'];
00418                                         }
00419                                         if ($vArr['state'])     {
00420                                                 $usestate = $vArr['state'];
00421                                         }
00422                                         if ($vArr['authorcompany'])     {
00423                                                 $useauthorcompany = $vArr['authorcompany'];
00424                                         }
00425                                         if ($vArr['authorname'])        {
00426                                                 $useauthorname = $vArr['authorname'];
00427                                         }
00428                                         $usecat = $vArr['category'];
00429                                 }
00430                                 if ($vArr['reviewstate'] && ($iv>$maxrev))      {
00431                                         $maxrev = $iv;
00432                                         $lastrev = $version;
00433                                 }
00434                         }
00435                         if (!strlen($usecat))   {
00436                                 $usecat = 4;            // Extensions without a category end up in "misc"
00437                         } else  {
00438                                 if (isset($this->revCatArr[$usecat]))   {
00439                                         $usecat = $this->revCatArr[$usecat];
00440                                 } else  {
00441                                         $usecat = 4;            // Extensions without a category end up in "misc"
00442                                 }
00443                         }
00444                         if (isset($this->revStateArr[$usestate]))       {
00445                                 $usestate = $this->revCatArr[$usestate];
00446                         } else  {
00447                                 $usestate = 999;                // Extensions without a category end up in "misc"
00448                         }
00449                         foreach ($extArr['versions'] as $version => $vArr)      {
00450                                 $vArr['version'] = $version;
00451                                 $vArr['intversion'] = $verArr[$version];
00452                                 $vArr['extkey'] = $extkey;
00453                                 $vArr['alldownloadcounter'] = $extArr['downloadcounter'];
00454                                 $vArr['dependencies'] = serialize($vArr['dependencies']);
00455                                 $vArr['category'] = $usecat;
00456                                 $vArr['title'] = $usetitle;
00457                                 if ($version==$last)    {
00458                                         $vArr['lastversion'] = 1;
00459                                 }
00460                                 if ($version==$lastrev) {
00461                                         $vArr['lastreviewedversion'] = 1;
00462                                 }
00463                                 $vArr['state'] = isset($this->revStateArr[$vArr['state']])?$this->revStateArr[$vArr['state']]:$usestate;        // 999 = not set category
00464                                 $GLOBALS['TYPO3_DB']->exec_INSERTquery('cache_extensions', $vArr);
00465                         }
00466                 }
00467         }
00468 
00475         function parseMirrorsXML($string) {
00476                 global $TYPO3_CONF_VARS;
00477 
00478                 // Create parser:
00479                 $parser = xml_parser_create();
00480                 $vals = array();
00481                 $index = array();
00482 
00483                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00484                 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
00485 
00486                 if ((double)phpversion()>=5)    {
00487                         $preg_result = array();
00488                         preg_match('/^[[:space:]]*<\?xml[^>]*encoding[[:space:]]*=[[:space:]]*"([^"]*)"/',substr($string,0,200),$preg_result);
00489                         $theCharset = $preg_result[1] ? $preg_result[1] : ($TYPO3_CONF_VARS['BE']['forceCharset'] ? $TYPO3_CONF_VARS['BE']['forceCharset'] : 'iso-8859-1');
00490                         xml_parser_set_option($parser, XML_OPTION_TARGET_ENCODING, $theCharset);  // us-ascii / utf-8 / iso-8859-1
00491                 }
00492 
00493                 // Parse content:
00494                 xml_parse_into_struct($parser, $string, $vals, $index);
00495 
00496                 // If error, return error message:
00497                 if (xml_get_error_code($parser))        {
00498                         $line = xml_get_current_line_number($parser);
00499                         $error = xml_error_string(xml_get_error_code($parser));
00500                         xml_parser_free($parser);
00501                         return 'Error in XML parser while decoding mirrors XML file. Line '.$line.': '.$error;
00502                 } else  {
00503                         // Init vars:
00504                         $stack = array(array());
00505                         $stacktop = 0;
00506                         $mirrornumber = 0;
00507                         $current=array();
00508                         $tagName = '';
00509                         $documentTag = '';
00510 
00511                         // Traverse the parsed XML structure:
00512                         foreach($vals as $val) {
00513 
00514                                 // First, process the tag-name (which is used in both cases, whether "complete" or "close")
00515                                 $tagName = ($val['tag']=='mirror' && $val['type']=='open') ? '__plh' : $val['tag'];
00516                                 if (!$documentTag)      $documentTag = $tagName;
00517 
00518                                 // Setting tag-values, manage stack:
00519                                 switch($val['type'])    {
00520                                         case 'open':            // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
00521                                                 $current[$tagName] = array();   // Setting blank place holder
00522                                                 $stack[$stacktop++] = $current;
00523                                                 $current = array();
00524                                                 break;
00525                                         case 'close':   // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
00526                                         $oldCurrent = $current;
00527                                         $current = $stack[--$stacktop];
00528                                         end($current);  // Going to the end of array to get placeholder key, key($current), and fill in array next:
00529                                         if($tagName=='mirror') {
00530                                                 unset($current['__plh']);
00531                                                 $current[$oldCurrent['host']] = $oldCurrent;
00532                                         } else {
00533                                                 $current[key($current)] = $oldCurrent;
00534                                         }
00535                                         unset($oldCurrent);
00536                                         break;
00537                                         case 'complete':        // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
00538                                         $current[$tagName] = (string)$val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!
00539                                         break;
00540                                 }
00541                         }
00542                         return $current[$tagName];
00543                 }
00544         }
00545 
00552         function parseL10nXML($string) {
00553                 // Create parser:
00554                 $parser = xml_parser_create();
00555                 $vals = array();
00556                 $index = array();
00557 
00558                 xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
00559                 xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
00560 
00561                 // Parse content:
00562                 xml_parse_into_struct($parser, $string, $vals, $index);
00563 
00564                 // If error, return error message:
00565                 if (xml_get_error_code($parser))        {
00566                         $line = xml_get_current_line_number($parser);
00567                         $error = xml_error_string(xml_get_error_code($parser));
00568                         debug($error);
00569                         xml_parser_free($parser);
00570                         return 'Error in XML parser while decoding l10n XML file. Line '.$line.': '.$error;
00571                 } else  {
00572                         // Init vars:
00573                         $stack = array(array());
00574                         $stacktop = 0;
00575                         $mirrornumber = 0;
00576                         $current=array();
00577                         $tagName = '';
00578                         $documentTag = '';
00579 
00580                         // Traverse the parsed XML structure:
00581                         foreach($vals as $val) {
00582 
00583                                 // First, process the tag-name (which is used in both cases, whether "complete" or "close")
00584                                 $tagName = ($val['tag']=='languagepack' && $val['type']=='open') ? $val['attributes']['language'] : $val['tag'];
00585                                 if (!$documentTag)      $documentTag = $tagName;
00586 
00587                                 // Setting tag-values, manage stack:
00588                                 switch($val['type'])    {
00589                                         case 'open':            // If open tag it means there is an array stored in sub-elements. Therefore increase the stackpointer and reset the accumulation array:
00590                                                 $current[$tagName] = array();   // Setting blank place holder
00591                                                 $stack[$stacktop++] = $current;
00592                                                 $current = array();
00593                                                 break;
00594                                         case 'close':   // If the tag is "close" then it is an array which is closing and we decrease the stack pointer.
00595                                         $oldCurrent = $current;
00596                                         $current = $stack[--$stacktop];
00597                                         end($current);  // Going to the end of array to get placeholder key, key($current), and fill in array next:
00598                                         $current[key($current)] = $oldCurrent;
00599                                         unset($oldCurrent);
00600                                         break;
00601                                         case 'complete':        // If "complete", then it's a value. If the attribute "base64" is set, then decode the value, otherwise just set it.
00602                                         $current[$tagName] = (string)$val['value']; // Had to cast it as a string - otherwise it would be evaluate false if tested with isset()!!
00603                                         break;
00604                                 }
00605                         }
00606                         return $current[$tagName];
00607                 }
00608         }
00609 }
00610 ?>


Généré par Le spécialiste TYPO3 avec  doxygen 1.4.6