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