|
|
| version 1.15, 2003/12/02 13:24:32 | version 1.31, 2015/10/26 01:21:59 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: plugins to xml library, controlling i/o; implementation | Parser: plugins to xml library, controlling i/o; implementation |
| Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) | Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) |
| */ | */ |
| Line 9 | Line 9 |
| #ifdef XML | #ifdef XML |
| static const char * const IDENT="$Date$"; | volatile const char * IDENT_PA_XML_IO_C="$Id$" IDENT_PA_XML_IO_H; |
| #include "libxslt/extensions.h" | #include "libxslt/extensions.h" |
| #include "pa_threads.h" | |
| #include "pa_globals.h" | #include "pa_globals.h" |
| #include "pa_request.h" | #include "pa_request.h" |
| THREAD_LOCAL HashStringBool* xml_dependencies = NULL; | |
| static void add_dependency(const String::Body url) { | |
| if(xml_dependencies) // do we need to monitor now? | |
| xml_dependencies->put(url, true); | |
| } | |
| void pa_xmlStartMonitoringDependencies() { | |
| xml_dependencies=new HashStringBool; | |
| } | |
| void pa_xmlStopMonitoringDependencies() { | |
| xml_dependencies=NULL; | |
| } | |
| HashStringBool* pa_xmlGetDependencies() { | |
| HashStringBool* result=xml_dependencies; | |
| xml_dependencies=NULL; | |
| return result; | |
| } | |
| #ifndef DOXYGEN | #ifndef DOXYGEN |
| struct MemoryStream { | struct MemoryStream { |
| const char* m_buf; | const char* m_buf; |
| Line 37 struct MemoryStream { | Line 59 struct MemoryStream { |
| #endif | #endif |
| static void * | static void * |
| xmlFileOpen_ReadIntoStream (const char* filename, bool adjust_path_to_root_from_document_root=false) { | xmlFileOpen_ReadIntoStream (const char* do_not_store_filename, bool adjust_path_to_root_from_document_root=false) { |
| #ifdef PA_SAFE_MODE | |
| //copied from libxml/catalog.c | |
| # define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog" | |
| // disable attempts to consult default catalog [usually, that file belongs to other user/group] | |
| if(strcmp(do_not_store_filename, XML_XML_DEFAULT_CATALOG)==0) | |
| return 0; | |
| #endif | |
| Request& r=pa_thread_request(); | Request& r=pa_thread_request(); |
| char adjust_buf[MAX_STRING]; | char adjust_buf[MAX_STRING]; |
| if(adjust_path_to_root_from_document_root) { | if(adjust_path_to_root_from_document_root) { |
| Line 47 xmlFileOpen_ReadIntoStream (const char* | Line 77 xmlFileOpen_ReadIntoStream (const char* |
| adjust_buf[0]=0; | adjust_buf[0]=0; |
| strcat(adjust_buf, document_root); | strcat(adjust_buf, document_root); |
| strcat(adjust_buf, &filename[16]); | strcat(adjust_buf, &do_not_store_filename[16]); |
| filename=adjust_buf; | do_not_store_filename=adjust_buf; |
| } else | } else |
| if(strstr(filename, "file://")) | if(!strstr(do_not_store_filename, "http://")) { |
| filename+=7/*strlen("file://")*/; | if(strstr(do_not_store_filename, "file://")) { |
| else if(strstr(filename, "://")) | do_not_store_filename+=7/*strlen("file://")*/; |
| return 0; // plug out [do not handle other prefixes] | #ifdef WIN32 |
| if( | |
| do_not_store_filename[0]=='/' | |
| && do_not_store_filename[1] | |
| && do_not_store_filename[2]==':' | |
| && do_not_store_filename[3]=='/' | |
| ) { | |
| // skip leading slash for absolute path file:///C:/path/to/file | |
| do_not_store_filename++; | |
| } | |
| #endif | |
| } else if(*do_not_store_filename && do_not_store_filename[1]!=':' && strstr(do_not_store_filename, "://")) { | |
| pa_xmlStopMonitoringDependencies(); | |
| return 0; // plug out [do not handle other prefixes] | |
| } | |
| } | |
| const char* can_store_filename=pa_strdup(do_not_store_filename); | |
| add_dependency(can_store_filename); | |
| const char *buf; | const char *buf; |
| try { | try { |
| buf=file_read_text(r.charsets, *new String(filename)); | buf=file_load_text(r, *new String(can_store_filename), |
| true/*fail_on_read_problem*/, | |
| 0/*params*/, | |
| false/*don't transcode result because it must be fit with @encoding value!*/); | |
| } catch(const Exception& e) { | } catch(const Exception& e) { |
| if(strcmp(e.type(), "file.missing")==0) | |
| return 0; // let the library try that and report an error properly | |
| buf=e.comment(); | buf=e.comment(); |
| } catch(...) { | } catch(...) { |
| buf="xmlFileOpenLocalhost: unknown error"; | buf="xmlFileOpen_ReadIntoStream: unknown error"; |
| } | } |
| MemoryStream* stream=new(UseGC) MemoryStream; | MemoryStream* stream=new MemoryStream; |
| stream->m_buf=buf; | stream->m_buf=buf; |
| stream->m_size=strlen(buf); | stream->m_size=strlen(buf); |
| return (void *)stream; | return (void *)stream; |
| } | } |
| #ifdef PA_SAFE_MODE | |
| static int | static int |
| xmlFileMatchSafeMode(const char* file_spec_cstr) { | xmlFileMatchMonitor(const char* /*file_spec_cstr*/) { |
| return 1; // always intercept, causing xmlFileOpenSafeMode to be called | return 1; // always intercept, causing xmlFileOpenMonitor to be called |
| } | } |
| static void * | static void * |
| xmlFileOpenSafeMode(const char* filename) { | xmlFileOpenMonitor(const char* filename) { |
| return xmlFileOpen_ReadIntoStream(filename); // handles localfile case, else returns 0 | return xmlFileOpen_ReadIntoStream(filename); // handles localfile case, else returns 0 |
| } | } |
| #endif | |
| /** | /** |
| Line 136 xmlFileOpenMethod (const char* afilename | Line 188 xmlFileOpenMethod (const char* afilename |
| Request::Execute_nonvirtual_method_result body= | Request::Execute_nonvirtual_method_result body= |
| r.execute_nonvirtual_method(r.main_class, *method, vparam, true); | r.execute_nonvirtual_method(r.main_class, *method, vparam, true); |
| if(body.string) { | if(body.string) { |
| buf=body.string->cstr(String::L_UNSPECIFIED); | buf=body.string->untaint_cstr(r.flang); |
| } else | } else |
| throw Exception(0, | throw Exception(0, |
| new String(afilename), | new String(afilename), |
| Line 148 xmlFileOpenMethod (const char* afilename | Line 200 xmlFileOpenMethod (const char* afilename |
| } catch(...) { | } catch(...) { |
| buf="xmlFileOpenLocalhost: unknown error"; | buf="xmlFileOpenLocalhost: unknown error"; |
| } | } |
| MemoryStream* stream=new(UseGC) MemoryStream; | MemoryStream* stream=new MemoryStream; |
| stream->m_buf=buf; | stream->m_buf=buf; |
| stream->m_size=strlen(buf); | stream->m_size=strlen(buf); |
| return (void *)stream; | return (void *)stream; |
| Line 181 pa_xmlFileCloseMethod (void * /*context* | Line 233 pa_xmlFileCloseMethod (void * /*context* |
| void pa_xml_io_init() { | void pa_xml_io_init() { |
| #ifdef PA_SAFE_MODE | // file open monitorer [for xslt cacher] |
| // safe mode checker, always fail match, but checks non-"://" there | // safe mode checker, always fail match, but checks non-"://" there |
| xmlRegisterInputCallbacks( | xmlRegisterInputCallbacks( |
| xmlFileMatchSafeMode, xmlFileOpenSafeMode, | xmlFileMatchMonitor, xmlFileOpenMonitor, |
| pa_xmlFileReadMethod, pa_xmlFileCloseMethod); | pa_xmlFileReadMethod, pa_xmlFileCloseMethod); |
| #endif | |
| // http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc | // http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc |
| xmlRegisterInputCallbacks( | xmlRegisterInputCallbacks( |
| xmlFileMatchLocalhost, xmlFileOpenLocalhost, | xmlFileMatchLocalhost, xmlFileOpenLocalhost, |