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