1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2016 The PHP Group |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.0 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/3_0.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: Pierre-Alain Joye <paj@pearfr.org> |
16 | Ilia Alshanetsky <ilia@prohost.org> |
17 +----------------------------------------------------------------------+
18
19 $Id: 2b1a7a0910b094a8f56f81d474ff1837c4389a28 $
20 */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include "php.h"
27 #include "php_ini.h"
28 #include "ext/standard/info.h"
29 #include <enchant.h>
30 #include "php_enchant.h"
31
32 typedef EnchantBroker * EnchantBrokerPtr;
33 typedef struct _broker_struct enchant_broker;
34 typedef struct _dict_struct enchant_dict;
35
36 typedef enchant_broker * enchant_brokerPtr;
37 typedef enchant_dict * enchant_dictPtr;
38
39 typedef struct _broker_struct {
40 EnchantBroker *pbroker;
41 enchant_dict **dict;
42 unsigned int dictcnt;
43 long rsrc_id;
44 } _enchant_broker;
45
46 typedef struct _dict_struct {
47 unsigned int id;
48 EnchantDict *pdict;
49 enchant_broker *pbroker;
50 long rsrc_id;
51 enchant_dict *next;
52 enchant_dict *prev;
53 } _enchant_dict;
54
55
56 /* True global resources - no need for thread safety here */
57 static int le_enchant_broker;
58 static int le_enchant_dict;
59
60 /* If you declare any globals in php_enchant.h uncomment this:*/
61 /*ZEND_DECLARE_MODULE_GLOBALS(enchant)*/
62
63 #define PHP_ENCHANT_MYSPELL 1
64 #define PHP_ENCHANT_ISPELL 2
65
66 /* {{{ arginfo */
67 ZEND_BEGIN_ARG_INFO(arginfo_enchant_broker_init, 0)
68 ZEND_END_ARG_INFO()
69
70 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_free, 0, 0, 1)
71 ZEND_ARG_INFO(0, broker)
72 ZEND_END_ARG_INFO()
73
74 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_set_dict_path, 0, 0, 3)
75 ZEND_ARG_INFO(0, broker)
76 ZEND_ARG_INFO(0, name)
77 ZEND_ARG_INFO(0, value)
78 ZEND_END_ARG_INFO()
79
80 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_get_dict_path, 0, 0, 2)
81 ZEND_ARG_INFO(0, broker)
82 ZEND_ARG_INFO(0, name)
83 ZEND_END_ARG_INFO()
84
85 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_request_dict, 0, 0, 2)
86 ZEND_ARG_INFO(0, broker)
87 ZEND_ARG_INFO(0, tag)
88 ZEND_END_ARG_INFO()
89
90 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_request_pwl_dict, 0, 0, 2)
91 ZEND_ARG_INFO(0, broker)
92 ZEND_ARG_INFO(0, filename)
93 ZEND_END_ARG_INFO()
94
95 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_free_dict, 0, 0, 1)
96 ZEND_ARG_INFO(0, dict)
97 ZEND_END_ARG_INFO()
98
99 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_broker_set_ordering, 0, 0, 3)
100 ZEND_ARG_INFO(0, broker)
101 ZEND_ARG_INFO(0, tag)
102 ZEND_ARG_INFO(0, ordering)
103 ZEND_END_ARG_INFO()
104
105 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_quick_check, 0, 0, 2)
106 ZEND_ARG_INFO(0, dict)
107 ZEND_ARG_INFO(0, word)
108 ZEND_ARG_INFO(1, suggestions)
109 ZEND_END_ARG_INFO()
110
111 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_check, 0, 0, 2)
112 ZEND_ARG_INFO(0, dict)
113 ZEND_ARG_INFO(0, word)
114 ZEND_END_ARG_INFO()
115
116 ZEND_BEGIN_ARG_INFO_EX(arginfo_enchant_dict_store_replacement, 0, 0, 3)
117 ZEND_ARG_INFO(0, dict)
118 ZEND_ARG_INFO(0, mis)
119 ZEND_ARG_INFO(0, cor)
120 ZEND_END_ARG_INFO()
121 /* }}} */
122
123 /* {{{ enchant_functions[]
124 *
125 * Every user visible function must have an entry in enchant_functions[].
126 */
127 zend_function_entry enchant_functions[] = {
128 PHP_FE(enchant_broker_init, arginfo_enchant_broker_init)
129 PHP_FE(enchant_broker_free, arginfo_enchant_broker_free)
130 PHP_FE(enchant_broker_get_error, arginfo_enchant_broker_free)
131 PHP_FE(enchant_broker_set_dict_path, arginfo_enchant_broker_set_dict_path)
132 PHP_FE(enchant_broker_get_dict_path, arginfo_enchant_broker_get_dict_path)
133 PHP_FE(enchant_broker_list_dicts, arginfo_enchant_broker_free)
134 PHP_FE(enchant_broker_request_dict, arginfo_enchant_broker_request_dict)
135 PHP_FE(enchant_broker_request_pwl_dict, arginfo_enchant_broker_request_pwl_dict)
136 PHP_FE(enchant_broker_free_dict, arginfo_enchant_broker_free_dict)
137 PHP_FE(enchant_broker_dict_exists, arginfo_enchant_broker_request_dict)
138 PHP_FE(enchant_broker_set_ordering, arginfo_enchant_broker_set_ordering)
139 PHP_FE(enchant_broker_describe, arginfo_enchant_broker_free)
140 PHP_FE(enchant_dict_check, arginfo_enchant_dict_check)
141 PHP_FE(enchant_dict_suggest, arginfo_enchant_dict_check)
142 PHP_FE(enchant_dict_add_to_personal, arginfo_enchant_dict_check)
143 PHP_FE(enchant_dict_add_to_session, arginfo_enchant_dict_check)
144 PHP_FE(enchant_dict_is_in_session, arginfo_enchant_dict_check)
145 PHP_FE(enchant_dict_store_replacement, arginfo_enchant_dict_store_replacement)
146 PHP_FE(enchant_dict_get_error, arginfo_enchant_broker_free_dict)
147 PHP_FE(enchant_dict_describe, arginfo_enchant_broker_free_dict)
148 PHP_FE(enchant_dict_quick_check, arginfo_enchant_dict_quick_check)
149 PHP_FE_END
150 };
151 /* }}} */
152
153 /* {{{ enchant_module_entry
154 */
155 zend_module_entry enchant_module_entry = {
156 #if ZEND_MODULE_API_NO >= 20010901
157 STANDARD_MODULE_HEADER,
158 #endif
159 "enchant",
160 enchant_functions,
161 PHP_MINIT(enchant),
162 PHP_MSHUTDOWN(enchant),
163 NULL, /* Replace with NULL if there's nothing to do at request start */
164 NULL, /* Replace with NULL if there's nothing to do at request end */
165 PHP_MINFO(enchant),
166 #if ZEND_MODULE_API_NO >= 20010901
167 PHP_ENCHANT_VERSION,
168 #endif
169 STANDARD_MODULE_PROPERTIES
170 };
171 /* }}} */
172
173 #ifdef COMPILE_DL_ENCHANT
ZEND_GET_MODULE(enchant)174 ZEND_GET_MODULE(enchant)
175 #endif
176
177 static void
178 enumerate_providers_fn (const char * const name,
179 const char * const desc,
180 const char * const file,
181 void * ud) /* {{{ */
182 {
183 zval *zdesc = (zval *) ud;
184 zval *tmp_array;
185
186 MAKE_STD_ZVAL(tmp_array);
187 array_init(tmp_array);
188
189 add_assoc_string(tmp_array, "name", (char *)name, 1);
190 add_assoc_string(tmp_array, "desc", (char *)desc, 1);
191 add_assoc_string(tmp_array, "file", (char *)file, 1);
192
193 if (Z_TYPE_P(zdesc)!=IS_ARRAY) {
194 array_init(zdesc);
195 }
196
197 add_next_index_zval(zdesc, tmp_array);
198 }
199 /* }}} */
200
201 static void
describe_dict_fn(const char * const lang,const char * const name,const char * const desc,const char * const file,void * ud)202 describe_dict_fn (const char * const lang,
203 const char * const name,
204 const char * const desc,
205 const char * const file,
206 void * ud) /* {{{ */
207 {
208 zval *zdesc = (zval *) ud;
209 array_init(zdesc);
210 add_assoc_string(zdesc, "lang", (char *)lang, 1);
211 add_assoc_string(zdesc, "name", (char *)name, 1);
212 add_assoc_string(zdesc, "desc", (char *)desc, 1);
213 add_assoc_string(zdesc, "file", (char *)file, 1);
214 }
215 /* }}} */
216
php_enchant_list_dicts_fn(const char * const lang_tag,const char * const provider_name,const char * const provider_desc,const char * const provider_file,void * ud)217 static void php_enchant_list_dicts_fn( const char * const lang_tag,
218 const char * const provider_name, const char * const provider_desc,
219 const char * const provider_file, void * ud) /* {{{ */
220 {
221 zval *zdesc = (zval *) ud;
222 zval *tmp_array;
223
224 MAKE_STD_ZVAL(tmp_array);
225 array_init(tmp_array);
226 add_assoc_string(tmp_array, "lang_tag", (char *)lang_tag, 1);
227 add_assoc_string(tmp_array, "provider_name", (char *)provider_name, 1);
228 add_assoc_string(tmp_array, "provider_desc", (char *)provider_desc, 1);
229 add_assoc_string(tmp_array, "provider_file", (char *)provider_file, 1);
230
231 if (Z_TYPE_P(zdesc) != IS_ARRAY) {
232 array_init(zdesc);
233 }
234 add_next_index_zval(zdesc, tmp_array);
235
236 }
237 /* }}} */
238
php_enchant_broker_free(zend_rsrc_list_entry * rsrc TSRMLS_DC)239 static void php_enchant_broker_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
240 {
241 if (rsrc->ptr) {
242 enchant_broker *broker = (enchant_broker *)rsrc->ptr;
243 if (broker) {
244 if (broker->pbroker) {
245 if (broker->dictcnt && broker->dict) {
246 if (broker->dict) {
247 int total;
248 total = broker->dictcnt-1;
249 do {
250 zend_list_delete(broker->dict[total]->rsrc_id);
251 efree(broker->dict[total]);
252 total--;
253 } while (total>=0);
254 }
255 efree(broker->dict);
256 broker->dict = NULL;
257 }
258 enchant_broker_free(broker->pbroker);
259 }
260 efree(broker);
261 }
262 }
263 }
264 /* }}} */
265
php_enchant_dict_free(zend_rsrc_list_entry * rsrc TSRMLS_DC)266 static void php_enchant_dict_free(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
267
268 {
269 if (rsrc->ptr) {
270 enchant_dict *pdict = (enchant_dict *)rsrc->ptr;
271 if (pdict) {
272 if (pdict->pdict && pdict->pbroker) {
273 enchant_broker_free_dict(pdict->pbroker->pbroker, pdict->pdict);
274 if (pdict->id) {
275 pdict->pbroker->dict[pdict->id-1]->next = NULL;
276 }
277 zend_list_delete(pdict->pbroker->rsrc_id);
278 }
279
280 }
281 }
282 }
283 /* }}} */
284
285 /* {{{ PHP_MINIT_FUNCTION
286 */
PHP_MINIT_FUNCTION(enchant)287 PHP_MINIT_FUNCTION(enchant)
288 {
289 le_enchant_broker = zend_register_list_destructors_ex(php_enchant_broker_free, NULL, "enchant_broker", module_number);
290 le_enchant_dict = zend_register_list_destructors_ex(php_enchant_dict_free, NULL, "enchant_dict", module_number);
291 REGISTER_LONG_CONSTANT("ENCHANT_MYSPELL", PHP_ENCHANT_MYSPELL, CONST_CS | CONST_PERSISTENT);
292 REGISTER_LONG_CONSTANT("ENCHANT_ISPELL", PHP_ENCHANT_ISPELL, CONST_CS | CONST_PERSISTENT);
293 return SUCCESS;
294 }
295 /* }}} */
296
297 /* {{{ PHP_MSHUTDOWN_FUNCTION
298 */
PHP_MSHUTDOWN_FUNCTION(enchant)299 PHP_MSHUTDOWN_FUNCTION(enchant)
300 {
301 return SUCCESS;
302 }
303 /* }}} */
304
__enumerate_providers_fn(const char * const name,const char * const desc,const char * const file,void * ud)305 static void __enumerate_providers_fn (const char * const name,
306 const char * const desc,
307 const char * const file,
308 void * ud) /* {{{ */
309 {
310 php_info_print_table_row(3, name, desc, file);
311 }
312 /* }}} */
313
314 /* {{{ PHP_MINFO_FUNCTION
315 */
PHP_MINFO_FUNCTION(enchant)316 PHP_MINFO_FUNCTION(enchant)
317 {
318 EnchantBroker *pbroker;
319
320 pbroker = enchant_broker_init();
321 php_info_print_table_start();
322 php_info_print_table_header(2, "enchant support", "enabled");
323 php_info_print_table_row(2, "Version", PHP_ENCHANT_VERSION);
324 #ifdef ENCHANT_VERSION_STRING
325 php_info_print_table_row(2, "Libenchant Version", ENCHANT_VERSION_STRING);
326 #elif defined(HAVE_ENCHANT_BROKER_SET_PARAM)
327 php_info_print_table_row(2, "Libenchant Version", "1.5.0 or later");
328 #endif
329 php_info_print_table_row(2, "Revision", "$Id: 2b1a7a0910b094a8f56f81d474ff1837c4389a28 $");
330 php_info_print_table_end();
331
332 php_info_print_table_start();
333 enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL);
334 php_info_print_table_end();
335 enchant_broker_free(pbroker);
336 }
337 /* }}} */
338
339 #define PHP_ENCHANT_GET_BROKER \
340 ZEND_FETCH_RESOURCE(pbroker, enchant_broker *, &broker, -1, "enchant_broker", le_enchant_broker); \
341 if (!pbroker || !pbroker->pbroker) { \
342 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Resource broker invalid"); \
343 RETURN_FALSE; \
344 }
345
346 #define PHP_ENCHANT_GET_DICT \
347 ZEND_FETCH_RESOURCE(pdict, enchant_dict *, &dict, -1, "enchant_dict", le_enchant_dict); \
348 if (!pdict || !pdict->pdict) { \
349 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Invalid dictionary resource."); \
350 RETURN_FALSE; \
351 }
352
353 /* {{{ proto resource enchant_broker_init()
354 create a new broker object capable of requesting */
PHP_FUNCTION(enchant_broker_init)355 PHP_FUNCTION(enchant_broker_init)
356 {
357 enchant_broker *broker;
358 EnchantBroker *pbroker;
359
360 if (zend_parse_parameters_none() == FAILURE) {
361 return;
362 }
363
364 pbroker = enchant_broker_init();
365
366 if (pbroker) {
367 broker = (enchant_broker *) emalloc(sizeof(enchant_broker));
368 broker->pbroker = pbroker;
369 broker->dict = NULL;
370 broker->dictcnt = 0;
371 broker->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, broker, le_enchant_broker);
372 } else {
373 RETURN_FALSE;
374 }
375 }
376 /* }}} */
377
378 /* {{{ proto boolean enchant_broker_free(resource broker)
379 Destroys the broker object and its dictionnaries */
PHP_FUNCTION(enchant_broker_free)380 PHP_FUNCTION(enchant_broker_free)
381 {
382 zval *broker;
383 enchant_broker *pbroker;
384
385 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
386 RETURN_FALSE;
387 }
388 PHP_ENCHANT_GET_BROKER;
389
390 zend_list_delete(Z_RESVAL_P(broker));
391 RETURN_TRUE;
392 }
393 /* }}} */
394
395 /* {{{ proto string enchant_broker_get_error(resource broker)
396 Returns the last error of the broker */
PHP_FUNCTION(enchant_broker_get_error)397 PHP_FUNCTION(enchant_broker_get_error)
398 {
399 zval *broker;
400 enchant_broker *pbroker;
401 char *msg;
402
403 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
404 RETURN_FALSE;
405 }
406
407 PHP_ENCHANT_GET_BROKER;
408
409 msg = enchant_broker_get_error(pbroker->pbroker);
410 if (msg) {
411 RETURN_STRING((char *)msg, 1);
412 }
413 RETURN_FALSE;
414 }
415 /* }}} */
416
417 #if HAVE_ENCHANT_BROKER_SET_PARAM
418 /* {{{ proto bool enchant_broker_set_dict_path(resource broker, int dict_type, string value)
419 Set the directory path for a given backend, works with ispell and myspell */
PHP_FUNCTION(enchant_broker_set_dict_path)420 PHP_FUNCTION(enchant_broker_set_dict_path)
421 {
422 zval *broker;
423 enchant_broker *pbroker;
424 long dict_type;
425 char *value;
426 int value_len;
427
428 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &broker, &dict_type, &value, &value_len) == FAILURE) {
429 RETURN_FALSE;
430 }
431
432 if (!value_len) {
433 RETURN_FALSE;
434 }
435
436 PHP_ENCHANT_GET_BROKER;
437
438 switch (dict_type) {
439 case PHP_ENCHANT_MYSPELL:
440 PHP_ENCHANT_GET_BROKER;
441 enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", (const char *)value);
442 RETURN_TRUE;
443 break;
444
445 case PHP_ENCHANT_ISPELL:
446 PHP_ENCHANT_GET_BROKER;
447 enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", (const char *)value);
448 RETURN_TRUE;
449 break;
450
451 default:
452 RETURN_FALSE;
453 }
454 }
455 /* }}} */
456
457
458 /* {{{ proto string enchant_broker_get_dict_path(resource broker, int dict_type)
459 Get the directory path for a given backend, works with ispell and myspell */
PHP_FUNCTION(enchant_broker_get_dict_path)460 PHP_FUNCTION(enchant_broker_get_dict_path)
461 {
462 zval *broker;
463 enchant_broker *pbroker;
464 long dict_type;
465 char *value;
466
467 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &broker, &dict_type) == FAILURE) {
468 RETURN_FALSE;
469 }
470
471 PHP_ENCHANT_GET_BROKER;
472
473 switch (dict_type) {
474 case PHP_ENCHANT_MYSPELL:
475 PHP_ENCHANT_GET_BROKER;
476 value = enchant_broker_get_param(pbroker->pbroker, "enchant.myspell.dictionary.path");
477 break;
478
479 case PHP_ENCHANT_ISPELL:
480 PHP_ENCHANT_GET_BROKER;
481 value = enchant_broker_get_param(pbroker->pbroker, "enchant.ispell.dictionary.path");
482 break;
483
484 default:
485 RETURN_FALSE;
486 }
487
488 RETURN_STRING(value, 1);
489 }
490 /* }}} */
491 #else
492 /* {{{ proto bool enchant_broker_set_dict_path(resource broker, int dict_type, string value)
493 Set the directory path for a given backend, works with ispell and myspell */
PHP_FUNCTION(enchant_broker_set_dict_path)494 PHP_FUNCTION(enchant_broker_set_dict_path)
495 {
496 RETURN_FALSE;
497 }
498 /* }}} */
499
500
501 /* {{{ proto string enchant_broker_get_dict_path(resource broker, int dict_type)
502 Get the directory path for a given backend, works with ispell and myspell */
PHP_FUNCTION(enchant_broker_get_dict_path)503 PHP_FUNCTION(enchant_broker_get_dict_path)
504 {
505 RETURN_FALSE;
506 }
507 /* }}} */
508 #endif
509
510 /* {{{ proto string enchant_broker_list_dicts(resource broker)
511 Lists the dictionaries available for the given broker */
PHP_FUNCTION(enchant_broker_list_dicts)512 PHP_FUNCTION(enchant_broker_list_dicts)
513 {
514 zval *broker;
515 enchant_broker *pbroker;
516
517 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
518 RETURN_FALSE;
519 }
520
521 PHP_ENCHANT_GET_BROKER;
522
523 enchant_broker_list_dicts(pbroker->pbroker, php_enchant_list_dicts_fn, (void *)return_value);
524 }
525 /* }}} */
526
527 /* {{{ proto resource enchant_broker_request_dict(resource broker, string tag)
528 create a new dictionary using tag, the non-empty language tag you wish to request
529 a dictionary for ("en_US", "de_DE", ...) */
PHP_FUNCTION(enchant_broker_request_dict)530 PHP_FUNCTION(enchant_broker_request_dict)
531 {
532 zval *broker;
533 enchant_broker *pbroker;
534 enchant_dict *dict;
535 EnchantDict *d;
536 char *tag;
537 int taglen;
538 int pos;
539
540 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) {
541 RETURN_FALSE;
542 }
543
544 PHP_ENCHANT_GET_BROKER;
545
546 if (taglen == 0) {
547 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Tag cannot be empty");
548 RETURN_FALSE;
549 }
550
551 d = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag);
552 if (d) {
553 pos = pbroker->dictcnt++;
554 if (pbroker->dictcnt) {
555 pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
556 } else {
557 pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
558 pos = 0;
559 }
560
561 dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
562 dict->id = pos;
563 dict->pbroker = pbroker;
564 dict->pdict = d;
565 dict->prev = pos ? pbroker->dict[pos-1] : NULL;
566 dict->next = NULL;
567 pbroker->dict[pos] = dict;
568
569 if (pos) {
570 pbroker->dict[pos-1]->next = dict;
571 }
572
573 dict->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict);
574 zend_list_addref(pbroker->rsrc_id);
575 } else {
576 RETURN_FALSE;
577 }
578 }
579 /* }}} */
580
581 /* {{{ proto resource enchant_broker_request_pwl_dict(resource broker, string filename)
582 creates a dictionary using a PWL file. A PWL file is personal word file one word per line. It must exist before the call.*/
PHP_FUNCTION(enchant_broker_request_pwl_dict)583 PHP_FUNCTION(enchant_broker_request_pwl_dict)
584 {
585 zval *broker;
586 enchant_broker *pbroker;
587 enchant_dict *dict;
588 EnchantDict *d;
589 char *pwl;
590 int pwllen;
591 int pos;
592
593 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp", &broker, &pwl, &pwllen) == FAILURE) {
594 RETURN_FALSE;
595 }
596
597 #if PHP_API_VERSION < 20100412
598 if ((PG(safe_mode) && (!php_checkuid(pwl, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(pwl TSRMLS_CC)) {
599 #else
600 if (php_check_open_basedir(pwl TSRMLS_CC)) {
601 #endif
602 RETURN_FALSE;
603 }
604
605 PHP_ENCHANT_GET_BROKER;
606
607 d = enchant_broker_request_pwl_dict(pbroker->pbroker, (const char *)pwl);
608 if (d) {
609 pos = pbroker->dictcnt++;
610 if (pbroker->dictcnt) {
611 pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
612 } else {
613 pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
614 pos = 0;
615 }
616
617 dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
618 dict->id = pos;
619 dict->pbroker = pbroker;
620 dict->pdict = d;
621 dict->prev = pos?pbroker->dict[pos-1]:NULL;
622 dict->next = NULL;
623 pbroker->dict[pos] = dict;
624 if (pos) {
625 pbroker->dict[pos-1]->next = dict;
626 }
627 dict->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, dict, le_enchant_dict);
628 } else {
629 RETURN_FALSE;
630 }
631 }
632 /* }}} */
633
634 /* {{{ proto resource enchant_broker_free_dict(resource dict)
635 Free the dictionary resource */
636 PHP_FUNCTION(enchant_broker_free_dict)
637 {
638 zval *dict;
639 enchant_dict *pdict;
640
641 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
642 RETURN_FALSE;
643 }
644
645 PHP_ENCHANT_GET_DICT;
646
647 zend_list_delete(Z_RESVAL_P(dict));
648 RETURN_TRUE;
649 }
650 /* }}} */
651
652 /* {{{ proto bool enchant_broker_dict_exists(resource broker, string tag)
653 Whether a dictionary exists or not. Using non-empty tag */
654 PHP_FUNCTION(enchant_broker_dict_exists)
655 {
656 zval *broker;
657 char *tag;
658 int taglen;
659 enchant_broker * pbroker;
660
661 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &broker, &tag, &taglen) == FAILURE) {
662 RETURN_FALSE;
663 }
664
665 PHP_ENCHANT_GET_BROKER;
666
667 RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag));
668 }
669 /* }}} */
670
671 /* {{{ proto bool enchant_broker_set_ordering(resource broker, string tag, string ordering)
672 Declares a preference of dictionaries to use for the language
673 described/referred to by 'tag'. The ordering is a comma delimited
674 list of provider names. As a special exception, the "*" tag can
675 be used as a language tag to declare a default ordering for any
676 language that does not explicitly declare an ordering. */
677
678 PHP_FUNCTION(enchant_broker_set_ordering)
679 {
680 zval *broker;
681 char *pordering;
682 int porderinglen;
683 char *ptag;
684 int ptaglen;
685 enchant_broker * pbroker;
686
687 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &broker, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) {
688 RETURN_FALSE;
689 }
690
691 PHP_ENCHANT_GET_BROKER;
692
693 enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
694 RETURN_TRUE;
695 }
696 /* }}} */
697
698 /* {{{ proto array enchant_broker_describe(resource broker)
699 Enumerates the Enchant providers and tells you some rudimentary information about them. The same info is provided through phpinfo() */
700 PHP_FUNCTION(enchant_broker_describe)
701 {
702 EnchantBrokerDescribeFn describetozval = enumerate_providers_fn;
703 zval *broker;
704 enchant_broker * pbroker;
705
706 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &broker) == FAILURE) {
707 RETURN_FALSE;
708 }
709
710 PHP_ENCHANT_GET_BROKER;
711
712 enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
713 }
714 /* }}} */
715
716 /* {{{ proto bool enchant_dict_quick_check(resource dict, string word [, array &suggestions])
717 If the word is correctly spelled return true, otherwise return false, if suggestions variable
718 is provided, fill it with spelling alternatives. */
719 PHP_FUNCTION(enchant_dict_quick_check)
720 {
721 zval *dict, *sugg = NULL;
722 char *word;
723 int wordlen;
724 enchant_dict *pdict;
725
726 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &dict, &word, &wordlen, &sugg) == FAILURE) {
727 RETURN_FALSE;
728 }
729
730 if (sugg) {
731 zval_dtor(sugg);
732 array_init(sugg);
733 }
734
735 PHP_ENCHANT_GET_DICT;
736
737 if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) {
738 int n_sugg;
739 size_t n_sugg_st;
740 char **suggs;
741
742 if (!sugg && ZEND_NUM_ARGS() == 2) {
743 RETURN_FALSE;
744 }
745
746 suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg_st);
747 memcpy(&n_sugg, &n_sugg_st, sizeof(n_sugg));
748 if (suggs && n_sugg) {
749 int i;
750 for (i = 0; i < n_sugg; i++) {
751 add_next_index_string(sugg, suggs[i], 1);
752 }
753 enchant_dict_free_suggestions(pdict->pdict, suggs);
754 }
755
756
757 RETURN_FALSE;
758 }
759 RETURN_TRUE;
760 }
761 /* }}} */
762
763 /* {{{ proto bool enchant_dict_check(resource dict, string word)
764 If the word is correctly spelled return true, otherwise return false */
765 PHP_FUNCTION(enchant_dict_check)
766 {
767 zval *dict;
768 char *word;
769 int wordlen;
770 enchant_dict *pdict;
771
772 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
773 RETURN_FALSE;
774 }
775
776 PHP_ENCHANT_GET_DICT;
777
778 RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen));
779 }
780 /* }}} */
781
782 /* {{{ proto array enchant_dict_suggest(resource dict, string word)
783 Will return a list of values if any of those pre-conditions are not met.*/
784 PHP_FUNCTION(enchant_dict_suggest)
785 {
786 zval *dict;
787 char *word;
788 int wordlen;
789 char **suggs;
790 enchant_dict *pdict;
791 int n_sugg;
792 size_t n_sugg_st;
793
794 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
795 RETURN_FALSE;
796 }
797
798 PHP_ENCHANT_GET_DICT;
799
800 suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg_st);
801 memcpy(&n_sugg, &n_sugg_st, sizeof(n_sugg));
802 if (suggs && n_sugg) {
803 int i;
804
805 array_init(return_value);
806 for (i = 0; i < n_sugg; i++) {
807 add_next_index_string(return_value, suggs[i], 1);
808 }
809
810 enchant_dict_free_suggestions(pdict->pdict, suggs);
811 }
812 }
813 /* }}} */
814
815 /* {{{ proto void enchant_dict_add_to_personal(resource dict, string word)
816 add 'word' to personal word list */
817 PHP_FUNCTION(enchant_dict_add_to_personal)
818 {
819 zval *dict;
820 char *word;
821 int wordlen;
822 enchant_dict *pdict;
823
824 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
825 RETURN_FALSE;
826 }
827
828 PHP_ENCHANT_GET_DICT;
829
830 enchant_dict_add_to_personal(pdict->pdict, word, wordlen);
831 }
832 /* }}} */
833
834 /* {{{ proto void enchant_dict_add_to_session(resource dict, string word)
835 add 'word' to this spell-checking session */
836 PHP_FUNCTION(enchant_dict_add_to_session)
837 {
838 zval *dict;
839 char *word;
840 int wordlen;
841 enchant_dict *pdict;
842
843 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
844 RETURN_FALSE;
845 }
846
847 PHP_ENCHANT_GET_DICT;
848
849 enchant_dict_add_to_session(pdict->pdict, word, wordlen);
850 }
851 /* }}} */
852
853 /* {{{ proto bool enchant_dict_is_in_session(resource dict, string word)
854 whether or not 'word' exists in this spelling-session */
855 PHP_FUNCTION(enchant_dict_is_in_session)
856 {
857 zval *dict;
858 char *word;
859 int wordlen;
860 enchant_dict *pdict;
861
862 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &dict, &word, &wordlen) == FAILURE) {
863 RETURN_FALSE;
864 }
865
866 PHP_ENCHANT_GET_DICT;
867
868 RETURN_BOOL(enchant_dict_is_in_session(pdict->pdict, word, wordlen));
869 }
870 /* }}} */
871
872 /* {{{ proto void enchant_dict_store_replacement(resource dict, string mis, string cor)
873 add a correction for 'mis' using 'cor'.
874 Notes that you replaced @mis with @cor, so it's possibly more likely
875 that future occurrences of @mis will be replaced with @cor. So it might
876 bump @cor up in the suggestion list.*/
877 PHP_FUNCTION(enchant_dict_store_replacement)
878 {
879 zval *dict;
880 char *mis, *cor;
881 int mislen, corlen;
882
883 enchant_dict *pdict;
884
885 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &dict, &mis, &mislen, &cor, &corlen) == FAILURE) {
886 RETURN_FALSE;
887 }
888
889 PHP_ENCHANT_GET_DICT;
890
891 enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
892 }
893 /* }}} */
894
895 /* {{{ proto string enchant_dict_get_error(resource dict)
896 Returns the last error of the current spelling-session */
897 PHP_FUNCTION(enchant_dict_get_error)
898 {
899 zval *dict;
900 enchant_dict *pdict;
901 char *msg;
902
903 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
904 RETURN_FALSE;
905 }
906
907 PHP_ENCHANT_GET_DICT;
908
909 msg = enchant_dict_get_error(pdict->pdict);
910 if (msg) {
911 RETURN_STRING((char *)msg, 1);
912 }
913
914 RETURN_FALSE;
915 }
916 /* }}} */
917
918 /* {{{ proto array enchant_dict_describe(resource dict)
919 Describes an individual dictionary 'dict' */
920 PHP_FUNCTION(enchant_dict_describe)
921 {
922 zval *dict;
923 enchant_dict *pdict;
924
925 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &dict) == FAILURE) {
926 RETURN_FALSE;
927 }
928
929 PHP_ENCHANT_GET_DICT;
930
931 enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value);
932 }
933 /* }}} */
934
935 /*
936 * Local variables:
937 * tab-width: 4
938 * c-basic-offset: 4
939 * End:
940 * vim600: noet sw=4 ts=4 fdm=marker
941 * vim<600: noet sw=4 ts=4
942 */
943