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

1.1       paf         1: /** @file
                      2:        Parser: plugins to xml library, controlling i/o; implementation
                      3: 
1.16      paf         4:        Copyright (c) 2001-2004 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.17    ! paf        12: static const char * const IDENT="$Date: 2004/02/11 15:33: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.15      paf        88:        Request& r=pa_thread_request();
                     89:        char adjust_buf[MAX_STRING];    
                     90:        if(adjust_path_to_root_from_document_root) {
                     91:                const char* document_root=r.request_info.document_root;
                     92:                if(!document_root)
                     93:                        document_root=".";
                     94: 
                     95:                adjust_buf[0]=0;
                     96:                strcat(adjust_buf, document_root);
1.17    ! paf        97:                strcat(adjust_buf, &do_not_store_filename[16]);
        !            98:                do_not_store_filename=adjust_buf;
1.15      paf        99:        } else
1.17    ! paf       100:                if(strstr(do_not_store_filename, "file://"))
        !           101:                        do_not_store_filename+=7/*strlen("file://")*/; 
        !           102:                else if(*do_not_store_filename && do_not_store_filename[1]!=':' && strstr(do_not_store_filename, "://"))  {
        !           103:                        pa_xmlStopMonitoringDependencies();
1.15      paf       104:                        return 0; // plug out [do not handle other prefixes]
1.17    ! paf       105:                }
        !           106: 
        !           107:        const char* can_store_filename=pa_strdup(do_not_store_filename);
        !           108:        add_dependency(can_store_filename);
1.15      paf       109: 
                    110:        const char *buf;
                    111:        try {
1.17    ! paf       112:                buf=file_read_text(r.charsets, *new String(can_store_filename));
1.15      paf       113:        } catch(const Exception& e) {
1.17    ! paf       114:                if(strcmp(e.type(), "file.missing")==0)
        !           115:                        return 0; // let the library try that and report an error properly
        !           116: 
1.15      paf       117:                buf=e.comment();
                    118:        } catch(...) {
1.17    ! paf       119:                buf="xmlFileOpen_ReadIntoStream: unknown error";
1.15      paf       120:        }
                    121:        MemoryStream* stream=new(UseGC) MemoryStream;
                    122:        stream->m_buf=buf;
                    123:        stream->m_size=strlen(buf);
                    124:        return (void *)stream;
                    125: }
1.9       paf       126: 
                    127: static int
1.17    ! paf       128: xmlFileMatchMonitor(const char* /*file_spec_cstr*/) {
        !           129:        return 1; // always intercept, causing xmlFileOpenMonitor to be called
1.15      paf       130: }
                    131: static void *
1.17    ! paf       132: xmlFileOpenMonitor(const char* filename) {
1.15      paf       133:        return xmlFileOpen_ReadIntoStream(filename); // handles localfile case, else returns 0
1.9       paf       134: }
                    135: 
                    136: 
1.1       paf       137: /**
                    138:  * xmlFileMatchWithLocalhostEqDocumentRoot:
                    139:  * filename:  the URI for matching
                    140:  *
                    141:  * check if the URI matches an HTTP one
                    142:  *
                    143:  * Returns 1 if matches, 0 otherwise
                    144:  */
                    145: static int
                    146: xmlFileMatchLocalhost(const char* filename) {
                    147:        if (!strncmp(filename, "http://localhost", 16))
                    148:                return(1);
                    149:        return(0);
                    150: }
                    151: 
                    152: /**
1.15      paf       153:  * xmlFileOpenLocalhost:
1.1       paf       154:  * filename:  the URI for matching
                    155:  *
                    156:  * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
                    157:  *
                    158:  * Returns an I/O context or NULL in case of error
                    159:  */
                    160: static void *
                    161: xmlFileOpenLocalhost (const char* filename) {
1.15      paf       162:        return xmlFileOpen_ReadIntoStream(filename, true/*adjust path to root from document_root*/);
1.1       paf       163: }
                    164: 
1.2       paf       165: static int
                    166: xmlFileMatchMethod(const char* filename) {
1.3       paf       167:        if (!strncmp(filename, "parser://", 9 /*strlen("parser://"), and check xmlFileOpenMethod*/))
1.2       paf       168:                return(1);
                    169:        return(0);
                    170: }
                    171: 
1.5       paf       172: /// parser://method/param/here -> ^MAIN:method[/params/here]
1.2       paf       173: static void *
                    174: xmlFileOpenMethod (const char* afilename) {
1.15      paf       175:        const char* buf;
                    176:        try {
                    177:                Request& r=pa_thread_request();
                    178: 
                    179:                char* s=pa_strdup(afilename+9 /*strlen("parser://")*/);
                    180:                const char* method_cstr=lsplit(&s, '/');
                    181:                const String* method=new String(method_cstr);
                    182:                String::Body param_body("/");  
                    183:                if(s)
                    184:                        param_body.append_know_length(s, strlen(s));
                    185: 
                    186:                VString* vparam=new VString(*new String(param_body, String::L_TAINTED));
                    187:                {
                    188:                        Temp_lang temp_lang(r, String::L_XML); // default language: XML
                    189:                        Request::Execute_nonvirtual_method_result body=
                    190:                                r.execute_nonvirtual_method(r.main_class, *method, vparam, true);
                    191:                        if(body.string) {
                    192:                                buf=body.string->cstr(String::L_UNSPECIFIED);
                    193:                        } else
                    194:                                throw Exception(0,
                    195:                                        new String(afilename),
                    196:                                        "'%s' method not found in %s class", 
                    197:                                                        method_cstr, MAIN_CLASS_NAME);
1.2       paf       198:                }
1.15      paf       199:        } catch(const Exception& e) {
                    200:                buf=e.comment();
                    201:        } catch(...) {
                    202:                buf="xmlFileOpenLocalhost: unknown error";
1.2       paf       203:        }
1.15      paf       204:        MemoryStream* stream=new(UseGC) MemoryStream;
                    205:        stream->m_buf=buf;
                    206:        stream->m_size=strlen(buf);
                    207:        return (void *)stream;
1.2       paf       208: }
                    209: 
1.15      paf       210: /**
                    211:  * pa_xmlFileReadMethod:
                    212:  * @context:  the I/O context
                    213:  * @buffer:  where to drop data
                    214:  * @len:  number of bytes to write
                    215:  *
                    216:  * Read @len bytes to @buffer from the I/O channel.
                    217:  *
                    218:  * Returns the number of bytes written
                    219:  */
1.2       paf       220: static int
                    221: pa_xmlFileReadMethod (void * context, //< MemoryStream actually
                    222:                                          char * buffer, int len) 
                    223: {
                    224:        MemoryStream& stream=*static_cast<MemoryStream*>(context);
                    225: 
                    226:        return stream.read(buffer, len);
                    227: }
                    228: 
                    229: static int
                    230: pa_xmlFileCloseMethod (void * /*context*/) {
                    231:        return 0;
                    232: }
                    233: 
                    234: 
1.1       paf       235: 
                    236: void pa_xml_io_init() {
1.17    ! paf       237:        // file open monitorer [for xslt cacher]
1.9       paf       238:        // safe mode checker, always fail match, but checks non-"://" there
                    239:        xmlRegisterInputCallbacks(
1.17    ! paf       240:                xmlFileMatchMonitor, xmlFileOpenMonitor,
1.15      paf       241:                pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
1.17    ! paf       242: 
1.1       paf       243:        // http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
                    244:        xmlRegisterInputCallbacks(
                    245:                xmlFileMatchLocalhost, xmlFileOpenLocalhost,
1.8       paf       246:                pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
1.2       paf       247: 
1.5       paf       248:        // parser://method/param/here -> ^MAIN:method[/params/here]
1.2       paf       249:        xmlRegisterInputCallbacks(
                    250:                xmlFileMatchMethod, xmlFileOpenMethod,
                    251:                pa_xmlFileReadMethod, pa_xmlFileCloseMethod);
1.1       paf       252: }
                    253: 
                    254: #endif

E-mail: