root/trunk/fastxsl.c

Revision 5, 26.6 kB (checked in by shughes, 10 years ago)

check shared and properly do allocation

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   +----------------------------------------------------------------------+
17
18   $Id: fastxsl.c,v 1.1.1.1 2004/02/17 23:31:44 sterling Exp $
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <libxml/xmlmemory.h>
26 #include <libxml/debugXML.h>
27 #include <libxml/HTMLtree.h>
28 #include <libxml/xmlIO.h>
29 #include <libxml/xinclude.h>
30 #include <libxml/catalog.h>
31 #include <libxslt/xslt.h>
32 #include <libxslt/xsltInternals.h>
33 #include <libxslt/transform.h>
34 #include <libxslt/xsltutils.h>
35
36 #include <mm.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39
40 #include "fl_hash.h"
41 #include "php.h"
42 #include "php_ini.h"
43 #include "ext/standard/info.h"
44 #include "php_fastxsl.h"
45
46 ZEND_DECLARE_MODULE_GLOBALS(fastxsl);
47
48 static int le_fastxsl_stylesheet;
49 #define le_fastxsl_stylesheet_name "FastXSL Stylesheet"
50 static int le_fastxsl_document;
51 #define le_fastxsl_document_name "FastXSL Document"
52
53 #define FASTXSL_PRM_ALLOC 1
54 #define FASTXSL_SHARED_ALLOC 2
55
56 static php_ss_wrapper *
57 SS_Wrapper_Alloc(int shared TSRMLS_DC)
58 {
59         php_ss_wrapper *wrapper;
60
61         if (shared) {
62                 if (shared == FASTXSL_SHARED_ALLOC) {
63                         wrapper = (php_ss_wrapper *) mm_calloc(FASTXSL_G(cache)->mm, 1, sizeof(php_ss_wrapper));
64                 } else {
65                         wrapper = (php_ss_wrapper *) calloc(1, sizeof(php_ss_wrapper));
66                 }
67                 wrapper->persistant = 1;
68         } else {
69                 wrapper = (php_ss_wrapper *) calloc(1, sizeof(php_ss_wrapper));
70         }
71
72         return wrapper;
73 }
74
75 static php_xd_wrapper *
76 XD_Wrapper_Alloc(void)
77 {
78         php_xd_wrapper *wrapper;
79
80         wrapper = (php_xd_wrapper *) calloc(1, sizeof(php_xd_wrapper));
81         return wrapper;
82 }
83
84 static xmlFreeFunc    free_ptr;
85 static xmlMallocFunc  malloc_ptr;
86 static xmlReallocFunc realloc_ptr;
87 static xmlStrdupFunc  strdup_ptr;
88
89 static void
90 ShmCache_Free(void *ptr)
91 {
92         TSRMLS_FETCH();
93         FASTXSL_G(tmp_allocated_size) -= mm_sizeof(FASTXSL_G(cache)->mm, ptr);
94        
95         mm_free(FASTXSL_G(cache)->mm, ptr);
96 }
97
98 static void *
99 ShmCache_Malloc(size_t size)
100 {
101         void *ptr;
102         TSRMLS_FETCH();
103
104         ptr = mm_malloc(FASTXSL_G(cache)->mm, size);
105         if (!ptr) {
106                 php_error(E_ERROR, "Ran out of Shared memory to allocate data for FastXSL cache, "
107                                            "in function %s() cannot allocate %d bytes (%d available, %d allocated)",
108                                                    get_active_function_name(TSRMLS_C), size, mm_available(FASTXSL_G(cache)->mm),
109                                                    mm_maxsize() - mm_available(FASTXSL_G(cache)->mm));
110                 return NULL;
111         }
112
113         FASTXSL_G(tmp_allocated_size) += size;
114
115         return ptr;
116 }
117
118 static void *
119 ShmCache_Calloc(size_t nmemb, size_t size)
120 {
121         void *ptr;
122
123         ptr = ShmCache_Malloc(nmemb * size);
124         memset(ptr, 0, nmemb * size);
125
126         return ptr;
127 }
128
129 static void *
130 ShmCache_Realloc(void *ptr, size_t size)
131 {
132         void *newptr;
133         long  oldsize;
134         TSRMLS_FETCH();
135
136         oldsize = mm_sizeof(FASTXSL_G(cache)->mm, ptr);
137         newptr = mm_realloc(FASTXSL_G(cache)->mm, ptr, size);
138         if (!newptr) {
139                 TSRMLS_FETCH();
140                 php_error(E_ERROR, "Ran out of Shared memory to allocate data for FastXSL cache, "
141                                            "in function %s() cannot allocate %d bytes (%d available, %d allocated)",
142                                                    get_active_function_name(TSRMLS_C), size, mm_available(FASTXSL_G(cache)->mm),
143                                                    mm_maxsize() - mm_available(FASTXSL_G(cache)->mm));
144                 return NULL;
145         }
146         FASTXSL_G(tmp_allocated_size) += (size - oldsize);
147
148         return newptr;
149 }
150
151 static char *
152 ShmCache_Strdup(const char *string)
153 {
154         char *newstring;
155         int   string_length;
156
157         string_length = strlen(string);
158         newstring = ShmCache_Malloc(string_length);
159         memcpy(newstring, string, string_length);
160         newstring[string_length] = 0;
161
162         return newstring;
163 }
164
165 static void
166 Php_Free(void *ptr)
167 {
168         efree(ptr);
169 }
170
171 static void *
172 Php_Malloc(size_t size)
173 {
174         return emalloc(size);
175 }
176
177 static void *
178 Php_Realloc(void *ptr, size_t size)
179 {
180         return erealloc(ptr, size);
181 }
182
183 static char *
184 Php_Strdup(const char *string)
185 {
186         return estrdup(string);
187 }
188
189 static void
190 ShmCache_UseAllocationFunctions(void)
191 {
192         xmlMemSetup(ShmCache_Free, ShmCache_Malloc, ShmCache_Realloc, ShmCache_Strdup);
193 }
194
195 static void
196 Php_UseAllocationFunctions(void)
197 {
198         xmlMemSetup(Php_Free, Php_Malloc, Php_Realloc, Php_Strdup);
199 }
200
201 static void
202 Xml_UseAllocationFunctions(void)
203 {
204         xmlMemSetup(free_ptr, malloc_ptr, realloc_ptr, strdup_ptr);
205 }
206
207 static php_ss_wrapper *
208 ShmCache_Stylesheet_ParseAndStore(char *filename, size_t filename_len, int mtime TSRMLS_DC)
209 {
210         php_ss_wrapper *wrapper;
211        
212         wrapper = SS_Wrapper_Alloc(FASTXSL_SHARED_ALLOC TSRMLS_CC);
213
214         ShmCache_UseAllocationFunctions();
215         FASTXSL_G(tmp_allocated_size) = 0;
216         wrapper->ss = xsltParseStylesheetFile(filename);
217         if (!wrapper->ss) {
218                 Xml_UseAllocationFunctions();
219                 return NULL;
220         }
221         Xml_UseAllocationFunctions();
222         wrapper->mtime = mtime;
223         wrapper->allocsize = FASTXSL_G(tmp_allocated_size);
224        
225         fl_hash_add(FASTXSL_G(cache)->table, filename, filename_len, wrapper);
226
227         return wrapper;
228 }
229
230 static void
231 ShmCache_Stylesheet_Free(php_ss_wrapper *wrapper TSRMLS_DC)
232 {
233         if (wrapper->ss) {
234                 ShmCache_UseAllocationFunctions();
235                 xsltFreeStylesheet(wrapper->ss);
236                 Xml_UseAllocationFunctions();
237         }
238         mm_free(FASTXSL_G(cache)->mm, wrapper);
239 }
240
241 static void
242 ShmCache_Stylesheet_Delete(char *filename, size_t filename_len)
243 {
244         php_ss_wrapper *wrapper;
245
246         wrapper = fl_hash_find(FASTXSL_G(cache)->table, filename, filename_len);
247         if (wrapper) {
248                 fl_hash_delete(FASTXSL_G(cache)->table, filename, filename_len);
249                 ShmCache_Stylesheet_Free(wrapper);
250         }
251 }
252
253 static php_ss_wrapper *
254 PrmCache_Stylesheet_ParseAndStore(char *filename, size_t filename_len, int mtime)
255 {
256         php_ss_wrapper *wrapper;
257
258         wrapper = SS_Wrapper_Alloc(FASTXSL_PRM_ALLOC TSRMLS_CC);
259
260         wrapper->ss = xsltParseStylesheetFile(filename);
261         if (!wrapper->ss) {
262                 return NULL;
263         }
264         wrapper->mtime = mtime;
265        
266         fl_hash_add(FASTXSL_G(cache)->prmtable, filename, filename_len, wrapper);
267
268         return wrapper;
269 }
270
271 static void
272 PrmCache_Stylesheet_Free(php_ss_wrapper *wrapper)
273 {
274         if (wrapper->ss) {
275                 xsltFreeStylesheet(wrapper->ss);
276         }
277         free(wrapper);
278 }
279
280 static void
281 PrmCache_Stylesheet_Delete(char *filename, size_t filename_len TSRMLS_DC)
282 {
283         php_ss_wrapper *wrapper;
284
285         wrapper = fl_hash_find(FASTXSL_G(cache)->prmtable, filename, filename_len);
286         if (wrapper) {
287                 fl_hash_delete(FASTXSL_G(cache)->prmtable, filename, filename_len);
288                 PrmCache_Stylesheet_Free(wrapper TSRMLS_CC);
289         }
290 }
291
292 /* {{{ proto array fastxsl_prmcache_getstatistics(void)
293    Get an array of statistics regarding the fastxsl documents in the process resident memory cache */
294 PHP_FUNCTION(fastxsl_prmcache_getstatistics)
295 {
296         php_ss_wrapper *wrapper;       
297
298         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
299                 return;
300         }
301
302 }
303 /* }}} */
304
305 /* {{{ proto array fastxsl_shmcache_getstatistics(void)
306    Get an array of statistics regarding the documents in the shared memory cache */
307 PHP_FUNCTION(fastxsl_shmcache_getstatistics)
308 {
309         php_ss_wrapper *ss_wrapper;
310         FL_Bucket      *bucket;
311         zval           *files_array;
312         zval           *info_array;
313         int             i;
314         long            allocated_bytes = 0;
315        
316         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) {
317                 return;
318         }
319
320         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
321        
322         array_init(return_value);
323
324         MAKE_STD_ZVAL(files_array);
325         array_init(files_array);
326
327         for (i = 0; i < FL_HASH_SIZE; i++) {
328                 for (bucket = FASTXSL_G(cache)->table->buckets[i]; bucket != NULL; bucket = bucket->next) {
329                         ss_wrapper = (php_ss_wrapper *) bucket->data;
330
331                         MAKE_STD_ZVAL(info_array);
332                         array_init(info_array);
333
334                         add_assoc_long(info_array, "allocated", ss_wrapper->allocsize);
335                         add_assoc_long(info_array, "mtime", ss_wrapper->mtime);
336
337                         add_assoc_zval(files_array, bucket->key, info_array);
338
339                         allocated_bytes += ss_wrapper->allocsize;
340                 }
341         }
342         add_assoc_zval(return_value, "files", files_array);
343
344         add_assoc_long(return_value, "shm_allocated", allocated_bytes);
345         add_assoc_long(return_value, "shm_maxsize", (long) mm_maxsize());
346
347         mm_unlock(FASTXSL_G(cache)->mm);
348 }
349 /* }}} */
350
351 /* {{{ proto resource fastxsl_stylesheet_parsefile(string filename)
352    Parse a stylesheet file located at filename. */
353 PHP_FUNCTION(fastxsl_stylesheet_parsefile)
354 {
355         php_ss_wrapper *wrapper;
356         char           *filename;
357         size_t          filename_len;
358
359         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename,
360                                 &filename_len) == FAILURE) {
361                 return;
362         }
363
364         wrapper = SS_Wrapper_Alloc(0 TSRMLS_CC);
365         wrapper->ss = xsltParseStylesheetFile((const xmlChar *) filename);
366         if (!wrapper->ss) {
367                 RETURN_FALSE;
368         }
369
370         ZEND_REGISTER_RESOURCE(return_value, wrapper, le_fastxsl_stylesheet);
371 }
372 /* }}} */
373
374 /* {{{ proto resource fastxsl_xml_parsestring(string text)
375   Parse a string containing an XML document and return a resource pointer to the resulting libxml2 tree */
376 PHP_FUNCTION(fastxsl_xml_parsestring)
377 {
378         php_xd_wrapper *wrapper;
379         char           *text;
380         size_t          text_len;
381
382         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
383                 return;
384         }
385
386         wrapper = XD_Wrapper_Alloc();
387         wrapper->xd = xmlParseDoc(text);
388         if (!wrapper->xd) {
389                 RETURN_FALSE;
390         }
391
392         ZEND_REGISTER_RESOURCE(return_value, wrapper, le_fastxsl_document);
393 }
394 /* }}} */
395
396 /* {{{ proto resource fastxsl_xml_parsefile(string filename)
397    Parse an XML file into a FastXSL resource */
398 PHP_FUNCTION(fastxsl_xml_parsefile)
399 {
400         php_xd_wrapper *wrapper;
401         char           *filename;
402         size_t          filename_len;
403
404         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename,
405                                 &filename_len) == FAILURE) {
406                 return;
407         }
408
409         wrapper = XD_Wrapper_Alloc();
410         wrapper->xd = xmlParseFile((const xmlChar *) filename);
411         if (!wrapper->xd) {
412                 RETURN_FALSE;
413         }
414
415         ZEND_REGISTER_RESOURCE(return_value, wrapper, le_fastxsl_document);
416 }
417 /* }}} */
418
419 static int
420 ParseTransformParameters(zval *z_parameters, char ***parameters TSRMLS_DC)
421 {
422         zval         **current;
423         HashTable     *h_parameters;
424         HashPosition   pos;
425         char          *key;
426         int            key_length;
427         unsigned long  ival;
428         int            index = 0;
429
430         h_parameters = Z_ARRVAL_P(z_parameters);
431
432         if (zend_hash_num_elements(h_parameters) == 0) {
433                 *parameters = NULL;
434                 return SUCCESS;
435         }
436        
437         *parameters = calloc(1, (zend_hash_num_elements(h_parameters) * (2 * sizeof(char *))) + 1);
438         if (!*parameters) {
439                 php_error(E_WARNING, "Cannot allocate parameters array to pass to FastXSL");
440                 return FAILURE;
441         }
442        
443         for (zend_hash_internal_pointer_reset_ex(h_parameters, &pos);
444              zend_hash_get_current_data_ex(h_parameters, (void **) &current, &pos) == SUCCESS;
445                  zend_hash_move_forward_ex(h_parameters, &pos)) {
446                 if (zend_hash_get_current_key_ex(h_parameters, &key, &key_length,
447                                         &ival, 0, &pos) == HASH_KEY_IS_LONG) {
448                         efree(*parameters);
449                         *parameters = NULL;
450
451                         php_error(E_WARNING,
452                                         "Parameters array passed to %s() may not contain numeric keys",
453                                         get_active_function_name(TSRMLS_C));
454                         return FAILURE;
455                 }
456
457                 convert_to_string_ex(current);
458
459                 (*parameters)[index++] = key;
460                 (*parameters)[index++] = Z_STRVAL_PP(current);
461         }
462         (*parameters)[index] = NULL;
463
464         return SUCCESS;
465 }
466
467 /* {{{ proto resource fastxsl_shmcache_transform(string filename, resource xmldoc[, array parameters])
468    Transform a XML document, "xmldoc", by a XSL stylesheet "filename" with transform "parameters." */
469 PHP_FUNCTION(fastxsl_shmcache_transform)
470 {
471         char            **parameters = NULL;
472         php_xd_wrapper   *xd_wrapper;
473         php_xd_wrapper   *result_wrapper;
474         php_ss_wrapper   *ss_wrapper;
475         char             *ss_filename;
476         size_t            ss_filename_len;
477         zval             *z_xd_wrapper;
478         zval             *z_parameters;
479         struct stat       sb;
480        
481         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &ss_filename, &ss_filename_len,
482                                 &z_xd_wrapper, &z_parameters) == FAILURE) {
483                 return;
484         }
485        
486         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
487                         le_fastxsl_document);
488
489         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
490                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
491                         RETURN_FALSE;
492                 }
493         }
494
495         result_wrapper = XD_Wrapper_Alloc();
496
497         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RW);
498         if (!FASTXSL_G(nostat)) {
499                 if (stat(ss_filename, &sb) == -1) {
500                         ShmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
501                         mm_unlock(FASTXSL_G(cache)->mm);
502                         free(parameters);
503                         RETURN_FALSE;
504                 }
505         } else {
506                 sb.st_mtime = 0;
507         }
508        
509         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->table, ss_filename, ss_filename_len);
510         if (!ss_wrapper) {
511                 ss_wrapper = ShmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime);
512                 if (!ss_wrapper) {
513                         mm_unlock(FASTXSL_G(cache)->mm);
514                         free(parameters);
515                         RETURN_FALSE;
516                 }
517         } else {
518                 if (!FASTXSL_G(nostat)) {
519                         if (ss_wrapper->mtime != sb.st_mtime) {
520                                 ShmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
521                                 ss_wrapper = ShmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime TSRMLS_CC);
522                                 if (!ss_wrapper) {
523                                         mm_unlock(FASTXSL_G(cache)->mm);
524                                         free(parameters);
525                                         RETURN_FALSE;
526                                 }
527                         }
528                 }
529         }
530
531         result_wrapper->xd = xsltApplyStylesheet(ss_wrapper->ss, xd_wrapper->xd,
532                         (const char **) parameters);
533
534         mm_unlock(FASTXSL_G(cache)->mm);
535        
536         if (parameters)
537                 free(parameters);
538        
539         if (!result_wrapper->xd) {
540                 RETURN_FALSE;
541         }       
542        
543         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
544 }
545 /* }}} */
546
547 /* {{{ proto resource fastxsl_prmcache_transform(string filename, resource xmldoc[, array parameters])
548    Transform a XML document, "xmldoc", by a XSL stylesheet "filename" with transform "parameters." */
549 PHP_FUNCTION(fastxsl_prmcache_transform)
550 {
551         char            **parameters = NULL;
552         php_xd_wrapper   *xd_wrapper;
553         php_xd_wrapper   *result_wrapper;
554         php_ss_wrapper   *ss_wrapper;
555         char             *ss_filename;
556         size_t            ss_filename_len;
557         zval             *z_xd_wrapper;
558         zval             *z_parameters;
559         struct stat       sb;
560        
561         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|z", &ss_filename, &ss_filename_len,
562                                 &z_xd_wrapper, &z_parameters) == FAILURE) {
563                 return;
564         }
565         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
566                         le_fastxsl_document);
567
568         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
569                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
570                         RETURN_FALSE;
571                 }
572         }
573
574         result_wrapper = XD_Wrapper_Alloc();
575
576         if (!FASTXSL_G(nostat)) {
577                 if (stat(ss_filename, &sb) == -1) {
578                         PrmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
579                         free(parameters);
580                         RETURN_FALSE;
581                 }
582         } else {
583                 sb.st_mtime = 0;
584         }
585        
586         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->prmtable, ss_filename, ss_filename_len);
587         if (!ss_wrapper) {
588                 ss_wrapper = PrmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime TSRMLS_CC);
589                 if (!ss_wrapper) {
590                         free(parameters);
591                         RETURN_FALSE;
592                 }
593         } else {
594                 if (!FASTXSL_G(nostat)) {
595                         if (ss_wrapper->mtime != sb.st_mtime) {
596                                 PrmCache_Stylesheet_Delete(ss_filename, ss_filename_len TSRMLS_CC);
597                                 ss_wrapper = PrmCache_Stylesheet_ParseAndStore(ss_filename, ss_filename_len, sb.st_mtime TSRMLS_CC);
598                                 if (!ss_wrapper) {
599                                         free(parameters);
600                                         RETURN_FALSE;
601                                 }
602                         }
603                 }
604         }
605
606         result_wrapper->xd = xsltApplyStylesheet(ss_wrapper->ss, xd_wrapper->xd,
607                         (const char **) parameters);
608
609         if (parameters)
610                 free(parameters);
611        
612         if (!result_wrapper->xd) {
613                 RETURN_FALSE;
614         }       
615        
616         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
617 }
618
619 /* {{{ proto void fastxsl_nocache_transform(resource stylesheet, resource xmldoc[, array parameters])
620    Transform the stylesheet document by the xml document with parameters. */
621 PHP_FUNCTION(fastxsl_nocache_transform)
622 {
623         char           **parameters = NULL;
624         php_xd_wrapper  *xd_wrapper;
625         php_xd_wrapper  *result_wrapper;
626         php_ss_wrapper  *ss_wrapper;
627         zval            *z_xd_wrapper;
628         zval            *z_ss_wrapper;
629         zval            *z_parameters;
630
631         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|z", &z_ss_wrapper,
632                                 &z_xd_wrapper, &z_parameters) == FAILURE) {
633                 return;
634         }
635         ZEND_FETCH_RESOURCE(ss_wrapper, php_ss_wrapper *, &z_ss_wrapper, -1, "FastXSL Stylesheet",
636                         le_fastxsl_stylesheet);
637         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
638                         le_fastxsl_document);
639
640         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
641                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
642                         RETURN_FALSE;
643                 }
644         }
645
646         result_wrapper = XD_Wrapper_Alloc();
647        
648         result_wrapper->xd = xsltApplyStylesheet(ss_wrapper->ss, xd_wrapper->xd,
649                         (const char **) parameters);
650         if (parameters)
651                 free(parameters);
652
653         if (!result_wrapper->xd) {
654                 RETURN_FALSE;
655         }       
656
657        
658         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
659 }
660 /* }}} */
661
662 /* {{{ proto void fastxsl_nocache_profile(resource stylesheet, resource xmldoc[, array parameters, string filename])
663    Profile the stylesheet document by the xml document with parameters and output the results to filename (or stderr, if filename doesn't exist). */
664 PHP_FUNCTION(fastxsl_nocache_profile)
665 {
666         char           **parameters = NULL;
667         char            *filename = "php://stderr";
668         php_xd_wrapper  *xd_wrapper;
669         php_xd_wrapper  *result_wrapper;
670         php_ss_wrapper  *ss_wrapper;
671         zval            *z_xd_wrapper;
672         zval            *z_ss_wrapper;
673         zval            *z_parameters;
674         FILE            *dbgprof;
675         int              filename_len;
676
677         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|zs", &z_ss_wrapper,
678                                 &z_xd_wrapper, &z_parameters, &filename, &filename_len) == FAILURE) {
679                 return;
680         }
681         ZEND_FETCH_RESOURCE(ss_wrapper, php_ss_wrapper *, &z_ss_wrapper, -1, "FastXSL Stylesheet",
682                         le_fastxsl_stylesheet);
683         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
684                         le_fastxsl_document);
685
686         if (ZEND_NUM_ARGS() > 2 && Z_TYPE_P(z_parameters) == IS_ARRAY) {
687                 if (ParseTransformParameters(z_parameters, &parameters TSRMLS_CC) == FAILURE) {
688                         RETURN_FALSE;
689                 }
690         }
691
692         if (!strcmp(filename, "php://stdout")) {
693                 dbgprof = stdout;
694         } else if (!strcmp(filename, "php://stderr")) {
695                 dbgprof = stderr;
696         } else {
697                 dbgprof = fopen(filename, "w");
698         }
699
700         result_wrapper = XD_Wrapper_Alloc();
701
702         result_wrapper->xd = xsltProfileStylesheet(ss_wrapper->ss, xd_wrapper->xd,
703                         (const char **) parameters, dbgprof);
704        
705         if (parameters)
706                 free(parameters);
707
708         fclose(dbgprof);
709        
710         if (!result_wrapper->xd) {
711                 RETURN_FALSE;
712         }       
713        
714         ZEND_REGISTER_RESOURCE(return_value, result_wrapper, le_fastxsl_document);
715 }
716 /* }}} */
717
718 /* {{{ proto string fastxsl_nocache_tostring(resource stylesheet, resource xmldoc)
719    Return the contents of an XML stylesheet result as a string */
720 PHP_FUNCTION(fastxsl_nocache_tostring)
721 {
722         zval           *z_xd_wrapper;
723         zval           *z_ss_wrapper;
724         php_ss_wrapper *ss_wrapper;
725         php_xd_wrapper *xd_wrapper;
726         xmlChar        *result = NULL;
727         int             length;
728
729         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &z_ss_wrapper,
730                                 &z_xd_wrapper) == FAILURE) {
731                 return;
732         }
733         ZEND_FETCH_RESOURCE(ss_wrapper, php_ss_wrapper *, &z_ss_wrapper, -1, "FastXSL XML Stylesheet",
734                         le_fastxsl_stylesheet);
735         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
736                         le_fastxsl_document);
737
738         xsltSaveResultToString(&result, &length, xd_wrapper->xd, ss_wrapper->ss);
739
740         if (result) {
741                 RETVAL_STRINGL((char *) result, length, 1);
742                 xmlFree(result);
743         } else {
744                 RETURN_FALSE;
745         }
746 }
747 /* }}} */
748
749 /* {{{ proto string fastxsl_shmcache_tostring(string filename, resource xmldoc)
750    Return the string representation of xmldoc which is the result of an XSLT transformation on filename */
751 PHP_FUNCTION(fastxsl_shmcache_tostring)
752 {
753         zval           *z_xd_wrapper;
754         php_ss_wrapper *ss_wrapper;
755         php_xd_wrapper *xd_wrapper;
756         xmlChar        *result = NULL;
757         char           *ss_filename;
758         size_t          ss_filename_len;
759         int             length;
760
761         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &ss_filename, &ss_filename_len,
762                                 &z_xd_wrapper) == FAILURE) {
763                 return;
764         }
765         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
766                         le_fastxsl_document);
767
768         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RD);
769         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->table, ss_filename, ss_filename_len);
770         if (!ss_wrapper) {
771                 mm_unlock(FASTXSL_G(cache)->mm);
772                 RETURN_FALSE;
773         }
774         xsltSaveResultToString(&result, &length, xd_wrapper->xd, ss_wrapper->ss);
775         mm_unlock(FASTXSL_G(cache)->mm);
776         if (result) {
777                 RETVAL_STRINGL((char *) result, length, 1);
778                 xmlFree(result);
779         } else {
780                 RETURN_FALSE;
781         }
782 }
783 /* }}} */
784
785 /* {{{ proto string fastxsl_prmcache_tostring(string filename, resource xmldoc)
786    Return the string representation of xmldoc which is the result of an XSLT transformation on filename */
787 PHP_FUNCTION(fastxsl_prmcache_tostring)
788 {
789         zval           *z_xd_wrapper;
790         php_ss_wrapper *ss_wrapper;
791         php_xd_wrapper *xd_wrapper;
792         xmlChar        *result = NULL;
793         char           *ss_filename;
794         size_t          ss_filename_len;
795         int             length;
796
797         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &ss_filename, &ss_filename_len,
798                                 &z_xd_wrapper) == FAILURE) {
799                 return;
800         }
801         ZEND_FETCH_RESOURCE(xd_wrapper, php_xd_wrapper *, &z_xd_wrapper, -1, "FastXSL XML Document",
802                         le_fastxsl_document);
803
804         ss_wrapper = fl_hash_find(FASTXSL_G(cache)->prmtable, ss_filename, ss_filename_len);
805         if (!ss_wrapper) {
806                 RETURN_FALSE;
807         }
808         xsltSaveResultToString(&result, &length, xd_wrapper->xd, ss_wrapper->ss);
809        
810         if (result) {
811                 RETVAL_STRINGL((char *) result, length, 1);
812                 xmlFree(result);
813         } else {
814                 RETURN_FALSE;
815         }
816 }
817 /* }}} */
818
819 function_entry fastxsl_functions[] = {
820         PHP_FE(fastxsl_stylesheet_parsefile,         NULL)
821         PHP_FE(fastxsl_xml_parsefile,                NULL)
822         PHP_FE(fastxsl_xml_parsestring,              NULL)
823         PHP_FE(fastxsl_shmcache_transform,           NULL)
824         PHP_FE(fastxsl_prmcache_transform,           NULL)
825         PHP_FE(fastxsl_nocache_transform,            NULL)
826         PHP_FE(fastxsl_nocache_profile,              NULL)
827         PHP_FE(fastxsl_nocache_tostring,             NULL)
828         PHP_FE(fastxsl_shmcache_tostring,            NULL)
829         PHP_FE(fastxsl_prmcache_tostring,            NULL)
830         PHP_FE(fastxsl_shmcache_getstatistics,       NULL)
831         PHP_FE(fastxsl_prmcache_getstatistics,       NULL)
832         {NULL, NULL, NULL}
833 };
834
835
836 zend_module_entry fastxsl_module_entry = {
837 #if ZEND_MODULE_API_NO >= 20010901
838         STANDARD_MODULE_HEADER,
839 #endif
840         "fastxsl",
841         fastxsl_functions,
842         PHP_MINIT(fastxsl),
843         NULL,
844         NULL,   
845         NULL,
846         PHP_MINFO(fastxsl),
847 #if ZEND_MODULE_API_NO >= 20010901
848         "0.1",
849 #endif
850         STANDARD_MODULE_PROPERTIES
851 };
852
853
854 #ifdef COMPILE_DL_FASTXSL
855 ZEND_GET_MODULE(fastxsl)
856 #endif
857
858 static void
859 SS_Wrapper_Dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
860 {
861         php_ss_wrapper *wrapper = (php_ss_wrapper *) rsrc->ptr;
862        
863         if (wrapper->persistant) {
864                 return;
865         }
866        
867         if (wrapper->ss)
868                 xsltFreeStylesheet(wrapper->ss);
869
870         free(wrapper);
871 }
872
873 static void
874 XD_Wrapper_Dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
875 {
876         php_xd_wrapper *wrapper = (php_xd_wrapper *) rsrc->ptr;
877        
878         if (wrapper->xd)
879                 xmlFreeDoc(wrapper->xd);
880         free(wrapper);
881 }
882
883 static int
884 Stream_MatchWrapper(const char *filename)
885 {
886         TSRMLS_FETCH();
887         return php_stream_locate_url_wrapper(filename, NULL, STREAM_LOCATE_WRAPPERS_ONLY TSRMLS_CC) ? 1 : 0;
888 }
889
890 static void *
891 Stream_XmlWrite_OpenWrapper(const char *filename)
892 {
893         TSRMLS_FETCH();
894         return php_stream_open_wrapper((char *) filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL);
895 }
896
897 static int
898 Stream_XmlWrite_WriteWrapper(void *context, const char *buffer, int length)
899 {
900         TSRMLS_FETCH();
901         return php_stream_write((php_stream *) context, (char *) buffer, length);
902 }
903
904 static int
905 Stream_CloseWrapper(void *context)
906 {
907         TSRMLS_FETCH();
908         return php_stream_close((php_stream *) context);
909 }
910
911
912 extern int xmlLoadExtDtdDefaultValue;
913
914 /**
915  * Allocators for the fl_hash storage
916  */
917 static FL_Allocator mm_allocators = {ShmCache_Free, ShmCache_Malloc, ShmCache_Calloc};
918 static FL_Allocator normal_allocators = {free, malloc, calloc};
919
920 static void
921 php_fastxsl_init_globals(zend_fastxsl_globals *globals)
922 {
923         memset(globals, 0, sizeof(zend_fastxsl_globals));
924        
925         globals->cache = calloc(1, sizeof(fl_cache));
926 }
927
928
929 static void
930 php_fastxsl_destroy_globals(zend_fastxsl_globals *globals)
931 {
932         fl_cache *cache;
933        
934         cache = globals->cache;
935         if (cache) {
936                 if (cache->owner != getpid()) {
937                         return;
938                 }
939
940                 mm_lock(cache->mm, MM_LOCK_RW);
941                 fl_hash_free(cache->table);
942                 mm_unlock(cache->mm);
943
944                 mm_destroy(cache->mm);
945
946                 fl_hash_free(cache->prmtable);
947         }
948 }
949
950 PHP_INI_BEGIN()
951         STD_PHP_INI_ENTRY("fastxsl.shmpath", "/tmp/fastxsl_mem", PHP_INI_SYSTEM, OnUpdateString, shmpath, zend_fastxsl_globals, fastxsl_globals)
952         STD_PHP_INI_BOOLEAN("fastxsl.nostat", "0", PHP_INI_ALL, OnUpdateInt, nostat, zend_fastxsl_globals, fastxsl_globals)
953 PHP_INI_END()
954
955 PHP_MINIT_FUNCTION(fastxsl)
956 {
957         char   *shmpath;
958         size_t  shmpath_len;
959         char    euid[30];
960
961         ZEND_INIT_MODULE_GLOBALS(fastxsl, php_fastxsl_init_globals, php_fastxsl_destroy_globals);
962
963         REGISTER_INI_ENTRIES();
964        
965         le_fastxsl_stylesheet = zend_register_list_destructors_ex(SS_Wrapper_Dtor, NULL,
966                         le_fastxsl_stylesheet_name, module_number);
967         le_fastxsl_document   = zend_register_list_destructors_ex(XD_Wrapper_Dtor, NULL,
968                         le_fastxsl_document_name,   module_number);
969
970         xsltRegisterAllExtras();
971         xmlSubstituteEntitiesDefault(1);
972         xmlLoadExtDtdDefaultValue = 1;
973
974         xmlMemGet(&free_ptr, &malloc_ptr, &realloc_ptr, &strdup_ptr);
975         xmlRegisterOutputCallbacks(Stream_MatchWrapper, Stream_XmlWrite_OpenWrapper,
976                                            Stream_XmlWrite_WriteWrapper, Stream_CloseWrapper);
977        
978
979         if (!sprintf(euid, "%d", geteuid())) {
980                 return FAILURE;
981         }
982
983         shmpath_len = strlen(FASTXSL_G(shmpath)) + strlen(euid);
984         shmpath = do_alloca(shmpath_len + 1);
985
986         strcpy(shmpath, FASTXSL_G(shmpath));
987         strcat(shmpath, euid);
988        
989         FASTXSL_G(cache)->owner = getpid();
990         FASTXSL_G(cache)->mm = mm_create(0, shmpath);
991
992         free_alloca(shmpath);
993         if (!FASTXSL_G(cache)->mm) {
994                 return FAILURE;
995         }
996
997         mm_lock(FASTXSL_G(cache)->mm, MM_LOCK_RW);
998         FASTXSL_G(cache)->table = fl_hash_new(&mm_allocators, NULL);
999         mm_unlock(FASTXSL_G(cache)->mm);
1000         FASTXSL_G(cache)->prmtable = fl_hash_new(&normal_allocators, NULL);
1001
1002         return SUCCESS;
1003 }
1004
1005 PHP_MINFO_FUNCTION(fastxsl)
1006 {
1007         php_info_print_table_start();
1008         php_info_print_table_header(2, "fastxsl support", "enabled");
1009         php_info_print_table_end();
1010
1011 }
1012
Note: See TracBrowser for help on using the browser.