/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source 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. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */ package com.caucho.quercus.lib.xml; import com.caucho.quercus.QuercusModuleException; import com.caucho.quercus.annotation.NotNull; import com.caucho.quercus.annotation.Optional; import com.caucho.quercus.annotation.Reference; import com.caucho.quercus.env.BooleanValue; import com.caucho.quercus.env.Env; import com.caucho.quercus.env.LongValue; import com.caucho.quercus.env.StringValue; import com.caucho.quercus.env.UnicodeValueImpl; import com.caucho.quercus.env.Value; import com.caucho.quercus.module.AbstractQuercusModule; import com.caucho.util.L10N; /** * PHP XML */ public class XmlModule extends AbstractQuercusModule { private static final L10N L = new L10N(XmlModule.class); public static final int XML_OPTION_CASE_FOLDING = 0x0; public static final int XML_OPTION_SKIP_TAGSTART = 0x1; public static final int XML_OPTION_SKIP_WHITE = 0x2; public static final int XML_OPTION_TARGET_ENCODING = 0x3; public static final int XML_ERROR_NONE = 0; public static final int XML_ERROR_NO_MEMORY = 1; public static final int XML_ERROR_SYNTAX = 2; public static final int XML_ERROR_NO_ELEMENTS = 3; public static final int XML_ERROR_INVALID_TOKEN = 4; public static final int XML_ERROR_UNCLOSED_TOKEN = 5; public static final int XML_ERROR_PARTIAL_CHAR = 6; public static final int XML_ERROR_TAG_MISMATCH = 7; public static final int XML_ERROR_DUPLICATE_ATTRIBUTE = 8; public static final int XML_ERROR_JUNK_AFTER_DOC_ELEMENT = 9; public static final int XML_ERROR_PARAM_ENTITY_REF = 10; public static final int XML_ERROR_UNDEFINED_ENTITY = 11; public static final int XML_ERROR_RECURSIVE_ENTITY_REF = 12; public static final int XML_ERROR_ASYNC_ENTITY = 13; public static final int XML_ERROR_BAD_CHAR_REF = 14; public static final int XML_ERROR_BINARY_ENTITY_REF = 15; public static final int XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF = 16; public static final int XML_ERROR_MISPLACED_XML_PI = 17; public static final int XML_ERROR_UNKNOWN_ENCODING = 18; public static final int XML_ERROR_INCORRECT_ENCODING = 19; public static final int XML_ERROR_UNCLOSED_CDATA_SECTION = 20; public static final int XML_ERROR_EXTERNAL_ENTITY_HANDLING = 21; public static final int XML_ERROR_NOT_STANDALONE = 22; public static final int XML_ERROR_UNEXPECTED_STATE = 23; public static final int XML_ERROR_ENTITY_DECLARED_IN_PE = 24; public static final int XML_ERROR_FEATURE_REQUIRES_XML_DTD = 25; public static final int XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING = 26; public static final int XML_ERROR_UNBOUND_PREFIX = 27; public static final int XML_ERROR_UNDECLARING_PREFIX = 28; public static final int XML_ERROR_INCOMPLETE_PE = 29; public static final int XML_ERROR_XML_DECL = 30; public static final int XML_ERROR_TEXT_DECL = 31; public static final int XML_ERROR_PUBLICID = 32; public static final int XML_ERROR_SUSPENDED = 33; public static final int XML_ERROR_NOT_SUSPENDED = 34; public static final int XML_ERROR_ABORTED = 35; public static final int XML_ERROR_FINISHED = 36; public static final int XML_ERROR_SUSPEND_PE = 37; public String []getLoadedExtensions() { return new String[] { "xml" }; } /** * Converts from iso-8859-1 to utf8 */ public static Value utf8_encode(Env env, StringValue str) { StringValue sb = str.createStringBuilder(); int len = str.length(); for (int i = 0; i < len; i++) { int ch = str.charAt(i); if (ch < 0x80) sb.append((char) ch); else if (ch < 0x800) { sb.append((char) (0xc0 + (ch >> 6))); sb.append((char) (0x80 + (ch & 0x3f))); } else { sb.append((char) (0xe0 + (ch >> 12))); sb.append((char) (0x80 + ((ch >> 6) & 0x3f))); sb.append((char) (0x80 + ((ch) & 0x3f))); } } return sb; } /** * Converts from utf8 to iso-8859-1 */ public static Value utf8_decode(Env env, StringValue str) { StringValue sb = env.createUnicodeBuilder(); int len = str.length(); for (int i = 0; i < len; i++) { int ch = str.charAt(i) & 0xff; if (ch < 0x80) sb.append((char) ch); else if ((ch & 0xe0) == 0xc0) { int d1 = (ch & 0x1f) << 6; int d2 = str.charAt(++i) & 0x3f; sb.append((char) (d1 + d2)); } else { int d1 = (ch & 0xf) << 12; int d2 = (str.charAt(++i) & 0x3f) << 6; int d3 = (str.charAt(++i) & 0x3f); sb.append((char) (d1 + d2 + d3)); } } return sb; } /** * Returns the parser's byte */ public Value xml_get_current_byte_index(Xml parser) { if (parser == null) return BooleanValue.FALSE; return LongValue.create(parser.getByteIndex()); } /** * Returns the parser's line */ public Value xml_get_current_line_number(Xml parser) { if (parser == null) return BooleanValue.FALSE; return LongValue.create(parser.getLine()); } /** * Returns the parser's column */ public Value xml_get_current_column_number(Xml parser) { if (parser == null) return BooleanValue.FALSE; return LongValue.create(parser.getColumn()); } /** * Returns the error code for xml parser */ public Value xml_get_error_code(Xml parser) { if (parser == null) return BooleanValue.FALSE; return LongValue.create(parser.getErrorCode()); } /** * Returns the error string for xml parser */ public Value xml_error_string(int code) { switch (code) { case XML_ERROR_NONE: return StringValue.create("No error"); case XML_ERROR_SYNTAX: return StringValue.create("syntax error"); default: return BooleanValue.FALSE; } } /** * @see boolean Xml.xml_parse * * @param parser * @param data * @param isFinal * @return false if parser == null * @throws Exception */ public int xml_parse(Env env, @NotNull Xml parser, StringValue data, @Optional("true") boolean isFinal) { if (parser == null) return 0; else if (data.length() == 0) return 0; try { return parser.xml_parse(env, data, isFinal); } catch (Exception e) { throw QuercusModuleException.create(e); } } /** * returns a new Xml Parser */ public Xml xml_parser_create(Env env, @Optional("'UTF-8'") String outputEncoding) { if (outputEncoding == null) outputEncoding = "UTF-8"; return new Xml(env, outputEncoding, null); } /** * XXX: Should we return warning if separator is * anything but ":"??? * * @param env * @param outputEncoding * @param separator * @return namespace aware Xml Parser */ public Xml xml_parser_create_ns(Env env, @Optional("'UTF-8'") String outputEncoding, @Optional("':'") String separator) { if (outputEncoding == null) outputEncoding = "UTF-8"; return new Xml(env, outputEncoding, separator); } /** * * @see boolean Xml.xml_parser_set_option * * @param parser * @param option * @param value * @return false if parser == null */ public boolean xml_parser_set_option(@NotNull Xml parser, @NotNull int option, @NotNull Value value) { if (parser == null) return false; return parser.xml_parser_set_option(option, value); } /** * @see boolean Xml.xml_parser_get_option * * @param parser * @param option * @return false if parser == null */ public Value xml_parser_get_option(Env env, @NotNull Xml parser, @NotNull int option) { if (parser == null) return BooleanValue.FALSE; return parser.xml_parser_get_option(env, option); } /** * @see boolean Xml.xml_set_element_handler * * @param parser * @param startElementHandler * @param endElementHandler * @return false if parser == null */ public boolean xml_set_element_handler(Env env, @NotNull Xml parser, @NotNull Value startElementHandler, @NotNull Value endElementHandler) { if (parser == null) return false; return parser.xml_set_element_handler(env, startElementHandler, endElementHandler); } /** * @see boolean Xml.xml_set_character_data_handler * * @param parser * @param handler * @return false if parser == null */ public boolean xml_set_character_data_handler(Env env, @NotNull Xml parser, @NotNull Value handler) { if (parser == null) return false; return parser.xml_set_character_data_handler(env, handler); } /** * @see boolean Xml.xml_set_start_namespace_decl_handler * * @param parser * @param startNamespaceDeclHandler * @return false if parser == null */ public boolean xml_set_start_namespace_decl_handler( Env env, @NotNull Xml parser, @NotNull Value startNamespaceDeclHandler) { if (parser == null) return false; return parser.xml_set_start_namespace_decl_handler( env, startNamespaceDeclHandler); } /** * * @param parser * @param obj * @return false if parser == null */ public boolean xml_set_object(@NotNull Xml parser, @NotNull Value obj) { if (parser == null) return false; return parser.xml_set_object(obj); } /** * * @param parser * @param handler * @return false if parser == null */ public boolean xml_set_processing_instruction_handler(Env env, @NotNull Xml parser, @NotNull Value handler) { if (parser == null) return false; return parser.xml_set_processing_instruction_handler(env, handler); } /** * * @param parser * @param handler * @return false if parser == null */ public boolean xml_set_default_handler(Env env, @NotNull Xml parser, @NotNull Value handler) { if (parser == null) return false; return parser.xml_set_default_handler(env, handler); } /** * @see boolean Xml.xml_set_notation_decl_handler * * @param parser * @param handler * @return false is parser == null */ public boolean xml_set_notation_decl_handler(Env env, @NotNull Xml parser, @NotNull Value handler) { if (parser == null) return false; return parser.xml_set_notation_decl_handler(env, handler); } /** * * @param parser * @param handler * @return false if parser == null */ public boolean xml_set_end_namespace_decl_handler(Env env, @NotNull Xml parser, @NotNull Value handler) { if (parser == null) return false; return parser.xml_set_end_namespace_decl_handler(env, handler); } /** * * @param parser * @param data * @param valueArray * @param indexArray * @return false if parser == null * @throws Exception */ public int xml_parse_into_struct(Env env, @NotNull Xml parser, StringValue data, @Reference Value valueArray, @Optional @Reference Value indexArray) { try { if (parser == null) return 0; return parser.xml_parse_into_struct(env, data, valueArray, indexArray); } catch (Exception e) { throw QuercusModuleException.create(e); } } /** * stub function. parser_free taken care of by garbage collection * * @param parser * @return false if parser == null, otherwise true */ public boolean xml_parser_free(@NotNull Xml parser) { if (parser == null) return false; else return true; } /** * @see boolean Xml.xml_set_unparsed_entity_decl_handler * * @param parser * @param handler * @return false if parser == null, otherwise true */ public boolean xml_set_unparsed_entity_decl_handler(Env env, @NotNull Xml parser, @NotNull Value handler) { if (parser == null) return false; return parser.xml_set_unparsed_entity_decl_handler(env, handler); } // @todo xml_error_string // @todo xml_get_current_byte_index // @todo xml_get_current_column_number // @todo xml_get_current_line_number // @todo xml_get_error_code // @todo xml_set_external_entity_ref_handler }