PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/Doduo_1.1/WebKitSite/blog/wp-includes/atomlib.php

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