--- parser3/src/main/pa_xml_io.C 2019/11/05 19:35:00 1.37 +++ parser3/src/main/pa_xml_io.C 2025/05/26 00:52:15 1.46 @@ -1,15 +1,15 @@ /** @file Parser: plugins to xml library, controlling i/o; implementation - Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com) - Author: Alexandr Petrosian (http://paf.design.ru) + Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com) + Authors: Konstantin Morshnev , Alexandr Petrosian */ #include "pa_xml_io.h" #ifdef XML -volatile const char * IDENT_PA_XML_IO_C="$Id: pa_xml_io.C,v 1.37 2019/11/05 19:35:00 moko Exp $" IDENT_PA_XML_IO_H; +volatile const char * IDENT_PA_XML_IO_C="$Id: pa_xml_io.C,v 1.46 2025/05/26 00:52:15 moko Exp $" IDENT_PA_XML_IO_H; #include "libxslt/extensions.h" @@ -17,15 +17,15 @@ volatile const char * IDENT_PA_XML_IO_C= #include "pa_globals.h" #include "pa_request.h" -THREAD_LOCAL HashStringBool* xml_dependencies = NULL; +THREAD_LOCAL HashStringBool* xml_dependencies = NULL; // every TLS should be referenced elsewhere, or GC will collect it -static void add_dependency(const String::Body url) { +static void add_dependency(const char *url) { if(xml_dependencies) // do we need to monitor now? xml_dependencies->put(url, true); } -void pa_xmlStartMonitoringDependencies() { - xml_dependencies=new HashStringBool; +HashStringBool* pa_xmlStartMonitoringDependencies() { + return xml_dependencies=new HashStringBool; // to keep another reference on TLS } void pa_xmlStopMonitoringDependencies() { @@ -60,7 +60,19 @@ struct MemoryStream : public PA_Allocate }; #endif -static void * xmlFileOpen_ReadIntoStream (const char* afilename, bool adjust_path_to_root_from_document_root=false) { +static int xmlFileMatchMonitor(const char* /*file_spec_cstr*/) { + return 1; // always intercept, causing xmlFileOpenMonitor to be called +} + +/** + * xmlFileOpenMonitor: + * afilename: the URI for matching + * + * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc + * + * Returns an I/O context or NULL in case of error + */ +static void *xmlFileOpenMonitor(const char* afilename) { #ifdef PA_SAFE_MODE //copied from libxml/catalog.c # define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog" @@ -70,17 +82,12 @@ static void * xmlFileOpen_ReadIntoStream #endif Request& r=pa_thread_request(); - char adjust_buf[MAX_STRING]; - if(adjust_path_to_root_from_document_root) { + if(!strncmp(afilename, "http://localhost", 16)) { const char* document_root=r.request_info.document_root; if(!document_root) document_root="."; - - adjust_buf[0]=0; - strcat(adjust_buf, document_root); - strcat(adjust_buf, &afilename[16]); - afilename=adjust_buf; - } else + afilename=pa_strcat(document_root, &afilename[16]); + } else { if(!strstr(afilename, "http://")) { if(strstr(afilename, "file://")) { afilename+=7 /*strlen("file://")*/; @@ -95,13 +102,14 @@ static void * xmlFileOpen_ReadIntoStream return 0; // plug out [do not handle other prefixes] } } + afilename=pa_strdup(afilename); + } - const char* can_store_filename=pa_strdup(afilename); - add_dependency(can_store_filename); + add_dependency(afilename); const char *buf; try { - buf=file_load_text(r, *new String(can_store_filename), + buf=file_load_text(r, *new String(afilename), true /*fail_on_read_problem*/, 0 /*params*/, false /*don't transcode result because it must be fit with @encoding value!*/); @@ -116,38 +124,6 @@ static void * xmlFileOpen_ReadIntoStream return (void *)new MemoryStream(buf); } -static int xmlFileMatchMonitor(const char* /*file_spec_cstr*/) { - return 1; // always intercept, causing xmlFileOpenMonitor to be called -} - -static void *xmlFileOpenMonitor(const char* filename) { - return xmlFileOpen_ReadIntoStream(filename); // handles localfile case, else returns 0 -} - -/** - * xmlFileMatchWithLocalhostEqDocumentRoot: - * filename: the URI for matching - * - * check if the URI matches an HTTP one - * - * Returns 1 if matches, 0 otherwise - */ -static int xmlFileMatchLocalhost(const char* filename) { - return !strncmp(filename, "http://localhost", 16); -} - -/** - * xmlFileOpenLocalhost: - * filename: the URI for matching - * - * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc - * - * Returns an I/O context or NULL in case of error - */ -static void *xmlFileOpenLocalhost(const char* filename) { - return xmlFileOpen_ReadIntoStream(filename, true/*adjust path to root from document_root*/); -} - static int xmlFileMatchMethod(const char* filename) { return !strncmp(filename, "parser://", 9 /*strlen("parser://"), and check xmlFileOpenMethod*/); } @@ -161,16 +137,14 @@ static void *xmlFileOpenMethod (const ch char* s=pa_strdup(afilename+9 /*strlen("parser://")*/); const char* method_cstr=lsplit(&s, '/'); const String* method=new String(method_cstr); - String::Body param_body("/"); + String::Body param_body("/"); if(s) param_body.append_know_length(s, strlen(s)); - VString* vparam=new VString(*new String(param_body, String::L_TAINTED)); - Request::Execute_nonvirtual_method_result body=r.execute_nonvirtual_method(r.main_class, *method, vparam, true); - if(body.string) { - buf=body.string->untaint_cstr(String::L_XML); - } else + const String *body=r.execute_method(r.main_class, *method, new VString(*new String(param_body, String::L_TAINTED))); + if(!body) throw Exception(0, new String(afilename), "'%s' method not found in %s class", method_cstr, MAIN_CLASS_NAME); + buf=body->untaint_cstr(String::L_XML); } catch(const Exception& e) { buf=e.comment(); } catch(...) { @@ -203,9 +177,6 @@ void pa_xml_io_init() { // safe mode checker, always fail match, but checks non-"://" there xmlRegisterInputCallbacks(xmlFileMatchMonitor, xmlFileOpenMonitor, pa_xmlFileReadMethod, pa_xmlFileCloseMethod); - // http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc - xmlRegisterInputCallbacks(xmlFileMatchLocalhost, xmlFileOpenLocalhost, pa_xmlFileReadMethod, pa_xmlFileCloseMethod); - // parser://method/param/here -> ^MAIN:method[/params/here] - should be last to be called first xmlRegisterInputCallbacks(xmlFileMatchMethod, xmlFileOpenMethod, pa_xmlFileReadMethod, pa_xmlFileCloseMethod); }