Annotation of parser3/src/main/pa_globals.C, revision 1.129
1.15 paf 1: /** @file
1.16 paf 2: Parser: globals.
3:
1.112 paf 4: Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com)
1.113 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.16 paf 6:
1.129 ! paf 7: $Id: pa_globals.C,v 1.128 2002/06/12 10:58:42 paf Exp $
1.1 paf 8: */
9:
1.102 paf 10: #include "pa_config_includes.h"
11:
12: #ifdef XML
13: #include "libxslt/extensions.h"
14: #include "libxslt/xsltutils.h"
1.116 paf 15: extern "C" {
1.102 paf 16: #include "libexslt/exslt.h"
1.116 paf 17: };
1.102 paf 18: #endif
19:
1.1 paf 20: #include "pa_globals.h"
1.32 paf 21: #include "pa_string.h"
22: #include "pa_hash.h"
1.42 paf 23: #include "pa_sql_driver_manager.h"
1.77 parser 24: #include "pa_dictionary.h"
1.100 paf 25: #include "pa_stylesheet_manager.h"
1.83 parser 26: #include "pa_sapi.h"
1.90 paf 27: #include "pa_cache_managers.h"
1.95 paf 28: #include "pa_charsets.h"
29: #include "pa_charset.h"
1.101 paf 30: #include "pa_threads.h"
1.84 parser 31:
1.8 paf 32: String *content_type_name;
1.75 parser 33: String *charset_name;
1.8 paf 34: String *body_name;
1.13 paf 35: String *value_name;
1.14 paf 36: String *expires_name;
37: String *path_name;
1.17 paf 38: String *name_name;
39: String *size_name;
40: String *text_name;
1.8 paf 41:
1.39 paf 42: String *content_disposition_name;
43: String *content_disposition_filename_name;
44:
1.129 ! paf 45: String *rootconf_method_name;
1.1 paf 46: String *auto_method_name;
47:
48: String *main_class_name;
49:
1.6 paf 50: String *result_var_name;
1.64 parser 51: String *match_var_name;
1.6 paf 52:
1.119 paf 53: String *exception_var_name;
54: String *exception_type_part_name;
55: String *exception_source_part_name;
56: String *exception_comment_part_name;
57: String *exception_handled_part_name;
58:
1.79 parser 59: String *charsets_name;
1.36 paf 60: String *mime_types_name;
61: String *vfile_mime_type_name;
1.63 parser 62: String *origins_mode_name;
1.67 parser 63:
1.69 parser 64: String *class_path_name;
65:
1.67 parser 66: String *switch_data_name;
67:
1.120 paf 68: String *cache_data_name;
69:
1.70 parser 70: String *sql_limit_name;
71: String *sql_offset_name;
72: String *sql_default_name;
73:
1.95 paf 74: String *charset_UTF8_name;
75:
1.71 parser 76: String *hash_default_element_name;
1.42 paf 77:
1.124 paf 78: Table *string_match_table_template;
1.123 paf 79:
1.1 paf 80: Hash *untaint_lang_name2enum;
81:
1.95 paf 82: Charset *utf8_charset;
1.32 paf 83:
1.5 paf 84: short hex_value[0x100];
1.111 paf 85:
86: #ifdef XML
87: GdomeDOMImplementation *domimpl;
88: #endif
1.5 paf 89:
90: static void setup_hex_value() {
1.68 parser 91: memset(hex_value, 0, sizeof(hex_value));
1.5 paf 92: hex_value['0'] = 0;
93: hex_value['1'] = 1;
94: hex_value['2'] = 2;
95: hex_value['3'] = 3;
96: hex_value['4'] = 4;
97: hex_value['5'] = 5;
98: hex_value['6'] = 6;
99: hex_value['7'] = 7;
100: hex_value['8'] = 8;
101: hex_value['9'] = 9;
102: hex_value['A'] = 10;
103: hex_value['B'] = 11;
104: hex_value['C'] = 12;
105: hex_value['D'] = 13;
106: hex_value['E'] = 14;
107: hex_value['F'] = 15;
108: hex_value['a'] = 10;
109: hex_value['b'] = 11;
110: hex_value['c'] = 12;
111: hex_value['d'] = 13;
112: hex_value['e'] = 14;
113: hex_value['f'] = 15;
114: }
1.1 paf 115:
1.99 paf 116: #ifdef XML
1.101 paf 117:
118: const int MAX_CONCURRENT_XML_GENERIC_ERROR_THREADS=10;
119:
120: struct XML_Generic_error_info {
121: pa_thread_t thread_id;
122: char *message;
123: } xml_generic_error_infos[MAX_CONCURRENT_XML_GENERIC_ERROR_THREADS];
124:
125: XML_Generic_error_info *xml_generic_error_info(pa_thread_t thread_id) {
126: for(int i=0; i<MAX_CONCURRENT_XML_GENERIC_ERROR_THREADS; i++) {
127: XML_Generic_error_info *p=xml_generic_error_infos+i;
128: if(p->thread_id==thread_id)
129: return p;
130: }
131: return 0;
132: }
133:
1.99 paf 134: static void
1.101 paf 135: xmlParserGenericErrorFunc(void *ctx, const char *msg, ...) {
136: pa_thread_t thread_id=pa_get_thread_id();
137:
138: // infinitely looking for free slot to fill it
139: while(true) {
140: SYNCHRONIZED; // find+fill blocked
141:
142: // first try to get existing for this thread_id
143: XML_Generic_error_info *p=xml_generic_error_info(thread_id);
144: if(!p) { // occupy empty one
145: p=xml_generic_error_info(0);
146: if(!p) // wait for empty for it to appear
147: continue;
148: }
149:
1.102 paf 150: p->thread_id=thread_id;
1.101 paf 151: size_t offset=p->message?strlen(p->message):0;
152: p->message=(char *)realloc(p->message, offset+MAX_STRING);
153: if(!p->message)
154: SAPI::die(
155: "out of memory in 'xmlParserGenericErrorFunc', failed to reallocate to %u bytes",
156: offset+MAX_STRING);
157:
158: va_list args;
159: va_start(args, msg);
160: vsnprintf(p->message+offset, MAX_STRING, msg, args);
161: va_end(args);
162:
163: break;
164: }
165: }
166:
1.102 paf 167: bool xmlHaveGenericErrors() {
168: pa_thread_t thread_id=pa_get_thread_id();
169:
170: SYNCHRONIZED; // find blocked
171:
172: return xml_generic_error_info(thread_id)!=0;
173: }
174:
1.101 paf 175: const char *xmlGenericErrors() {
176: pa_thread_t thread_id=pa_get_thread_id();
177:
178: SYNCHRONIZED; // find+free blocked
179:
180: XML_Generic_error_info *p=xml_generic_error_info(thread_id);
181: if(!p) // no errors for our thread_id registered
182: return 0;
183:
184: const char *result=p->message;
185:
186: // free slot up
187: memset(p, 0, sizeof(*p));
188:
189: // it is up to caller to free it
190: return result;
1.99 paf 191: }
1.110 paf 192:
193: /**
194: * xmlFileMatchWithLocalhostEqDocumentRoot:
195: * filename: the URI for matching
196: *
197: * check if the URI matches an HTTP one
198: *
199: * Returns 1 if matches, 0 otherwise
200: */
201: static int
202: xmlFileMatchLocalhost(const char *filename) {
203: if (!strncmp(filename, "http://localhost", 16))
204: return(1);
205: return(0);
206: }
207:
208:
209: /**
210: * xmlFileOpenHttpLocalhost :
211: * filename: the URI for matching
212: *
213: * http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
214: *
215: * input from FILE *, supports compressed input
216: * if filename is " " then the standard input is used
217: *
218: * Returns an I/O context or NULL in case of error
219: */
220: static void *
221: xmlFileOpenLocalhost (const char *filename) {
222: FILE *fd;
223: const char* documentRoot;
224: char path[1000];
225:
226: path[0]=0;
227: strcat(path, (documentRoot=getenv("DOCUMENT_ROOT"))?documentRoot:".");
228: strcat(path, &filename[16]);
229:
230: #ifdef WIN32
231: fd = fopen(path, "rb");
232: #else
233: fd = fopen(path, "r");
234: #endif /* WIN32 */
235: return((void *) fd);
236: }
237:
238: /**
239: * xmlFileRead:
240: * @context: the I/O context
241: * @buffer: where to drop data
242: * @len: number of bytes to write
243: *
244: * Read @len bytes to @buffer from the I/O channel.
245: *
246: * Returns the number of bytes written
247: */
248: static int
249: xmlFileRead (void * context, char * buffer, int len) {
250: return(fread(&buffer[0], 1, len, (FILE *) context));
251: }
252:
253: /**
254: * xmlFileWrite:
255: * @context: the I/O context
256: * @buffer: where to drop data
257: * @len: number of bytes to write
258: *
259: * Write @len bytes from @buffer to the I/O channel.
260: *
261: * Returns the number of bytes written
262: */
263: static int
264: xmlFileWrite (void * context, const char * buffer, int len) {
265: return(fwrite(&buffer[0], 1, len, (FILE *) context));
266: }
267:
268: /**
269: * xmlFileClose:
270: * @context: the I/O context
271: *
272: * Close an I/O channel
273: */
274: static int
275: xmlFileClose (void * context) {
276: return ( ( fclose((FILE *) context) == EOF ) ? -1 : 0 );
277: }
278:
1.99 paf 279: #endif
280:
1.83 parser 281: void pa_globals_destroy(void *) {
282: try {
1.96 paf 283: #ifdef XML
284: GdomeException exc;
285: gdome_di_unref (domimpl, &exc);
286: #endif
1.93 paf 287: if(cache_managers)
288: cache_managers->~Cache_managers();
1.95 paf 289:
290: charsets->~Charsets();
1.83 parser 291:
292: } catch(const Exception& e) {
293: SAPI::die("pa_globals_destroy failed: %s", e.comment());
294: }
295: }
296:
1.108 paf 297: /// @test hint on one should call this for each thread xmlSubstituteEntitiesDefault(1);
1.27 paf 298: void pa_globals_init(Pool& pool) {
1.83 parser 299: pool.register_cleanup(pa_globals_destroy, 0);
300:
1.32 paf 301: #undef NEW
302: #define NEW new(pool)
303:
1.5 paf 304: // hex value
305: setup_hex_value();
306:
1.1 paf 307: // names
1.32 paf 308: content_type_name=NEW String(pool, CONTENT_TYPE_NAME);
1.75 parser 309: charset_name=NEW String(pool, CHARSET_NAME);
1.32 paf 310: body_name=NEW String(pool, BODY_NAME);
311: value_name=NEW String(pool, VALUE_NAME);
312: expires_name=NEW String(pool, EXPIRES_NAME);
313: path_name=NEW String(pool, PATH_NAME);
314: name_name=NEW String(pool, NAME_NAME);
315: size_name=NEW String(pool, SIZE_NAME);
316: text_name=NEW String(pool, TEXT_NAME);
317:
1.39 paf 318: content_disposition_name=NEW String(pool, CONTENT_DISPOSITION_NAME);
319: content_disposition_filename_name=NEW String(pool, CONTENT_DISPOSITION_FILENAME_NAME);
1.32 paf 320:
1.129 ! paf 321: rootconf_method_name=NEW String(pool, ROOTCONF_METHOD_NAME);
1.32 paf 322: auto_method_name=NEW String(pool, AUTO_METHOD_NAME);
323:
324: main_class_name=NEW String(pool, MAIN_CLASS_NAME);
1.6 paf 325:
1.32 paf 326: result_var_name=NEW String(pool, RESULT_VAR_NAME);
1.64 parser 327: match_var_name=NEW String(pool, MATCH_VAR_NAME);
1.6 paf 328:
1.119 paf 329: exception_var_name=NEW String(pool, EXCEPTION_VAR_NAME);
330: exception_type_part_name=NEW String(pool, EXCEPTION_TYPE_PART_NAME);
331: exception_source_part_name=NEW String(pool, EXCEPTION_SOURCE_PART_NAME);
332: exception_comment_part_name=NEW String(pool, EXCEPTION_COMMENT_PART_NAME);
333: exception_handled_part_name=NEW String(pool, EXCEPTION_HANDLED_PART_NAME);
1.4 paf 334:
1.79 parser 335: charsets_name=NEW String(pool, CHARSETS_NAME);
1.36 paf 336: mime_types_name=NEW String(pool, MIME_TYPES_NAME);
337: vfile_mime_type_name=NEW String(pool, VFILE_MIME_TYPE_NAME);
1.63 parser 338: origins_mode_name=NEW String(pool, ORIGINS_MODE_NAME);
1.69 parser 339:
340: class_path_name=NEW String(pool, CLASS_PATH_NAME);
1.66 parser 341:
342: //^switch ^case
343: switch_data_name=NEW String(pool, SWITCH_DATA_NAME);
1.120 paf 344:
345: //^cache
346: cache_data_name=NEW String(pool, CACHE_DATA_NAME);
1.70 parser 347:
348: // sql
349: sql_limit_name=NEW String(pool, SQL_LIMIT_NAME);
350: sql_offset_name=NEW String(pool, SQL_OFFSET_NAME);
351: sql_default_name=NEW String(pool, SQL_DEFAULT_NAME);
1.71 parser 352:
1.95 paf 353: // charsets
354: charset_UTF8_name=NEW String(pool, CHARSET_UTF8_NAME);
355:
1.71 parser 356: // hash
357: hash_default_element_name=NEW String(pool, HASH_DEFAULT_ELEMENT_NAME);
1.70 parser 358:
1.1 paf 359: // hashes
1.32 paf 360: untaint_lang_name2enum=NEW Hash(pool);
1.87 paf 361: #define ULN(cstr, LANG) \
362: untaint_lang_name2enum->put(*NEW String(pool, cstr), (int)String::UL_##LANG);
363: ULN("as-is", AS_IS);
364: ULN("file-spec", FILE_SPEC);
365: ULN("http-header", HTTP_HEADER);
366: ULN("mail-header", MAIL_HEADER);
367: ULN("uri", URI);
368: ULN("table", TABLE);
369: ULN("sql", SQL);
370: ULN("js", JS);
371: ULN("xml", XML);
372: ULN("html", HTML);
1.92 paf 373: ULN("optimized-html", HTML|String::UL_OPTIMIZE_BIT);
1.123 paf 374:
375: // table
376: { // create table
1.124 paf 377: Array *string_match_table_columns=NEW Array(pool);
1.123 paf 378: *string_match_table_columns+=NEW String(pool, STRING_PRE_MATCH_NAME);
379: *string_match_table_columns+=NEW String(pool, STRING_MATCH_NAME);
380: *string_match_table_columns+=NEW String(pool, STRING_POST_MATCH_NAME);
381: for(int i=1; i<=MAX_STRING_MATCH_TABLE_COLUMNS; i++) {
1.125 paf 382: char *column=(char *)pool.malloc(MAX_NUMBER);
1.123 paf 383: snprintf(column, MAX_NUMBER, "%d", i);
384: *string_match_table_columns+=NEW String(pool, column); // .i column name
385: }
1.124 paf 386: string_match_table_template=NEW Table(pool, 0, string_match_table_columns);
1.123 paf 387: }
1.1 paf 388:
1.95 paf 389: // charsets
390: charsets=NEW Charsets(pool);
391: charsets->put(*charset_UTF8_name,
392: utf8_charset=NEW Charset(pool, *charset_UTF8_name, 0/*no file=system*/));
1.88 paf 393:
1.101 paf 394:
1.88 paf 395: // Status registration, must be initialized before all registrants
1.90 paf 396: cache_managers=NEW Cache_managers(pool);
1.42 paf 397:
1.73 parser 398: // SQL driver manager
1.90 paf 399: cache_managers->put(*NEW String(pool, "sql"),
400: SQL_driver_manager=NEW SQL_Driver_manager(pool));
1.74 parser 401:
1.76 parser 402: #ifdef XML
1.96 paf 403: // initializing xml libs
404:
405: /* First I get a DOMImplementation reference */
406: domimpl = gdome_di_mkref ();
407: /*
408: * Register the EXSLT extensions and the test module
409: */
410: exsltRegisterAll();
411: xsltRegisterTestModule();
412: xmlDefaultSAXHandlerInit();
413: /*
414: * disable CDATA from being built in the document tree
415: */
1.101 paf 416: // never added yet xmlDefaultSAXHandler.cdataBlock = NULL;
1.99 paf 417:
418: /*
419: * Initialization function for the XML parser.
420: * This is not reentrant. Call once before processing in case of
421: * use in multithreaded programs.
422: */
423: xmlInitParser();
1.107 paf 424:
425: // 1. this is needed for proper parsing of stylesheets
426: // there were a situation where honest entity ruined innocent xpath compilation
427: // doc says "you sould turn it on on stylesheet load" without deepening into details
428: // 2. when dom tree with entites goes under transform text nodes
429: // got [erroreosly] cut on first entity occurance
1.109 paf 430: // --
1.107 paf 431: // that is why this is:
432: xmlSubstituteEntitiesDefault(1);
1.100 paf 433:
434: // Bit in the loadsubset context field to tell to do ID/REFs lookups
435: xmlLoadExtDtdDefaultValue |= XML_DETECT_IDS;
436: // Bit in the loadsubset context field to tell to do complete the elements attributes lists
437: // with the ones defaulted from the DTDs
438: //never added yet xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS;
1.99 paf 439:
1.104 paf 440: //regretfully this not only replaces entities on parse, but also on generate xmlSubstituteEntitiesDefault(1);
1.105 paf 441: // never switched this on xmlIndentTreeOutput=1;
1.104 paf 442:
1.101 paf 443: memset(xml_generic_error_infos, 0, sizeof(xml_generic_error_infos));
444: xmlSetGenericErrorFunc(0, xmlParserGenericErrorFunc);
1.102 paf 445: xsltSetGenericErrorFunc(0, xmlParserGenericErrorFunc);
1.105 paf 446: // FILE *f=fopen("y:\\xslt.log", "wt");
447: // xsltSetGenericDebugFunc(f/*stderr*/, 0);
1.110 paf 448:
449: // http://localhost/abc -> $ENV{DOCUMENT_ROOT}/abc | ./abc
450: xmlRegisterInputCallbacks(
451: xmlFileMatchLocalhost, xmlFileOpenLocalhost,
452: xmlFileRead, xmlFileClose);
1.96 paf 453:
454: // XSLT stylesheet manager
1.90 paf 455: cache_managers->put(*NEW String(pool, "stylesheet"),
456: stylesheet_manager=NEW Stylesheet_manager(pool));
1.76 parser 457: #endif
1.1 paf 458: }
1.76 parser 459:
460: #if defined(XML) && defined(_MSC_VER)
1.127 paf 461: # define XML_LIBS "/parser3project/win32/xml"
1.96 paf 462: # pragma comment(lib, XML_LIBS "/glib/lib/libglib-1.3-11.lib")
1.76 parser 463: # ifdef _DEBUG
1.114 paf 464: # pragma comment(lib, XML_LIBS "/libxml2-x.x.x/win32/dsp/libxml2_so_debug/libxml2.lib")
465: # pragma comment(lib, XML_LIBS "/libxslt-x.x.x/win32/dsp/libexslt_so_debug/libexslt.lib")
466: # pragma comment(lib, XML_LIBS "/libxslt-x.x.x/win32/dsp/libxslt_so_debug/libxslt.lib")
467: # pragma comment(lib, XML_LIBS "/gdome2-x.x.x/win32/dsp/Debug/libgdome.lib")
1.76 parser 468: # else
1.114 paf 469: # pragma comment(lib, XML_LIBS "/libxml2-x.x.x/win32/dsp/libxml2_so_release/libxml2.lib")
470: # pragma comment(lib, XML_LIBS "/libxslt-x.x.x/win32/dsp/libexslt_so_release/libexslt.lib")
471: # pragma comment(lib, XML_LIBS "/libxslt-x.x.x/win32/dsp/libxslt_so_release/libxslt.lib")
472: # pragma comment(lib, XML_LIBS "/gdome2-x.x.x/win32/dsp/Release/libgdome.lib")
1.85 paf 473: # endif
474: #endif
E-mail: