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