PageRenderTime 64ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-includes/atomlib.php

https://github.com/alx/barceloneta
PHP | 354 lines | 231 code | 61 blank | 62 comment | 59 complexity | 4266adfe07df3392cc31d8c1637cf893 MD5 | raw file
  1. <?php
  2. /**
  3. * Atom Syndication Format PHP Library
  4. *
  5. * @package AtomLib
  6. * @link http://code.google.com/p/phpatomlib/
  7. *
  8. * @author Elias Torres <elias@torrez.us>
  9. * @version 0.4
  10. * @since 2.3
  11. */
  12. /**
  13. * Structure that store common Atom Feed Properties
  14. *
  15. * @package AtomLib
  16. */
  17. class AtomFeed {
  18. /**
  19. * Stores Links
  20. * @var array
  21. * @access public
  22. */
  23. var $links = array();
  24. /**
  25. * Stores Categories
  26. * @var array
  27. * @access public
  28. */
  29. var $categories = array();
  30. /**
  31. * Stores Entries
  32. *
  33. * @var array
  34. * @access public
  35. */
  36. var $entries = array();
  37. }
  38. /**
  39. * Structure that store Atom Entry Properties
  40. *
  41. * @package AtomLib
  42. */
  43. class AtomEntry {
  44. /**
  45. * Stores Links
  46. * @var array
  47. * @access public
  48. */
  49. var $links = array();
  50. /**
  51. * Stores Categories
  52. * @var array
  53. * @access public
  54. */
  55. var $categories = array();
  56. }
  57. /**
  58. * AtomLib Atom Parser API
  59. *
  60. * @package AtomLib
  61. */
  62. class AtomParser {
  63. var $NS = 'http://www.w3.org/2005/Atom';
  64. var $ATOM_CONTENT_ELEMENTS = array('content','summary','title','subtitle','rights');
  65. var $ATOM_SIMPLE_ELEMENTS = array('id','updated','published','draft');
  66. var $debug = false;
  67. var $depth = 0;
  68. var $indent = 2;
  69. var $in_content;
  70. var $ns_contexts = array();
  71. var $ns_decls = array();
  72. var $content_ns_decls = array();
  73. var $content_ns_contexts = array();
  74. var $is_xhtml = false;
  75. var $is_html = false;
  76. var $is_text = true;
  77. var $skipped_div = false;
  78. var $FILE = "php://input";
  79. var $feed;
  80. var $current;
  81. function AtomParser() {
  82. $this->feed = new AtomFeed();
  83. $this->current = null;
  84. $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";');
  85. $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";');
  86. }
  87. function _p($msg) {
  88. if($this->debug) {
  89. print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n";
  90. }
  91. }
  92. function error_handler($log_level, $log_text, $error_file, $error_line) {
  93. $this->error = $log_text;
  94. }
  95. function parse() {
  96. set_error_handler(array(&$this, 'error_handler'));
  97. array_unshift($this->ns_contexts, array());
  98. $parser = xml_parser_create_ns();
  99. xml_set_object($parser, $this);
  100. xml_set_element_handler($parser, "start_element", "end_element");
  101. xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
  102. xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
  103. xml_set_character_data_handler($parser, "cdata");
  104. xml_set_default_handler($parser, "_default");
  105. xml_set_start_namespace_decl_handler($parser, "start_ns");
  106. xml_set_end_namespace_decl_handler($parser, "end_ns");
  107. $this->content = '';
  108. $ret = true;
  109. $fp = fopen($this->FILE, "r");
  110. while ($data = fread($fp, 4096)) {
  111. if($this->debug) $this->content .= $data;
  112. if(!xml_parse($parser, $data, feof($fp))) {
  113. trigger_error(sprintf(__('XML error: %s at line %d')."\n",
  114. xml_error_string(xml_get_error_code($xml_parser)),
  115. xml_get_current_line_number($xml_parser)));
  116. $ret = false;
  117. break;
  118. }
  119. }
  120. fclose($fp);
  121. xml_parser_free($parser);
  122. restore_error_handler();
  123. return $ret;
  124. }
  125. function start_element($parser, $name, $attrs) {
  126. $tag = array_pop(split(":", $name));
  127. switch($name) {
  128. case $this->NS . ':feed':
  129. $this->current = $this->feed;
  130. break;
  131. case $this->NS . ':entry':
  132. $this->current = new AtomEntry();
  133. break;
  134. };
  135. $this->_p("start_element('$name')");
  136. #$this->_p(print_r($this->ns_contexts,true));
  137. #$this->_p('current(' . $this->current . ')');
  138. array_unshift($this->ns_contexts, $this->ns_decls);
  139. $this->depth++;
  140. if(!empty($this->in_content)) {
  141. $this->content_ns_decls = array();
  142. if($this->is_html || $this->is_text)
  143. trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup.");
  144. $attrs_prefix = array();
  145. // resolve prefixes for attributes
  146. foreach($attrs as $key => $value) {
  147. $with_prefix = $this->ns_to_prefix($key, true);
  148. $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value);
  149. }
  150. $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix)));
  151. if(strlen($attrs_str) > 0) {
  152. $attrs_str = " " . $attrs_str;
  153. }
  154. $with_prefix = $this->ns_to_prefix($name);
  155. if(!$this->is_declared_content_ns($with_prefix[0])) {
  156. array_push($this->content_ns_decls, $with_prefix[0]);
  157. }
  158. $xmlns_str = '';
  159. if(count($this->content_ns_decls) > 0) {
  160. array_unshift($this->content_ns_contexts, $this->content_ns_decls);
  161. $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0])));
  162. if(strlen($xmlns_str) > 0) {
  163. $xmlns_str = " " . $xmlns_str;
  164. }
  165. }
  166. array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">"));
  167. } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) {
  168. $this->in_content = array();
  169. $this->is_xhtml = $attrs['type'] == 'xhtml';
  170. $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html';
  171. $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text';
  172. $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type']));
  173. if(in_array('src',array_keys($attrs))) {
  174. $this->current->$tag = $attrs;
  175. } else {
  176. array_push($this->in_content, array($tag,$this->depth, $type));
  177. }
  178. } else if($tag == 'link') {
  179. array_push($this->current->links, $attrs);
  180. } else if($tag == 'category') {
  181. array_push($this->current->categories, $attrs);
  182. }
  183. $this->ns_decls = array();
  184. }
  185. function end_element($parser, $name) {
  186. $tag = array_pop(split(":", $name));
  187. $ccount = count($this->in_content);
  188. # if we are *in* content, then let's proceed to serialize it
  189. if(!empty($this->in_content)) {
  190. # if we are ending the original content element
  191. # then let's finalize the content
  192. if($this->in_content[0][0] == $tag &&
  193. $this->in_content[0][1] == $this->depth) {
  194. $origtype = $this->in_content[0][2];
  195. array_shift($this->in_content);
  196. $newcontent = array();
  197. foreach($this->in_content as $c) {
  198. if(count($c) == 3) {
  199. array_push($newcontent, $c[2]);
  200. } else {
  201. if($this->is_xhtml || $this->is_text) {
  202. array_push($newcontent, $this->xml_escape($c));
  203. } else {
  204. array_push($newcontent, $c);
  205. }
  206. }
  207. }
  208. if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) {
  209. $this->current->$tag = array($origtype, join('',$newcontent));
  210. } else {
  211. $this->current->$tag = join('',$newcontent);
  212. }
  213. $this->in_content = array();
  214. } else if($this->in_content[$ccount-1][0] == $tag &&
  215. $this->in_content[$ccount-1][1] == $this->depth) {
  216. $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>";
  217. } else {
  218. # else, just finalize the current element's content
  219. $endtag = $this->ns_to_prefix($name);
  220. array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>"));
  221. }
  222. }
  223. array_shift($this->ns_contexts);
  224. $this->depth--;
  225. if($name == ($this->NS . ':entry')) {
  226. array_push($this->feed->entries, $this->current);
  227. $this->current = null;
  228. }
  229. $this->_p("end_element('$name')");
  230. }
  231. function start_ns($parser, $prefix, $uri) {
  232. $this->_p("starting: " . $prefix . ":" . $uri);
  233. array_push($this->ns_decls, array($prefix,$uri));
  234. }
  235. function end_ns($parser, $prefix) {
  236. $this->_p("ending: #" . $prefix . "#");
  237. }
  238. function cdata($parser, $data) {
  239. $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#");
  240. if(!empty($this->in_content)) {
  241. array_push($this->in_content, $data);
  242. }
  243. }
  244. function _default($parser, $data) {
  245. # when does this gets called?
  246. }
  247. function ns_to_prefix($qname, $attr=false) {
  248. # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div')
  249. $components = split(":", $qname);
  250. # grab the last one (e.g 'div')
  251. $name = array_pop($components);
  252. if(!empty($components)) {
  253. # re-join back the namespace component
  254. $ns = join(":",$components);
  255. foreach($this->ns_contexts as $context) {
  256. foreach($context as $mapping) {
  257. if($mapping[1] == $ns && strlen($mapping[0]) > 0) {
  258. return array($mapping, "$mapping[0]:$name");
  259. }
  260. }
  261. }
  262. }
  263. if($attr) {
  264. return array(null, $name);
  265. } else {
  266. foreach($this->ns_contexts as $context) {
  267. foreach($context as $mapping) {
  268. if(strlen($mapping[0]) == 0) {
  269. return array($mapping, $name);
  270. }
  271. }
  272. }
  273. }
  274. }
  275. function is_declared_content_ns($new_mapping) {
  276. foreach($this->content_ns_contexts as $context) {
  277. foreach($context as $mapping) {
  278. if($new_mapping == $mapping) {
  279. return true;
  280. }
  281. }
  282. }
  283. return false;
  284. }
  285. function xml_escape($string)
  286. {
  287. return str_replace(array('&','"',"'",'<','>'),
  288. array('&amp;','&quot;','&apos;','&lt;','&gt;'),
  289. $string );
  290. }
  291. }
  292. ?>