RPA Toolkit
cf82217a0133f2935a75287623b10c2f3f5b3e02
[rpatk.git] / phpext / prpa / prpa.c
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2008 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.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:                                                              |
16   +----------------------------------------------------------------------+
17 */
18
19 /* $Id: header,v 1.16.2.1.2.1.2.1 2008/02/07 19:39:50 iliaa Exp $ */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_prpa.h"
29 #include "TSRM/TSRM.h"
30 #include "rpadbex.h"
31 #include "rpastat.h"
32 #include "rpastatpriv.h"
33 #include "rpaerror.h"
34 #include "rparecord.h"
35
36 typedef struct _php_rpa_dbex {
37         rpadbex_t* hDbex;
38         zval *zinput;
39 #ifdef ZTS
40         TSRMLS_D;       
41 #endif
42 } php_rpa_dbex;
43
44 #define PHP_RPA_DBEX_RES_NAME "php rpa dbex"
45
46
47 typedef struct _php_rpa_stat {
48         rpastat_t* stat;
49         zval *zinput;
50 #ifdef ZTS
51         TSRMLS_D;
52 #endif
53 } php_rpa_stat;
54
55 #define PHP_RPA_STAT_RES_NAME "php rpa stat"
56
57
58 typedef struct _php_rpa_records {
59         rarray_t* records;
60 #ifdef ZTS
61         TSRMLS_D;
62 #endif
63 } php_rpa_records;
64
65 #define PHP_RPA_RECORDS_RES_NAME "php rpa records"
66
67
68 static int le_rpa;
69 static int le_rpa_dbex;
70 static int le_rpa_stat;
71 //static int le_rpa_records;
72 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
73 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
74 static void php_rpa_records_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC);
75
76
77 /* If you declare any globals in php_prpa.h uncomment this:
78 ZEND_DECLARE_MODULE_GLOBALS(prpa)
79 */
80
81 /* True global resources - no need for thread safety here */
82 static int le_prpa;
83
84 /* {{{ prpa_functions[]
85  *
86  * Every user visible function must have an entry in prpa_functions[].
87  */
88 zend_function_entry prpa_functions[] = {
89     PHP_FE(rpa_dbex_version, NULL)
90     PHP_FE(rpa_dbex_create, NULL)
91     PHP_FE(rpa_dbex_open, NULL)
92     PHP_FE(rpa_dbex_close, NULL)
93     PHP_FE(rpa_dbex_load, NULL)
94     PHP_FE(rpa_dbex_compile, NULL)
95     PHP_FE(rpa_dbex_lookup, NULL)
96     PHP_FE(rpa_dbex_first, NULL)
97     PHP_FE(rpa_dbex_last, NULL)
98     PHP_FE(rpa_dbex_cfgset, NULL)
99     PHP_FE(rpa_dbex_dumpproductions, NULL)
100     PHP_FE(rpa_stat_create, NULL)
101     PHP_FE(rpa_stat_match, NULL)
102     PHP_FE(rpa_stat_scan, NULL)
103     PHP_FE(rpa_stat_parse, NULL)
104
105
106 #if 0
107     PHP_FE(rpa_records_create, NULL)
108     PHP_FE(rpa_records_length, NULL)
109     PHP_FE(rpa_records_get, NULL)
110
111     PHP_FE(rpa_dbex_strmatch, NULL)
112     PHP_FE(rpa_dbex_set_encoding, NULL)
113     PHP_FE(rpa_dbex_match, NULL)
114     PHP_FE(rpa_dbex_parse, NULL)
115     PHP_FE(rpa_dbex_scan, NULL)
116     PHP_FE(rpa_dbex_get_pattern, NULL)
117     PHP_FE(rpa_dbex_default_pattern, NULL)
118     PHP_FE(rpa_dbex_first_pattern, NULL)
119     PHP_FE(rpa_dbex_last_pattern, NULL)
120     PHP_FE(rpa_dbex_next_pattern, NULL)
121     PHP_FE(rpa_dbex_prev_pattern, NULL)
122     PHP_FE(rpa_dbex_pattern_name, NULL)
123     PHP_FE(rpa_dbex_pattern_regex, NULL)
124     PHP_FE(rpa_dbex_add_callback, NULL)
125 #endif
126         {NULL, NULL, NULL}      /* Must be the last line in prpa_functions[] */
127 };
128 /* }}} */
129
130 /* {{{ prpa_module_entry
131  */
132 zend_module_entry prpa_module_entry = {
133 #if ZEND_MODULE_API_NO >= 20010901
134         STANDARD_MODULE_HEADER,
135 #endif
136         "prpa",
137         prpa_functions,
138         PHP_MINIT(prpa),
139         PHP_MSHUTDOWN(prpa),
140         PHP_RINIT(prpa),                /* Replace with NULL if there's nothing to do at request start */
141         PHP_RSHUTDOWN(prpa),    /* Replace with NULL if there's nothing to do at request end */
142         PHP_MINFO(prpa),
143 #if ZEND_MODULE_API_NO >= 20010901
144         "0.1", /* Replace with version number for your extension */
145 #endif
146         STANDARD_MODULE_PROPERTIES
147 };
148 /* }}} */
149
150 #ifdef COMPILE_DL_PRPA
151 ZEND_GET_MODULE(prpa)
152 #endif
153
154 /* {{{ PHP_INI
155  */
156 /* Remove comments and fill if you need to have entries in php.ini
157 PHP_INI_BEGIN()
158     STD_PHP_INI_ENTRY("prpa.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_prpa_globals, prpa_globals)
159     STD_PHP_INI_ENTRY("prpa.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_prpa_globals, prpa_globals)
160 PHP_INI_END()
161 */
162 /* }}} */
163
164 /* {{{ php_prpa_init_globals
165  */
166 /* Uncomment this function if you have INI entries
167 static void php_prpa_init_globals(zend_prpa_globals *prpa_globals)
168 {
169         prpa_globals->global_value = 0;
170         prpa_globals->global_string = NULL;
171 }
172 */
173 /* }}} */
174
175 /* {{{ PHP_MINIT_FUNCTION
176  */
177 PHP_MINIT_FUNCTION(prpa)
178 {
179         /* If you have INI entries, uncomment these lines 
180         REGISTER_INI_ENTRIES();
181         */
182     le_rpa_dbex = zend_register_list_destructors_ex(php_rpa_dbex_dtor, NULL, PHP_RPA_DBEX_RES_NAME, module_number);
183     le_rpa_stat = zend_register_list_destructors_ex(php_rpa_stat_dtor, NULL, PHP_RPA_STAT_RES_NAME, module_number);
184 //    le_rpa_records = zend_register_list_destructors_ex(php_rpa_records_dtor, NULL, PHP_RPA_RECORDS_RES_NAME, module_number);
185
186     REGISTER_LONG_CONSTANT("RPA_ENCODING_BYTE", RPA_ENCODING_BYTE, CONST_CS | CONST_PERSISTENT);
187     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF8", RPA_ENCODING_UTF8, CONST_CS | CONST_PERSISTENT);
188     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF8", RPA_ENCODING_ICASE_UTF8, CONST_CS | CONST_PERSISTENT);
189     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF16LE", RPA_ENCODING_UTF16LE, CONST_CS | CONST_PERSISTENT);
190     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF16LE", RPA_ENCODING_ICASE_UTF16LE, CONST_CS | CONST_PERSISTENT);
191     REGISTER_LONG_CONSTANT("RPA_RECORD_START", RPA_RECORD_START, CONST_CS | CONST_PERSISTENT);
192     REGISTER_LONG_CONSTANT("RPA_RECORD_END", RPA_RECORD_END, CONST_CS | CONST_PERSISTENT);
193     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_DEBUG", RPA_DBEXCFG_DEBUG, CONST_CS | CONST_PERSISTENT);
194     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_OPTIMIZATIONS", RPA_DBEXCFG_OPTIMIZATIONS, CONST_CS | CONST_PERSISTENT);
195
196         return SUCCESS;
197 }
198 /* }}} */
199
200 /* {{{ PHP_MSHUTDOWN_FUNCTION
201  */
202 PHP_MSHUTDOWN_FUNCTION(prpa)
203 {
204         /* uncomment this line if you have INI entries
205         UNREGISTER_INI_ENTRIES();
206         */
207         return SUCCESS;
208 }
209 /* }}} */
210
211 /* Remove if there's nothing to do at request start */
212 /* {{{ PHP_RINIT_FUNCTION
213  */
214 PHP_RINIT_FUNCTION(prpa)
215 {
216         return SUCCESS;
217 }
218 /* }}} */
219
220 /* Remove if there's nothing to do at request end */
221 /* {{{ PHP_RSHUTDOWN_FUNCTION
222  */
223 PHP_RSHUTDOWN_FUNCTION(prpa)
224 {
225         return SUCCESS;
226 }
227 /* }}} */
228
229 /* {{{ PHP_MINFO_FUNCTION
230  */
231 PHP_MINFO_FUNCTION(prpa)
232 {
233         php_info_print_table_start();
234         php_info_print_table_header(2, "prpa support", "enabled");
235         php_info_print_table_end();
236
237         /* Remove comments if you have entries in php.ini
238         DISPLAY_INI_ENTRIES();
239         */
240 }
241 /* }}} */
242
243
244 PHP_FUNCTION(rpa_dbex_version)
245 {
246     RETURN_STRING((char*)rpa_dbex_version(), 1);
247 }
248
249
250 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
251 {
252     php_rpa_stat *phpstat = (php_rpa_stat*)rsrc->ptr;
253
254     if (phpstat) {
255         rpa_stat_destroy(phpstat->stat);
256         efree(phpstat);
257     }
258 }
259
260
261 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
262 {
263     php_rpa_dbex *pPhpDbex = (php_rpa_dbex*)rsrc->ptr;
264
265     if (pPhpDbex) {
266                 rpa_dbex_destroy(pPhpDbex->hDbex);
267 /*
268                 zval_dtor(pPhpDbex->zcallbacks);
269                 Z_DELREF_P(pPhpDbex->zcallbacks);
270                 Z_DELREF_P(pPhpDbex->zcallbacks);
271                 php_printf("refcnt: %d\n", Z_REFCOUNT_P(pPhpDbex->zcallbacks));
272                 efree(pPhpDbex->zcallbacks);
273 */
274                 efree(pPhpDbex);
275     }
276 }
277
278
279 static void php_rpa_records_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
280 {
281     php_rpa_records *phprecords = (php_rpa_records*)rsrc->ptr;
282
283     if (phprecords) {
284         rpa_records_destroy(phprecords->records);
285         efree(phprecords);
286     }
287 }
288
289
290 PHP_FUNCTION(rpa_dbex_create)
291 {
292     php_rpa_dbex *pPhpDbex;
293
294 /*
295     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) {
296                 RETURN_FALSE;
297     }
298 */
299
300     pPhpDbex = emalloc(sizeof(php_rpa_dbex));
301     pPhpDbex->hDbex = rpa_dbex_create();
302
303 /*
304         ALLOC_INIT_ZVAL(pPhpDbex->zcallbacks);
305         Z_ADDREF_P(pPhpDbex->zcallbacks);
306         array_init(pPhpDbex->zcallbacks);
307 */
308     ZEND_REGISTER_RESOURCE(return_value, pPhpDbex, le_rpa_dbex);
309 }
310
311
312 PHP_FUNCTION(rpa_dbex_open)
313 {
314         zval *zres;
315     php_rpa_dbex *pPhpDbex;
316         int ret;
317
318     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
319                 RETURN_LONG(-1);
320     }
321
322     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
323
324         ret = rpa_dbex_open(pPhpDbex->hDbex);
325         RETURN_LONG(ret);
326 }
327
328
329 PHP_FUNCTION(rpa_dbex_close)
330 {
331         zval *zres;
332     php_rpa_dbex *pPhpDbex;
333
334     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
335                 RETURN_LONG(-1);
336     }
337
338     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
339
340         rpa_dbex_close(pPhpDbex->hDbex);
341         RETURN_LONG(0);
342 }
343
344
345 PHP_FUNCTION(rpa_dbex_load)
346 {
347         zval *zres;
348     php_rpa_dbex *pPhpDbex;
349         char *patterns;
350         int patterns_len;
351         int ret;
352
353
354     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
355                 RETURN_LONG(-1);
356     }
357
358     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
359
360     ret = rpa_dbex_load_s(pPhpDbex->hDbex, patterns);
361         RETURN_LONG(ret);
362 }
363
364
365 PHP_FUNCTION(rpa_dbex_lookup)
366 {
367         zval *zres;
368     php_rpa_dbex *pPhpDbex;
369         char *name;
370         int name_len;
371         long ret;
372
373     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == FAILURE) {
374                 RETURN_LONG(-1);
375     }
376
377     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
378
379     ret = rpa_dbex_lookup(pPhpDbex->hDbex, name, name_len);
380         RETURN_LONG(ret);
381 }
382
383
384 PHP_FUNCTION(rpa_dbex_first)
385 {
386         zval *zres;
387     php_rpa_dbex *pPhpDbex;
388         long ret;
389
390     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
391                 RETURN_LONG(-1);
392     }
393
394     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
395
396     ret = rpa_dbex_first(pPhpDbex->hDbex);
397         RETURN_LONG(ret);
398 }
399
400
401 PHP_FUNCTION(rpa_dbex_last)
402 {
403         zval *zres;
404     php_rpa_dbex *pPhpDbex;
405         long ret;
406
407     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
408                 RETURN_LONG(-1);
409     }
410
411     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
412
413     ret = rpa_dbex_last(pPhpDbex->hDbex);
414         RETURN_LONG(ret);
415 }
416
417
418 PHP_FUNCTION(rpa_dbex_compile)
419 {
420         zval *zres;
421     php_rpa_dbex *pPhpDbex;
422         char *patterns;
423         int patterns_len;
424         int ret;
425
426
427     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
428                 RETURN_LONG(-1);
429     }
430
431     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
432
433     ret = rpa_dbex_compile(pPhpDbex->hDbex);
434         RETURN_LONG(ret);
435 }
436
437
438 PHP_FUNCTION(rpa_dbex_dumpproductions)
439 {
440         zval *zres;
441     php_rpa_dbex *pPhpDbex;
442         long ret;
443
444     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
445                 RETURN_LONG(-1);
446     }
447
448     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
449
450     ret = rpa_dbex_dumpproductions(pPhpDbex->hDbex);
451         RETURN_LONG(ret);
452 }
453
454
455 PHP_FUNCTION(rpa_dbex_cfgset)
456 {
457         zval *zres;
458     php_rpa_dbex *pPhpDbex;
459     long cfg, val;
460         long ret;
461
462     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &zres, cfg, val) == FAILURE) {
463                 RETURN_LONG(-1);
464     }
465
466     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
467
468     ret = rpa_dbex_cfgset(pPhpDbex->hDbex, cfg, val);
469         RETURN_LONG(ret);
470 }
471
472
473 PHP_FUNCTION(rpa_stat_create)
474 {
475         zval *zres;
476     php_rpa_dbex *pPhpDbex;
477     php_rpa_stat *phpstat;
478         int ret;
479         long stackSize = 0L;
480
481
482     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &stackSize) == FAILURE) {
483                 RETURN_LONG(-1);
484     }
485
486     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
487     phpstat = emalloc(sizeof(php_rpa_stat));
488     phpstat->stat = rpa_stat_create(pPhpDbex->hDbex, stackSize);
489     ZEND_REGISTER_RESOURCE(return_value, phpstat, le_rpa_stat);
490 }
491
492
493 PHP_FUNCTION(rpa_stat_match)
494 {
495         zval *zstat;
496     php_rpa_stat *phpstat;
497         long rid;
498         long encoding;
499         long ret;
500         char *input;
501         int input_len;
502
503     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls", &zstat, &rid, &encoding, &input, &input_len) == FAILURE) {
504                 RETURN_LONG(-1);
505     }
506     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
507     ret = rpa_stat_match(phpstat->stat, rid, encoding, input, input, input + input_len);
508         RETURN_LONG(ret);
509 }
510
511
512 PHP_FUNCTION(rpa_stat_scan)
513 {
514         zval *zstat;
515     php_rpa_stat *phpstat;
516         long rid;
517         long encoding;
518         long ret;
519         char *input;
520         int input_len;
521         zval *zwhere;
522         const char *where = NULL;
523
524     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllsz", &zstat, &rid, &encoding, &input, &input_len, &zwhere) == FAILURE) {
525                 RETURN_LONG(-1);
526     }
527     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
528     ret = rpa_stat_scan(phpstat->stat, rid, encoding, input, input, input + input_len, &where);
529         if (ret) {
530                 ZVAL_LONG(zwhere, where - input);
531         } else {
532                 ZVAL_NULL(zwhere);
533         }
534
535         RETURN_LONG(ret);
536 }
537
538
539 PHP_FUNCTION(rpa_stat_parse)
540 {
541         zval *zstat;
542     php_rpa_stat *phpstat;
543         long rid;
544         long encoding;
545         long ret, i;
546         char *input;
547         int input_len;
548         zval *zrecords = NULL;
549         rarray_t *records = rpa_records_create();
550
551     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls|z", &zstat, &rid, &encoding, &input, &input_len, &zrecords) == FAILURE) {
552                 RETURN_LONG(-1);
553     }
554     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
555     ret = rpa_stat_parse(phpstat->stat, rid, encoding, input, input, input + input_len, records);
556     if (ret <= 0)
557         goto error;
558     if (zrecords) {
559         rparecord_t *record;
560         array_init(zrecords);
561         for (i = 0; i < rpa_records_length(records); i++) {
562                 zval *zrecord;
563                 record = rpa_records_slot(records, i);
564                 ALLOC_INIT_ZVAL(zrecord);
565                 array_init(zrecord);
566                 add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
567                 add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
568                 add_assoc_long(zrecord, "type", record->type);
569                 add_assoc_long(zrecord, "uid", record->ruleuid);
570                 add_next_index_zval(zrecords, zrecord);
571         }
572     }
573
574 error:
575         rpa_records_destroy(records);
576         RETURN_LONG(ret);
577 }
578
579
580 PHP_FUNCTION(rpa_records_create)
581 {
582     php_rpa_records *phprecords;
583
584     phprecords = emalloc(sizeof(php_rpa_records));
585     phprecords->records = rpa_records_create();
586
587     ZEND_REGISTER_RESOURCE(return_value, phprecords, le_rpa_dbex);
588 }
589
590
591 #if 0
592 static php_cbinfo *php_cbinfo_create(php_rpa_dbex *pPhpDbex, const char *php_callback, zval *userdata)
593 {
594         php_cbinfo *pCbInfo;
595
596         if ((pCbInfo = emalloc(sizeof(php_cbinfo))) == NULL)
597                 return NULL;
598
599         pCbInfo->pPhpDbex = pPhpDbex;
600         pCbInfo->php_callback = estrdup(php_callback);
601         pCbInfo->userdata = userdata;
602         if (userdata) {
603                 ZVAL_ADDREF(userdata);
604 //              Z_SET_ISREF_P(userdata);
605         }
606         return pCbInfo;
607 }
608
609
610 static void php_cbinfo_destroy(php_cbinfo *pCbInfo)
611 {
612         if (!pCbInfo)
613                 return;
614         if (pCbInfo->php_callback)
615                 efree(pCbInfo->php_callback);
616         if (pCbInfo->userdata) {
617                 if (ZVAL_REFCOUNT(pCbInfo->userdata) == 1) {
618                         zval_ptr_dtor(&pCbInfo->userdata);
619                 } else {
620                         ZVAL_DELREF(pCbInfo->userdata);
621                 }
622         }
623         efree(pCbInfo);
624 }
625
626
627 static void php_do_rpa_dbex_strmatch(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ */
628 {
629     /* parameters */
630     char             *subject;          /* String to match against */
631     char             *regex;            /* Regular expression */
632     int               subject_len;
633     int               regex_len;
634         int                               ret = 0;
635
636         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &subject, 
637                                                           &subject_len,
638                                                           &regex,
639                                                           &regex_len) == FAILURE) {
640                 RETURN_LONG(-1);
641     }
642 /*
643         ret = emalloc(subject_len + regex_len + 100);
644         php_sprintf(ret, "Hello from rpalib, subject: %s, regex: %s", subject, regex);
645     RETURN_STRING(ret, 0);
646 */
647         ret = rpa_dbex_strmatch(subject, regex);
648         RETURN_LONG(ret);
649 }
650
651
652 /* {{{ proto int rpa_dbex_strmatch(string subject, string pattern)
653    Perform a regular expression match */
654 PHP_FUNCTION(rpa_dbex_strmatch)
655 {
656     php_do_rpa_dbex_strmatch(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
657 }
658
659
660 PHP_FUNCTION(rpa_dbex_greetme)
661 {
662     zval *zname;
663
664     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) {
665         RETURN_NULL();
666     }
667
668     convert_to_string(zname);
669
670     php_printf("Hello ");
671     PHPWRITE(Z_STRVAL_P(zname), Z_STRLEN_P(zname));
672     php_printf(" ");
673
674     RETURN_TRUE;
675 }
676
677
678
679
680
681
682 PHP_FUNCTION(rpa_dbex_load_string)
683 {
684         zval *zres;
685     php_rpa_dbex *pPhpDbex;
686         char *patterns;
687         int patterns_len;
688         int ret;
689
690
691     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
692                 RETURN_LONG(-1);
693     }
694
695     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
696
697     ret = rpa_dbex_load_string(pPhpDbex->hDbex, patterns);
698         RETURN_LONG(ret);
699 }
700
701
702 PHP_FUNCTION(rpa_dbex_set_encoding)
703 {
704         zval *zres;
705     php_rpa_dbex *pPhpDbex;
706         char *patterns;
707         long encoding;
708         int patterns_len;
709         int ret;
710
711
712     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &encoding) == FAILURE) {
713                 RETURN_LONG(-1);
714     }
715
716     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
717
718     ret = rpa_dbex_set_encoding(pPhpDbex->hDbex, encoding);
719         RETURN_LONG(ret);
720 }
721
722
723 PHP_FUNCTION(rpa_dbex_match)
724 {
725         zval *zdbex;
726         zval *zpattern;
727         zval *zinput;
728     php_rpa_dbex *pPhpDbex;
729     php_rpa_pattern *pPhpPattern;
730         char *input;
731         int input_len;
732         int ret;
733
734     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &zdbex, &zpattern, &zinput) == FAILURE) {
735                 RETURN_LONG(-1);
736     }
737         input = Z_STRVAL_P(zinput);
738         input_len = Z_STRLEN_P(zinput);
739     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
740     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
741 #ifdef ZTS
742         pPhpDbex->tsrm_ls = TSRMLS_C;
743 #endif
744         pPhpDbex->zinput = zinput;
745     ret = rpa_dbex_match(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len);
746         RETURN_LONG(ret);
747 }
748
749
750 PHP_FUNCTION(rpa_dbex_parse)
751 {
752         zval *zdbex;
753         zval *zpattern;
754         zval *zinput;
755     php_rpa_dbex *pPhpDbex;
756     php_rpa_pattern *pPhpPattern;
757         char *input;
758         int input_len;
759         int ret;
760
761     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &zdbex, &zpattern, &zinput) == FAILURE) {
762                 RETURN_LONG(-1);
763     }
764         input = Z_STRVAL_P(zinput);
765         input_len = Z_STRLEN_P(zinput);
766     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
767     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
768 #ifdef ZTS
769         pPhpDbex->tsrm_ls = TSRMLS_C;
770 #endif
771         pPhpDbex->zinput = zinput;
772     ret = rpa_dbex_parse(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len);
773         RETURN_LONG(ret);
774 }
775
776
777 PHP_FUNCTION(rpa_dbex_scan)
778 {
779         zval *zdbex;
780         zval *zpattern;
781         zval *zinput;
782         zval *zwhere;
783     php_rpa_dbex *pPhpDbex;
784     php_rpa_pattern *pPhpPattern;
785         char *input;
786         const char *where = NULL;
787         int input_len;
788         int ret;
789
790     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrzz", &zdbex, &zpattern, &zinput, &zwhere) == FAILURE) {
791                 RETURN_LONG(-1);
792     }
793         input = Z_STRVAL_P(zinput);
794         input_len = Z_STRLEN_P(zinput);
795     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
796     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
797 #ifdef ZTS
798         pPhpDbex->tsrm_ls = TSRMLS_C;
799 #endif
800         pPhpDbex->zinput = zinput;
801     ret = rpa_dbex_scan(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len, &where);
802         if (ret) {
803                 ZVAL_LONG(zwhere, where - input);
804         } else {
805                 ZVAL_NULL(zwhere);
806         }
807
808         RETURN_LONG(ret);
809 }
810
811
812 PHP_FUNCTION(rpa_dbex_get_pattern)
813 {
814         zval *zres;
815         php_rpa_dbex *pPhpDbex;
816         php_rpa_pattern *pPhpPattern;
817         char *name;
818         int name_len;
819         rpa_pattern_handle hPattern;
820
821         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == FAILURE) {
822                 RETURN_FALSE;
823         }
824         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
825         hPattern = rpa_dbex_get_pattern(pPhpDbex->hDbex, name);
826         if (!hPattern)
827                 RETURN_FALSE;
828         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
829         pPhpPattern->hPattern = hPattern;
830         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
831 }
832
833
834 PHP_FUNCTION(rpa_dbex_default_pattern)
835 {
836         zval *zres;
837         php_rpa_dbex *pPhpDbex;
838         php_rpa_pattern *pPhpPattern;
839         rpa_pattern_handle hPattern;
840
841         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
842                 RETURN_FALSE;
843         }
844         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
845         hPattern = rpa_dbex_default_pattern(pPhpDbex->hDbex);
846         if (!hPattern)
847                 RETURN_FALSE;
848         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
849         pPhpPattern->hPattern = hPattern;
850         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
851 }
852
853
854 PHP_FUNCTION(rpa_dbex_first_pattern)
855 {
856         zval *zres;
857         php_rpa_dbex *pPhpDbex;
858         php_rpa_pattern *pPhpPattern;
859         rpa_pattern_handle hPattern;
860
861         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
862                 RETURN_FALSE;
863         }
864         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
865         hPattern = rpa_dbex_first_pattern(pPhpDbex->hDbex);
866         if (!hPattern)
867                 RETURN_FALSE;
868         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
869         pPhpPattern->hPattern = hPattern;
870         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
871 }
872
873
874 PHP_FUNCTION(rpa_dbex_last_pattern)
875 {
876         zval *zres;
877         php_rpa_dbex *pPhpDbex;
878         php_rpa_pattern *pPhpPattern;
879         rpa_pattern_handle hPattern;
880
881         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
882                 RETURN_FALSE;
883         }
884         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
885         hPattern = rpa_dbex_last_pattern(pPhpDbex->hDbex);
886         if (!hPattern)
887                 RETURN_FALSE;
888         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
889         pPhpPattern->hPattern = hPattern;
890         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
891 }
892
893
894 PHP_FUNCTION(rpa_dbex_next_pattern)
895 {
896         zval *zresFirst, *zresSecond;
897         php_rpa_dbex *pPhpDbex;
898         php_rpa_pattern *pPhpPatternCur;
899         php_rpa_pattern *pPhpPattern;
900         rpa_pattern_handle hPattern;
901
902         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
903                 RETURN_FALSE;
904         }
905         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
906     ZEND_FETCH_RESOURCE(pPhpPatternCur, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
907                 
908         hPattern = rpa_dbex_next_pattern(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPatternCur ? pPhpPatternCur->hPattern : NULL);
909         if (!hPattern)
910                 RETURN_FALSE;
911         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
912         pPhpPattern->hPattern = hPattern;
913         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
914 }
915
916
917 PHP_FUNCTION(rpa_dbex_prev_pattern)
918 {
919         zval *zresFirst, *zresSecond;
920         php_rpa_dbex *pPhpDbex;
921         php_rpa_pattern *pPhpPatternCur;
922         php_rpa_pattern *pPhpPattern;
923         rpa_pattern_handle hPattern;
924
925         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
926                 RETURN_FALSE;
927         }
928         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
929     ZEND_FETCH_RESOURCE(pPhpPatternCur, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
930                 
931         hPattern = rpa_dbex_prev_pattern(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPatternCur ? pPhpPatternCur->hPattern : NULL);
932         if (!hPattern)
933                 RETURN_FALSE;
934         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
935         pPhpPattern->hPattern = hPattern;
936         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
937 }
938
939
940 PHP_FUNCTION(rpa_dbex_pattern_name)
941 {
942         zval *zresFirst, *zresSecond;
943         php_rpa_dbex *pPhpDbex;
944         php_rpa_pattern *pPhpPattern;
945         const char *name;
946         char *ret;
947
948         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
949                 RETURN_FALSE;
950         }
951         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
952     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
953                 
954         name = rpa_dbex_pattern_name(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPattern ? pPhpPattern->hPattern : NULL);
955         if (!name)
956                 RETURN_FALSE;
957         ret = estrdup(name);
958         RETURN_STRING(ret, 0);
959 }
960
961
962 PHP_FUNCTION(rpa_dbex_pattern_regex)
963 {
964         zval *zresFirst, *zresSecond;
965         php_rpa_dbex *pPhpDbex;
966         php_rpa_pattern *pPhpPattern;
967         long int seq = 0;
968         const char *regex;
969         char *ret;
970
971         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &zresFirst, &zresSecond, &seq) == FAILURE) {
972                 RETURN_FALSE;
973         }
974         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
975     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
976                 
977         regex = rpa_dbex_pattern_regex(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPattern ? pPhpPattern->hPattern : NULL, seq);
978         if (!regex)
979                 RETURN_FALSE;
980         ret = estrdup(regex);
981         RETURN_STRING(ret, 0);
982 }
983
984
985 static int php_rpa_callback_proxy(const char *name, void *userdata, const char *input, unsigned int size, unsigned int reason, const char *start, const char *end)
986 {
987         php_cbinfo *pCbInfo = (php_cbinfo*)userdata;
988         zval *retval_ptr = NULL;  /* Function return value */
989     zval **args[7];           /* Argument to pass to function */
990         zval *zcallback;
991         zval *zname;
992         zval *zoffset;
993         zval *zsize;
994         zval *zreason;
995         zval *zuserdata;
996         zval *zempty;
997         int ret = size;
998 #ifdef ZTS
999         TSRMLS_D = pCbInfo->pPhpDbex->tsrm_ls;
1000 #endif
1001
1002         MAKE_STD_ZVAL(zcallback);
1003         MAKE_STD_ZVAL(zname);
1004         MAKE_STD_ZVAL(zoffset);
1005         MAKE_STD_ZVAL(zsize);
1006         MAKE_STD_ZVAL(zreason);
1007         MAKE_STD_ZVAL(zuserdata);
1008         MAKE_STD_ZVAL(zempty);
1009
1010         ZVAL_STRING(zcallback, pCbInfo->php_callback, 1);
1011         ZVAL_LONG(zsize, size);
1012         ZVAL_LONG(zreason, reason);
1013         ZVAL_LONG(zempty, 0);
1014         ZVAL_LONG(zoffset, input - start);
1015         ZVAL_STRING(zname, name, 1);
1016
1017         args[0] = &zname;
1018         if (pCbInfo->userdata) {
1019                 args[1] = &pCbInfo->userdata;
1020         } else {
1021                 args[1] = &zempty;
1022         }
1023
1024
1025         args[2] = &zoffset;
1026         args[3] = &zsize;
1027         args[4] = &zreason;
1028         args[5] = &pCbInfo->pPhpDbex->zinput;
1029
1030
1031         if (call_user_function_ex(EG(function_table), NULL, zcallback, &retval_ptr, 6, args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
1032                 convert_to_long(retval_ptr);
1033                 ret = (int) Z_LVAL_P(retval_ptr);
1034                 zval_ptr_dtor(&retval_ptr);
1035         } else {
1036                 if (!EG(exception)) {
1037                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call function: %s()", Z_STRVAL_P(zcallback));
1038                 }
1039         }
1040
1041 /*
1042         zval_ptr_dtor(&zcallback);
1043         zval_ptr_dtor(&zname);
1044         zval_ptr_dtor(&zsize);
1045         zval_ptr_dtor(&zreason);
1046         zval_ptr_dtor(&zuserdata);
1047         zval_ptr_dtor(&zoffset);
1048         zval_ptr_dtor(&zempty);
1049 */
1050
1051         return ret;
1052 }
1053
1054
1055 PHP_FUNCTION(rpa_dbex_add_callback)
1056 {
1057         zval *zresDbex, *zresCallback, *zresUserData = NULL;
1058         php_rpa_dbex *pPhpDbex;
1059         php_rpa_pattern *pPhpPattern;
1060         char *name;
1061         long reason;
1062         int name_len = 0;
1063         char *callback;
1064         int callback_len = 0;
1065         unsigned long ret = 0;
1066         php_cbinfo *pCbInfo;
1067
1068         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsls|z", &zresDbex, &name, &name_len, &reason, 
1069                                                           &callback, &callback_len, &zresUserData) == FAILURE) {
1070                 RETURN_LONG(-1);
1071         }
1072         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresDbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1073
1074         pCbInfo = php_cbinfo_create(pPhpDbex, callback, zresUserData);
1075         ret = rpa_dbex_add_callback(pPhpDbex ? pPhpDbex->hDbex : NULL, name, reason, php_rpa_callback_proxy, pCbInfo);
1076         RETURN_LONG(ret);
1077 }
1078
1079 #endif