1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Pierre-Alain Joye <paj@pearfr.org> |
14 | Ilia Alshanetsky <ilia@prohost.org> |
15 +----------------------------------------------------------------------+
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include <config.h>
20 #endif
21
22 #include "php.h"
23 #include "php_ini.h"
24 #include "ext/standard/info.h"
25 #include "Zend/zend_attributes.h"
26 #include "Zend/zend_exceptions.h"
27 #include <enchant.h>
28 #include "php_enchant.h"
29
30 #define PHP_ENCHANT_MYSPELL 1
31 #define PHP_ENCHANT_ISPELL 2
32 #ifdef HAVE_ENCHANT_GET_VERSION
33 #define PHP_ENCHANT_GET_VERSION enchant_get_version()
34 #endif
35
36 #include "enchant_arginfo.h"
37
38 typedef struct _broker_struct {
39 EnchantBroker *pbroker;
40 int nb_dict;
41 zend_object std;
42 } enchant_broker;
43
44 typedef struct _dict_struct {
45 EnchantDict *pdict;
46 zval zbroker;
47 zend_object std;
48 } enchant_dict;
49
50 zend_class_entry *enchant_broker_ce;
51 static zend_object_handlers enchant_broker_handlers;
52
enchant_broker_from_obj(zend_object * obj)53 static inline enchant_broker *enchant_broker_from_obj(zend_object *obj) {
54 return (enchant_broker *)((char *)(obj) - XtOffsetOf(enchant_broker, std));
55 }
56
57 #define Z_ENCHANT_BROKER_P(zv) enchant_broker_from_obj(Z_OBJ_P(zv))
58
enchant_broker_create_object(zend_class_entry * class_type)59 static zend_object *enchant_broker_create_object(zend_class_entry *class_type) {
60 enchant_broker *intern = zend_object_alloc(sizeof(enchant_broker), class_type);
61
62 zend_object_std_init(&intern->std, class_type);
63 object_properties_init(&intern->std, class_type);
64
65 return &intern->std;
66 }
67
68 zend_class_entry *enchant_dict_ce;
69 static zend_object_handlers enchant_dict_handlers;
70
enchant_dict_from_obj(zend_object * obj)71 static inline enchant_dict *enchant_dict_from_obj(zend_object *obj) {
72 return (enchant_dict *)((char *)(obj) - XtOffsetOf(enchant_dict, std));
73 }
74
75 #define Z_ENCHANT_DICT_P(zv) enchant_dict_from_obj(Z_OBJ_P(zv))
76
enchant_dict_create_object(zend_class_entry * class_type)77 static zend_object *enchant_dict_create_object(zend_class_entry *class_type) {
78 enchant_dict *intern = zend_object_alloc(sizeof(enchant_dict), class_type);
79
80 zend_object_std_init(&intern->std, class_type);
81 object_properties_init(&intern->std, class_type);
82
83 return &intern->std;
84 }
85
86 /* {{{ enchant_module_entry */
87 zend_module_entry enchant_module_entry = {
88 STANDARD_MODULE_HEADER,
89 "enchant",
90 ext_functions,
91 PHP_MINIT(enchant),
92 PHP_MSHUTDOWN(enchant),
93 NULL, /* Replace with NULL if there's nothing to do at request start */
94 NULL, /* Replace with NULL if there's nothing to do at request end */
95 PHP_MINFO(enchant),
96 PHP_ENCHANT_VERSION,
97 STANDARD_MODULE_PROPERTIES
98 };
99 /* }}} */
100
101 #ifdef COMPILE_DL_ENCHANT
ZEND_GET_MODULE(enchant)102 ZEND_GET_MODULE(enchant)
103 #endif
104
105 static void
106 enumerate_providers_fn (const char * const name,
107 const char * const desc,
108 const char * const file,
109 void * ud) /* {{{ */
110 {
111 zval *zdesc = (zval *) ud;
112 zval tmp_array;
113
114 array_init(&tmp_array);
115
116 add_assoc_string(&tmp_array, "name", (char *)name);
117 add_assoc_string(&tmp_array, "desc", (char *)desc);
118 add_assoc_string(&tmp_array, "file", (char *)file);
119 add_next_index_zval(zdesc, &tmp_array);
120 }
121 /* }}} */
122
123 static void
describe_dict_fn(const char * const lang,const char * const name,const char * const desc,const char * const file,void * ud)124 describe_dict_fn (const char * const lang,
125 const char * const name,
126 const char * const desc,
127 const char * const file,
128 void * ud) /* {{{ */
129 {
130 zval *zdesc = (zval *) ud;
131 array_init(zdesc);
132 add_assoc_string(zdesc, "lang", (char *)lang);
133 add_assoc_string(zdesc, "name", (char *)name);
134 add_assoc_string(zdesc, "desc", (char *)desc);
135 add_assoc_string(zdesc, "file", (char *)file);
136 }
137 /* }}} */
138
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)139 static void php_enchant_list_dicts_fn( const char * const lang_tag,
140 const char * const provider_name, const char * const provider_desc,
141 const char * const provider_file, void * ud) /* {{{ */
142 {
143 zval *zdesc = (zval *) ud;
144 zval tmp_array;
145
146 array_init(&tmp_array);
147 add_assoc_string(&tmp_array, "lang_tag", (char *)lang_tag);
148 add_assoc_string(&tmp_array, "provider_name", (char *)provider_name);
149 add_assoc_string(&tmp_array, "provider_desc", (char *)provider_desc);
150 add_assoc_string(&tmp_array, "provider_file", (char *)provider_file);
151 add_next_index_zval(zdesc, &tmp_array);
152
153 }
154 /* }}} */
155
php_enchant_broker_free(zend_object * object)156 static void php_enchant_broker_free(zend_object *object) /* {{{ */
157 {
158 enchant_broker *broker = enchant_broker_from_obj(object);
159
160 if (broker->pbroker) { /* may have been freed by enchant_broker_free */
161 enchant_broker_free(broker->pbroker);
162 broker->pbroker = NULL;
163 }
164 zend_object_std_dtor(object);
165 }
166 /* }}} */
167
php_enchant_dict_free(zend_object * object)168 static void php_enchant_dict_free(zend_object *object) /* {{{ */
169
170 {
171 enchant_dict *dict = enchant_dict_from_obj(object);
172
173 if (dict->pdict) { /* may have been freed by enchant_broker_free_dict */
174 enchant_broker *broker = Z_ENCHANT_BROKER_P(&dict->zbroker);
175
176 if (broker && broker->pbroker) {
177 enchant_broker_free_dict(broker->pbroker, dict->pdict);
178 broker->nb_dict--;
179 zval_ptr_dtor(&dict->zbroker);
180 }
181 dict->pdict = NULL;
182 }
183 zend_object_std_dtor(object);
184 }
185 /* }}} */
186
187 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(enchant)188 PHP_MINIT_FUNCTION(enchant)
189 {
190 enchant_broker_ce = register_class_EnchantBroker();
191 enchant_broker_ce->create_object = enchant_broker_create_object;
192 enchant_broker_ce->default_object_handlers = &enchant_broker_handlers;
193
194 memcpy(&enchant_broker_handlers, &std_object_handlers, sizeof(zend_object_handlers));
195 enchant_broker_handlers.offset = XtOffsetOf(enchant_broker, std);
196 enchant_broker_handlers.free_obj = php_enchant_broker_free;
197 enchant_broker_handlers.clone_obj = NULL;
198 enchant_broker_handlers.compare = zend_objects_not_comparable;
199
200 enchant_dict_ce = register_class_EnchantDictionary();
201 enchant_dict_ce->create_object = enchant_dict_create_object;
202 enchant_dict_ce->default_object_handlers = &enchant_dict_handlers;
203
204 memcpy(&enchant_dict_handlers, &std_object_handlers, sizeof(zend_object_handlers));
205 enchant_dict_handlers.offset = XtOffsetOf(enchant_dict, std);
206 enchant_dict_handlers.free_obj = php_enchant_dict_free;
207 enchant_dict_handlers.clone_obj = NULL;
208 enchant_dict_handlers.compare = zend_objects_not_comparable;
209
210 register_enchant_symbols(module_number);
211
212 return SUCCESS;
213 }
214 /* }}} */
215
216 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(enchant)217 PHP_MSHUTDOWN_FUNCTION(enchant)
218 {
219 return SUCCESS;
220 }
221 /* }}} */
222
__enumerate_providers_fn(const char * const name,const char * const desc,const char * const file,void * ud)223 static void __enumerate_providers_fn (const char * const name,
224 const char * const desc,
225 const char * const file,
226 void * ud) /* {{{ */
227 {
228 php_info_print_table_row(3, name, desc, file);
229 }
230 /* }}} */
231
232 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(enchant)233 PHP_MINFO_FUNCTION(enchant)
234 {
235 EnchantBroker *pbroker;
236
237 pbroker = enchant_broker_init();
238 php_info_print_table_start();
239 php_info_print_table_row(2, "enchant support", "enabled");
240 #ifdef HAVE_ENCHANT_GET_VERSION
241 php_info_print_table_row(2, "Libenchant Version", enchant_get_version());
242 #elif defined(HAVE_ENCHANT_BROKER_SET_PARAM)
243 php_info_print_table_row(2, "Libenchant Version", "1.5.x");
244 #endif
245 php_info_print_table_end();
246
247 php_info_print_table_start();
248 enchant_broker_describe(pbroker, __enumerate_providers_fn, NULL);
249 php_info_print_table_end();
250 enchant_broker_free(pbroker);
251 }
252 /* }}} */
253
254 #define PHP_ENCHANT_GET_BROKER \
255 pbroker = Z_ENCHANT_BROKER_P(broker); \
256 if (!pbroker->pbroker) { \
257 zend_value_error("Invalid or uninitialized EnchantBroker object"); \
258 RETURN_THROWS(); \
259 }
260
261 #define PHP_ENCHANT_GET_DICT \
262 pdict = Z_ENCHANT_DICT_P(dict); \
263 if (!pdict->pdict) { \
264 zend_value_error("Invalid or uninitialized EnchantDictionary object"); \
265 RETURN_THROWS(); \
266 }
267
268 /* {{{ create a new broker object capable of requesting */
PHP_FUNCTION(enchant_broker_init)269 PHP_FUNCTION(enchant_broker_init)
270 {
271 enchant_broker *broker;
272 EnchantBroker *pbroker;
273
274 if (zend_parse_parameters_none() == FAILURE) {
275 RETURN_THROWS();
276 }
277
278 pbroker = enchant_broker_init();
279 if (pbroker) {
280 object_init_ex(return_value, enchant_broker_ce);
281 broker = Z_ENCHANT_BROKER_P(return_value);
282 broker->pbroker = pbroker;
283 broker->nb_dict = 0;
284 } else {
285 RETURN_FALSE;
286 }
287 }
288 /* }}} */
289
290 /* {{{ Destroys the broker object and its dictionaries */
PHP_FUNCTION(enchant_broker_free)291 PHP_FUNCTION(enchant_broker_free)
292 {
293 zval *broker;
294 enchant_broker *pbroker;
295
296 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
297 RETURN_THROWS();
298 }
299 PHP_ENCHANT_GET_BROKER;
300
301 if (pbroker->nb_dict > 0) {
302 zend_throw_error(NULL, "Cannot free EnchantBroker object with open EnchantDictionary objects");
303 RETURN_THROWS();
304 }
305 if (pbroker->pbroker) {
306 enchant_broker_free(pbroker->pbroker);
307 pbroker->pbroker = NULL;
308 }
309 RETURN_TRUE;
310 }
311 /* }}} */
312
313 /* {{{ Returns the last error of the broker */
PHP_FUNCTION(enchant_broker_get_error)314 PHP_FUNCTION(enchant_broker_get_error)
315 {
316 zval *broker;
317 enchant_broker *pbroker;
318 const char *msg;
319
320 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
321 RETURN_THROWS();
322 }
323
324 PHP_ENCHANT_GET_BROKER;
325
326 msg = enchant_broker_get_error(pbroker->pbroker);
327 if (msg) {
328 RETURN_STRING((char *)msg);
329 }
330 RETURN_FALSE;
331 }
332 /* }}} */
333
334 /* {{{ Set the directory path for a given backend, works with ispell and myspell */
PHP_FUNCTION(enchant_broker_set_dict_path)335 PHP_FUNCTION(enchant_broker_set_dict_path)
336 {
337 zval *broker;
338 zend_long dict_type;
339 char *value;
340 size_t value_len;
341
342 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ols", &broker, enchant_broker_ce, &dict_type, &value, &value_len) == FAILURE) {
343 RETURN_THROWS();
344 }
345
346 #ifdef HAVE_ENCHANT_BROKER_SET_PARAM
347 enchant_broker *pbroker;
348 if (!value_len) {
349 RETURN_FALSE;
350 }
351
352 PHP_ENCHANT_GET_BROKER;
353
354 switch (dict_type) {
355 case PHP_ENCHANT_MYSPELL:
356 PHP_ENCHANT_GET_BROKER;
357 enchant_broker_set_param(pbroker->pbroker, "enchant.myspell.dictionary.path", (const char *)value);
358 RETURN_TRUE;
359 break;
360
361 case PHP_ENCHANT_ISPELL:
362 PHP_ENCHANT_GET_BROKER;
363 enchant_broker_set_param(pbroker->pbroker, "enchant.ispell.dictionary.path", (const char *)value);
364 RETURN_TRUE;
365 break;
366
367 default:
368 RETURN_FALSE;
369 }
370 #endif
371 }
372 /* }}} */
373
374
375 /* {{{ Get the directory path for a given backend, works with ispell and myspell */
PHP_FUNCTION(enchant_broker_get_dict_path)376 PHP_FUNCTION(enchant_broker_get_dict_path)
377 {
378 zval *broker;
379 zend_long dict_type;
380
381 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &broker, enchant_broker_ce, &dict_type) == FAILURE) {
382 RETURN_THROWS();
383 }
384
385 #ifdef HAVE_ENCHANT_BROKER_SET_PARAM
386 enchant_broker *pbroker;
387 char *value;
388 PHP_ENCHANT_GET_BROKER;
389
390 switch (dict_type) {
391 case PHP_ENCHANT_MYSPELL:
392 PHP_ENCHANT_GET_BROKER;
393 value = enchant_broker_get_param(pbroker->pbroker, "enchant.myspell.dictionary.path");
394 break;
395
396 case PHP_ENCHANT_ISPELL:
397 PHP_ENCHANT_GET_BROKER;
398 value = enchant_broker_get_param(pbroker->pbroker, "enchant.ispell.dictionary.path");
399 break;
400
401 default:
402 RETURN_FALSE;
403 }
404
405 if (value == NULL) {
406 php_error_docref(NULL, E_WARNING, "dict_path not set");
407 RETURN_FALSE;
408 }
409
410 RETURN_STRING(value);
411 #endif
412 }
413 /* }}} */
414
415 /* {{{ Lists the dictionaries available for the given broker */
PHP_FUNCTION(enchant_broker_list_dicts)416 PHP_FUNCTION(enchant_broker_list_dicts)
417 {
418 zval *broker;
419 enchant_broker *pbroker;
420
421 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
422 RETURN_THROWS();
423 }
424
425 PHP_ENCHANT_GET_BROKER;
426
427 array_init(return_value);
428 enchant_broker_list_dicts(pbroker->pbroker, php_enchant_list_dicts_fn, (void *)return_value);
429 }
430 /* }}} */
431
432 /* {{{ create a new dictionary using tag, the non-empty language tag you wish to request
433 a dictionary for ("en_US", "de_DE", ...) */
PHP_FUNCTION(enchant_broker_request_dict)434 PHP_FUNCTION(enchant_broker_request_dict)
435 {
436 zval *broker;
437 enchant_broker *pbroker;
438 enchant_dict *dict;
439 EnchantDict *pdict;
440 char *tag;
441 size_t taglen;
442
443 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &broker, enchant_broker_ce, &tag, &taglen) == FAILURE) {
444 RETURN_THROWS();
445 }
446
447 PHP_ENCHANT_GET_BROKER;
448
449 if (taglen == 0) {
450 zend_argument_must_not_be_empty_error(2);
451 RETURN_THROWS();
452 }
453
454 pdict = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag);
455 if (pdict) {
456 pbroker->nb_dict++;
457
458 object_init_ex(return_value, enchant_dict_ce);
459 dict = Z_ENCHANT_DICT_P(return_value);
460 dict->pdict = pdict;
461 ZVAL_COPY(&dict->zbroker, broker);
462 } else {
463 RETURN_FALSE;
464 }
465 }
466 /* }}} */
467
468 /* {{{ 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)469 PHP_FUNCTION(enchant_broker_request_pwl_dict)
470 {
471 zval *broker;
472 enchant_broker *pbroker;
473 enchant_dict *dict;
474 EnchantDict *pdict;
475 const char *pwl;
476 size_t pwllen;
477
478 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op", &broker, enchant_broker_ce, &pwl, &pwllen) == FAILURE) {
479 RETURN_THROWS();
480 }
481
482 if (php_check_open_basedir(pwl)) {
483 RETURN_FALSE;
484 }
485
486 PHP_ENCHANT_GET_BROKER;
487
488 pdict = enchant_broker_request_pwl_dict(pbroker->pbroker, pwl);
489 if (pdict) {
490 pbroker->nb_dict++;
491
492 object_init_ex(return_value, enchant_dict_ce);
493 dict = Z_ENCHANT_DICT_P(return_value);
494 dict->pdict = pdict;
495 ZVAL_COPY(&dict->zbroker, broker);
496 } else {
497 RETURN_FALSE;
498 }
499 }
500 /* }}} */
501
502 /* {{{ Free the dictionary resource */
PHP_FUNCTION(enchant_broker_free_dict)503 PHP_FUNCTION(enchant_broker_free_dict)
504 {
505 zval *dict;
506 enchant_dict *pdict;
507
508 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &dict, enchant_dict_ce) == FAILURE) {
509 RETURN_THROWS();
510 }
511
512 PHP_ENCHANT_GET_DICT;
513
514 if (pdict->pdict) {
515 enchant_broker *broker = Z_ENCHANT_BROKER_P(&pdict->zbroker);
516
517 if (broker && broker->pbroker) {
518 enchant_broker_free_dict(broker->pbroker, pdict->pdict);
519 broker->nb_dict--;
520 zval_ptr_dtor(&pdict->zbroker);
521 }
522 pdict->pdict = NULL;
523 }
524
525 RETURN_TRUE;
526 }
527 /* }}} */
528
529 /* {{{ Whether a dictionary exists or not. Using non-empty tag */
PHP_FUNCTION(enchant_broker_dict_exists)530 PHP_FUNCTION(enchant_broker_dict_exists)
531 {
532 zval *broker;
533 char *tag;
534 size_t taglen;
535 enchant_broker * pbroker;
536
537 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &broker, enchant_broker_ce, &tag, &taglen) == FAILURE) {
538 RETURN_THROWS();
539 }
540
541 PHP_ENCHANT_GET_BROKER;
542
543 RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag));
544 }
545 /* }}} */
546
547 /* {{{ Declares a preference of dictionaries to use for the language
548 described/referred to by 'tag'. The ordering is a comma delimited
549 list of provider names. As a special exception, the "*" tag can
550 be used as a language tag to declare a default ordering for any
551 language that does not explicitly declare an ordering. */
552
PHP_FUNCTION(enchant_broker_set_ordering)553 PHP_FUNCTION(enchant_broker_set_ordering)
554 {
555 zval *broker;
556 char *pordering;
557 size_t porderinglen;
558 char *ptag;
559 size_t ptaglen;
560 enchant_broker * pbroker;
561
562 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss", &broker, enchant_broker_ce, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) {
563 RETURN_THROWS();
564 }
565
566 PHP_ENCHANT_GET_BROKER;
567
568 enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
569 RETURN_TRUE;
570 }
571 /* }}} */
572
573 /* {{{ Enumerates the Enchant providers and tells you some rudimentary information about them. The same info is provided through phpinfo() */
PHP_FUNCTION(enchant_broker_describe)574 PHP_FUNCTION(enchant_broker_describe)
575 {
576 EnchantBrokerDescribeFn describetozval = enumerate_providers_fn;
577 zval *broker;
578 enchant_broker * pbroker;
579
580 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &broker, enchant_broker_ce) == FAILURE) {
581 RETURN_THROWS();
582 }
583
584 PHP_ENCHANT_GET_BROKER;
585
586 array_init(return_value);
587 enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
588 }
589 /* }}} */
590
591 /* {{{ If the word is correctly spelled return true, otherwise return false, if suggestions variable
592 is provided, fill it with spelling alternatives. */
PHP_FUNCTION(enchant_dict_quick_check)593 PHP_FUNCTION(enchant_dict_quick_check)
594 {
595 zval *dict, *sugg = NULL;
596 char *word;
597 size_t wordlen;
598 enchant_dict *pdict;
599
600 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|z", &dict, enchant_dict_ce, &word, &wordlen, &sugg) == FAILURE) {
601 RETURN_THROWS();
602 }
603
604 if (sugg) {
605 sugg = zend_try_array_init(sugg);
606 if (!sugg) {
607 RETURN_THROWS();
608 }
609 }
610
611 PHP_ENCHANT_GET_DICT;
612
613 if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) {
614 size_t n_sugg;
615 char **suggs;
616
617 if (!sugg && ZEND_NUM_ARGS() == 2) {
618 RETURN_FALSE;
619 }
620
621 suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg);
622 if (suggs && n_sugg) {
623 size_t i;
624 for (i = 0; i < n_sugg; i++) {
625 add_next_index_string(sugg, suggs[i]);
626 }
627 enchant_dict_free_string_list(pdict->pdict, suggs);
628 }
629
630 RETURN_FALSE;
631 }
632
633 RETURN_TRUE;
634 }
635 /* }}} */
636
637 /* {{{ If the word is correctly spelled return true, otherwise return false */
PHP_FUNCTION(enchant_dict_check)638 PHP_FUNCTION(enchant_dict_check)
639 {
640 zval *dict;
641 char *word;
642 size_t wordlen;
643 enchant_dict *pdict;
644
645 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
646 RETURN_THROWS();
647 }
648
649 PHP_ENCHANT_GET_DICT;
650
651 RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen));
652 }
653 /* }}} */
654
655 /* {{{ Will return a list of values if any of those pre-conditions are not met.*/
PHP_FUNCTION(enchant_dict_suggest)656 PHP_FUNCTION(enchant_dict_suggest)
657 {
658 zval *dict;
659 char *word;
660 size_t wordlen;
661 char **suggs;
662 enchant_dict *pdict;
663 size_t n_sugg;
664
665 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
666 RETURN_THROWS();
667 }
668
669 PHP_ENCHANT_GET_DICT;
670 array_init(return_value);
671
672 suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg);
673 if (suggs && n_sugg) {
674 size_t i;
675
676 for (i = 0; i < n_sugg; i++) {
677 add_next_index_string(return_value, suggs[i]);
678 }
679
680 enchant_dict_free_string_list(pdict->pdict, suggs);
681 }
682 }
683 /* }}} */
684
685 /* {{{ add 'word' to personal word list */
PHP_FUNCTION(enchant_dict_add)686 PHP_FUNCTION(enchant_dict_add)
687 {
688 zval *dict;
689 char *word;
690 size_t wordlen;
691 enchant_dict *pdict;
692
693 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
694 RETURN_THROWS();
695 }
696
697 PHP_ENCHANT_GET_DICT;
698
699 enchant_dict_add(pdict->pdict, word, wordlen);
700 }
701 /* }}} */
702
703 /* {{{ add 'word' to this spell-checking session */
PHP_FUNCTION(enchant_dict_add_to_session)704 PHP_FUNCTION(enchant_dict_add_to_session)
705 {
706 zval *dict;
707 char *word;
708 size_t wordlen;
709 enchant_dict *pdict;
710
711 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
712 RETURN_THROWS();
713 }
714
715 PHP_ENCHANT_GET_DICT;
716
717 enchant_dict_add_to_session(pdict->pdict, word, wordlen);
718 }
719 /* }}} */
720
721 /* {{{ whether or not 'word' exists in this spelling-session */
PHP_FUNCTION(enchant_dict_is_added)722 PHP_FUNCTION(enchant_dict_is_added)
723 {
724 zval *dict;
725 char *word;
726 size_t wordlen;
727 enchant_dict *pdict;
728
729 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &dict, enchant_dict_ce, &word, &wordlen) == FAILURE) {
730 RETURN_THROWS();
731 }
732
733 PHP_ENCHANT_GET_DICT;
734
735 RETURN_BOOL(enchant_dict_is_added(pdict->pdict, word, wordlen));
736 }
737 /* }}} */
738
739 /* {{{ add a correction for 'mis' using 'cor'.
740 Notes that you replaced @mis with @cor, so it's possibly more likely
741 that future occurrences of @mis will be replaced with @cor. So it might
742 bump @cor up in the suggestion list.*/
PHP_FUNCTION(enchant_dict_store_replacement)743 PHP_FUNCTION(enchant_dict_store_replacement)
744 {
745 zval *dict;
746 char *mis, *cor;
747 size_t mislen, corlen;
748
749 enchant_dict *pdict;
750
751 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Oss", &dict, enchant_dict_ce, &mis, &mislen, &cor, &corlen) == FAILURE) {
752 RETURN_THROWS();
753 }
754
755 PHP_ENCHANT_GET_DICT;
756
757 enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
758 }
759 /* }}} */
760
761 /* {{{ Returns the last error of the current spelling-session */
PHP_FUNCTION(enchant_dict_get_error)762 PHP_FUNCTION(enchant_dict_get_error)
763 {
764 zval *dict;
765 enchant_dict *pdict;
766 const char *msg;
767
768 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &dict, enchant_dict_ce) == FAILURE) {
769 RETURN_THROWS();
770 }
771
772 PHP_ENCHANT_GET_DICT;
773
774 msg = enchant_dict_get_error(pdict->pdict);
775 if (msg) {
776 RETURN_STRING((char *)msg);
777 }
778
779 RETURN_FALSE;
780 }
781 /* }}} */
782
783 /* {{{ Describes an individual dictionary 'dict' */
PHP_FUNCTION(enchant_dict_describe)784 PHP_FUNCTION(enchant_dict_describe)
785 {
786 zval *dict;
787 enchant_dict *pdict;
788
789 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &dict, enchant_dict_ce) == FAILURE) {
790 RETURN_THROWS();
791 }
792
793 PHP_ENCHANT_GET_DICT;
794
795 enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value);
796 }
797 /* }}} */
798