/********************************************************************************** * nWordPress is an automated migration of WordPress 2.5.1 performed by Numiton. * * copyright : (C) 2008 Numiton - www.numiton.com * email : numiton@users.sourceforge.net * * $Id: AtomParser.java,v 1.5 2008/10/14 13:15:49 numiton Exp $ * **********************************************************************************/ /********************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * **********************************************************************************/ /*************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * ***************************************************************************/ package org.numiton.nwp.wp_includes; import static com.numiton.VarHandling.*; import static com.numiton.generic.PhpWeb.getIncluded; import java.io.Serializable; import java.util.Map; import org.apache.log4j.Logger; import org.numiton.nwp.GlobalConsts; import org.numiton.nwp.GlobalVars; import com.numiton.array.Array; import com.numiton.array.ArrayEntry; import com.numiton.error.ErrorHandling; import com.numiton.file.FileSystemOrSocket; import com.numiton.generic.*; import com.numiton.ntile.til.libraries.php.quercus.QRegExPosix; import com.numiton.ntile.til.libraries.php.quercus.QStrings; import com.numiton.string.Strings; import com.numiton.xml.XMLParser; /** * AtomLib Atom Parser API * @package AtomLib */ public class AtomParser implements ContextCarrierInterface, Serializable, Cloneable { protected static final Logger LOG = Logger.getLogger(AtomParser.class.getName()); public GlobalConsts gConsts; public GlobalVars gVars; public String NS = "http://www.w3.org/2005/Atom"; public Array<Object> ATOM_CONTENT_ELEMENTS = new Array<Object>(new ArrayEntry<Object>("content"), new ArrayEntry<Object>("summary"), new ArrayEntry<Object>("title"), new ArrayEntry<Object>("subtitle"), new ArrayEntry<Object>("rights")); public Array<Object> ATOM_SIMPLE_ELEMENTS = new Array<Object>(new ArrayEntry<Object>("id"), new ArrayEntry<Object>("updated"), new ArrayEntry<Object>("published"), new ArrayEntry<Object>("draft")); public boolean debug = false; public int depth = 0; public int indent = 2; public Array<Object> in_content = new Array<Object>(); public Array<Object> ns_contexts = new Array<Object>(); public Array<Object> ns_decls = new Array<Object>(); public Array<Object> content_ns_decls = new Array<Object>(); public Array<Object> content_ns_contexts = new Array<Object>(); public boolean is_xhtml = false; public boolean is_html = false; public boolean is_text = true; public boolean skipped_div = false; public String FILE = "php://input"; public AtomFeed feed; public AtomBase current; public Object error; public String content; public AtomParser(GlobalVars javaGlobalVariables, GlobalConsts javaGlobalConstants) { setContext(javaGlobalVariables, javaGlobalConstants); this.feed = new AtomFeed(gVars, gConsts); this.current = null; } public String createFunction_map_attrs_func(Object k, Object v) { return k + "=\"" + strval(v) + "\""; } public String createFunction_map_xmlns_func(Object p, Array<String> n) { String xd = "xmlns"; if (Strings.strlen(n.getValue(0)) > 0) { xd += (":" + n.getValue(0)); } return xd + "=\"" + n.getValue(1) + "\""; } public void _p(String msg) { if (this.debug) { print(gVars.webEnv, Strings.str_repeat(" ", this.depth * this.indent) + msg + "\n"); } } public void error_handler(Object log_level, Object log_text, Object error_file, Object error_line) { this.error = log_text; } public boolean parse() { int parser = 0; boolean ret = false; int fp = 0; String data = null; int xml_parser = 0; ErrorHandling.set_error_handler(gVars.webEnv, new Callback("error_handler", this)); Array.array_unshift(this.ns_contexts, new Array<Object>()); parser = XMLParser.xml_parser_create_ns(gVars.webEnv); XMLParser.xml_set_object(gVars.webEnv, parser, this); XMLParser.xml_set_element_handler(gVars.webEnv, parser, new Callback("start_element", this), new Callback("end_element", this)); XMLParser.xml_parser_set_option(gVars.webEnv, parser, XMLParser.XML_OPTION_CASE_FOLDING, 0); XMLParser.xml_parser_set_option(gVars.webEnv, parser, XMLParser.XML_OPTION_SKIP_WHITE, 0); XMLParser.xml_set_character_data_handler(gVars.webEnv, parser, new Callback("cdata", this)); XMLParser.xml_set_default_handler(gVars.webEnv, parser, new Callback("_default", this)); XMLParser.xml_set_start_namespace_decl_handler(gVars.webEnv, parser, new Callback("start_ns", this)); XMLParser.xml_set_end_namespace_decl_handler(gVars.webEnv, parser, new Callback("end_ns", this)); this.content = ""; ret = true; fp = FileSystemOrSocket.fopen(gVars.webEnv, this.FILE, "r"); while (booleanval(data = FileSystemOrSocket.fread(gVars.webEnv, fp, 4096))) { if (this.debug) { this.content = this.content + data; } if (!booleanval(XMLParser.xml_parse(gVars.webEnv, parser, data, FileSystemOrSocket.feof(gVars.webEnv, fp)))) { ErrorHandling.trigger_error(gVars.webEnv, QStrings.sprintf(getIncluded(L10nPage.class, gVars, gConsts).__("XML error: %s at line %d", "default") + "\n", XMLParser.xml_error_string(XMLParser.xml_get_error_code(gVars.webEnv, xml_parser)), XMLParser.xml_get_current_line_number(gVars.webEnv, xml_parser))); ret = false; break; } } FileSystemOrSocket.fclose(gVars.webEnv, fp); XMLParser.xml_parser_free(gVars.webEnv, parser); ErrorHandling.restore_error_handler(gVars.webEnv); return ret; } public void start_element(Object parser, String name, Array<Object> attrs) { Object tag = null; Array<Object> attrs_prefix = new Array<Object>(); Array<Object> with_prefix = new Array<Object>(); String key = null; Object value = null; String attrs_str = null; String xmlns_str = null; String type = null; tag = Array.array_pop(QRegExPosix.split(":", name)); { int javaSwitchSelector37 = 0; if (equal(name, this.NS + ":feed")) { javaSwitchSelector37 = 1; } if (equal(name, this.NS + ":entry")) { javaSwitchSelector37 = 2; } switch (javaSwitchSelector37) { case 1: { this.current = this.feed; break; } case 2: { this.current = new AtomEntry(gVars, gConsts); break; } } } this._p("start_element(\'" + name + "\')"); // $this->_p(print_r($this->ns_contexts,true)); // $this->_p('current(' . $this->current . ')'); Array.array_unshift(this.ns_contexts, this.ns_decls); this.depth++; if (!empty(this.in_content)) { this.content_ns_decls = new Array<Object>(); if (this.is_html || this.is_text) { ErrorHandling.trigger_error(gVars.webEnv, "Invalid content in element found. Content must not be of type text or html if it contains markup."); } attrs_prefix = new Array<Object>(); // resolve prefixes for attributes for (Map.Entry javaEntry368 : attrs.entrySet()) { key = strval(javaEntry368.getKey()); value = javaEntry368.getValue(); with_prefix = this.ns_to_prefix(key, true); attrs_prefix.putValue(with_prefix.getValue(1), this.xml_escape(strval(value))); } attrs_str = Strings.join(" ", Array.array_map(new Callback("createFunction_map_attrs_func", this), Array.array_keys(attrs_prefix), Array.array_values(attrs_prefix))); if (Strings.strlen(attrs_str) > 0) { attrs_str = " " + attrs_str; } with_prefix = this.ns_to_prefix(name); if (!this.is_declared_content_ns(with_prefix.getValue(0))) { Array.array_push(this.content_ns_decls, with_prefix.getValue(0)); } xmlns_str = ""; if (Array.count(this.content_ns_decls) > 0) { Array.array_unshift(this.content_ns_contexts, this.content_ns_decls); xmlns_str = xmlns_str + Strings.join(" ", Array.array_map( new Callback("createFunction_map_xmlns_func", this), Array.array_keys(this.content_ns_contexts.getArrayValue(0)), Array.array_values(this.content_ns_contexts.getArrayValue(0)))); if (Strings.strlen(xmlns_str) > 0) { xmlns_str = " " + xmlns_str; } } Array.array_push( this.in_content, new Array<Object>(new ArrayEntry<Object>(tag), new ArrayEntry<Object>(this.depth), new ArrayEntry<Object>("<" + strval(with_prefix.getValue(1)) + xmlns_str + attrs_str + ">"))); } else if (Array.in_array(tag, this.ATOM_CONTENT_ELEMENTS) || Array.in_array(tag, this.ATOM_SIMPLE_ELEMENTS)) { this.in_content = new Array<Object>(); this.is_xhtml = equal(attrs.getValue("type"), "xhtml"); this.is_html = equal(attrs.getValue("type"), "html") || equal(attrs.getValue("type"), "text/html"); this.is_text = !Array.in_array("type", Array.array_keys(attrs)) || equal(attrs.getValue("type"), "text"); type = (this.is_xhtml ? "XHTML" : (this.is_html ? "HTML" : (this.is_text ? "TEXT" : strval(attrs.getValue("type"))))); if (Array.in_array("src", Array.array_keys(attrs))) { // Modified by Numiton if (equal(tag, "content")) { this.current.content = attrs; } else if (equal(tag, "summary")) { this.current.summary = attrs; } else if (equal(tag, "title")) { this.current.title = attrs; } else if (equal(tag, "subtitle")) { this.current.subtitle = attrs; } else if (equal(tag, "rights")) { this.current.rights = attrs; } else { /* Other possible values, but of incompatible type: - id - updated - published - draft */ LOG.warn("Invalid tag value: " + tag + ". Trying to assign: " + var_export_internal(attrs)); } } else { Array.array_push(this.in_content, new Array<Object>(new ArrayEntry<Object>(tag), new ArrayEntry<Object>(this.depth), new ArrayEntry<Object>(type))); } } else if (equal(tag, "link")) { Array.array_push(this.current.links, attrs); } else if (equal(tag, "category")) { Array.array_push(this.current.categories, attrs); } this.ns_decls = new Array<Object>(); } public void end_element(Object parser, String name) { Object tag = null; int ccount = 0; Object origtype = null; Array<String> newcontent; Array<Object> c = new Array<Object>(); Array<Object> endtag = new Array<Object>(); tag = Array.array_pop(QRegExPosix.split(":", name)); ccount = Array.count(this.in_content); if (!empty(this.in_content)) { // if we are *in* content, then let's proceed to serialize it // then let's finalize the content if (equal(this.in_content.getArrayValue(0).getValue(0), tag) && equal(this.in_content.getArrayValue(0).getValue(1), this.depth)) { origtype = this.in_content.getArrayValue(0).getValue(2); Array.array_shift(this.in_content); newcontent = new Array<String>(); for (Map.Entry javaEntry369 : this.in_content.entrySet()) { c = (Array<Object>) javaEntry369.getValue(); if (equal(Array.count(c), 3)) { Array.array_push(newcontent, c.getValue(2)); } else { if (this.is_xhtml || this.is_text) { Array.array_push(newcontent, this.xml_escape(c)); } else { Array.array_push(newcontent, c); } } } if (Array.in_array(tag, this.ATOM_CONTENT_ELEMENTS)) { // Modified by Numiton Array value = new Array(new ArrayEntry(origtype, Strings.join("", newcontent))); if (equal(tag, "content")) { this.current.content = value; } else if (equal(tag, "summary")) { this.current.summary = value; } else if (equal(tag, "title")) { this.current.title = value; } else if (equal(tag, "subtitle")) { this.current.subtitle = value; } else if (equal(tag, "rights")) { this.current.rights = value; } } else { // Modified by Numiton String value = Strings.join("", newcontent); if (equal(tag, "id")) { this.current.id = value; } else if (equal(tag, "updated")) { this.current.updated = value; } else if (equal(tag, "published")) { this.current.published = value; } else if (equal(tag, "draft")) { this.current.draft = value; } } this.in_content = new Array<Object>(); } else if (equal(this.in_content.getArrayValue(ccount - 1).getValue(0), tag) && equal(this.in_content.getArrayValue(ccount - 1).getValue(1), this.depth)) { this.in_content.getArrayValue(ccount - 1).putValue(2, Strings.substr(strval(this.in_content.getArrayValue(ccount - 1).getValue(2)), 0, -1) + "/>"); } else { // else, just finalize the current element's content endtag = this.ns_to_prefix(name); Array.array_push(this.in_content, new Array<Object>(new ArrayEntry<Object>(tag), new ArrayEntry<Object>(this.depth), new ArrayEntry<Object>("</" + strval(endtag.getValue(1)) + ">"))); } } Array.array_shift(this.ns_contexts); this.depth--; if (equal(name, this.NS + ":entry")) { Array.array_push(this.feed.entries, this.current); this.current = null; } this._p("end_element(\'" + name + "\')"); } public void start_ns(Object parser, Object prefix, Object uri) { this._p("starting: " + prefix + ":" + uri); Array.array_push(this.ns_decls, new Array<Object>(new ArrayEntry<Object>(prefix), new ArrayEntry<Object>(uri))); } public void end_ns(Object parser, Object prefix) { this._p("ending: #" + prefix + "#"); } public void cdata(Object parser, String data) { this._p("data: #" + Strings.str_replace(new Array<Object>(new ArrayEntry<Object>("\n")), new Array<Object>(new ArrayEntry<Object>("\\n")), Strings.trim(data)) + "#"); if (!empty(this.in_content)) { Array.array_push(this.in_content, data); } } public void _default(Object parser, Object data) { // when does this gets called? } public Array<Object> ns_to_prefix(String name) { return ns_to_prefix(name, false); } public Array<Object> ns_to_prefix(String qname, boolean attr) { Array<String> components = new Array<String>(); Object name = null; String ns = null; Array<Object> mapping = new Array<Object>(); Array<Object> context = null; // split 'http://www.w3.org/1999/xhtml:div' into ('http','//www.w3.org/1999/xhtml','div') components = QRegExPosix.split(":", qname); // grab the last one (e.g 'div') name = Array.array_pop(components); if (!empty(components)) { // re-join back the namespace component ns = Strings.join(":", components); for (Map.Entry javaEntry370 : this.ns_contexts.entrySet()) { context = (Array<Object>) javaEntry370.getValue(); for (Map.Entry javaEntry371 : context.entrySet()) { mapping = (Array<Object>) javaEntry371.getValue(); if (equal(mapping.getValue(1), ns) && (Strings.strlen(strval(mapping.getValue(0))) > 0)) { return new Array<Object>(new ArrayEntry<Object>(mapping), new ArrayEntry<Object>(strval(mapping.getValue(0)) + ":" + strval(name))); } } } } if (attr) { return new Array<Object>(new ArrayEntry<Object>(null), new ArrayEntry<Object>(name)); } else { for (Map.Entry javaEntry372 : this.ns_contexts.entrySet()) { context = (Array<Object>) javaEntry372.getValue(); for (Map.Entry javaEntry373 : context.entrySet()) { mapping = (Array<Object>) javaEntry373.getValue(); if (equal(Strings.strlen(strval(mapping.getValue(0))), 0)) { return new Array<Object>(new ArrayEntry<Object>(mapping), new ArrayEntry<Object>(name)); } } } } return new Array<Object>(); } public boolean is_declared_content_ns(Object new_mapping) { Object mapping = null; Array<Object> context = null; for (Map.Entry javaEntry374 : this.content_ns_contexts.entrySet()) { context = (Array<Object>) javaEntry374.getValue(); for (Map.Entry javaEntry375 : context.entrySet()) { mapping = javaEntry375.getValue(); if (equal(new_mapping, mapping)) { return true; } } } return false; } public Array<String> xml_escape(Array string) { return Strings.str_replace( new Array<String>(new ArrayEntry<String>("&"), new ArrayEntry<String>("\""), new ArrayEntry<String>("\'"), new ArrayEntry<String>("<"), new ArrayEntry<String>(">")), new Array<String>(new ArrayEntry<String>("&"), new ArrayEntry<String>("""), new ArrayEntry<String>("'"), new ArrayEntry<String>("<"), new ArrayEntry<String>(">")), string); } public String xml_escape(String string) { return Strings.str_replace( new Array<String>(new ArrayEntry<String>("&"), new ArrayEntry<String>("\""), new ArrayEntry<String>("\'"), new ArrayEntry<String>("<"), new ArrayEntry<String>(">")), new Array<String>(new ArrayEntry<String>("&"), new ArrayEntry<String>("""), new ArrayEntry<String>("'"), new ArrayEntry<String>("<"), new ArrayEntry<String>(">")), string); } public void setContext(GlobalVariablesContainer javaGlobalVariables, GlobalConstantsInterface javaGlobalConstants) { gConsts = (GlobalConsts) javaGlobalConstants; gVars = (GlobalVars) javaGlobalVariables; gVars.gConsts = gConsts; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public GlobalVariablesContainer getGlobalVars() { return gVars; } }