--- parser3/src/classes/xdoc.C 2016/04/06 16:08:19 1.185 +++ parser3/src/classes/xdoc.C 2021/10/19 16:16:35 1.201 @@ -1,7 +1,7 @@ /** @file Parser: @b xdoc parser class. - Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2020 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ @@ -28,7 +28,7 @@ #include "xnode.h" #include "pa_charsets.h" -volatile const char * IDENT_XDOC_C="$Id: xdoc.C,v 1.185 2016/04/06 16:08:19 moko Exp $"; +volatile const char * IDENT_XDOC_C="$Id: xdoc.C,v 1.201 2021/10/19 16:16:35 moko Exp $"; // defines @@ -47,6 +47,7 @@ public: // global variable +DECLARE_CLASS_VAR(xnode, new MXnode); // must be here as Xdoc is inherited from Xnode and should be inited before DECLARE_CLASS_VAR(xdoc, new MXdoc); // helper classes @@ -117,39 +118,6 @@ private: xsltTransformContext *_Ptr; }; -class xsltStylesheet_auto_ptr { -public: - explicit xsltStylesheet_auto_ptr(xsltStylesheet *_APtr = 0) - : _Owns(_APtr != 0), _Ptr(_APtr) {} - xsltStylesheet_auto_ptr(const xsltStylesheet_auto_ptr& _Y) - : _Owns(_Y._Owns), _Ptr(_Y.release()) {} - xsltStylesheet_auto_ptr& operator=(const xsltStylesheet_auto_ptr& _Y) - {if (this != &_Y) - {if (_Ptr != _Y.get()) - {if (_Owns && _Ptr) - xsltFreeStylesheet(_Ptr); - _Owns = _Y._Owns; } - else if (_Y._Owns) - _Owns = true; - _Ptr = _Y.release(); } - return (*this); } - ~xsltStylesheet_auto_ptr() - {if (_Owns && _Ptr) - xsltFreeStylesheet(_Ptr); } - xsltStylesheet& operator*() const - {return (*get()); } - xsltStylesheet *operator->() const - {return (get()); } - xsltStylesheet *get() const - {return (_Ptr); } - xsltStylesheet *release() const - {((xsltStylesheet_auto_ptr *)this)->_Owns = false; - return (_Ptr); } -private: - bool _Owns; - xsltStylesheet *_Ptr; -}; - // methods static void writeNode(Request& r, VXdoc& xdoc, xmlNode* node) { @@ -159,7 +127,7 @@ static void writeNode(Request& r, VXdoc& "error creating node"); // OOM, bad name, things like that // write out result - r.write_no_lang(xdoc.wrap(*node)); + r.write(xdoc.wrap(*node)); } struct IdsIteratorInfo { @@ -167,9 +135,8 @@ struct IdsIteratorInfo { xmlNode *element; }; -/* Hash Scanner function for pa_getElementById */ -extern "C" void // switching to calling convetion of libxml -idsHashScanner (void *payload, void *data, xmlChar *name) { +/* switching to calling convetion of libxml */ +extern "C" void idsHashScanner (void *payload, void *data, const xmlChar *name) { IdsIteratorInfo *priv = (IdsIteratorInfo *)data; if (priv->element == NULL && xmlStrEqual (name, priv->elementId)) @@ -180,11 +147,10 @@ idsHashScanner (void *payload, void *dat } } -static xmlNode* -pa_getElementById(xmlDoc& xmldoc, xmlChar* elementId) { +static xmlNode* pa_getElementById(xmlDoc& xmldoc, xmlChar* elementId) { xmlHashTable *ids = (xmlHashTable *)xmldoc.ids; IdsIteratorInfo iter={elementId, NULL}; - xmlHashScan(ids, idsHashScanner, &iter); + xmlHashScan(ids, (xmlHashScanner)idsHashScanner, &iter); return iter.element; } @@ -365,10 +331,7 @@ static void _importNode(Request& r, Meth writeNode(r, vdoc, node); } -/* -GdomeElement *gdome_doc_createElementNS (GdomeDocument *self, GdomeDOMString *namespaceURI, GdomeDOMString *qualifiedName, GdomeException *exc); -GdomeAttr *gdome_doc_createAttributeNS (GdomeDocument *self, GdomeDOMString *namespaceURI, GdomeDOMString *qualifiedName, GdomeException *exc); -*/ +#define XML_PARSE_OPTIONS (XML_PARSE_DTDLOAD | XML_PARSE_NOENT | XML_PARSE_HUGE) static void _create(Request& r, MethodParams& params) { Charset& source_charset=r.charsets.source(); @@ -378,13 +341,12 @@ static void _create(Request& r, MethodPa xmlDoc* xmldoc; bool set_encoding=false; if(param.get_junction()) { // {...} - Temp_lang temp_lang(r, String::L_XML); + const String& xml=r.process_to_string(param); + String::Body sbody=xml.cstr_to_string_body_untaint(String::L_XML, r.connection(false), &r.charsets); - String::Body sbody=xml.cstr_to_string_body_untaint(r.flang, r.connection(false), &r.charsets); - xmldoc=xmlParseMemory(sbody.cstr(), sbody.length()); + xmldoc=xmlReadMemory(sbody.cstr(), sbody.length(), NULL, NULL, XML_PARSE_OPTIONS); - //printf("document=0x%p\n", document); if(!xmldoc || xmlHaveGenericErrors()) throw XmlException(0, r); @@ -395,19 +357,6 @@ static void _create(Request& r, MethodPa if(xmlValidateNCName(localName, 0) != 0) throw XmlException(0, XML_INVALID_LOCAL_NAME, localName); -#if 0 - GdomeDocumentType *documentType=gdome_di_createDocumentType ( - docimpl, - r.transcode(qualifiedName), - 0/*publicId*/, - 0/*systemId*/, - &exc); - if(!documentType || exc || xmlHaveGenericErrors()) - throw Exception( - method_name, - exc); - /// +xalan createXMLDecl ? -#endif xmldoc=xmlNewDoc(0); if(!xmldoc || xmlHaveGenericErrors()) throw XmlException(0, r); @@ -419,8 +368,8 @@ static void _create(Request& r, MethodPa set_encoding=true; // must be last action in if, see after if} } else { - VFile* vfile=param.as_vfile(String::L_AS_IS); - xmldoc=xmlParseMemory(vfile->value_ptr(), vfile->value_size()); + VFile* vfile=param.as_vfile(); + xmldoc=xmlReadMemory(vfile->value_ptr(), vfile->value_size(), NULL, NULL, XML_PARSE_OPTIONS); if(!xmldoc || xmlHaveGenericErrors()) throw XmlException(0, r); } @@ -433,7 +382,7 @@ static void _create(Request& r, MethodPa const char* URI_cstr; if(params.count()>1) { // absolute(param) const String& URI=params.as_string(0, "URI must be string"); - URI_cstr=r.absolute(URI).cstr(); + URI_cstr=r.full_disk_path(URI).cstr(); } else // default = disk path to requested document URI_cstr=r.request_info.path_translated; if(URI_cstr) @@ -452,12 +401,12 @@ static void _load(Request& r, MethodPara const String* uri=¶ms.as_string(0, "URI must be string"); const char* uri_cstr; if(uri->pos("://")==STRING_NOT_FOUND) // disk path - uri_cstr=r.absolute(*uri).taint_cstr(String::L_FILE_SPEC); + uri_cstr=r.full_disk_path(*uri).taint_cstr(String::L_FILE_SPEC); else // xxx:// uri_cstr=uri->taint_cstr(String::L_AS_IS); // leave as-is for xmlParseFile to handle /// @todo!! add SAFE MODE!! - xmlDoc* xmldoc=xmlParseFile(uri_cstr); + xmlDoc* xmldoc=xmlReadFile(uri_cstr, NULL, XML_PARSE_OPTIONS); if(!xmldoc || xmlHaveGenericErrors()) throw XmlException(uri, r); @@ -476,7 +425,7 @@ String::C xdoc2buf(Request& r, VXdoc& vd render=&r.charsets.source(); header=&r.charsets.client(); } else { - header=render=&charsets.get(oo.encoding->change_case(r.charsets.source(), String::CC_UPPER)); + header=render=&pa_charsets.get(*oo.encoding); } const char* render_encoding=render->NAME_CSTR(); const char* header_encoding=header->NAME_CSTR(); @@ -490,11 +439,9 @@ String::C xdoc2buf(Request& r, VXdoc& vd xmlOutputBuffer_auto_ptr outputBuffer(xmlAllocOutputBuffer(renderer)); - xsltStylesheet_auto_ptr stylesheet(xsltNewStylesheet()); - if(!stylesheet.get()) - throw Exception(0, - 0, - "xsltNewStylesheet failed"); + xsltStylesheet *stylesheet = xsltNewStylesheet(); + if(!stylesheet) + throw Exception(0, 0, "xsltNewStylesheet failed"); #define OOSTRING2STYLE(name) \ stylesheet->name=oo.name?BAD_CAST xmlMemStrdup((const char*)r.transcode(*oo.name)):0 @@ -515,7 +462,7 @@ String::C xdoc2buf(Request& r, VXdoc& vd xmldoc.encoding=BAD_CAST xmlMemStrdup(render_encoding); if(header_encoding) stylesheet->encoding=BAD_CAST xmlMemStrdup(header_encoding); - if(xsltSaveResultTo(outputBuffer.get(), &xmldoc, stylesheet.get())<0 + if(xsltSaveResultTo(outputBuffer.get(), &xmldoc, stylesheet)<0 || xmlHaveGenericErrors()) throw XmlException(0, r); @@ -570,13 +517,13 @@ static void _file(Request& r, MethodPara vfile.set_binary(false/*not tainted*/, buf.str?buf.str:""/*to distinguish from stat-ed file*/, buf.length, oo.filename, &vhcontent_type); // write out result - r.write_no_lang(vfile); + r.write(vfile); } static void _save(Request& r, MethodParams& params) { VXdoc& vdoc=GET_SELF(r, VXdoc); - const String& file_spec=r.absolute(params.as_string(0, FILE_NAME_MUST_BE_STRING)); + const String& file_spec=r.full_disk_path(params.as_string(0, FILE_NAME_MUST_BE_STRING)); XDocOutputOptions oo(vdoc.output_options); oo.append(r, get_options(params, 1)); @@ -593,7 +540,7 @@ static void _string(Request& r, MethodPa true/*use source charset to render, client charset to put to header*/); // write out result - r.write_no_lang(String(buf, String::L_AS_IS)); + r.write(String(buf, String::L_AS_IS)); } #ifndef DOXYGEN @@ -612,8 +559,7 @@ static void add_xslt_param( *info->current_transform_param++=(s=info->r->transcode(meaning->as_string())); *info->strings+=s; } -static VXdoc& _transform(Request& r, const String* stylesheet_source, - VXdoc& vdoc, xsltStylesheetPtr stylesheet, const xmlChar** transform_params) +static VXdoc& _transform(Request& r, const String* stylesheet_source, VXdoc& vdoc, xsltStylesheetPtr stylesheet, const xmlChar** transform_params) { xmlDoc& xmldoc=vdoc.get_xmldoc(); @@ -674,7 +620,7 @@ static void _transform(Request& r, Metho const xmlChar** transform_params=0; if(params.count()>1) if(HashStringValue* hash=params.as_hash(1, "transform options")) { - transform_params=new const xmlChar*[hash->count()*2+1]; + transform_params=new(PointerGC) const xmlChar*[hash->count()*2+1]; Add_xslt_param_info info={ &r, &transform_strings, @@ -686,37 +632,30 @@ static void _transform(Request& r, Metho VXdoc* result; if(Value *vxdoc=params[0].as(VXDOC_TYPE)) { // stylesheet (xdoc) - xmlDoc& stylesheetdoc=static_cast(vxdoc)->get_xmldoc(); + VXdoc& vstylesheet=static_cast(*vxdoc); + xmlDoc& stylesheetdoc=vstylesheet.get_xmldoc(); + // compile xdoc stylesheet - xsltStylesheet_auto_ptr stylesheet_ptr(xsltParseStylesheetDoc(&stylesheetdoc)); + xsltStylesheet *stylesheet=xsltParseStylesheetDoc(&stylesheetdoc); if(xmlHaveGenericErrors()) throw XmlException(0, r); - if(!stylesheet_ptr.get()) - throw Exception("xml", - 0, - "stylesheet failed to compile"); - // strange thing - xsltParseStylesheetDoc records document and destroys it in stylesheet destructor - // we don't need that - stylesheet_ptr->doc=0; + if(!stylesheet) + throw Exception("xml", 0, "stylesheet failed to compile"); // transform! - result=&_transform(r, 0, - vdoc, stylesheet_ptr.get(), - transform_params); + result=&_transform(r, 0, vdoc, stylesheet, transform_params); } else { // stylesheet (file name) // extablish stylesheet connection - const String& stylesheet_filespec= - r.absolute(params.as_string(0, "stylesheet must be file name (string) or DOM document (xdoc)")); - Stylesheet_connection_ptr connection=stylesheet_manager->get_connection(stylesheet_filespec); + const String& stylesheet_filespec=r.full_disk_path(params.as_string(0, "stylesheet must be file name (string) or DOM document (xdoc)")); + Stylesheet_connection_ptr connection(stylesheet_manager->get_connection(stylesheet_filespec)); // load and compile file to stylesheet [or get cached if any] // transform! - result=&_transform(r, &stylesheet_filespec, vdoc, connection->stylesheet(), - transform_params); + result=&_transform(r, &stylesheet_filespec, vdoc, connection->stylesheet(), transform_params); } // write out result - r.write_no_lang(*result); + r.write(*result); } // constructor @@ -794,6 +733,7 @@ MXdoc::MXdoc(): MXnode(XDOC_CLASS_NAME) // global variable +DECLARE_CLASS_VAR(xnode, 0); // fictive DECLARE_CLASS_VAR(xdoc, 0); // fictive #endif