root/trunk/fastxsl.c

Revision 21, 35.5 kB (checked in by george, 8 years ago)

cleanup and configurables

Line 
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 4                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2003 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 2.02 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available at through the world-wide-web at                           |
10   | http://www.php.net/license/2_02.txt.                                 |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author: Sterling Hughes <sterling@php.net>                           |
16   |         George Schlossnagle <george@omniti.com>                      |
17   +----------------------------------------------------------------------+
18
19   $Id: fastxsl.c,v 1.1.1.1 2004/02/17 23:31:44 sterling Exp $
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <libxml/xmlmemory.h>
27 #include <libxml/debugXML.h>
28 #include <libxml/HTMLtree.h>
29 #include <libxml/xmlIO.h>
30 #include <libxml/xinclude.h>
31 #include <libxml/catalog.h>
32 #include <libxml/xpathInternals.h>
33 #include <libxml/xpath.h>
34 #include <libxslt/xslt.h>
35 #include <libxslt/xsltInternals.h>
36 #include <libxslt/transform.h>
37 #include <libxslt/xsltutils.h>
38
39 #ifdef FASTXSL_MM
40 #include <mm.h>
41 #endif
42 #include <sys/types.h>
43 #include <sys/file.h>
44 #include <unistd.h>
45
46 #include "fl_hash.h"
47 #include "php.h"
48 #include "php_ini.h"
49 #include "ext/standard/info.h"
50 #include "php_fastxsl.h"
51
52 ZEND_DECLARE_MODULE_GLOBALS(fastxsl);
53
54 static int inshm = 0;
55
56 static int le_fastxsl_stylesheet;
57 #define le_fastxsl_stylesheet_name "FastXSL Stylesheet"
58 static int le_fastxsl_document;
59 #define le_fastxsl_document_name "FastXSL Document"
60
61 #define FASTXSL_PRM_ALLOC 1
62 #define FASTXSL_SHARED_ALLOC 2
63
64 void fastxsl_errorfunc(void *ctx, const char *msg, ...);
65 static void ShmCache_Stylesheet_Free(php_ss_wrapper *wrapper TSRMLS_DC);
66 static void _SS_Wrapper_Dtor(php_ss_wrapper *wrapper);
67 static void _XD_Wrapper_Dtor(php_xd_wrapper *wrapper);
68
69 static php_ss_wrapper *
70 SS_Wrapper_Alloc(int shared TSRMLS_DC)
71 {
72         php_ss_wrapper *wrapper;
73
74         if (shared) {
75 #ifdef FASTXSL_MM
76                 if (shared == FASTXSL_SHARED_ALLOC) {
77                         wrapper = (php_ss_wrapper *) mm_calloc(FASTXSL_G(cache)->mm, 1, sizeof(php_ss_wrapper));
78                 } else {
79                         wrapper = (php_ss_wrapper *) calloc(1, sizeof(php_ss_wrapper));
80                 }
81                 if(!wrapper) {
82                         mm_display_info(FASTXSL_G(cache)->mm);
83                 }
84                 wrapper->persistant = 1;
85 #else
86                 wrapper = (php_ss_wrapper *) calloc(1, sizeof(php_ss_wrapper));
87                 wrapper->persistant = 1;
88 #endif
89         } else {
90                 wrapper = (php_ss_wrapper *) calloc(1, sizeof(php_ss_wrapper));
91         }
92
93         return wrapper;
94 }
95
96 static php_xd_wrapper *
97 XD_Wrapper_Alloc(void)
98 {
99         php_xd_wrapper *wrapper;
100
101         wrapper = (php_xd_wrapper *) calloc(1, sizeof(php_xd_wrapper));
102         return wrapper;
103 }
104
105 static xmlFreeFunc    free_ptr;
106 static xmlMallocFunc  malloc_ptr;
107 static xmlMallocFunc  mallocatomic_ptr;
108 static xmlReallocFunc realloc_ptr;
109 static xmlStrdupFunc  strdup_ptr;
110
111 #ifdef FASTXSL_MM
112 static void
113 ShmCache_Free(void *ptr)
114 {
115         TSRMLS_FETCH();
116         if(!inshm) assert(0);
117         FASTXSL_G(tmp_allocated_size) -= mm_sizeof(FASTXSL_G(cache)->mm, ptr);
118         mm_free(FASTXSL_G(cache)->mm, ptr);
119 }
120
121 static void *
122 ShmCache_Malloc(size_t size)
123 {
124         void *ptr;
125         TSRMLS_FETCH();
126         if(!inshm) assert(0);
127         ptr = mm_malloc(FASTXSL_G(cache)->mm, size);
128         if (!ptr) {
129                 php_error(E_ERROR, "Ran out of Shared memory to allocate data for FastXSL cache, "
130                                            "in function %s() cannot allocate %ld bytes (%ld available, %ld allocated)",
131                                                    get_active_function_name(TSRMLS_C), size, mm_available(FASTXSL_G(cache)->mm),
132                                                    mm_maxsize() - mm_available(FASTXSL_G(cache)->mm));
133                 return NULL;
134         }
135
136         FASTXSL_G(tmp_allocated_size) += size;
137         return ptr;
138 }
139
140 static void *
141 ShmCache_Calloc(size_t nmemb, size_t size)
142 {
143         void *ptr;
144
145         if(!inshm) assert(0);
146         ptr = ShmCache_Malloc(nmemb * size);
147         memset(ptr, 0, nmemb * size);
148         return ptr;
149 }
150
151 static void *
152 ShmCache_Realloc(void *ptr, size_t size)
153 {
154         void *newptr;
155         long  oldsize;
156         TSRMLS_FETCH();
157
158         if(!inshm) assert(0);
159         oldsize = mm_sizeof(FASTXSL_G(cache)->mm, ptr);
160         newptr = mm_realloc(FASTXSL_G(cache)->mm, ptr, size);
161         if (!newptr) {
162                 TSRMLS_FETCH();
163                 php_error(E_ERROR, "Ran out of Shared memory to allocate data for FastXSL cache, "
164                                            "in function %s() cannot allocate %d bytes (%d available, %d allocated)",
165                                                    get_active_function_name(TSRMLS_C), size, mm_available(FASTXSL_G(cache)->mm),
166                                                    mm_maxsize() - mm_available(FASTXSL_G(cache)->mm));
167                 return NULL;
168         }
169         FASTXSL_G(tmp_allocated_size) += (size - oldsize);
170         return newptr;
171 }
172
173 static char *
174 ShmCache_Strdup(const char *string)
175 {
176         char *newstring;
177         int   string_length;
178
179         if(!inshm) assert(0);
180         string_length = strlen(string);
181         newstring = ShmCache_Malloc(string_length + 1);
182         memcpy(newstring, string, string_length);
183         newstring[string_length] = 0;
184
185         return newstring;
186 }
187 #endif
188
189 static void
190 Php_Free(void *ptr)
191 {
192         efree(ptr);
193 }
194
195 static void *
196 Php_Malloc(size_t size)
197 {
198         return emalloc(size);
199 }
200
201 static void *
202 Php_Realloc(void *ptr, size_t size)
203 {
204         return erealloc(ptr, size);
205 }
206
207 static char *
208 Php_Strdup(const char *string)
209 {
210         return estrdup(string);
211 }
212
213 #ifdef FASTXSL_MM
214 static void
215 ShmCache_UseAllocationFunctions(void)
216 {
217         xmlMemSetup(ShmCache_Free, ShmCache_Malloc, ShmCache_Realloc, ShmCache_Strdup);
218 }
219 #endif
220
221 static void
222 Php_UseAllocationFunctions(void)
223 {
224         xmlMemSetup(Php_Free, Php_Malloc, Php_Realloc, Php_Strdup);
225 }
226
227 static void
228 Xml_UseAllocationFunctions(void)
229 {
230         xmlMemSetup(free_ptr, malloc_ptr,  realloc_ptr, strdup);
231 }
232
233 #ifdef FASTXSL_MM
234 static php_ss_wrapper *
235 ShmCache_Stylesheet_ParseAndStore(char *filename, size_t filename_len, int mtime TSRMLS_DC)
236 {
237         php_ss_wrapper *wrapper;
238         int rv;
239         wrapper = SS_Wrapper_Alloc(FASTXSL_SHARED_ALLOC TSRMLS_CC);
240
241         ShmCache_UseAllocationFunctions();
242         wrapper->alloc_type = FASTXSL_SHMALLOC;
243         FASTXSL_G(tmp_allocated_size) = 0;
244         zend_set_timeout(0);
245         wrapper->ss = xsltParseStylesheetFile(filename);
246         Xml_UseAllocationFunctions();
247         if (!wrapper->ss) {
248                 _SS_Wrapper_Dtor(wrapper);
249                 return NULL;
250         }
251         wrapper->mtime = mtime;
252         wrapper->allocsize = FASTXSL_G(tmp_allocated_size);
253         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
254         rv = fl_hash_add(FASTXSL_G(cache)->table, filename, filename_len, wrapper);
255         mm_unlock(FASTXSL_G(cache)->mm);
256         if(rv == 0) {
257                 /* we failed */
258                 php_ss_wrapper *fallback;
259                 mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
260                 fallback = fl_hash_find(FASTXSL_G(cache)->table, filename,
261                                         filename_len);
262                 mm_unlock(FASTXSL_G(cache)->mm);
263                 if(fallback) {
264                         ShmCache_Stylesheet_Free(wrapper);
265                         wrapper = fallback;
266                 } else {
267                 }
268         } else {
269         }
270
271         return wrapper;
272 }
273
274 static void
275 ShmCache_Stylesheet_Free(php_ss_wrapper *wrapper TSRMLS_DC)
276 {
277         if (wrapper->ss) {
278                 //xmlCleanupParserr();
279                 ShmCache_UseAllocationFunctions();
280 inshm = 1;
281                 xsltFreeStylesheet(wrapper->ss);
282 inshm = 0;
283                 //xmlCleanupParserr();
284                 Xml_UseAllocationFunctions();
285         }
286         mm_free(FASTXSL_G(cache)->mm, wrapper);
287 }
288
289 static void
290 ShmCache_Stylesheet_Delete(char *filename, size_t filename_len)
291 {
292         php_ss_wrapper *wrapper;
293
294         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
295         wrapper = fl_hash_find(FASTXSL_G(cache)->table, filename, filename_len);
296         mm_unlock(FASTXSL_G(cache)->mm);
297         if (wrapper) {
298                 mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
299                 fl_hash_delete(FASTXSL_G(cache)->table, filename, filename_len);
300                 mm_unlock(FASTXSL_G(cache)->mm);
301                 ShmCache_Stylesheet_Free(wrapper);
302         }
303 }
304 #endif
305
306 static php_ss_wrapper *
307 PrmCache_Stylesheet_ParseAndStore(char *filename, size_t filename_len, int mtime TSRMLS_DC)
308 {
309         php_ss_wrapper *wrapper;
310
311         wrapper = (php_ss_wrapper *) SS_Wrapper_Alloc(FASTXSL_PRM_ALLOC TSRMLS_CC);
312         wrapper->alloc_type = FASTXSL_PRMALLOC;
313
314         wrapper->ss = xsltParseStylesheetFile((xmlChar *)filename);
315         if (!wrapper->ss) {
316                 return NULL;
317         }
318         wrapper->mtime = mtime;
319        
320         if(fl_hash_add(FASTXSL_G(cache)->prmtable, filename, filename_len, wrapper) == 0) {
321                 /* we failed, not much we can do here, and no race */
322         }
323
324         return wrapper;
325 }
326
327 static void
328 PrmCache_Stylesheet_Free(php_ss_wrapper *wrapper TSRMLS_DC)
329 {
330         if (wrapper->ss) {
331                 xsltFreeStylesheet(wrapper->ss);
332         }
333         free(wrapper);
334 }
335
336 static void
337 PrmCache_Stylesheet_Delete(char *filename, size_t filename_len TSRMLS_DC)
338 {
339         php_ss_wrapper *wrapper;
340
341         wrapper = fl_hash_find(FASTXSL_G(cache)->prmtable, filename, filename_len);
342         if (wrapper) {
343                 fl_hash_delete(FASTXSL_G(cache)->prmtable, filename, filename_len);
344                 PrmCache_Stylesheet_Free(wrapper TSRMLS_CC);
345         }
346 }
347
348 /* {{{ proto array fastxsl_prmcache_getstatistics(void)
349    Get an array of statistics regarding the fastxsl documents in the process resident memory cache */
350 PHP_FUNCTION(fastxsl_prmcache_getstatistics)
351 {
352         php_ss_wrapper *wrapper;       
353
354         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
355                 return;
356         }
357
358 }
359 /* }}} */
360
361 /* {{{ proto array fastxsl_shmcache_getstatistics(void)
362    Get an array of statistics regarding the documents in the shared memory cache */
363 #ifdef FASTXSL_MM
364 PHP_FUNCTION(fastxsl_shmcache_getstatistics)
365 {
366         php_ss_wrapper *ss_wrapper;
367         FL_Bucket      *bucket;
368         zval           *files_array;
369         zval           *info_array;
370         int             i;
371         long            allocated_bytes = 0;
372        
373         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
374                 return;
375         }
376
377         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
378        
379         array_init(return_value);
380
381         MAKE_STD_ZVAL(files_array);
382         array_init(files_array);
383
384         for (i = 0; i < FL_HASH_SIZE; i++) {
385                 for (bucket = FASTXSL_G(cache)->table->buckets[i]; bucket != NULL; bucket = bucket->next) {
386                         ss_wrapper = (php_ss_wrapper *) bucket->data;
387
388                         MAKE_STD_ZVAL(info_array);
389                         array_init(info_array);
390
391                         add_assoc_long(info_array, "allocated", ss_wrapper->allocsize);
392                         add_assoc_long(info_array, "hits", ss_wrapper->hits);
393                         add_assoc_long(info_array, "mtime", ss_wrapper->mtime);
394
395                         add_assoc_zval(files_array, bucket->key, info_array);
396
397                         allocated_bytes += ss_wrapper->allocsize;
398                 }
399         }
400         add_assoc_zval(return_value, "files", files_array);
401
402         add_assoc_long(return_value, "apparent_allocated", allocated_bytes);
403         add_assoc_long(return_value, "allocated", mm_maxsize() - mm_available(FASTXSL_G(cache)->mm));
404         add_assoc_long(return_value, "shm_size", (long) mm_maxsize());
405         mm_unlock(FASTXSL_G(cache)->mm);
406 }
407
408 #endif
409 /* }}} */
410
411 /* {{{ proto resource fastxsl_stylesheet_parsefile(string filename)
412    Parse a stylesheet file located at filename. */
413 PHP_FUNCTION(fastxsl_stylesheet_parsefile)
414 {
415         php_ss_wrapper *wrapper;
416         char           *filename;
417         size_t          filename_len;
418
419         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename,
420                                 &filename_len) == FAILURE) {
421                 return;
422         }
423
424         wrapper = (php_ss_wrapper *) SS_Wrapper_Alloc(0 TSRMLS_CC);
425         wrapper->alloc_type = FASTXSL_PRMALLOC;
426         Xml_UseAllocationFunctions();
427         wrapper->ss = xsltParseStylesheetFile((xmlChar*)filename);
428         if (!wrapper->ss) {
429                 RETURN_FALSE;
430         }
431
432         ZEND_REGISTER_RESOURCE(return_value, wrapper, le_fastxsl_stylesheet);
433 }
434 /* }}} */
435
436 /* {{{ proto resource fastxsl_xml_parsestring(string text)
437   Parse a string containing an XML document and return a resource pointer to the resulting libxml2 tree */
438 PHP_FUNCTION(fastxsl_xml_parsestring)
439 {
440         php_xd_wrapper *wrapper;
441         char           *text;
442         size_t          text_len;
443
444         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
445                 return;
446         }
447
448         wrapper = XD_Wrapper_Alloc();
449         wrapper->alloc_type = FASTXSL_PRMALLOC;
450         Xml_UseAllocationFunctions();
451         wrapper->xd = xmlParseDoc((xmlChar *) text);
452         if (!wrapper->xd) {
453                 _XD_Wrapper_Dtor(wrapper);
454                 RETURN_FALSE;
455         }
456
457         ZEND_REGISTER_RESOURCE(return_value, wrapper, le_fastxsl_document);
458 }
459 /* }}} */
460
461 /* {{{ proto resource fastxsl_xml_parsefile(string filename)
462    Parse an XML file into a FastXSL resource */
463 PHP_FUNCTION(fastxsl_xml_parsefile)
464 {
465         php_xd_wrapper *wrapper;
466         char           *filename;
467         size_t          filename_len;
468
469         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename,
470                                 &filename_len) == FAILURE) {
471                 return;
472         }
473
474         wrapper = XD_Wrapper_Alloc();
475         wrapper->alloc_type = FASTXSL_PRMALLOC;
476         wrapper->xd = xmlParseFile((const char *) filename);
477         if (!wrapper->xd) {
478                 _XD_Wrapper_Dtor(wrapper);
479                 RETURN_FALSE;
480         }
481
482         ZEND_REGISTER_RESOURCE(return_value, wrapper, le_fastxsl_document);
483 }
484 /* }}} */
485
486 static int
487 ParseTransformParameters(zval *z_parameters, char ***parameters TSRMLS_DC)
488 {
489         zval         **current;
490         HashTable     *h_parameters;
491         HashPosition   pos;
492         char          *key;
493         uint           key_length;
494         unsigned long  ival;
495         int            index = 0;
496
497         h_parameters = Z_ARRVAL_P(z_parameters);
498
499         if (zend_hash_num_elements(h_parameters) == 0) {
500                 *parameters = NULL;
501                 return SUCCESS;
502         }
503        
504         *parameters = calloc(1, (zend_hash_num_elements(h_parameters) * (2 * sizeof(char *))) + 1);
505         if (!*parameters) {
506                 php_error(E_WARNING, "Cannot allocate parameters array to pass to FastXSL");
507                 return FAILURE;
508         }
509        
510         for (zend_hash_internal_pointer_reset_ex(h_parameters, &pos);
511              zend_hash_get_current_data_ex(h_parameters, (void **) &current, &pos) == SUCCESS;
512                  zend_hash_move_forward_ex(h_parameters, &pos)) {
513                 if (zend_hash_get_current_key_ex(h_parameters, &key, &key_length,
514                                         &ival, 0, &pos) == HASH_KEY_IS_LONG) {
515                         efree(*parameters);
516                         *parameters = NULL;
517
518                         php_error(E_WARNING,
519                                         "Parameters array passed to %s() may not contain numeric keys",
520                                         get_active_function_name(TSRMLS_C));
521                         return FAILURE;
522                 }
523
524                 convert_to_string_ex(current);
525
526                 (*parameters)[index++] = key;
527                 (*parameters)[index++] = Z_STRVAL_PP(current);
528         }
529         (*parameters)[index] = NULL;
530
531         return SUCCESS;
532 }
533
534 /* {{{ proto resource fastxsl_shmcache_transform(string filename, resource xmldoc[, array parameters])
535    Transform a XML document, "xmldoc", by a XSL stylesheet "filename" with transform "parameters." */
536 #ifdef FASTXSL_MM
537 PHP_FUNCTION(fastxsl_shmcache_transform)
538 {
539         char            **parameters = NULL;
540         php_xd_wrapper   *xd_wrapper;
541         php_xd_wrapper   *result_wrapper;
542         php_ss_wrapper   *ss_wrapper;
543         char             *ss_filename;
544         size_t            ss_filename_len;
545         zval             *z_xd_wrapper;
546         zval             *z_parameters;
547         struct stat       sb;
548         int lockfd;
549        
550         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &ss_filename, &ss_filename_len,
551                                 &z_xd_wrapper, &z_parameters) == FAILURE) {
552                 return;
553         }
554        
555         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
556                         le_fastxsl_document);
557
558         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
559                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
560                         RETURN_FALSE;
561                 }
562         }
563
564         result_wrapper = XD_Wrapper_Alloc();
565         result_wrapper->alloc_type = FASTXSL_PRMALLOC;
566         lockfd = open(ss_filename, O_RDONLY);
567         if(lockfd < 0) {
568                 /* FIXME non-existent file */
569                 RETURN_FALSE;
570         }
571         if (!FASTXSL_G(nostat)) {
572                 if (fstat(lockfd, &sb) == -1) {
573                         ShmCache_UseAllocationFunctions();
574 inshm = 1;
575                         ShmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
576 inshm = 0;
577                         Xml_UseAllocationFunctions();
578                         _XD_Wrapper_Dtor(result_wrapper);
579                         free(parameters);
580                         close(lockfd);
581                         RETURN_FALSE;
582                 }
583         } else {
584                 sb.st_mtime = 0;
585         }
586         flock(lockfd, LOCK_EX);
587         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RW);
588         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->table, ss_filename, ss_filename_len);
589         mm_unlock(FASTXSL_G(cache)->mm);
590         if (!ss_wrapper) {
591                 ShmCache_UseAllocationFunctions();
592 inshm = 1;
593                 ss_wrapper = ShmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime);
594 inshm = 0;
595                 if (!ss_wrapper) {
596                         flock(lockfd, LOCK_UN);
597                         close(lockfd);
598                         //xmlCleanupParserr();
599                         Xml_UseAllocationFunctions();
600                         _XD_Wrapper_Dtor(result_wrapper);
601                         free(parameters);
602                         RETURN_FALSE;
603                 }
604         } else {
605                 if (!FASTXSL_G(nostat)) {
606                         if (ss_wrapper->mtime != sb.st_mtime) {
607                                 //xmlCleanupParserr();
608                                 ShmCache_UseAllocationFunctions();
609 inshm = 1;
610                                 ShmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
611                                 ss_wrapper = ShmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime TSRMLS_CC);
612 inshm = 0;
613                                 //xmlCleanupParserr();
614                                 Xml_UseAllocationFunctions();
615                                 if (!ss_wrapper) {
616                                         flock(lockfd, LOCK_UN);
617                                         close(lockfd);
618                                         _XD_Wrapper_Dtor(result_wrapper);
619                                         free(parameters);
620                                         RETURN_FALSE;
621                                 }
622                         }
623                 }
624         }
625         ss_wrapper->hits++;
626         //xmlCleanupParserr();
627         Xml_UseAllocationFunctions();
628         flock(lockfd, LOCK_UN);
629         close(lockfd);
630         result_wrapper->xd = xsltApplyStylesheet(ss_wrapper->ss, xd_wrapper->xd,
631                         (const char **) parameters);
632
633        
634         if (parameters)
635                 free(parameters);
636        
637         if (!result_wrapper->xd) {
638                 RETURN_FALSE;
639         }       
640        
641         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
642 }
643 #endif
644 /* }}} */
645
646 /* {{{ proto resource fastxsl_prmcache_transform(string filename, resource xmldoc[, array parameters])
647    Transform a XML document, "xmldoc", by a XSL stylesheet "filename" with transform "parameters." */
648 PHP_FUNCTION(fastxsl_prmcache_transform)
649 {
650         char            **parameters = NULL;
651         php_xd_wrapper   *xd_wrapper;
652         php_xd_wrapper   *result_wrapper;
653         php_ss_wrapper   *ss_wrapper;
654         char             *ss_filename;
655         size_t            ss_filename_len;
656         zval             *z_xd_wrapper;
657         zval             *z_parameters;
658         struct stat       sb;
659        
660         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &ss_filename, &ss_filename_len,
661                                 &z_xd_wrapper, &z_parameters) == FAILURE) {
662                 return;
663         }
664         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
665                         le_fastxsl_document);
666
667         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
668                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
669                         RETURN_FALSE;
670                 }
671         }
672
673         result_wrapper = XD_Wrapper_Alloc();
674         result_wrapper->alloc_type = FASTXSL_PRMALLOC;
675
676         if (!FASTXSL_G(nostat)) {
677                 if (stat(ss_filename, &sb) == -1) {
678                         PrmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
679                         _XD_Wrapper_Dtor(result_wrapper);
680                         free(parameters);
681                         RETURN_FALSE;
682                 }
683         } else {
684                 sb.st_mtime = 0;
685         }
686        
687         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->prmtable, ss_filename, ss_filename_len);
688         if (!ss_wrapper) {
689                 ss_wrapper = PrmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime TSRMLS_CC);
690                 if (!ss_wrapper) {
691                         _XD_Wrapper_Dtor(result_wrapper);
692                         free(parameters);
693                         RETURN_FALSE;
694                 }
695         } else {
696                 if (!FASTXSL_G(nostat)) {
697                         if (ss_wrapper->mtime != sb.st_mtime) {
698                                 PrmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
699                                 ss_wrapper = PrmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime TSRMLS_CC);
700                                 if (!ss_wrapper) {
701                                         _XD_Wrapper_Dtor(result_wrapper);
702                                         free(parameters);
703                                         RETURN_FALSE;
704                                 }
705                         }
706                 }
707         }
708         ss_wrapper->hits++;
709         result_wrapper->xd = xsltApplyStylesheet(ss_wrapper->ss, xd_wrapper->xd,
710                         (const char **) parameters);
711         ////xmlCleanupParserr();
712
713         if (parameters)
714                 free(parameters);
715        
716         if (!result_wrapper->xd) {
717                 _XD_Wrapper_Dtor(result_wrapper);
718                 RETURN_FALSE;
719         }       
720        
721         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
722 }
723
724 /* {{{ proto void fastxsl_nocache_transform(resource stylesheet, resource xmldoc[, array parameters])
725    Transform the stylesheet document by the xml document with parameters. */
726 PHP_FUNCTION(fastxsl_nocache_transform)
727 {
728         char           **parameters = NULL;
729         php_xd_wrapper  *xd_wrapper;
730         php_xd_wrapper  *result_wrapper;
731         php_ss_wrapper  *ss_wrapper;
732         zval            *z_xd_wrapper;
733         zval            *z_ss_wrapper;
734         zval            *z_parameters;
735
736         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z", &z_ss_wrapper,
737                                 &z_xd_wrapper, &z_parameters) == FAILURE) {
738                 return;
739         }
740         ZEND_FETCH_RESOURCE(ss_wrapper, php_ss_wrapper *, &z_ss_wrapper, -1, "FastXSL Stylesheet",
741                         le_fastxsl_stylesheet);
742         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
743                         le_fastxsl_document);
744
745         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
746                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
747                         RETURN_FALSE;
748                 }
749         }
750
751         result_wrapper = XD_Wrapper_Alloc();
752         result_wrapper->alloc_type = FASTXSL_PRMALLOC;
753         result_wrapper->xd = xsltApplyStylesheet(ss_wrapper->ss, xd_wrapper->xd,
754                         (const char **) parameters);
755         if (parameters)
756                 free(parameters);
757
758         if (!result_wrapper->xd) {
759                 _XD_Wrapper_Dtor(result_wrapper);
760                 RETURN_FALSE;
761         }       
762
763        
764         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
765 }
766 /* }}} */
767
768 /* {{{ proto void fastxsl_nocache_profile(resource stylesheet, resource xmldoc[, array parameters, string filename])
769    Profile the stylesheet document by the xml document with parameters and output the results to filename (or stderr, if filename doesn't exist). */
770 PHP_FUNCTION(fastxsl_nocache_profile)
771 {
772         char           **parameters = NULL;
773         char            *filename = "php://stderr";
774         php_xd_wrapper  *xd_wrapper;
775         php_xd_wrapper  *result_wrapper;
776         php_ss_wrapper  *ss_wrapper;
777         zval            *z_xd_wrapper;
778         zval            *z_ss_wrapper;
779         zval            *z_parameters;
780         FILE            *dbgprof;
781         int              filename_len;
782
783         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|zs", &z_ss_wrapper,
784                                 &z_xd_wrapper, &z_parameters, &filename, &filename_len) == FAILURE) {
785                 return;
786         }
787         ZEND_FETCH_RESOURCE(ss_wrapper, php_ss_wrapper *, &z_ss_wrapper, -1, "FastXSL Stylesheet",
788                         le_fastxsl_stylesheet);
789         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
790                         le_fastxsl_document);
791
792         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
793                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
794                         RETURN_FALSE;
795                 }
796         }
797
798         if (!strcmp(filename, "php://stdout")) {
799                 dbgprof = stdout;
800         } else if (!strcmp(filename, "php://stderr")) {
801                 dbgprof = stderr;
802         } else {
803                 dbgprof = fopen(filename, "w");
804         }
805
806         result_wrapper = XD_Wrapper_Alloc();
807         result_wrapper->alloc_type = FASTXSL_PRMALLOC;
808
809         result_wrapper->xd = xsltProfileStylesheet(ss_wrapper->ss, xd_wrapper->xd,
810                         (const char **) parameters, dbgprof);
811         if (parameters)
812                 free(parameters);
813
814         fclose(dbgprof);
815        
816         if (!result_wrapper->xd) {
817                 _XD_Wrapper_Dtor(result_wrapper);
818                 RETURN_FALSE;
819         }       
820        
821         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
822 }
823 /* }}} */
824
825 /* {{{ proto string fastxsl_nocache_tostring(resource stylesheet, resource xmldoc)
826    Return the contents of an XML stylesheet result as a string */
827 PHP_FUNCTION(fastxsl_nocache_tostring)
828 {
829         zval           *z_xd_wrapper;
830         zval           *z_ss_wrapper;
831         php_ss_wrapper *ss_wrapper;
832         php_xd_wrapper *xd_wrapper;
833         xmlChar        *result = NULL;
834         int             length;
835
836         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &z_ss_wrapper,
837                                 &z_xd_wrapper) == FAILURE) {
838                 return;
839         }
840         ZEND_FETCH_RESOURCE(ss_wrapper, php_ss_wrapper *, &z_ss_wrapper, -1, "FastXSL XML Stylesheet",
841                         le_fastxsl_stylesheet);
842         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
843                         le_fastxsl_document);
844
845         xsltSaveResultToString(&result, &length, xd_wrapper->xd, ss_wrapper->ss);
846
847         if (result) {
848                 RETVAL_STRINGL((char *) result, length, 1);
849                 xmlFree(result);
850         } else {
851                 RETURN_FALSE;
852         }
853 }
854 /* }}} */
855
856 /* {{{ proto string fastxsl_shmcache_tostring(string filename, resource xmldoc)
857    Return the string representation of xmldoc which is the result of an XSLT transformation on filename */
858 #ifdef FASTXSL_MM
859 PHP_FUNCTION(fastxsl_shmcache_tostring)
860 {
861         zval           *z_xd_wrapper;
862         php_ss_wrapper *ss_wrapper;
863         php_xd_wrapper *xd_wrapper;
864         xmlChar        *result = NULL;
865         char           *ss_filename;
866         size_t          ss_filename_len;
867         int             length;
868
869         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &ss_filename, &ss_filename_len,
870                                 &z_xd_wrapper) == FAILURE) {
871                 return;
872         }
873         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
874                         le_fastxsl_document);
875         Xml_UseAllocationFunctions();
876         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
877         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->table, ss_filename, ss_filename_len);
878         mm_unlock(FASTXSL_G(cache)->mm);
879         if (!ss_wrapper) {
880                 RETURN_FALSE;
881         }
882         ss_wrapper->hits++;
883         xsltSaveResultToString(&result, &length, xd_wrapper->xd, ss_wrapper->ss);
884         if (result) {
885                 RETVAL_STRINGL((char *) result, length, 1);
886                 xmlFree(result);
887         } else {
888                 RETVAL_FALSE;
889         }
890         Xml_UseAllocationFunctions();
891 }
892 #endif
893 /* }}} */
894
895 /* {{{ proto string fastxsl_prmcache_tostring(string filename, resource xmldoc)
896    Return the string representation of xmldoc which is the result of an XSLT transformation on filename */
897 PHP_FUNCTION(fastxsl_prmcache_tostring)
898 {
899         zval           *z_xd_wrapper;
900         php_ss_wrapper *ss_wrapper;
901         php_xd_wrapper *xd_wrapper;
902         xmlChar        *result = NULL;
903         char           *ss_filename;
904         size_t          ss_filename_len;
905         int             length;
906
907         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &ss_filename, &ss_filename_len,
908                                 &z_xd_wrapper) == FAILURE) {
909                 return;
910         }
911         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
912                         le_fastxsl_document);
913
914         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->prmtable, ss_filename, ss_filename_len);
915         if (!ss_wrapper) {
916                 RETURN_FALSE;
917         }
918         ss_wrapper->hits++;
919         xsltSaveResultToString(&result, &length, xd_wrapper->xd, ss_wrapper->ss);
920        
921         if (result) {
922                 RETVAL_STRINGL((char *) result, length, 1);
923                 xmlFree(result);
924         } else {
925                 RETURN_FALSE;
926         }
927 }
928 /* }}} */
929
930 function_entry fastxsl_functions[] = {
931         PHP_FE(fastxsl_stylesheet_parsefile,         NULL)
932         PHP_FE(fastxsl_xml_parsefile,                NULL)
933         PHP_FE(fastxsl_xml_parsestring,              NULL)
934 #ifdef FASTXSL_MM
935         PHP_FE(fastxsl_shmcache_transform,           NULL)
936         PHP_FE(fastxsl_shmcache_tostring,            NULL)
937         PHP_FE(fastxsl_shmcache_getstatistics,       NULL)
938 #endif
939         PHP_FE(fastxsl_prmcache_transform,           NULL)
940         PHP_FE(fastxsl_nocache_transform,            NULL)
941         PHP_FE(fastxsl_nocache_profile,              NULL)
942         PHP_FE(fastxsl_nocache_tostring,             NULL)
943         PHP_FE(fastxsl_prmcache_tostring,            NULL)
944         PHP_FE(fastxsl_prmcache_getstatistics,       NULL)
945         {NULL, NULL, NULL}
946 };
947
948
949 zend_module_entry fastxsl_module_entry = {
950 #if ZEND_MODULE_API_NO >= 20010901
951         STANDARD_MODULE_HEADER,
952 #endif
953         "fastxsl",
954         fastxsl_functions,
955         PHP_MINIT(fastxsl),
956         PHP_MSHUTDOWN(fastxsl),
957         PHP_RINIT(fastxsl),
958         PHP_RSHUTDOWN(fastxsl),
959         PHP_MINFO(fastxsl),
960 #if ZEND_MODULE_API_NO >= 20010901
961         "0.1",
962 #endif
963         STANDARD_MODULE_PROPERTIES
964 };
965
966
967 #ifdef COMPILE_DL_FASTXSL
968 ZEND_GET_MODULE(fastxsl)
969 #endif
970
971 static void
972 _SS_Wrapper_Dtor(php_ss_wrapper *wrapper)
973 {
974         if(wrapper->ss) {
975                 if(wrapper->alloc_type == FASTXSL_SHMALLOC) {
976                         //xmlCleanupParserr();
977                         ShmCache_UseAllocationFunctions();
978                 } else {
979                         Xml_UseAllocationFunctions();
980                 }
981                 inshm = 1;
982                 xsltFreeStylesheet(wrapper->ss);
983                 inshm = 0;
984                 if(wrapper->alloc_type == FASTXSL_SHMALLOC) {
985                         //xmlCleanupParserr();
986                         Xml_UseAllocationFunctions();
987                 }
988         }
989         if(wrapper->persistant) {
990 #ifdef FASTXSL_MM
991                 mm_free(FASTXSL_G(cache)->mm, wrapper);
992 #endif
993         } else {
994                 free(wrapper);
995         }
996 }
997
998 static void
999 SS_Wrapper_Dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1000 {
1001         php_ss_wrapper *wrapper = (php_ss_wrapper *) rsrc->ptr;
1002         if (wrapper->persistant) {
1003                 return;
1004         }
1005         _SS_Wrapper_Dtor(wrapper);
1006 }
1007
1008 static void _XD_Wrapper_Dtor(php_xd_wrapper *wrapper) {
1009         if (wrapper->xd) {
1010                 if(wrapper->alloc_type == FASTXSL_SHMALLOC) {
1011                         ShmCache_UseAllocationFunctions();
1012                 } else {
1013                         Xml_UseAllocationFunctions();
1014                 }
1015 inshm = 1;
1016                 xmlFreeDoc(wrapper->xd);
1017 inshm = 0;
1018                 Xml_UseAllocationFunctions();
1019         }
1020         free(wrapper);
1021 }
1022
1023 static void
1024 XD_Wrapper_Dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
1025 {
1026         php_xd_wrapper *wrapper = (php_xd_wrapper *) rsrc->ptr;
1027         _XD_Wrapper_Dtor(wrapper);
1028 }
1029
1030 void fastxsl_errorfunc(void *ctx, const char *msg, ...)
1031 {
1032         char *frag;
1033         int fraglen;
1034         int output = 0;
1035         va_list args;
1036         TSRMLS_FETCH();
1037
1038         va_start(args, msg);
1039         fraglen = vspprintf(&frag, 0, msg, args);
1040         while(fraglen && frag[fraglen - 1] == '\n') {
1041                 frag[--fraglen] = '\0';
1042                 output = 1;
1043         }
1044         if(fraglen) {
1045                 if(FASTXSL_G(errbuf)) {
1046                         FASTXSL_G(errbuf) = erealloc(FASTXSL_G(errbuf), fraglen + strlen(FASTXSL_G(errbuf)));
1047                         strcat(FASTXSL_G(errbuf), frag);
1048                 } else {
1049                         FASTXSL_G(errbuf) = frag;
1050                 }
1051         }
1052         va_end(args);
1053         if(output) {
1054                 php_error_docref(NULL TSRMLS_CC, E_WARNING, FASTXSL_G(errbuf));
1055                 efree(FASTXSL_G(errbuf));
1056                 FASTXSL_G(errbuf) = NULL;
1057         }
1058 }
1059
1060 static int
1061 Stream_MatchWrapper(const char *filename)
1062 {
1063         TSRMLS_FETCH();
1064         return php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ? 1 : 0;
1065 }
1066
1067 static void *
1068 Stream_XmlWrite_OpenWrapper(const char *filename)
1069 {
1070         TSRMLS_FETCH();
1071         return php_stream_open_wrapper((char *) filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
1072 }
1073
1074 static int
1075 Stream_XmlWrite_WriteWrapper(void *context, const char *buffer, int length)
1076 {
1077         TSRMLS_FETCH();
1078         return php_stream_write((php_stream *) context, (char *) buffer, length);
1079 }
1080
1081 static int
1082 Stream_CloseWrapper(void *context)
1083 {
1084         TSRMLS_FETCH();
1085         return php_stream_close((php_stream *) context);
1086 }
1087
1088
1089 extern int xmlLoadExtDtdDefaultValue;
1090
1091 /**
1092  * Allocators for the fl_hash storage
1093  */
1094 #ifdef FASTXSL_MM
1095 static FL_Allocator mm_allocators = {ShmCache_Free, ShmCache_Malloc, ShmCache_Calloc};
1096 #endif
1097 static FL_Allocator normal_allocators = {free, malloc, calloc};
1098
1099 static void
1100 php_fastxsl_init_globals(zend_fastxsl_globals *globals)
1101 {
1102         memset(globals, 0, sizeof(zend_fastxsl_globals));
1103        
1104         globals->cache = calloc(1, sizeof(fl_cache));
1105 }
1106
1107
1108 static void
1109 php_fastxsl_destroy_globals(zend_fastxsl_globals *globals)
1110 {
1111         fl_cache *cache;
1112        
1113         cache = globals->cache;
1114         if (cache) {
1115                 if (cache->owner != getpid()) {
1116                         return;
1117                 }
1118                 fl_hash_free(cache->prmtable);
1119         }
1120 }
1121
1122 /* {{{ php function -> xslt exporting
1123  */
1124  
1125 static void fastxsl_ext_function(xmlXPathParserContextPtr ctxt, int nargs)
1126 {
1127         xsltTransformContextPtr tctxt;
1128         zval **params;
1129         zval *param;
1130         zval *function = NULL;
1131         zval *ret = NULL;
1132         xmlChar *fname;
1133         int param_count = nargs - 1;
1134         int i;
1135         TSRMLS_FETCH();
1136        
1137         tctxt = (xsltTransformContextPtr) xsltXPathGetTransformContext(ctxt);
1138         ////xmlCleanupParserr();
1139         if (tctxt == NULL) {
1140                 xsltGenericError(xsltGenericErrorContext,
1141                 "fastxsl extension functions: failed to get the transformation context\n");
1142                 return;
1143         }
1144         /* allocate for args.  first position is function name */
1145         params = emalloc(sizeof(zval *) * param_count);
1146         for(i = param_count - 1; i >=0; i--) {
1147                 xmlXPathObjectPtr obj;
1148                 xmlChar *tmp;
1149                 obj = valuePop(ctxt);
1150                 MAKE_STD_ZVAL(param);
1151                 switch(obj->type) {
1152                         case XPATH_UNDEFINED:
1153                                 ZVAL_NULL(param);
1154                                 break;
1155                         case XPATH_NODESET:
1156                                 tmp = xmlXPathCastToString(obj);
1157                                 ZVAL_STRING(param, (char *) tmp, 1);
1158                                 xmlFree(tmp);
1159                                 break;
1160                         case XPATH_BOOLEAN:
1161                                 ZVAL_BOOL(param, obj->boolval);
1162                                 break;
1163                         case XPATH_NUMBER:
1164                                 ZVAL_DOUBLE(param, obj->floatval);
1165                                 break;
1166                         case XPATH_STRING:
1167                                 ZVAL_STRING(param, (char *)obj->stringval, 1);
1168                                 break;
1169                         default:
1170                                 zend_error(E_WARNING, "inexact type conversion %d", obj->type);
1171                                 tmp = xmlXPathCastToString(obj);
1172                                 ZVAL_STRING(param, (char *)tmp, 1);
1173                                 xmlFree(tmp);
1174                                 break;
1175                 }
1176                 params[i] = param;
1177                 xmlXPathFreeObject(obj);
1178         }
1179         fname = xmlXPathPopString(ctxt);
1180         if(!fname) {
1181                 xsltGenericError(xsltGenericDebugContext,
1182                         "passed function name is not a string");
1183                 xmlXPathReturnEmptyString(ctxt);
1184                 goto cleanup;
1185         }
1186         MAKE_STD_ZVAL(function);
1187         ZVAL_STRING(function, (char *)fname, 1);
1188         xmlFree(fname);
1189         MAKE_STD_ZVAL(ret);
1190         ZVAL_FALSE(ret);
1191         if(call_user_function(EG(function_table), NULL, function, ret,
1192                                  param_count, params TSRMLS_CC) == FAILURE) {
1193                         xsltGenericError(xsltGenericDebugContext,
1194                                 "function evaluation error");
1195                 xmlXPathReturnEmptyString(ctxt);
1196                 goto cleanup;
1197         }
1198         switch(ret->type) {
1199                 case IS_BOOL:
1200                         xmlXPathReturnBoolean(ctxt, Z_BVAL_P(ret));
1201                         break;
1202                 case IS_LONG:
1203                         xmlXPathReturnNumber(ctxt, (float) Z_LVAL_P(ret));
1204                         break;
1205                 case IS_DOUBLE:
1206                         xmlXPathReturnNumber(ctxt, Z_DVAL_P(ret));
1207                         break;
1208                 case IS_STRING:
1209                         xmlXPathReturnString(ctxt, xmlStrdup((xmlChar *) Z_STRVAL_P(ret)));
1210                         break;
1211                 default:
1212                         convert_to_string_ex(&ret);
1213                         xmlXPathReturnString(ctxt, xmlStrdup((xmlChar *) Z_STRVAL_P(ret)));
1214                         break;
1215         }
1216 cleanup:
1217         if(params) {
1218                 for(i=0; i < param_count; i++) {
1219                         zval_ptr_dtor(&params[i]);
1220                 }
1221                 efree(params); params = NULL;
1222         }
1223         if(function) {
1224                 efree(function); function = NULL;
1225         }
1226         if(ret) {
1227                 efree(ret); ret = NULL;
1228         }
1229         return;
1230 }               
1231 /* }}} */
1232
1233
1234 PHP_INI_BEGIN()
1235         STD_PHP_INI_ENTRY("fastxsl.shmpath", "/tmp/fastxsl_mem", PHP_INI_SYSTEM, OnUpdateString, shmpath, zend_fastxsl_globals, fastxsl_globals)
1236         STD_PHP_INI_BOOLEAN("fastxsl.nostat", "0", PHP_INI_ALL, OnUpdateLong, nostat, zend_fastxsl_globals, fastxsl_globals)
1237         STD_PHP_INI_BOOLEAN("fastxsl.memalloc", "0", PHP_INI_SYSTEM, OnUpdateLong, memalloc, zend_fastxsl_globals, fastxsl_globals)
1238         STD_PHP_INI_BOOLEAN("fastxsl.register_functions", "0", PHP_INI_ALL, OnUpdateLong, register_functions, zend_fastxsl_globals, fastxsl_globals)
1239 PHP_INI_END()
1240
1241 PHP_MINIT_FUNCTION(fastxsl)
1242 {
1243         char   *shmpath;
1244         size_t  shmpath_len;
1245         char    euid[30];
1246
1247         ZEND_INIT_MODULE_GLOBALS(fastxsl, php_fastxsl_init_globals, php_fastxsl_destroy_globals);
1248        
1249         REGISTER_INI_ENTRIES();
1250        
1251         le_fastxsl_stylesheet = zend_register_list_destructors_ex(SS_Wrapper_Dtor, NULL,
1252         le_fastxsl_stylesheet_name, module_number);
1253         le_fastxsl_document   = zend_register_list_destructors_ex(XD_Wrapper_Dtor, NULL,
1254                         le_fastxsl_document_name,   module_number);
1255 #ifdef FASTXSL_MM
1256         if (!sprintf(euid, "%d", geteuid())) {
1257                 return FAILURE;
1258         }
1259
1260         shmpath_len = strlen(FASTXSL_G(shmpath)) + strlen(euid);
1261         shmpath = do_alloca(shmpath_len + 1);
1262
1263         strcpy(shmpath, FASTXSL_G(shmpath));
1264         strcat(shmpath, euid);
1265        
1266         FASTXSL_G(cache)->owner = getpid();
1267         FASTXSL_G(cache)->mm = mm_create(FASTXSL_G(memalloc), shmpath);
1268         free_alloca(shmpath);
1269         if (!FASTXSL_G(cache)->mm) {
1270                 return FAILURE;
1271         }
1272
1273         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RW);
1274         FASTXSL_G(cache)->table = fl_hash_new(&mm_allocators, NULL);
1275         mm_unlock(FASTXSL_G(cache)->mm);
1276 #endif
1277         FASTXSL_G(cache)->prmtable = fl_hash_new(&normal_allocators, NULL);
1278         //xmlGcMemGet(&free_ptr, &malloc_ptr, &mallocatomic_ptr, &realloc_ptr, &strdup_ptr);
1279         xmlMemGet(&free_ptr, &malloc_ptr, &realloc_ptr, &strdup_ptr);
1280         //xmlCleanupParserr();
1281         ShmCache_UseAllocationFunctions();
1282 inshm = 1;
1283         xsltRegisterAllExtras();
1284 #if HAVE_DOMEXSLT
1285         exsltRegisterAll();
1286 #endif
1287         xmlSubstituteEntitiesDefault(1);
1288         xmlLoadExtDtdDefaultValue = 1;
1289
1290         xmlRegisterOutputCallbacks(Stream_MatchWrapper, Stream_XmlWrite_OpenWrapper,
1291                                            Stream_XmlWrite_WriteWrapper, Stream_CloseWrapper);
1292         xsltSetGenericErrorFunc(NULL, fastxsl_errorfunc);
1293         xmlSetGenericErrorFunc(NULL, fastxsl_errorfunc);
1294        
1295         if(FASTXSL_G(register_functions)) {
1296                 xsltRegisterExtModuleFunction ((const xmlChar *) "function",
1297                                            (const xmlChar *) "http://php.net/fastxsl",
1298                                            fastxsl_ext_function);
1299         }
1300         //xmlCleanupParserr();
1301 inshm = 0;
1302         Xml_UseAllocationFunctions();
1303         return SUCCESS;
1304 }
1305
1306 PHP_MSHUTDOWN_FUNCTION(fastxsl)
1307 {
1308   UNREGISTER_INI_ENTRIES();
1309 }
1310 PHP_RINIT_FUNCTION(fastxsl)
1311 {
1312 #ifdef FASTXSL_MM
1313   /* just in case, set back the allocators */
1314   Xml_UseAllocationFunctions();
1315 #endif
1316 }
1317 PHP_RSHUTDOWN_FUNCTION(fastxsl)
1318 {
1319 #ifdef FASTXSL_MM
1320   /* just in case, set back the allocators */
1321   Xml_UseAllocationFunctions();
1322 #endif
1323 }
1324
1325 PHP_MINFO_FUNCTION(fastxsl)
1326 {
1327         php_info_print_table_start();
1328         php_info_print_table_header(2, "fastxsl support", "enabled");
1329         php_info_print_table_row(2, "libxml Version", LIBXML_DOTTED_VERSION);
1330         php_info_print_table_row(2, "libxslt Version", LIBXSLT_DOTTED_VERSION);
1331 #if HAVE_DOMEXSLT
1332         php_info_print_table_row(2, "libexslt Version", LIBEXSLT_DOTTED_VERSION);
1333 #endif
1334         php_info_print_table_end();
1335 }
Note: See TracBrowser for help on using the browser.