Diff for /parser3/src/main/pa_xml_io.C between versions 1.12 and 1.26

version 1.12, 2003/12/01 09:35:38 version 1.26, 2009/09/25 12:58:39
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-2009 ArtLebedev Group (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 13  static const char * const IDENT="$Date$" Line 13  static const char * const IDENT="$Date$"
   
 #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"
   
   static Hash<pa_thread_t, HashStringBool*> xml_dependencies;
   
   static void add_dependency(const String::Body url) { 
           pa_thread_t thread_id=pa_get_thread_id();
           HashStringBool* urls;
           {
                   SYNCHRONIZED;
   
                   // try to get existing for this thread_id
                   urls=xml_dependencies.get(thread_id);
           }
   
           if(urls) // do we need to monitor now?
                   urls->put(url, true);
   }
   
   void pa_xmlStartMonitoringDependencies() { 
           pa_thread_t thread_id=pa_get_thread_id();
           HashStringBool* urls=new HashStringBool;
           {
                   SYNCHRONIZED;  // find+fill blocked
   
                   xml_dependencies.put(thread_id, urls);
           }
   }
   
   void pa_xmlStopMonitoringDependencies() { 
           pa_thread_t thread_id=pa_get_thread_id();
           {
                   SYNCHRONIZED;  // find+fill blocked
   
                   xml_dependencies.put(thread_id, 0);
           }
   }
   
   HashStringBool* pa_xmlGetDependencies() {
           pa_thread_t thread_id=pa_get_thread_id();
           {
                   SYNCHRONIZED;  // find+remove blocked
   
                   HashStringBool* result=xml_dependencies.get(thread_id);
                   xml_dependencies.remove(thread_id);
                   return result;
           }
   }
   
 #ifndef DOXYGEN  #ifndef DOXYGEN
 struct MemoryStream {  struct MemoryStream {
         const char* m_buf;          const char* m_buf;
Line 28  struct MemoryStream { Line 75  struct MemoryStream {
                         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 83  struct MemoryStream {
 };  };
 #endif  #endif
   
   static void *
   xmlFileOpen_ReadIntoStream (const char* do_not_store_filename, bool adjust_path_to_root_from_document_root=false) {
 #ifdef PA_SAFE_MODE  #ifdef PA_SAFE_MODE
 static int  //copied from libxml/catalog.c
 xmlFileMatchSafeMode(const char* file_spec_cstr) {  #       define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
         if(strstr(file_spec_cstr, "://")) {          // disable attempts to consult default catalog [usually, that file belongs to other user/group]
                 String* file_spec=new String(file_spec_cstr, true);          if(strcmp(do_not_store_filename, XML_XML_DEFAULT_CATALOG)==0)
                 struct stat finfo;                  return 0;
                 if(stat(file_spec_cstr, &finfo)!=0)  #endif
                         throw Exception("file.missing",   
                                 file_spec,   
                                 "stat failed: %s (%d)",   
                                         strerror(errno), errno);  
   
                 check_safe_mode(finfo, file_spec, file_spec_cstr);          Request& r=pa_thread_request();
           char adjust_buf[MAX_STRING];    
           if(adjust_path_to_root_from_document_root) {
                   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, &do_not_store_filename[16]);
                   do_not_store_filename=adjust_buf;
           } else
                   if(!strstr(do_not_store_filename, "http://"))
                           if(strstr(do_not_store_filename, "file://")){
                                   do_not_store_filename+=7/*strlen("file://")*/;
   #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;
           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 0;          MemoryStream* stream=new(UseGC) MemoryStream;
           stream->m_buf=buf;
           stream->m_size=strlen(buf);
           return (void *)stream;
   }
   
   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
 }  }
 #endif  
   
   
 /**  /**
Line 71  xmlFileMatchLocalhost(const char* filena Line 172  xmlFileMatchLocalhost(const char* filena
         return(0);          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 *
 xmlFileOpenLocalhost (const char* filename) {  xmlFileOpenLocalhost (const char* filename) {
         Request& r=pa_thread_request();          return xmlFileOpen_ReadIntoStream(filename, true/*adjust path to root from document_root*/);
         const char* document_root=r.request_info.document_root;  
         if(!document_root)  
                 document_root=".";  
   
         char path[MAX_STRING];    
         path[0]=0;  
         strcat(path, document_root);  
         strcat(path, &filename[16]);  
   
         if(char *buf=file_read_text(r.charsets, *new String(path), false)) {  
                 MemoryStream *stream=new(UseGC) MemoryStream;  
                 stream->m_buf=buf  
                 stream->m_size=strlen(buf);  
                 return (void *)stream;  
         } else  
                 return 0;  
 }  }
   
 static int  static int
Line 114  xmlFileMatchMethod(const char* filename) Line 195  xmlFileMatchMethod(const char* filename)
 /// 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) {
         Request& r=pa_thread_request();          const char* buf;
           try {
         char* s=pa_strdup(afilename+9 /*strlen("parser://")*/);                  Request& r=pa_thread_request();
         const char* method_cstr=lsplit(&s, '/');  
         const String* method=new String(method_cstr);                  char* s=pa_strdup(afilename+9 /*strlen("parser://")*/);
         String::Body param_body("/");                    const char* method_cstr=lsplit(&s, '/');
         if(s)                  const String* method=new String(method_cstr);
                 param_body.append_know_length(s, strlen(s));                  String::Body param_body("/");  
                   if(s)
         VString* vparam=new VString(*new String(param_body, String::L_TAINTED));                          param_body.append_know_length(s, strlen(s));
         {  
                 Temp_lang temp_lang(r, String::L_XML); // default language: XML                  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);                          Temp_lang temp_lang(r, String::L_XML); // default language: XML
                 if(body.string) {                          Request::Execute_nonvirtual_method_result body=
                         MemoryStream *stream=new(UseGC) MemoryStream;                                  r.execute_nonvirtual_method(r.main_class, *method, vparam, true);
                         stream->m_buf=body.string->cstr(String::L_UNSPECIFIED);                          if(body.string) {
                         stream->m_size=strlen(stream->m_buf);                                  buf=body.string->untaint_cstr(r.flang);
                         return (void*)stream;                          } else
                                   throw Exception(0,
                                           new String(afilename),
                                           "'%s' method not found in %s class", 
                                                           method_cstr, MAIN_CLASS_NAME);
                 }                  }
           } catch(const Exception& e) {
                   buf=e.comment();
           } catch(...) {
                   buf="xmlFileOpenLocalhost: unknown error";
         }          }
           MemoryStream* stream=new(UseGC) MemoryStream;
         throw Exception(0,          stream->m_buf=buf;
                 new String(afilename),          stream->m_size=strlen(buf);
                 "'%s' method not found in %s class",           return (void *)stream;
                         method_cstr, MAIN_CLASS_NAME);  
 }  }
   
   /**
    * pa_xmlFileReadMethod:
    * @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  static int
 pa_xmlFileReadMethod (void * context, //< MemoryStream actually  pa_xmlFileReadMethod (void * context, //< MemoryStream actually
                                           char * buffer, int len)                                             char * buffer, int len) 
Line 159  pa_xmlFileCloseMethod (void * /*context* Line 257  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, 0,                  xmlFileMatchMonitor, xmlFileOpenMonitor,
                 0, 0);                  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,

Removed from v.1.12  
changed lines
  Added in v.1.26


E-mail: