PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/atomlib.php

https://gitlab.com/webkod3r/tripolis
PHP | 363 lines | 232 code | 62 blank | 69 comment | 59 complexity | 6ff12e8342f26fb6a7402a05c8552789 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.0
  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. /**
  82. * PHP5 constructor.
  83. */
  84. function __construct() {
  85. $this->feed = new AtomFeed();
  86. $this->current = null;
  87. $this->map_attrs_func = create_function('$k,$v', 'return "$k=\"$v\"";');
  88. $this->map_xmlns_func = create_function('$p,$n', '$xd = "xmlns"; if(strlen($n[0])>0) $xd .= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";');
  89. }
  90. /**
  91. * PHP4 constructor.
  92. */
  93. public function AtomParser() {
  94. self::__construct();
  95. }
  96. function _p($msg) {
  97. if($this->debug) {
  98. print str_repeat(" ", $this->depth * $this->indent) . $msg ."\n";
  99. }
  100. }
  101. function error_handler($log_level, $log_text, $error_file, $error_line) {
  102. $this->error = $log_text;
  103. }
  104. function parse() {
  105. set_error_handler(array(&$this, 'error_handler'));
  106. array_unshift($this->ns_contexts, array());
  107. $parser = xml_parser_create_ns();
  108. xml_set_object($parser, $this);
  109. xml_set_element_handler($parser, "start_element", "end_element");
  110. xml_parser_set_option($parser,XML_OPTION_CASE_FOLDING,0);
  111. xml_parser_set_option($parser,XML_OPTION_SKIP_WHITE,0);
  112. xml_set_character_data_handler($parser, "cdata");
  113. xml_set_default_handler($parser, "_default");
  114. xml_set_start_namespace_decl_handler($parser, "start_ns");
  115. xml_set_end_namespace_decl_handler($parser, "end_ns");
  116. $this->content = '';
  117. $ret = true;
  118. $fp = fopen($this->FILE, "r");
  119. while ($data = fread($fp, 4096)) {
  120. if($this->debug) $this->content .= $data;
  121. if(!xml_parse($parser, $data, feof($fp))) {
  122. /* translators: 1: error message, 2: line number */
  123. trigger_error(sprintf(__('XML Error: %1$s at line %2$s')."\n",
  124. xml_error_string(xml_get_error_code($parser)),
  125. xml_get_current_line_number($parser)));
  126. $ret = false;
  127. break;
  128. }
  129. }
  130. fclose($fp);
  131. xml_parser_free($parser);
  132. restore_error_handler();
  133. return $ret;
  134. }
  135. function start_element($parser, $name, $attrs) {
  136. $tag = array_pop(split(":", $name));
  137. switch($name) {
  138. case $this->NS . ':feed':
  139. $this->current = $this->feed;
  140. break;
  141. case $this->NS . ':entry':
  142. $this->current = new AtomEntry();
  143. break;
  144. };
  145. $this->_p("start_element('$name')");
  146. #$this->_p(print_r($this->ns_contexts,true));
  147. #$this->_p('current(' . $this->current . ')');
  148. array_unshift($this->ns_contexts, $this->ns_decls);
  149. $this->depth++;
  150. if(!empty($this->in_content)) {
  151. $this->content_ns_decls = array();
  152. if($this->is_html || $this->is_text)
  153. trigger_error("Invalid content in element found. Content must not be of type text or html if it contains markup.");
  154. $attrs_prefix = array();
  155. // resolve prefixes for attributes
  156. foreach($attrs as $key => $value) {
  157. $with_prefix = $this->ns_to_prefix($key, true);
  158. $attrs_prefix[$with_prefix[1]] = $this->xml_escape($value);
  159. }
  160. $attrs_str = join(' ', array_map($this->map_attrs_func, array_keys($attrs_prefix), array_values($attrs_prefix)));
  161. if(strlen($attrs_str) > 0) {
  162. $attrs_str = " " . $attrs_str;
  163. }
  164. $with_prefix = $this->ns_to_prefix($name);
  165. if(!$this->is_declared_content_ns($with_prefix[0])) {
  166. array_push($this->content_ns_decls, $with_prefix[0]);
  167. }
  168. $xmlns_str = '';
  169. if(count($this->content_ns_decls) > 0) {
  170. array_unshift($this->content_ns_contexts, $this->content_ns_decls);
  171. $xmlns_str .= join(' ', array_map($this->map_xmlns_func, array_keys($this->content_ns_contexts[0]), array_values($this->content_ns_contexts[0])));
  172. if(strlen($xmlns_str) > 0) {
  173. $xmlns_str = " " . $xmlns_str;
  174. }
  175. }
  176. array_push($this->in_content, array($tag, $this->depth, "<". $with_prefix[1] ."{$xmlns_str}{$attrs_str}" . ">"));
  177. } else if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS) || in_array($tag, $this->ATOM_SIMPLE_ELEMENTS)) {
  178. $this->in_content = array();
  179. $this->is_xhtml = $attrs['type'] == 'xhtml';
  180. $this->is_html = $attrs['type'] == 'html' || $attrs['type'] == 'text/html';
  181. $this->is_text = !in_array('type',array_keys($attrs)) || $attrs['type'] == 'text';
  182. $type = $this->is_xhtml ? 'XHTML' : ($this->is_html ? 'HTML' : ($this->is_text ? 'TEXT' : $attrs['type']));
  183. if(in_array('src',array_keys($attrs))) {
  184. $this->current->$tag = $attrs;
  185. } else {
  186. array_push($this->in_content, array($tag,$this->depth, $type));
  187. }
  188. } else if($tag == 'link') {
  189. array_push($this->current->links, $attrs);
  190. } else if($tag == 'category') {
  191. array_push($this->current->categories, $attrs);
  192. }
  193. $this->ns_decls = array();
  194. }
  195. function end_element($parser, $name) {
  196. $tag = array_pop(split(":", $name));
  197. $ccount = count($this->in_content);
  198. # if we are *in* content, then let's proceed to serialize it
  199. if(!empty($this->in_content)) {
  200. # if we are ending the original content element
  201. # then let's finalize the content
  202. if($this->in_content[0][0] == $tag &&
  203. $this->in_content[0][1] == $this->depth) {
  204. $origtype = $this->in_content[0][2];
  205. array_shift($this->in_content);
  206. $newcontent = array();
  207. foreach($this->in_content as $c) {
  208. if(count($c) == 3) {
  209. array_push($newcontent, $c[2]);
  210. } else {
  211. if($this->is_xhtml || $this->is_text) {
  212. array_push($newcontent, $this->xml_escape($c));
  213. } else {
  214. array_push($newcontent, $c);
  215. }
  216. }
  217. }
  218. if(in_array($tag, $this->ATOM_CONTENT_ELEMENTS)) {
  219. $this->current->$tag = array($origtype, join('',$newcontent));
  220. } else {
  221. $this->current->$tag = join('',$newcontent);
  222. }
  223. $this->in_content = array();
  224. } else if($this->in_content[$ccount-1][0] == $tag &&
  225. $this->in_content[$ccount-1][1] == $this->depth) {
  226. $this->in_content[$ccount-1][2] = substr($this->in_content[$ccount-1][2],0,-1) . "/>";
  227. } else {
  228. # else, just finalize the current element's content
  229. $endtag = $this->ns_to_prefix($name);
  230. array_push($this->in_content, array($tag, $this->depth, "</$endtag[1]>"));
  231. }
  232. }
  233. array_shift($this->ns_contexts);
  234. $this->depth--;
  235. if($name == ($this->NS . ':entry')) {
  236. array_push($this->feed->entries, $this->current);
  237. $this->current = null;
  238. }
  239. $this->_p("end_element('$name')");
  240. }
  241. function start_ns($parser, $prefix, $uri) {
  242. $this->_p("starting: " . $prefix . ":" . $uri);
  243. array_push($this->ns_decls, array($prefix,$uri));
  244. }
  245. function end_ns($parser, $prefix) {
  246. $this->_p("ending: #" . $prefix . "#");
  247. }
  248. function cdata($parser, $data) {
  249. $this->_p("data: #" . str_replace(array("\n"), array("\\n"), trim($data)) . "#");
  250. if(!empty($this->in_content)) {
  251. array_push($this->in_content, $data);
  252. }
  253. }
  254. function _default($parser, $data) {
  255. # when does this gets called?
  256. }
  257. function ns_to_prefix($qname, $attr=false) {
  258. # split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div')
  259. $components = split(":", $qname);
  260. # grab the last one (e.g 'div')
  261. $name = array_pop($components);
  262. if(!empty($components)) {
  263. # re-join back the namespace component
  264. $ns = join(":",$components);
  265. foreach($this->ns_contexts as $context) {
  266. foreach($context as $mapping) {
  267. if($mapping[1] == $ns && strlen($mapping[0]) > 0) {
  268. return array($mapping, "$mapping[0]:$name");
  269. }
  270. }
  271. }
  272. }
  273. if($attr) {
  274. return array(null, $name);
  275. } else {
  276. foreach($this->ns_contexts as $context) {
  277. foreach($context as $mapping) {
  278. if(strlen($mapping[0]) == 0) {
  279. return array($mapping, $name);
  280. }
  281. }
  282. }
  283. }
  284. }
  285. function is_declared_content_ns($new_mapping) {
  286. foreach($this->content_ns_contexts as $context) {
  287. foreach($context as $mapping) {
  288. if($new_mapping == $mapping) {
  289. return true;
  290. }
  291. }
  292. }
  293. return false;
  294. }
  295. function xml_escape($string)
  296. {
  297. return str_replace(array('&','"',"'",'<','>'),
  298. array('&amp;','&quot;','&apos;','&lt;','&gt;'),
  299. $string );
  300. }
  301. }