Diff for /parser3/src/main/pa_xml_io.C between versions 1.10 and 1.38

version 1.10, 2003/11/28 10:41:11 version 1.38, 2019/11/05 19:59:23
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-2017 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 : public PA_Allocated {
         const char* m_buf;          const char* m_buf;
         size_t m_size;          size_t m_size;
         size_t m_position;          size_t m_position;
   
           MemoryStream(const char *a_buf) : m_buf(a_buf), m_size(strlen(m_buf)), m_position(0) {}
   
         int read(char* a_buffer, size_t a_size) {          int read(char* a_buffer, size_t a_size) {
                 size_t left=m_size-m_position;                  size_t left=m_size-m_position;
                 if(!left)                  if(!left)
                         return 0;                          return 0;
   
                 size_t to_read=min(a_size, left);                  size_t to_read=min(a_size, left);
                 memcpy(a_buffer, m_buf, to_read);                  memcpy(a_buffer, m_buf+m_position, to_read);
                 m_position+=to_read;                  m_position+=to_read;
                 return to_read;                  return to_read;
         }          }
Line 36  struct MemoryStream { Line 60  struct MemoryStream {
 };  };
 #endif  #endif
   
   static int xmlFileMatchMonitor(const char* /*file_spec_cstr*/) {
 #ifdef PA_SAFE_MODE          return 1; // always intercept, causing xmlFileOpenMonitor to be called
 static int  
 xmlFileMatchSafeMode(const char* file_spec_cstr) {  
         if(strstr(filename, "://")) {  
                 String* file_spec=new String(file_spec_cstr, true);  
                 struct stat finfo;  
                 if(stat(file_spec_cstr, &finfo)!=0)  
                         throw Exception("file.missing",   
                                 file_spec,   
                                 "stat failed: %s (%d)",   
                                         strerror(errno), errno);  
   
                 check_safe_mode(finfo, file_spec, file_spec_cstr);  
         }  
         return 0;  
 }  
 #endif  
   
   
 /**  
  * 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) {  
         if (!strncmp(filename, "http://localhost", 16))  
                 return(1);  
         return(0);  
 }  }
   
   
 /**  /**
  * xmlFileOpenHttpLocalhost :   * xmlFileOpenLocalhost:
  * filename:  the URI for matching   * filename:  the URI for matching
  *   *
  * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc   * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
  *   *
  * input from FILE *, supports compressed input  
  * if filename is " " then the standard input is used  
  *  
  * Returns an I/O context or NULL in case of error   * Returns an I/O context or NULL in case of error
  */   */
 static void *  static void *xmlFileOpenMonitor(const char* afilename) {
 xmlFileOpenLocalhost (const char* filename) {  #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(afilename, XML_XML_DEFAULT_CATALOG)==0)
                   return 0;
   #endif
   
         Request& r=pa_thread_request();          Request& r=pa_thread_request();
         const char* document_root=r.request_info.document_root;          char adjust_buf[MAX_STRING];
         if(!document_root)          if(!strncmp(afilename, "http://localhost", 16)) {
                 document_root=".";                  const char* document_root=r.request_info.document_root;
                   if(!document_root)
         char path[MAX_STRING];                            document_root=".";
         path[0]=0;  
         strcat(path, document_root);                  adjust_buf[0]=0;
         strcat(path, &filename[16]);                  strcat(adjust_buf, document_root);
                   strcat(adjust_buf, &afilename[16]);
         MemoryStream *stream=new(UseGC) MemoryStream;                  afilename=adjust_buf;
         stream->m_buf=file_read_text(r.charsets, *new String(filename), true);          } else
         stream->m_size=strlen(stream->m_buf);                  if(!strstr(afilename, "http://")) {
                           if(strstr(afilename, "file://")) {
         return (void *)stream;                                  afilename+=7 /*strlen("file://")*/;
 }  #ifdef WIN32
                                   if(afilename[0]=='/' && afilename[1] && afilename[2]==':' && afilename[3]=='/') {
 static int                                          // skip leading slash for absolute path file:///C:/path/to/file
 xmlFileMatchMethod(const char* filename) {                                          afilename++;
         if (!strncmp(filename, "parser://", 9 /*strlen("parser://"), and check xmlFileOpenMethod*/))                                  }
                 return(1);  #endif
         return(0);                          } else if(afilename[0] && afilename[1]!=':' && strstr(afilename, "://")) {
                                   pa_xmlStopMonitoringDependencies();
                                   return 0; // plug out [do not handle other prefixes]
                           }
                   }
   
           const char* can_store_filename=pa_strdup(afilename);
           add_dependency(can_store_filename);
   
           const char *buf;
           try {
                   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) {
                   if(strcmp(e.type(), "file.missing")==0)
                           return 0; // let the library try that and report an error properly
   
                   buf=e.comment();
           } catch(...) {
                   buf="xmlFileOpen_ReadIntoStream: unknown error";
           }
           return (void *)new MemoryStream(buf);
   }
   
   static int xmlFileMatchMethod(const char* filename) {
           return !strncmp(filename, "parser://", 9 /*strlen("parser://"), and check xmlFileOpenMethod*/);
 }  }
   
 /// parser://method/param/here -> ^MAIN:method[/params/here]  /// parser://method/param/here -> ^MAIN:method[/params/here]
 static void *  static void *xmlFileOpenMethod (const char* afilename) {
 xmlFileOpenMethod (const char* afilename) {          const char* buf;
         Request& r=pa_thread_request();          try {
                   Request& r=pa_thread_request();
   
                   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("/");  
                   if(s)
                           param_body.append_know_length(s, strlen(s));
   
         char* s=pa_strdup(afilename+9 /*strlen("parser://")*/);                  VString* vparam=new VString(*new String(param_body, String::L_TAINTED));
         const char* method_cstr=lsplit(&s, '/');                  Request::Execute_nonvirtual_method_result body=r.execute_nonvirtual_method(r.main_class, *method, vparam, true);
         const String* method=new String(method_cstr);  
         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));  
         {  
                 Temp_lang temp_lang(r, String::L_XML); // default language: XML  
                 Request::Execute_nonvirtual_method_result body=  
                         r.execute_nonvirtual_method(r.main_class, *method, vparam, true);  
                 if(body.string) {                  if(body.string) {
                         MemoryStream *stream=new(UseGC) MemoryStream;                          buf=body.string->untaint_cstr(String::L_XML);
                         stream->m_buf=body.string->cstr(String::L_UNSPECIFIED);                  } else
                         stream->m_size=strlen(stream->m_buf);                          throw Exception(0, new String(afilename), "'%s' method not found in %s class", method_cstr, MAIN_CLASS_NAME);
                         return (void*)stream;          } catch(const Exception& e) {
                 }                  buf=e.comment();
           } catch(...) {
                   buf="xmlFileOpenLocalhost: unknown error";
         }          }
           return (void *)new MemoryStream(buf);
         throw Exception(0,  
                 new String(afilename),  
                 "'%s' method not found in %s class",   
                         method_cstr, MAIN_CLASS_NAME);  
 }  }
   
 static int  /**
 pa_xmlFileReadMethod (void * context, //< MemoryStream actually   * pa_xmlFileReadMethod:
                                           char * buffer, int len)    * @context:  the I/O context
 {   * @buffer:  where to drop data
    * @len:  number of bytes to write
    *
    * Read @len bytes to @buffer from the I/O channel.
    *
    * Returns the number of bytes written
    */
   static int pa_xmlFileReadMethod (void* context, char* buffer, int len){
         MemoryStream& stream=*static_cast<MemoryStream*>(context);          MemoryStream& stream=*static_cast<MemoryStream*>(context);
   
         return stream.read(buffer, len);          return stream.read(buffer, len);
 }  }
   
 static int  static int pa_xmlFileCloseMethod (void* /*context*/) {
 pa_xmlFileCloseMethod (void * /*context*/) {  
         return 0;          return 0;
 }  }
   
   
   
 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(xmlFileMatchMonitor, xmlFileOpenMonitor, pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
                 xmlFileMatchSafeMode, 0,  
                 0, 0);          // parser://method/param/here -> ^MAIN:method[/params/here] - should be last to be called first
 #endif          xmlRegisterInputCallbacks(xmlFileMatchMethod, xmlFileOpenMethod, 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]  
         xmlRegisterInputCallbacks(  
                 xmlFileMatchMethod, xmlFileOpenMethod,  
                 pa_xmlFileReadMethod, pa_xmlFileCloseMethod);  
 }  }
   
 #endif  #endif

Removed from v.1.10  
changed lines
  Added in v.1.38


E-mail: