PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/cpgdbal/include/lib.xml.php

https://github.com/cpg-contrib/coppermine
PHP | 347 lines | 120 code | 58 blank | 169 comment | 23 complexity | 85cd6f35d71a94ddcbbf8790b4ccde3c MD5 | raw file
  1. <?php
  2. /*************************
  3. Coppermine Photo Gallery
  4. ************************
  5. Copyright (c) 2003-2008 Dev Team
  6. v1.1 originally written by Gregory DEMAR
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License version 3
  9. as published by the Free Software Foundation.
  10. ********************************************
  11. Coppermine version: 1.5.0
  12. $HeadURL: https://coppermine.svn.sourceforge.net/svnroot/coppermine/trunk/cpg1.5.x/include/lib.xml.php $
  13. $Revision: 5129 $
  14. $LastChangedBy: gaugau $
  15. $Date: 2008-10-18 16:03:12 +0530 (Sat, 18 Oct 2008) $
  16. ********************************************
  17. Code below has been taken from lib.xml.php and slightly modified for use with coppermine
  18. Orginal: http://www.phpclasses.org/browse/file/17412.html
  19. **********************************************/
  20. ####### GNU General Public License #############################################
  21. # #
  22. # This file is part of HOA Open Accessibility. #
  23. # Copyright (c) 2007 Ivan ENDERLIN. All rights reserved. #
  24. # #
  25. # HOA Open Accessibility is free software; you can redistribute it and/or #
  26. # modify it under the terms of the GNU General Public License as published by #
  27. # the Free Software Foundation; either version 2 of the License, or #
  28. # (at your option) any later version. #
  29. # #
  30. # HOA Open Accessibility is distributed in the hope that it will be useful, #
  31. # but WITHOUT ANY WARRANTY; without even the implied warranty of #
  32. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
  33. # GNU General Public License for more details. #
  34. # #
  35. # You should have received a copy of the GNU General Public License #
  36. # along with HOA Open Accessibility; if not, write to the Free Software #
  37. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #
  38. # #
  39. ####### !GNU General Public License ############################################
  40. /**
  41. * Class Xml.
  42. *
  43. * Parse a XML document into a nested array.
  44. * @author ENDERLIN Ivan <ivan.enderlin@wanadoo.fr>
  45. * @copyright 2007 ENDERLIN Ivan.
  46. * @since PHP4
  47. * @version 0.3
  48. * @package Xml
  49. * @licence GNU GPL
  50. */
  51. class Xml {
  52. /**
  53. * Xml parser container.
  54. *
  55. * @var resource parser
  56. */
  57. var $parser;
  58. /**
  59. * Parse result.
  60. *
  61. * @var array pOut
  62. */
  63. var $pOut = array();
  64. /**
  65. * Contain the overlap tag temporarily .
  66. *
  67. * @var array track
  68. */
  69. var $track = array();
  70. /**
  71. * Current tag level.
  72. *
  73. * @var string tmpLevel
  74. */
  75. var $tmpLevel = '';
  76. /**
  77. * Attribut of current tag.
  78. *
  79. * @var array tmpAttrLevel
  80. */
  81. var $tmpAttrLevel = array();
  82. /**
  83. * Write result.
  84. *
  85. * @var string wOut
  86. */
  87. var $wOut = '';
  88. /**
  89. * parse
  90. * Set the parser Xml and theses options.
  91. * Xml file could be a string, a file, or curl.
  92. * When the source is loaded, we run the parse.
  93. * After, we clean all the memory and variables,
  94. * and return the result in an array.
  95. *
  96. * @access public
  97. * @param data string Source
  98. * @return array
  99. */
  100. function parse ($data) {
  101. // ini;
  102. $encoding = 'UTF-8';
  103. // (re)set array;
  104. $this->pOut = array();
  105. $this->parser = xml_parser_create();
  106. xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  107. xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, $encoding);
  108. xml_set_object($this->parser, $this);
  109. xml_set_element_handler($this->parser, 'startHandler', 'endHandler');
  110. xml_set_character_data_handler($this->parser, 'contentHandler');
  111. // format source;
  112. if($data == '') {
  113. return trigger_error('Xml parser need data.', E_USER_ERROR);
  114. }
  115. // parse $data;
  116. $parse = xml_parse($this->parser, $data);
  117. if(!$parse)
  118. return trigger_error('XML Error : %s at line %d.', E_USER_ERROR,
  119. array(xml_error_string(xml_get_error_code($this->parser)),
  120. xml_get_current_line_number($this->parser)));
  121. // destroy parser;
  122. xml_parser_free($this->parser);
  123. // unset extra vars;
  124. unset($data,
  125. $this->track,
  126. $this->tmpLevel);
  127. // remove global tag and return the result;
  128. return $this->pOut[0][key($this->pOut[0])];
  129. }
  130. /**
  131. * startHandler
  132. * Manage the open tag, and these attributs by callback.
  133. * The purpose is to create a pointer : {{int ptr}}.
  134. * If the pointer exists, we have a multi-tag situation.
  135. * Tag name is stocked like : '<tag>'
  136. * Attributs is stocked like : '<tag>-ATTR'
  137. * Return true but built $this->pOut.
  138. *
  139. * @access private
  140. * @param parser resource Parser resource.
  141. * @param tag string Tag name.
  142. * @param attr array Attribut.
  143. * @return bool
  144. */
  145. function startHandler ( $parser, $tag, $attr ) {
  146. // built $this->track;
  147. $this->track[] = $tag;
  148. // place pointer to the end;
  149. end($this->track);
  150. // temp level;
  151. $this->tmpLevel = key($this->track);
  152. // built attrLevel into $this->tmpAttrLevel
  153. if(isset($this->tmpAttrLevel[$this->tmpLevel]['attrLevel']))
  154. $this->tmpAttrLevel[$this->tmpLevel]['attrLevel']++;
  155. // built $this->pOut;
  156. if(!isset($this->pOut[key($this->track)][$tag])) {
  157. $this->pOut[key($this->track)][$tag] = '{{'.key($this->track).'}}';
  158. if(!isset($this->tmpAttrLevel[$this->tmpLevel]['attrLevel']))
  159. $this->tmpAttrLevel[$this->tmpLevel]['attrLevel'] = 0;
  160. }
  161. // built attributs;
  162. if(!empty($attr)) {
  163. $this->tmpAttrLevel[$this->tmpLevel][] = $this->tmpAttrLevel[$this->tmpLevel]['attrLevel'];
  164. end($this->tmpAttrLevel[$this->tmpLevel]);
  165. // it's the first attribut;
  166. if(!isset($this->pOut[key($this->track)][$tag.'-ATTR']))
  167. $this->pOut[key($this->track)][$tag.'-ATTR'] = $attr;
  168. // or it's not the first;
  169. else {
  170. // so it's the second;
  171. if(!prev($this->tmpAttrLevel[$this->tmpLevel])) {
  172. $this->pOut[key($this->track)][$tag.'-ATTR'] = array(
  173. current($this->tmpAttrLevel[$this->tmpLevel]) => $this->pOut[key($this->track)][$tag.'-ATTR'],
  174. next($this->tmpAttrLevel[$this->tmpLevel]) => $attr
  175. );
  176. }
  177. // or one other;
  178. else
  179. $this->pOut[key($this->track)][$tag.'-ATTR'][$this->tmpAttrLevel[$this->tmpLevel]['attrLevel']] = $attr;
  180. }
  181. }
  182. return true;
  183. }
  184. /**
  185. * contentHandler
  186. * Detect the pointer, or the multi-tag by callback.
  187. * If we have a pointer, the method replaces this pointer by the content.
  188. * Else we have a multi-tag, the method add a element to this array.
  189. * Return true but built $this->pOut.
  190. *
  191. * @access private
  192. * @param parser resource Parser resource.
  193. * @param contentHandler string Tag content.
  194. * @return bool
  195. */
  196. function contentHandler ( $parser, $contentHandler ) {
  197. // remove all spaces;
  198. if(!preg_match('#^\s*$#', $contentHandler)) {
  199. // $contentHandler is a string;
  200. if(is_string($this->pOut[key($this->track)][current($this->track)])) {
  201. // then $contentHandler is a pointer : {{int ptr}} case 1;
  202. if(preg_match('#{{([0-9]+)}}#', $this->pOut[key($this->track)][current($this->track)]))
  203. $this->pOut[key($this->track)][current($this->track)] = $contentHandler;
  204. // or then $contentHandler is a multi-tag content case 2;
  205. else {
  206. $this->pOut[key($this->track)][current($this->track)] = array(
  207. 0 => $this->pOut[key($this->track)][current($this->track)],
  208. 1 => $contentHandler
  209. );
  210. }
  211. }
  212. // or $contentHandler is an array;
  213. else {
  214. // then $contentHandler is the multi-tag array case 1;
  215. if(isset($this->pOut[key($this->track)][current($this->track)][0]))
  216. $this->pOut[key($this->track)][current($this->track)][] = $contentHandler;
  217. // or then $contentHandler is a node-tag case 2;
  218. else
  219. $this->pOut[key($this->track)][current($this->track)] = array(
  220. 0 => $this->pOut[key($this->track)][current($this->track)],
  221. 1 => $contentHandler
  222. );
  223. }
  224. }
  225. return true;
  226. }
  227. /**
  228. * endHandler
  229. * Detect the last pointer by callback.
  230. * Move the last tags block up.
  231. * And reset some temp variables.
  232. * Return true but built $this->pOut.
  233. *
  234. * @access private
  235. * @param parser resource Parser resource.
  236. * @param tag string Tag name.
  237. * @return bool
  238. */
  239. function endHandler ( $parser, $tag ) {
  240. // if level--;
  241. if(key($this->track) == $this->tmpLevel-1) {
  242. // search up tag;
  243. // use array_keys if an empty tag exists (taking the last tag);
  244. // if it's a normal framaset;
  245. $keyBack = array_keys($this->pOut[key($this->track)], '{{'.key($this->track).'}}');
  246. $count = count($keyBack);
  247. if($count != 0) {
  248. $keyBack = $keyBack{$count-1};
  249. // move this level up;
  250. $this->pOut[key($this->track)][$keyBack] = $this->pOut[key($this->track)+1];
  251. }
  252. // if we have a multi-tag framaset ($count == 0);
  253. else {
  254. // if place is set;
  255. if(isset($this->pOut[key($this->track)][current($this->track)][0])) {
  256. // if it's a string, we built an array;
  257. if(is_string($this->pOut[key($this->track)][current($this->track)]))
  258. $this->pOut[key($this->track)][current($this->track)] = array(
  259. 0 => $this->pOut[key($this->track)][current($this->track)],
  260. 1 => $this->pOut[key($this->track)+1]
  261. );
  262. // else add an index into the array;
  263. else
  264. $this->pOut[key($this->track)][current($this->track)][] = $this->pOut[key($this->track)+1];
  265. }
  266. // else set the place;
  267. else
  268. $this->pOut[key($this->track)][current($this->track)] = array(
  269. 0 => $this->pOut[key($this->track)][current($this->track)],
  270. 1 => $this->pOut[key($this->track)+1]
  271. );
  272. }
  273. // kick $this->pOut level out;
  274. array_pop($this->pOut);
  275. end($this->pOut);
  276. }
  277. // re-temp level;
  278. $this->tmpLevel = key($this->track);
  279. while(isset($this->tmpAttrLevel[$this->tmpLevel+1]))
  280. array_pop($this->tmpAttrLevel);
  281. // kick $this->track level out;
  282. array_pop($this->track);
  283. end($this->track);
  284. return true;
  285. }
  286. }
  287. ?>