Annotation of parser3/src/main/pa_xml_io.C, revision 1.19

1.1       paf         1: /** @file
                      2:        Parser: plugins to xml library, controlling i/o; implementation
                      3: 
1.19    ! paf         4:        Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
1.1       paf         5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
                      6: */
                      7: 
                      8: #include "pa_xml_io.h"
                      9: 
                     10: #ifdef XML
                     11: 
1.19    ! paf        12: static const char * const IDENT="$Date: 2004/04/08 08:46:16 $";
1.1       paf        13: 
                     14: #include "libxslt/extensions.h"
                     15: 
1.17      paf        16: #include "pa_threads.h"
1.1       paf        17: #include "pa_globals.h"
                     18: #include "pa_request.h"
                     19: 
1.17      paf        20: static Hash<pa_thread_t, HashStringBool*> xml_dependencies;
                     21: 
                     22: static void add_dependency(const String::Body url) { 
                     23:        pa_thread_t thread_id=pa_get_thread_id();
                     24:        HashStringBool* urls;
                     25:        {
                     26:                SYNCHRONIZED;
                     27: 
                     28:                // try to get existing for this thread_id
                     29:                urls=xml_dependencies.get(thread_id);
                     30:        }
                     31: 
                     32:        if(urls) // do we need to monitor now?
                     33:                urls->put(url, true);
                     34: }
                     35: 
                     36: void pa_xmlStartMonitoringDependencies() { 
                     37:        pa_thread_t thread_id=pa_get_thread_id();
                     38:        HashStringBool* urls=new HashStringBool;
                     39:        {
                     40:                SYNCHRONIZED;  // find+fill blocked
                     41: 
                     42:                xml_dependencies.put(thread_id, urls);
                     43:        }
                     44: }
                     45: 
                     46: void pa_xmlStopMonitoringDependencies() { 
                     47:        pa_thread_t thread_id=pa_get_thread_id();
                     48:        {
                     49:                SYNCHRONIZED;  // find+fill blocked
                     50: 
                     51:                xml_dependencies.put(thread_id, 0);
                     52:        }
                     53: }
                     54: 
                     55: HashStringBool* pa_xmlGetDependencies() {
                     56:        pa_thread_t thread_id=pa_get_thread_id();
                     57:        {
                     58:                SYNCHRONIZED;  // find+remove blocked
                     59: 
                     60:                HashStringBool* result=xml_dependencies.get(thread_id);
                     61:                xml_dependencies.remove(thread_id);
                     62:                return result;
                     63:        }
                     64: }
                     65: 
1.8       paf        66: #ifndef DOXYGEN
                     67: struct MemoryStream {
                     68:        const char* m_buf;
                     69:        size_t m_size;
                     70:        size_t m_position;
                     71: 
                     72:        int read(char* a_buffer, size_t a_size) {
                     73:                size_t left=m_size-m_position;
                     74:                if(!left)
                     75:                        return 0;
                     76: 
                     77:                size_t to_read=min(a_size, left);
1.14      paf        78:                memcpy(a_buffer, m_buf+m_position, to_read);
1.8       paf        79:                m_position+=to_read;
                     80:                return to_read;
                     81:        }
                     82: 
                     83: };
                     84: #endif
                     85: 
1.15      paf        86: static void *
1.17      paf        87: xmlFileOpen_ReadIntoStream (const char* do_not_store_filename, bool adjust_path_to_root_from_document_root=false) {
1.18      paf        88: #ifdef PA_SAFE_MODE
                     89: //copied from libxml/catalog.c
                     90: #      define XML_XML_DEFAULT_CATALOG "file:///etc/xml/catalog"
                     91:        // disable attempts to consult default catalog [usually, that file belongs to other user/group]
                     92:        if(strcmp(do_not_store_filename, XML_XML_DEFAULT_CATALOG)==0)
                     93:                return 0;
                     94: #endif
                     95: 
1.15      paf        96:        Request& r=pa_thread_request();
                     97:        char adjust_buf[MAX_STRING];    
                     98:        if(adjust_path_to_root_from_document_root) {
                     99:                const char* document_root=r.request_info.document_root;
                    100:                if(!document_root)
                    101:                        document_root=".";
                    102: 
                    103:                adjust_buf[0]=0;
                    104:                strcat(adjust_buf, document_root);
1.17      paf       105:                strcat(adjust_buf, &do_not_store_filename[16]);
                    106:                do_not_store_filename=adjust_buf;
1.15      paf       107:        } else
1.17      paf       108:                if(strstr(do_not_store_filename, "file://"))
                    109:                        do_not_store_filename+=7/*strlen("file://")*/; 
                    110:                else if(*do_not_store_filename && do_not_store_filename[1]!=':' && strstr(do_not_store_filename, "://"))  {
                    111:                        pa_xmlStopMonitoringDependencies();
1.15      paf       112:                        return 0; // plug out [do not handle other prefixes]
1.17      paf       113:                }
                    114: 
                    115:        const char* can_store_filename=pa_strdup(do_not_store_filename);
                    116:        add_dependency(can_store_filename);
1.15      paf       117: 
                    118:        const char *buf;
                    119:        try {
1.17      paf       120:                buf=file_read_text(r.charsets, *new String(can_store_filename));
1.15      paf       121:        } catch(const Exception& e) {
1.17      paf       122:                if(strcmp(e.type(), "file.missing")==0)
                    123:                        return 0; // let the library try that and report an error properly
                    124: 
1.15      paf       125:                buf=e.comment();
                    126:        } catch(...) {
1.17      paf       127:                buf="xmlFileOpen_ReadIntoStream: unknown error";
1.15      paf       128:        }
                    129:        MemoryStream* stream=new(UseGC) MemoryStream;
                    130:        stream->m_buf=buf;
                    131:        stream->m_size=strlen(buf);
                    132:        return (void *)stream;
                    133: }
1.9       paf       134: 
                    135: static int
1.17      paf       136: xmlFileMatchMonitor(const char* /*file_spec_cstr*/) {
                    137:        return 1; // always intercept, causing xmlFileOpenMonitor to be called
1.15      paf       138: }
                    139: static void *
1.17      paf       140: xmlFileOpenMonitor(const char* filename) {
1.15      paf       141:        return xmlFileOpen_ReadIntoStream(filename); // handles localfile case, else returns 0
1.9       paf       142: }
                    143: 
                    144: 
1.1       paf       145: /**
                    146:  * xmlFileMatchWithLocalhostEqDocumentRoot:
                    147:  * filename:  the URI for matching
                    148:  *
                    149:  * check if the URI matches an HTTP one
                    150:  *
                    151:  * Returns 1 if matches, 0 otherwise
                    152:  */
                    153: static int
                    154: xmlFileMatchLocalhost(const char* filename) {
                    155:        if (!strncmp(filename, "http://localhost", 16))
                    156:                return(1);
                    157:        return(0);
                    158: }
                    159: 
                    160: /**
1.15      paf       161:  * xmlFileOpenLocalhost:
1.1       paf       162:  * filename:  the URI for matching
                    163:  *
                    164:  * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
                    165:  *
                    166:  * Returns an I/O context or NULL in case of error
                    167:  */
                    168: static void *
                    169: xmlFileOpenLocalhost (const char* filename) {
1.15      paf       170:        return xmlFileOpen_ReadIntoStream(filename, true/*adjust path to root from document_root*/);
1.1       paf       171: }
                    172: 
1.2       paf       173: static int
                    174: xmlFileMatchMethod(const char* filename) {
1.3       paf       175:        if (!strncmp(filename, "parser://", 9 /*strlen("parser://"), and check xmlFileOpenMethod*/))
1.2       paf       176:                return(1);
                    177:        return(0);
                    178: }
                    179: 
1.5       paf       180: /// parser://method/param/here -> ^MAIN:method[/params/here]
1.2       paf       181: static void *
                    182: xmlFileOpenMethod (const char* afilename) {
1.15      paf       183:        const char* buf;
                    184:        try {
                    185:                Request& r=pa_thread_request();
                    186: 
                    187:                char* s=pa_strdup(afilename+9 /*strlen("parser://")*/);
                    188:                const char* method_cstr=lsplit(&s, '/');
                    189:                const String* method=new String(method_cstr);
                    190:                String::Body param_body("/");  
                    191:                if(s)
                    192:                        param_body.append_know_length(s, strlen(s));
                    193: 
                    194:                VString* vparam=new VString(*new String(param_body, String::L_TAINTED));
                    195:                {
                    196:                        Temp_lang temp_lang(r, String::L_XML); // default language: XML
                    197:                        Request::Execute_nonvirtual_method_result body=
                    198:                                r.execute_nonvirtual_method(r.main_class, *method, vparam, true);
                    199:                        if(body.string) {
                    200:                                buf=body.string->cstr(String::L_UNSPECIFIED);
                    201:                        } else
                    202:                                throw Exception(0,
                    203:                                        new String(afilename),
                    204:                                        "'%s' method not found in %s class", 
                    205:                                                        method_cstr, MAIN_CLASS_NAME);
1.2       paf       206:                }
1.15      paf       207:        } catch(const Exception& e) {
                    208:                buf=e.comment();
                    209:        } catch(...) {
                    210:                buf="xmlFileOpenLocalhost: unknown error";
1.2       paf       211:        }
1.15      paf       212:        MemoryStream* stream=new(UseGC) MemoryStream;
                    213:        stream->m_buf=buf;
                    214:        stream->m_size=strlen(buf);
                    215:        return (void *)stream;
1.2       paf       216: }
                    217: 
1.15      paf       218: /**
                    219:  * pa_xmlFileReadMethod:
                    220:  * @context:  the I/O context
                    221:  * @buffer:  where to drop data
                    222:  * @len:  number of bytes to write
                    223:  *
                    224:  * Read @len bytes to @buffer from the I/O channel.
                    225:  *
                    226:  * Returns the number of bytes written
                    227:  */
1.2       paf       228: static int
                    229: pa_xmlFileReadMethod (void * context, //< MemoryStream actually
                    230:                                          char * buffer, int len) 
                    231: {
                    232:        MemoryStream& stream=*static_cast<MemoryStream*>(context);
                    233: 
                    234:        return stream.read(buffer, len);
                    235: }
                    236: 
                    237: static int
                    238: pa_xmlFileCloseMethod (void * /*context*/) {
                    239:        return 0;
                    240: }
                    241: 
                    242: 
1.1       paf       243: 
                    244: void pa_xml_io_init() {
1.17      paf       245:        // file open monitorer [for xslt cacher]
1.9       paf       246:        // safe mode checker, always fail match, but checks non-"://" there
                    247:        xmlRegisterInputCallbacks(
1.17      paf       248:                xmlFileMatchMonitor, xmlFileOpenMonitor,
1.15      paf       249:                pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
1.17      paf       250: 
1.1       paf       251:        // http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
                    252:        xmlRegisterInputCallbacks(
                    253:                xmlFileMatchLocalhost, xmlFileOpenLocalhost,
1.8       paf       254:                pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
1.2       paf       255: 
1.5       paf       256:        // parser://method/param/here -> ^MAIN:method[/params/here]
1.2       paf       257:        xmlRegisterInputCallbacks(
                    258:                xmlFileMatchMethod, xmlFileOpenMethod,
                    259:                pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
1.1       paf       260: }
                    261: 
                    262: #endif

E-mail: