RPA Toolkit
work on the PHP extension.
[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(rpaparse, NULL)
90     PHP_FE(rpa_dbex_version, NULL)
91     PHP_FE(rpa_dbex_create, NULL)
92     PHP_FE(rpa_dbex_open, NULL)
93     PHP_FE(rpa_dbex_close, NULL)
94     PHP_FE(rpa_dbex_load, NULL)
95     PHP_FE(rpa_dbex_compile, NULL)
96     PHP_FE(rpa_dbex_lookup, NULL)
97     PHP_FE(rpa_dbex_first, NULL)
98     PHP_FE(rpa_dbex_last, NULL)
99     PHP_FE(rpa_dbex_cfgset, NULL)
100     PHP_FE(rpa_dbex_dumpproductions, NULL)
101     PHP_FE(rpa_dbex_error, NULL)
102     PHP_FE(rpa_stat_create, NULL)
103     PHP_FE(rpa_stat_match, NULL)
104     PHP_FE(rpa_stat_scan, NULL)
105     PHP_FE(rpa_stat_parse, NULL)
106     PHP_FE(rpa_stat_error, NULL)
107
108
109 #if 0
110     PHP_FE(rpa_records_create, NULL)
111     PHP_FE(rpa_records_length, NULL)
112     PHP_FE(rpa_records_get, NULL)
113
114     PHP_FE(rpa_dbex_strmatch, NULL)
115     PHP_FE(rpa_dbex_set_encoding, NULL)
116     PHP_FE(rpa_dbex_match, NULL)
117     PHP_FE(rpa_dbex_parse, NULL)
118     PHP_FE(rpa_dbex_scan, NULL)
119     PHP_FE(rpa_dbex_get_pattern, NULL)
120     PHP_FE(rpa_dbex_default_pattern, NULL)
121     PHP_FE(rpa_dbex_first_pattern, NULL)
122     PHP_FE(rpa_dbex_last_pattern, NULL)
123     PHP_FE(rpa_dbex_next_pattern, NULL)
124     PHP_FE(rpa_dbex_prev_pattern, NULL)
125     PHP_FE(rpa_dbex_pattern_name, NULL)
126     PHP_FE(rpa_dbex_pattern_regex, NULL)
127     PHP_FE(rpa_dbex_add_callback, NULL)
128 #endif
129         {NULL, NULL, NULL}      /* Must be the last line in prpa_functions[] */
130 };
131 /* }}} */
132
133 /* {{{ prpa_module_entry
134  */
135 zend_module_entry prpa_module_entry = {
136 #if ZEND_MODULE_API_NO >= 20010901
137         STANDARD_MODULE_HEADER,
138 #endif
139         "prpa",
140         prpa_functions,
141         PHP_MINIT(prpa),
142         PHP_MSHUTDOWN(prpa),
143         PHP_RINIT(prpa),                /* Replace with NULL if there's nothing to do at request start */
144         PHP_RSHUTDOWN(prpa),    /* Replace with NULL if there's nothing to do at request end */
145         PHP_MINFO(prpa),
146 #if ZEND_MODULE_API_NO >= 20010901
147         "0.1", /* Replace with version number for your extension */
148 #endif
149         STANDARD_MODULE_PROPERTIES
150 };
151 /* }}} */
152
153 #ifdef COMPILE_DL_PRPA
154 ZEND_GET_MODULE(prpa)
155 #endif
156
157 /* {{{ PHP_INI
158  */
159 /* Remove comments and fill if you need to have entries in php.ini
160 PHP_INI_BEGIN()
161     STD_PHP_INI_ENTRY("prpa.global_value",      "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_prpa_globals, prpa_globals)
162     STD_PHP_INI_ENTRY("prpa.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_prpa_globals, prpa_globals)
163 PHP_INI_END()
164 */
165 /* }}} */
166
167 /* {{{ php_prpa_init_globals
168  */
169 /* Uncomment this function if you have INI entries
170 static void php_prpa_init_globals(zend_prpa_globals *prpa_globals)
171 {
172         prpa_globals->global_value = 0;
173         prpa_globals->global_string = NULL;
174 }
175 */
176 /* }}} */
177
178 /* {{{ PHP_MINIT_FUNCTION
179  */
180 PHP_MINIT_FUNCTION(prpa)
181 {
182         /* If you have INI entries, uncomment these lines 
183         REGISTER_INI_ENTRIES();
184         */
185     le_rpa_dbex = zend_register_list_destructors_ex(php_rpa_dbex_dtor, NULL, PHP_RPA_DBEX_RES_NAME, module_number);
186     le_rpa_stat = zend_register_list_destructors_ex(php_rpa_stat_dtor, NULL, PHP_RPA_STAT_RES_NAME, module_number);
187 //    le_rpa_records = zend_register_list_destructors_ex(php_rpa_records_dtor, NULL, PHP_RPA_RECORDS_RES_NAME, module_number);
188
189     REGISTER_LONG_CONSTANT("RPA_ENCODING_BYTE", RPA_ENCODING_BYTE, CONST_CS | CONST_PERSISTENT);
190     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF8", RPA_ENCODING_UTF8, CONST_CS | CONST_PERSISTENT);
191     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF8", RPA_ENCODING_ICASE_UTF8, CONST_CS | CONST_PERSISTENT);
192     REGISTER_LONG_CONSTANT("RPA_ENCODING_UTF16LE", RPA_ENCODING_UTF16LE, CONST_CS | CONST_PERSISTENT);
193     REGISTER_LONG_CONSTANT("RPA_ENCODING_ICASE_UTF16LE", RPA_ENCODING_ICASE_UTF16LE, CONST_CS | CONST_PERSISTENT);
194     REGISTER_LONG_CONSTANT("RPA_RECORD_START", RPA_RECORD_START, CONST_CS | CONST_PERSISTENT);
195     REGISTER_LONG_CONSTANT("RPA_RECORD_END", RPA_RECORD_END, CONST_CS | CONST_PERSISTENT);
196     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_DEBUG", RPA_DBEXCFG_DEBUG, CONST_CS | CONST_PERSISTENT);
197     REGISTER_LONG_CONSTANT("RPA_DBEXCFG_OPTIMIZATIONS", RPA_DBEXCFG_OPTIMIZATIONS, CONST_CS | CONST_PERSISTENT);
198
199         return SUCCESS;
200 }
201 /* }}} */
202
203 /* {{{ PHP_MSHUTDOWN_FUNCTION
204  */
205 PHP_MSHUTDOWN_FUNCTION(prpa)
206 {
207         /* uncomment this line if you have INI entries
208         UNREGISTER_INI_ENTRIES();
209         */
210         return SUCCESS;
211 }
212 /* }}} */
213
214 /* Remove if there's nothing to do at request start */
215 /* {{{ PHP_RINIT_FUNCTION
216  */
217 PHP_RINIT_FUNCTION(prpa)
218 {
219         return SUCCESS;
220 }
221 /* }}} */
222
223 /* Remove if there's nothing to do at request end */
224 /* {{{ PHP_RSHUTDOWN_FUNCTION
225  */
226 PHP_RSHUTDOWN_FUNCTION(prpa)
227 {
228         return SUCCESS;
229 }
230 /* }}} */
231
232 /* {{{ PHP_MINFO_FUNCTION
233  */
234 PHP_MINFO_FUNCTION(prpa)
235 {
236         php_info_print_table_start();
237         php_info_print_table_header(2, "prpa support", "enabled");
238         php_info_print_table_end();
239
240         /* Remove comments if you have entries in php.ini
241         DISPLAY_INI_ENTRIES();
242         */
243 }
244 /* }}} */
245
246
247 PHP_FUNCTION(rpaparse)
248 {
249         rpadbex_t *dbex;
250         rpastat_t *stat;
251         long rid;
252         long encoding;
253         long ret, i;
254         char *bnf;
255         int bnf_len;
256         char *input;
257         int input_len;
258         zval *error = NULL;
259         zval *zrecords = NULL;
260         rarray_t *records = rpa_records_create();
261
262     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sls|zz", &bnf, &bnf_len, &encoding, &input, &input_len, &zrecords, &error) == FAILURE) {
263                 RETURN_LONG(-1);
264     }
265     dbex = rpa_dbex_create();
266     rpa_dbex_open(dbex);
267     rpa_dbex_load(dbex, bnf, bnf_len);
268     rpa_dbex_close(dbex);
269     rpa_dbex_compile(dbex);
270     stat = rpa_stat_create(dbex, 16000);
271     ret = rpa_stat_parse(stat, rpa_dbex_last(dbex), encoding, input, input, input + input_len, records);
272     if (ret <= 0)
273         goto error;
274     if (zrecords) {
275         rparecord_t *record;
276         array_init(zrecords);
277         for (i = 0; i < rpa_records_length(records); i++) {
278                 zval *zrecord;
279                 record = rpa_records_slot(records, i);
280                 ALLOC_INIT_ZVAL(zrecord);
281                 array_init(zrecord);
282                 add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
283                 add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
284                 add_assoc_long(zrecord, "type", record->type);
285                 add_assoc_long(zrecord, "uid", record->ruleuid);
286                 add_next_index_zval(zrecords, zrecord);
287         }
288     }
289
290 error:
291         rpa_records_destroy(records);
292         rpa_stat_destroy(stat);
293         rpa_dbex_destroy(dbex);
294         RETURN_LONG(ret);
295 }
296
297
298 PHP_FUNCTION(rpa_dbex_version)
299 {
300     RETURN_STRING((char*)rpa_dbex_version(), 1);
301 }
302
303
304 static void php_rpa_stat_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
305 {
306     php_rpa_stat *phpstat = (php_rpa_stat*)rsrc->ptr;
307
308     if (phpstat) {
309         rpa_stat_destroy(phpstat->stat);
310         efree(phpstat);
311     }
312 }
313
314
315 static void php_rpa_dbex_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
316 {
317     php_rpa_dbex *pPhpDbex = (php_rpa_dbex*)rsrc->ptr;
318
319     if (pPhpDbex) {
320                 rpa_dbex_destroy(pPhpDbex->hDbex);
321 /*
322                 zval_dtor(pPhpDbex->zcallbacks);
323                 Z_DELREF_P(pPhpDbex->zcallbacks);
324                 Z_DELREF_P(pPhpDbex->zcallbacks);
325                 php_printf("refcnt: %d\n", Z_REFCOUNT_P(pPhpDbex->zcallbacks));
326                 efree(pPhpDbex->zcallbacks);
327 */
328                 efree(pPhpDbex);
329     }
330 }
331
332
333 static void php_rpa_records_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
334 {
335     php_rpa_records *phprecords = (php_rpa_records*)rsrc->ptr;
336
337     if (phprecords) {
338         rpa_records_destroy(phprecords->records);
339         efree(phprecords);
340     }
341 }
342
343
344 PHP_FUNCTION(rpa_dbex_create)
345 {
346     php_rpa_dbex *pPhpDbex;
347
348 /*
349     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &name, &name_len, &age) == FAILURE) {
350                 RETURN_FALSE;
351     }
352 */
353
354     pPhpDbex = emalloc(sizeof(php_rpa_dbex));
355     pPhpDbex->hDbex = rpa_dbex_create();
356
357 /*
358         ALLOC_INIT_ZVAL(pPhpDbex->zcallbacks);
359         Z_ADDREF_P(pPhpDbex->zcallbacks);
360         array_init(pPhpDbex->zcallbacks);
361 */
362     ZEND_REGISTER_RESOURCE(return_value, pPhpDbex, le_rpa_dbex);
363 }
364
365
366 PHP_FUNCTION(rpa_dbex_open)
367 {
368         zval *zres;
369     php_rpa_dbex *pPhpDbex;
370         int ret;
371
372     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
373                 RETURN_LONG(-1);
374     }
375
376     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
377
378         ret = rpa_dbex_open(pPhpDbex->hDbex);
379         RETURN_LONG(ret);
380 }
381
382
383 PHP_FUNCTION(rpa_dbex_close)
384 {
385         zval *zres;
386     php_rpa_dbex *pPhpDbex;
387
388     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
389                 RETURN_LONG(-1);
390     }
391
392     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
393
394         rpa_dbex_close(pPhpDbex->hDbex);
395         RETURN_LONG(0);
396 }
397
398
399 PHP_FUNCTION(rpa_dbex_load)
400 {
401         zval *zres;
402     php_rpa_dbex *pPhpDbex;
403         char *patterns;
404         int patterns_len;
405         int ret;
406
407
408     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
409                 RETURN_LONG(-1);
410     }
411
412     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
413
414     ret = rpa_dbex_load_s(pPhpDbex->hDbex, patterns);
415         RETURN_LONG(ret);
416 }
417
418
419 PHP_FUNCTION(rpa_dbex_lookup)
420 {
421         zval *zres;
422     php_rpa_dbex *pPhpDbex;
423         char *name;
424         int name_len;
425         long ret;
426
427     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == 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_lookup(pPhpDbex->hDbex, name, name_len);
434         RETURN_LONG(ret);
435 }
436
437
438 PHP_FUNCTION(rpa_dbex_first)
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_first(pPhpDbex->hDbex);
451         RETURN_LONG(ret);
452 }
453
454
455 PHP_FUNCTION(rpa_dbex_last)
456 {
457         zval *zres;
458     php_rpa_dbex *pPhpDbex;
459         long ret;
460
461     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
462                 RETURN_LONG(-1);
463     }
464
465     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
466
467     ret = rpa_dbex_last(pPhpDbex->hDbex);
468         RETURN_LONG(ret);
469 }
470
471
472 PHP_FUNCTION(rpa_dbex_compile)
473 {
474         zval *zres;
475     php_rpa_dbex *pPhpDbex;
476         char *patterns;
477         int patterns_len;
478         int ret;
479
480
481     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
482                 RETURN_LONG(-1);
483     }
484
485     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
486
487     ret = rpa_dbex_compile(pPhpDbex->hDbex);
488         RETURN_LONG(ret);
489 }
490
491
492 PHP_FUNCTION(rpa_dbex_dumpproductions)
493 {
494         zval *zres;
495     php_rpa_dbex *pPhpDbex;
496         long ret;
497
498     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
499                 RETURN_LONG(-1);
500     }
501
502     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
503
504     ret = rpa_dbex_dumpproductions(pPhpDbex->hDbex);
505         RETURN_LONG(ret);
506 }
507
508
509 PHP_FUNCTION(rpa_dbex_cfgset)
510 {
511         zval *zres;
512     php_rpa_dbex *pPhpDbex;
513     long cfg, val;
514         long ret;
515
516     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rll", &zres, cfg, val) == FAILURE) {
517                 RETURN_LONG(-1);
518     }
519
520     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
521
522     ret = rpa_dbex_cfgset(pPhpDbex->hDbex, cfg, val);
523         RETURN_LONG(ret);
524 }
525
526
527 static rchar *dbexmsg[] = {
528         "OK",
529         "Out of memory",
530         "Invalid input.",
531         "Expression database is not open.",
532         "Expression database is not closed.",
533         "Expression name is not found.",
534         "Syntax error.",
535         "Unresolved expression name.",
536         "Invalid parameter.",
537         "Failed to compile rule.",
538         "Unknown",
539         "Unknown",
540         "Unknown",
541         "Unknown",
542         "Unknown",
543         "Unknown",
544         "Unknown",
545 };
546
547
548 static rchar *statmsg[] = {
549         "OK",
550         "Execution error.",
551         "Execution aborted by user.",
552         "Aborted on expression.",
553         "Unknown",
554         "Unknown",
555         "Unknown",
556         "Unknown",
557         "Unknown",
558         "Unknown",
559         "Unknown",
560 };
561
562
563 static void rpa_dbex_getdbexerrorstr(rpadbex_t *dbex, char *buffer, size_t size)
564 {
565         long n = 0;
566         char *ptr = buffer;
567         rpa_errinfo_t errorinfo;
568
569         memset(&errorinfo, 0, sizeof(errorinfo));
570     rpa_dbex_lasterrorinfo(dbex, &errorinfo);
571
572     if (errorinfo.mask & RPA_ERRINFO_CODE) {
573         n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo.code - 1000], errorinfo.code);
574     }
575     if (errorinfo.mask & RPA_ERRINFO_LINE) {
576         n += snprintf(ptr + n, size - n, "Line: %ld. ", errorinfo.line);
577     }
578     if (errorinfo.mask & RPA_ERRINFO_OFFSET) {
579         n += snprintf(ptr + n, size - n, "Offset: %ld. ", errorinfo.offset);
580     }
581     if (errorinfo.mask & RPA_ERRINFO_RULEID) {
582         n += snprintf(ptr + n, size - n, "RuleId: %ld. ", errorinfo.ruleid);
583     }
584     if (errorinfo.mask & RPA_ERRINFO_NAME) {
585         n += snprintf(ptr + n, size - n, "Name: %s. ", errorinfo.name);
586     }
587
588 }
589
590
591 PHP_FUNCTION(rpa_dbex_error)
592 {
593         zval *zres;
594         char buffer[2000];
595     php_rpa_dbex *pPhpDbex;
596
597         memset(buffer, 0, sizeof(buffer));
598     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
599                 RETURN_LONG(-1);
600     }
601
602     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
603     rpa_dbex_getdbexerrorstr(pPhpDbex->hDbex, buffer, sizeof(buffer));
604
605         RETURN_STRING(buffer, 1);
606 }
607
608
609 static void rpa_dbex_getstaterrorstr(rpastat_t *stat, char *buffer, size_t size)
610 {
611         long n = 0;
612         char *ptr = buffer;
613         rpa_errinfo_t errorinfo;
614
615         memset(&errorinfo, 0, sizeof(errorinfo));
616     rpa_stat_lasterrorinfo(stat, &errorinfo);
617
618     if (errorinfo.mask & RPA_ERRINFO_CODE) {
619         n += snprintf(ptr + n, size - n, "%s Code: %ld. ", dbexmsg[errorinfo.code - 2000], errorinfo.code);
620     }
621     if (errorinfo.mask & RPA_ERRINFO_LINE) {
622         n += snprintf(ptr + n, size - n, "Line: %ld. ", errorinfo.line);
623     }
624     if (errorinfo.mask & RPA_ERRINFO_OFFSET) {
625         n += snprintf(ptr + n, size - n, "Offset: %ld. ", errorinfo.offset);
626     }
627     if (errorinfo.mask & RPA_ERRINFO_RULEID) {
628         n += snprintf(ptr + n, size - n, "RuleId: %ld. ", errorinfo.ruleid);
629     }
630     if (errorinfo.mask & RPA_ERRINFO_NAME) {
631         n += snprintf(ptr + n, size - n, "Name: %s. ", errorinfo.name);
632     }
633
634 }
635
636
637 PHP_FUNCTION(rpa_stat_error)
638 {
639         zval *zres;
640         char buffer[2000];
641     php_rpa_stat *phpstat;
642
643         memset(buffer, 0, sizeof(buffer));
644     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
645                 RETURN_LONG(-1);
646     }
647
648     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zres, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
649     rpa_stat_geterrorstr(phpstat->stat, buffer, sizeof(buffer));
650
651         RETURN_STRING(buffer, 1);
652 }
653
654
655 PHP_FUNCTION(rpa_stat_create)
656 {
657         zval *zres;
658     php_rpa_dbex *pPhpDbex;
659     php_rpa_stat *phpstat;
660         int ret;
661         long stackSize = 0L;
662
663
664     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &stackSize) == FAILURE) {
665                 RETURN_LONG(-1);
666     }
667
668     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
669     phpstat = emalloc(sizeof(php_rpa_stat));
670     phpstat->stat = rpa_stat_create(pPhpDbex->hDbex, stackSize);
671     ZEND_REGISTER_RESOURCE(return_value, phpstat, le_rpa_stat);
672 }
673
674
675 PHP_FUNCTION(rpa_stat_match)
676 {
677         zval *zstat;
678     php_rpa_stat *phpstat;
679         long rid;
680         long encoding;
681         long ret;
682         char *input;
683         int input_len;
684
685     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls", &zstat, &rid, &encoding, &input, &input_len) == FAILURE) {
686                 RETURN_LONG(-1);
687     }
688     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
689     ret = rpa_stat_match(phpstat->stat, rid, encoding, input, input, input + input_len);
690         RETURN_LONG(ret);
691 }
692
693
694 PHP_FUNCTION(rpa_stat_scan)
695 {
696         zval *zstat;
697     php_rpa_stat *phpstat;
698         long rid;
699         long encoding;
700         long ret;
701         char *input;
702         int input_len;
703         zval *zwhere;
704         const char *where = NULL;
705
706     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rllsz", &zstat, &rid, &encoding, &input, &input_len, &zwhere) == FAILURE) {
707                 RETURN_LONG(-1);
708     }
709     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
710     ret = rpa_stat_scan(phpstat->stat, rid, encoding, input, input, input + input_len, &where);
711         if (ret) {
712                 ZVAL_LONG(zwhere, where - input);
713         } else {
714                 ZVAL_NULL(zwhere);
715         }
716
717         RETURN_LONG(ret);
718 }
719
720
721 PHP_FUNCTION(rpa_stat_parse)
722 {
723         zval *zstat;
724     php_rpa_stat *phpstat;
725         long rid;
726         long encoding;
727         long ret, i;
728         char *input;
729         int input_len;
730         zval *zrecords = NULL;
731         rarray_t *records = rpa_records_create();
732
733     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlls|z", &zstat, &rid, &encoding, &input, &input_len, &zrecords) == FAILURE) {
734                 RETURN_LONG(-1);
735     }
736     ZEND_FETCH_RESOURCE(phpstat, php_rpa_stat*, &zstat, -1, PHP_RPA_STAT_RES_NAME, le_rpa_stat);
737     ret = rpa_stat_parse(phpstat->stat, rid, encoding, input, input, input + input_len, records);
738     if (ret <= 0)
739         goto error;
740     if (zrecords) {
741         rparecord_t *record;
742         array_init(zrecords);
743         for (i = 0; i < rpa_records_length(records); i++) {
744                 zval *zrecord;
745                 record = rpa_records_slot(records, i);
746                 ALLOC_INIT_ZVAL(zrecord);
747                 array_init(zrecord);
748                 add_assoc_stringl(zrecord, "input", (char*)record->input, record->inputsiz, 1);
749                 add_assoc_string(zrecord, "rule", (char*)record->rule, 1);
750                 add_assoc_long(zrecord, "type", record->type);
751                 add_assoc_long(zrecord, "uid", record->ruleuid);
752                 add_next_index_zval(zrecords, zrecord);
753         }
754     }
755
756 error:
757         rpa_records_destroy(records);
758         RETURN_LONG(ret);
759 }
760
761
762 PHP_FUNCTION(rpa_records_create)
763 {
764     php_rpa_records *phprecords;
765
766     phprecords = emalloc(sizeof(php_rpa_records));
767     phprecords->records = rpa_records_create();
768
769     ZEND_REGISTER_RESOURCE(return_value, phprecords, le_rpa_dbex);
770 }
771
772
773 #if 0
774 static php_cbinfo *php_cbinfo_create(php_rpa_dbex *pPhpDbex, const char *php_callback, zval *userdata)
775 {
776         php_cbinfo *pCbInfo;
777
778         if ((pCbInfo = emalloc(sizeof(php_cbinfo))) == NULL)
779                 return NULL;
780
781         pCbInfo->pPhpDbex = pPhpDbex;
782         pCbInfo->php_callback = estrdup(php_callback);
783         pCbInfo->userdata = userdata;
784         if (userdata) {
785                 ZVAL_ADDREF(userdata);
786 //              Z_SET_ISREF_P(userdata);
787         }
788         return pCbInfo;
789 }
790
791
792 static void php_cbinfo_destroy(php_cbinfo *pCbInfo)
793 {
794         if (!pCbInfo)
795                 return;
796         if (pCbInfo->php_callback)
797                 efree(pCbInfo->php_callback);
798         if (pCbInfo->userdata) {
799                 if (ZVAL_REFCOUNT(pCbInfo->userdata) == 1) {
800                         zval_ptr_dtor(&pCbInfo->userdata);
801                 } else {
802                         ZVAL_DELREF(pCbInfo->userdata);
803                 }
804         }
805         efree(pCbInfo);
806 }
807
808
809 static void php_do_rpa_dbex_strmatch(INTERNAL_FUNCTION_PARAMETERS, int global) /* {{{ */
810 {
811     /* parameters */
812     char             *subject;          /* String to match against */
813     char             *regex;            /* Regular expression */
814     int               subject_len;
815     int               regex_len;
816         int                               ret = 0;
817
818         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &subject, 
819                                                           &subject_len,
820                                                           &regex,
821                                                           &regex_len) == FAILURE) {
822                 RETURN_LONG(-1);
823     }
824 /*
825         ret = emalloc(subject_len + regex_len + 100);
826         php_sprintf(ret, "Hello from rpalib, subject: %s, regex: %s", subject, regex);
827     RETURN_STRING(ret, 0);
828 */
829         ret = rpa_dbex_strmatch(subject, regex);
830         RETURN_LONG(ret);
831 }
832
833
834 /* {{{ proto int rpa_dbex_strmatch(string subject, string pattern)
835    Perform a regular expression match */
836 PHP_FUNCTION(rpa_dbex_strmatch)
837 {
838     php_do_rpa_dbex_strmatch(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
839 }
840
841
842 PHP_FUNCTION(rpa_dbex_greetme)
843 {
844     zval *zname;
845
846     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zname) == FAILURE) {
847         RETURN_NULL();
848     }
849
850     convert_to_string(zname);
851
852     php_printf("Hello ");
853     PHPWRITE(Z_STRVAL_P(zname), Z_STRLEN_P(zname));
854     php_printf(" ");
855
856     RETURN_TRUE;
857 }
858
859
860
861
862
863
864 PHP_FUNCTION(rpa_dbex_load_string)
865 {
866         zval *zres;
867     php_rpa_dbex *pPhpDbex;
868         char *patterns;
869         int patterns_len;
870         int ret;
871
872
873     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &patterns, &patterns_len) == FAILURE) {
874                 RETURN_LONG(-1);
875     }
876
877     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
878
879     ret = rpa_dbex_load_string(pPhpDbex->hDbex, patterns);
880         RETURN_LONG(ret);
881 }
882
883
884 PHP_FUNCTION(rpa_dbex_set_encoding)
885 {
886         zval *zres;
887     php_rpa_dbex *pPhpDbex;
888         char *patterns;
889         long encoding;
890         int patterns_len;
891         int ret;
892
893
894     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &encoding) == FAILURE) {
895                 RETURN_LONG(-1);
896     }
897
898     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
899
900     ret = rpa_dbex_set_encoding(pPhpDbex->hDbex, encoding);
901         RETURN_LONG(ret);
902 }
903
904
905 PHP_FUNCTION(rpa_dbex_match)
906 {
907         zval *zdbex;
908         zval *zpattern;
909         zval *zinput;
910     php_rpa_dbex *pPhpDbex;
911     php_rpa_pattern *pPhpPattern;
912         char *input;
913         int input_len;
914         int ret;
915
916     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &zdbex, &zpattern, &zinput) == FAILURE) {
917                 RETURN_LONG(-1);
918     }
919         input = Z_STRVAL_P(zinput);
920         input_len = Z_STRLEN_P(zinput);
921     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
922     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
923 #ifdef ZTS
924         pPhpDbex->tsrm_ls = TSRMLS_C;
925 #endif
926         pPhpDbex->zinput = zinput;
927     ret = rpa_dbex_match(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len);
928         RETURN_LONG(ret);
929 }
930
931
932 PHP_FUNCTION(rpa_dbex_parse)
933 {
934         zval *zdbex;
935         zval *zpattern;
936         zval *zinput;
937     php_rpa_dbex *pPhpDbex;
938     php_rpa_pattern *pPhpPattern;
939         char *input;
940         int input_len;
941         int ret;
942
943     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &zdbex, &zpattern, &zinput) == FAILURE) {
944                 RETURN_LONG(-1);
945     }
946         input = Z_STRVAL_P(zinput);
947         input_len = Z_STRLEN_P(zinput);
948     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
949     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
950 #ifdef ZTS
951         pPhpDbex->tsrm_ls = TSRMLS_C;
952 #endif
953         pPhpDbex->zinput = zinput;
954     ret = rpa_dbex_parse(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len);
955         RETURN_LONG(ret);
956 }
957
958
959 PHP_FUNCTION(rpa_dbex_scan)
960 {
961         zval *zdbex;
962         zval *zpattern;
963         zval *zinput;
964         zval *zwhere;
965     php_rpa_dbex *pPhpDbex;
966     php_rpa_pattern *pPhpPattern;
967         char *input;
968         const char *where = NULL;
969         int input_len;
970         int ret;
971
972     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrzz", &zdbex, &zpattern, &zinput, &zwhere) == FAILURE) {
973                 RETURN_LONG(-1);
974     }
975         input = Z_STRVAL_P(zinput);
976         input_len = Z_STRLEN_P(zinput);
977     ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zdbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
978     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zpattern, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
979 #ifdef ZTS
980         pPhpDbex->tsrm_ls = TSRMLS_C;
981 #endif
982         pPhpDbex->zinput = zinput;
983     ret = rpa_dbex_scan(pPhpDbex->hDbex, pPhpPattern->hPattern, input, input, input + input_len, &where);
984         if (ret) {
985                 ZVAL_LONG(zwhere, where - input);
986         } else {
987                 ZVAL_NULL(zwhere);
988         }
989
990         RETURN_LONG(ret);
991 }
992
993
994 PHP_FUNCTION(rpa_dbex_get_pattern)
995 {
996         zval *zres;
997         php_rpa_dbex *pPhpDbex;
998         php_rpa_pattern *pPhpPattern;
999         char *name;
1000         int name_len;
1001         rpa_pattern_handle hPattern;
1002
1003         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zres, &name, &name_len) == FAILURE) {
1004                 RETURN_FALSE;
1005         }
1006         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1007         hPattern = rpa_dbex_get_pattern(pPhpDbex->hDbex, name);
1008         if (!hPattern)
1009                 RETURN_FALSE;
1010         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
1011         pPhpPattern->hPattern = hPattern;
1012         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
1013 }
1014
1015
1016 PHP_FUNCTION(rpa_dbex_default_pattern)
1017 {
1018         zval *zres;
1019         php_rpa_dbex *pPhpDbex;
1020         php_rpa_pattern *pPhpPattern;
1021         rpa_pattern_handle hPattern;
1022
1023         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
1024                 RETURN_FALSE;
1025         }
1026         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1027         hPattern = rpa_dbex_default_pattern(pPhpDbex->hDbex);
1028         if (!hPattern)
1029                 RETURN_FALSE;
1030         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
1031         pPhpPattern->hPattern = hPattern;
1032         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
1033 }
1034
1035
1036 PHP_FUNCTION(rpa_dbex_first_pattern)
1037 {
1038         zval *zres;
1039         php_rpa_dbex *pPhpDbex;
1040         php_rpa_pattern *pPhpPattern;
1041         rpa_pattern_handle hPattern;
1042
1043         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
1044                 RETURN_FALSE;
1045         }
1046         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1047         hPattern = rpa_dbex_first_pattern(pPhpDbex->hDbex);
1048         if (!hPattern)
1049                 RETURN_FALSE;
1050         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
1051         pPhpPattern->hPattern = hPattern;
1052         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
1053 }
1054
1055
1056 PHP_FUNCTION(rpa_dbex_last_pattern)
1057 {
1058         zval *zres;
1059         php_rpa_dbex *pPhpDbex;
1060         php_rpa_pattern *pPhpPattern;
1061         rpa_pattern_handle hPattern;
1062
1063         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres) == FAILURE) {
1064                 RETURN_FALSE;
1065         }
1066         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zres, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1067         hPattern = rpa_dbex_last_pattern(pPhpDbex->hDbex);
1068         if (!hPattern)
1069                 RETURN_FALSE;
1070         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
1071         pPhpPattern->hPattern = hPattern;
1072         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
1073 }
1074
1075
1076 PHP_FUNCTION(rpa_dbex_next_pattern)
1077 {
1078         zval *zresFirst, *zresSecond;
1079         php_rpa_dbex *pPhpDbex;
1080         php_rpa_pattern *pPhpPatternCur;
1081         php_rpa_pattern *pPhpPattern;
1082         rpa_pattern_handle hPattern;
1083
1084         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
1085                 RETURN_FALSE;
1086         }
1087         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1088     ZEND_FETCH_RESOURCE(pPhpPatternCur, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
1089                 
1090         hPattern = rpa_dbex_next_pattern(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPatternCur ? pPhpPatternCur->hPattern : NULL);
1091         if (!hPattern)
1092                 RETURN_FALSE;
1093         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
1094         pPhpPattern->hPattern = hPattern;
1095         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
1096 }
1097
1098
1099 PHP_FUNCTION(rpa_dbex_prev_pattern)
1100 {
1101         zval *zresFirst, *zresSecond;
1102         php_rpa_dbex *pPhpDbex;
1103         php_rpa_pattern *pPhpPatternCur;
1104         php_rpa_pattern *pPhpPattern;
1105         rpa_pattern_handle hPattern;
1106
1107         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
1108                 RETURN_FALSE;
1109         }
1110         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1111     ZEND_FETCH_RESOURCE(pPhpPatternCur, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
1112                 
1113         hPattern = rpa_dbex_prev_pattern(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPatternCur ? pPhpPatternCur->hPattern : NULL);
1114         if (!hPattern)
1115                 RETURN_FALSE;
1116         pPhpPattern = emalloc(sizeof(php_rpa_pattern));
1117         pPhpPattern->hPattern = hPattern;
1118         ZEND_REGISTER_RESOURCE(return_value, pPhpPattern, le_rpa_pattern);
1119 }
1120
1121
1122 PHP_FUNCTION(rpa_dbex_pattern_name)
1123 {
1124         zval *zresFirst, *zresSecond;
1125         php_rpa_dbex *pPhpDbex;
1126         php_rpa_pattern *pPhpPattern;
1127         const char *name;
1128         char *ret;
1129
1130         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &zresFirst, &zresSecond) == FAILURE) {
1131                 RETURN_FALSE;
1132         }
1133         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1134     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
1135                 
1136         name = rpa_dbex_pattern_name(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPattern ? pPhpPattern->hPattern : NULL);
1137         if (!name)
1138                 RETURN_FALSE;
1139         ret = estrdup(name);
1140         RETURN_STRING(ret, 0);
1141 }
1142
1143
1144 PHP_FUNCTION(rpa_dbex_pattern_regex)
1145 {
1146         zval *zresFirst, *zresSecond;
1147         php_rpa_dbex *pPhpDbex;
1148         php_rpa_pattern *pPhpPattern;
1149         long int seq = 0;
1150         const char *regex;
1151         char *ret;
1152
1153         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &zresFirst, &zresSecond, &seq) == FAILURE) {
1154                 RETURN_FALSE;
1155         }
1156         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresFirst, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1157     ZEND_FETCH_RESOURCE(pPhpPattern, php_rpa_pattern*, &zresSecond, -1, PHP_RPA_PATTERN_RES_NAME, le_rpa_pattern);
1158                 
1159         regex = rpa_dbex_pattern_regex(pPhpDbex ? pPhpDbex->hDbex : NULL, pPhpPattern ? pPhpPattern->hPattern : NULL, seq);
1160         if (!regex)
1161                 RETURN_FALSE;
1162         ret = estrdup(regex);
1163         RETURN_STRING(ret, 0);
1164 }
1165
1166
1167 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)
1168 {
1169         php_cbinfo *pCbInfo = (php_cbinfo*)userdata;
1170         zval *retval_ptr = NULL;  /* Function return value */
1171     zval **args[7];           /* Argument to pass to function */
1172         zval *zcallback;
1173         zval *zname;
1174         zval *zoffset;
1175         zval *zsize;
1176         zval *zreason;
1177         zval *zuserdata;
1178         zval *zempty;
1179         int ret = size;
1180 #ifdef ZTS
1181         TSRMLS_D = pCbInfo->pPhpDbex->tsrm_ls;
1182 #endif
1183
1184         MAKE_STD_ZVAL(zcallback);
1185         MAKE_STD_ZVAL(zname);
1186         MAKE_STD_ZVAL(zoffset);
1187         MAKE_STD_ZVAL(zsize);
1188         MAKE_STD_ZVAL(zreason);
1189         MAKE_STD_ZVAL(zuserdata);
1190         MAKE_STD_ZVAL(zempty);
1191
1192         ZVAL_STRING(zcallback, pCbInfo->php_callback, 1);
1193         ZVAL_LONG(zsize, size);
1194         ZVAL_LONG(zreason, reason);
1195         ZVAL_LONG(zempty, 0);
1196         ZVAL_LONG(zoffset, input - start);
1197         ZVAL_STRING(zname, name, 1);
1198
1199         args[0] = &zname;
1200         if (pCbInfo->userdata) {
1201                 args[1] = &pCbInfo->userdata;
1202         } else {
1203                 args[1] = &zempty;
1204         }
1205
1206
1207         args[2] = &zoffset;
1208         args[3] = &zsize;
1209         args[4] = &zreason;
1210         args[5] = &pCbInfo->pPhpDbex->zinput;
1211
1212
1213         if (call_user_function_ex(EG(function_table), NULL, zcallback, &retval_ptr, 6, args, 0, NULL TSRMLS_CC) == SUCCESS && retval_ptr) {
1214                 convert_to_long(retval_ptr);
1215                 ret = (int) Z_LVAL_P(retval_ptr);
1216                 zval_ptr_dtor(&retval_ptr);
1217         } else {
1218                 if (!EG(exception)) {
1219                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call function: %s()", Z_STRVAL_P(zcallback));
1220                 }
1221         }
1222
1223 /*
1224         zval_ptr_dtor(&zcallback);
1225         zval_ptr_dtor(&zname);
1226         zval_ptr_dtor(&zsize);
1227         zval_ptr_dtor(&zreason);
1228         zval_ptr_dtor(&zuserdata);
1229         zval_ptr_dtor(&zoffset);
1230         zval_ptr_dtor(&zempty);
1231 */
1232
1233         return ret;
1234 }
1235
1236
1237 PHP_FUNCTION(rpa_dbex_add_callback)
1238 {
1239         zval *zresDbex, *zresCallback, *zresUserData = NULL;
1240         php_rpa_dbex *pPhpDbex;
1241         php_rpa_pattern *pPhpPattern;
1242         char *name;
1243         long reason;
1244         int name_len = 0;
1245         char *callback;
1246         int callback_len = 0;
1247         unsigned long ret = 0;
1248         php_cbinfo *pCbInfo;
1249
1250         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsls|z", &zresDbex, &name, &name_len, &reason, 
1251                                                           &callback, &callback_len, &zresUserData) == FAILURE) {
1252                 RETURN_LONG(-1);
1253         }
1254         ZEND_FETCH_RESOURCE(pPhpDbex, php_rpa_dbex*, &zresDbex, -1, PHP_RPA_DBEX_RES_NAME, le_rpa_dbex);
1255
1256         pCbInfo = php_cbinfo_create(pPhpDbex, callback, zresUserData);
1257         ret = rpa_dbex_add_callback(pPhpDbex ? pPhpDbex->hDbex : NULL, name, reason, php_rpa_callback_proxy, pCbInfo);
1258         RETURN_LONG(ret);
1259 }
1260
1261 #endif