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