1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1997-2017 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: cd376a1aeb4f5601617ecfc9c1fca767cbbebf95 $
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_API_VERSION < 20100412
595 if ((PG(safe_mode) && (!php_checkuid(pwl, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(pwl)) {
596 #else
597 if (php_check_open_basedir(pwl)) {
598 #endif
599 RETURN_FALSE;
600 }
601
602 PHP_ENCHANT_GET_BROKER;
603
604 d = enchant_broker_request_pwl_dict(pbroker->pbroker, (const char *)pwl);
605 if (d) {
606 pos = pbroker->dictcnt++;
607 if (pbroker->dictcnt) {
608 pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt);
609 } else {
610 pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *));
611 pos = 0;
612 }
613
614 dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict));
615 dict->id = pos;
616 dict->pbroker = pbroker;
617 dict->pdict = d;
618 pbroker->dict[pos] = dict;
619
620 dict->rsrc = zend_register_resource(dict, le_enchant_dict);
621 pbroker->rsrc->gc.refcount++;
622 RETURN_RES(dict->rsrc);
623 } else {
624 RETURN_FALSE;
625 }
626 }
627 /* }}} */
628
629 /* {{{ proto resource enchant_broker_free_dict(resource dict)
630 Free the dictionary resource */
631 PHP_FUNCTION(enchant_broker_free_dict)
632 {
633 zval *dict;
634 enchant_dict *pdict;
635
636 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &dict) == FAILURE) {
637 RETURN_FALSE;
638 }
639
640 PHP_ENCHANT_GET_DICT;
641
642 zend_list_close(Z_RES_P(dict));
643 RETURN_TRUE;
644 }
645 /* }}} */
646
647 /* {{{ proto bool enchant_broker_dict_exists(resource broker, string tag)
648 Whether a dictionary exists or not. Using non-empty tag */
649 PHP_FUNCTION(enchant_broker_dict_exists)
650 {
651 zval *broker;
652 char *tag;
653 size_t taglen;
654 enchant_broker * pbroker;
655
656 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &broker, &tag, &taglen) == FAILURE) {
657 RETURN_FALSE;
658 }
659
660 PHP_ENCHANT_GET_BROKER;
661
662 RETURN_BOOL(enchant_broker_dict_exists(pbroker->pbroker, tag));
663 }
664 /* }}} */
665
666 /* {{{ proto bool enchant_broker_set_ordering(resource broker, string tag, string ordering)
667 Declares a preference of dictionaries to use for the language
668 described/referred to by 'tag'. The ordering is a comma delimited
669 list of provider names. As a special exception, the "*" tag can
670 be used as a language tag to declare a default ordering for any
671 language that does not explicitly declare an ordering. */
672
673 PHP_FUNCTION(enchant_broker_set_ordering)
674 {
675 zval *broker;
676 char *pordering;
677 size_t porderinglen;
678 char *ptag;
679 size_t ptaglen;
680 enchant_broker * pbroker;
681
682 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &broker, &ptag, &ptaglen, &pordering, &porderinglen) == FAILURE) {
683 RETURN_FALSE;
684 }
685
686 PHP_ENCHANT_GET_BROKER;
687
688 enchant_broker_set_ordering(pbroker->pbroker, ptag, pordering);
689 RETURN_TRUE;
690 }
691 /* }}} */
692
693 /* {{{ proto array enchant_broker_describe(resource broker)
694 Enumerates the Enchant providers and tells you some rudimentary information about them. The same info is provided through phpinfo() */
695 PHP_FUNCTION(enchant_broker_describe)
696 {
697 EnchantBrokerDescribeFn describetozval = enumerate_providers_fn;
698 zval *broker;
699 enchant_broker * pbroker;
700
701 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &broker) == FAILURE) {
702 RETURN_FALSE;
703 }
704
705 PHP_ENCHANT_GET_BROKER;
706
707 enchant_broker_describe(pbroker->pbroker, describetozval, (void *)return_value);
708 }
709 /* }}} */
710
711 /* {{{ proto bool enchant_dict_quick_check(resource dict, string word [, array &suggestions])
712 If the word is correctly spelled return true, otherwise return false, if suggestions variable
713 is provided, fill it with spelling alternatives. */
714 PHP_FUNCTION(enchant_dict_quick_check)
715 {
716 zval *dict, *sugg = NULL;
717 char *word;
718 size_t wordlen;
719 enchant_dict *pdict;
720
721 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|z/", &dict, &word, &wordlen, &sugg) == FAILURE) {
722 RETURN_FALSE;
723 }
724
725 if (sugg) {
726 zval_dtor(sugg);
727 array_init(sugg);
728 }
729
730 PHP_ENCHANT_GET_DICT;
731
732 if (enchant_dict_check(pdict->pdict, word, wordlen) > 0) {
733 int n_sugg;
734 size_t n_sugg_st;
735 char **suggs;
736
737 if (!sugg && ZEND_NUM_ARGS() == 2) {
738 RETURN_FALSE;
739 }
740
741 suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg_st);
742 memcpy(&n_sugg, &n_sugg_st, sizeof(n_sugg));
743 if (suggs && n_sugg) {
744 int i;
745 for (i = 0; i < n_sugg; i++) {
746 add_next_index_string(sugg, suggs[i]);
747 }
748 enchant_dict_free_suggestions(pdict->pdict, suggs);
749 }
750
751
752 RETURN_FALSE;
753 }
754 RETURN_TRUE;
755 }
756 /* }}} */
757
758 /* {{{ proto bool enchant_dict_check(resource dict, string word)
759 If the word is correctly spelled return true, otherwise return false */
760 PHP_FUNCTION(enchant_dict_check)
761 {
762 zval *dict;
763 char *word;
764 size_t wordlen;
765 enchant_dict *pdict;
766
767 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
768 RETURN_FALSE;
769 }
770
771 PHP_ENCHANT_GET_DICT;
772
773 RETURN_BOOL(!enchant_dict_check(pdict->pdict, word, wordlen));
774 }
775 /* }}} */
776
777 /* {{{ proto array enchant_dict_suggest(resource dict, string word)
778 Will return a list of values if any of those pre-conditions are not met.*/
779 PHP_FUNCTION(enchant_dict_suggest)
780 {
781 zval *dict;
782 char *word;
783 size_t wordlen;
784 char **suggs;
785 enchant_dict *pdict;
786 int n_sugg;
787 size_t n_sugg_st;
788
789 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
790 RETURN_FALSE;
791 }
792
793 PHP_ENCHANT_GET_DICT;
794
795 suggs = enchant_dict_suggest(pdict->pdict, word, wordlen, &n_sugg_st);
796 memcpy(&n_sugg, &n_sugg_st, sizeof(n_sugg));
797 if (suggs && n_sugg) {
798 int i;
799
800 array_init(return_value);
801 for (i = 0; i < n_sugg; i++) {
802 add_next_index_string(return_value, suggs[i]);
803 }
804
805 enchant_dict_free_suggestions(pdict->pdict, suggs);
806 }
807 }
808 /* }}} */
809
810 /* {{{ proto void enchant_dict_add_to_personal(resource dict, string word)
811 add 'word' to personal word list */
812 PHP_FUNCTION(enchant_dict_add_to_personal)
813 {
814 zval *dict;
815 char *word;
816 size_t wordlen;
817 enchant_dict *pdict;
818
819 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
820 RETURN_FALSE;
821 }
822
823 PHP_ENCHANT_GET_DICT;
824
825 enchant_dict_add_to_personal(pdict->pdict, word, wordlen);
826 }
827 /* }}} */
828
829 /* {{{ proto void enchant_dict_add_to_session(resource dict, string word)
830 add 'word' to this spell-checking session */
831 PHP_FUNCTION(enchant_dict_add_to_session)
832 {
833 zval *dict;
834 char *word;
835 size_t wordlen;
836 enchant_dict *pdict;
837
838 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
839 RETURN_FALSE;
840 }
841
842 PHP_ENCHANT_GET_DICT;
843
844 enchant_dict_add_to_session(pdict->pdict, word, wordlen);
845 }
846 /* }}} */
847
848 /* {{{ proto bool enchant_dict_is_in_session(resource dict, string word)
849 whether or not 'word' exists in this spelling-session */
850 PHP_FUNCTION(enchant_dict_is_in_session)
851 {
852 zval *dict;
853 char *word;
854 size_t wordlen;
855 enchant_dict *pdict;
856
857 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &dict, &word, &wordlen) == FAILURE) {
858 RETURN_FALSE;
859 }
860
861 PHP_ENCHANT_GET_DICT;
862
863 RETURN_BOOL(enchant_dict_is_in_session(pdict->pdict, word, wordlen));
864 }
865 /* }}} */
866
867 /* {{{ proto void enchant_dict_store_replacement(resource dict, string mis, string cor)
868 add a correction for 'mis' using 'cor'.
869 Notes that you replaced @mis with @cor, so it's possibly more likely
870 that future occurrences of @mis will be replaced with @cor. So it might
871 bump @cor up in the suggestion list.*/
872 PHP_FUNCTION(enchant_dict_store_replacement)
873 {
874 zval *dict;
875 char *mis, *cor;
876 size_t mislen, corlen;
877
878 enchant_dict *pdict;
879
880 if (zend_parse_parameters(ZEND_NUM_ARGS(), "rss", &dict, &mis, &mislen, &cor, &corlen) == FAILURE) {
881 RETURN_FALSE;
882 }
883
884 PHP_ENCHANT_GET_DICT;
885
886 enchant_dict_store_replacement(pdict->pdict, mis, mislen, cor, corlen);
887 }
888 /* }}} */
889
890 /* {{{ proto string enchant_dict_get_error(resource dict)
891 Returns the last error of the current spelling-session */
892 PHP_FUNCTION(enchant_dict_get_error)
893 {
894 zval *dict;
895 enchant_dict *pdict;
896 char *msg;
897
898 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &dict) == FAILURE) {
899 RETURN_FALSE;
900 }
901
902 PHP_ENCHANT_GET_DICT;
903
904 msg = enchant_dict_get_error(pdict->pdict);
905 if (msg) {
906 RETURN_STRING((char *)msg);
907 }
908
909 RETURN_FALSE;
910 }
911 /* }}} */
912
913 /* {{{ proto array enchant_dict_describe(resource dict)
914 Describes an individual dictionary 'dict' */
915 PHP_FUNCTION(enchant_dict_describe)
916 {
917 zval *dict;
918 enchant_dict *pdict;
919
920 if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &dict) == FAILURE) {
921 RETURN_FALSE;
922 }
923
924 PHP_ENCHANT_GET_DICT;
925
926 enchant_dict_describe(pdict->pdict, describe_dict_fn, (void *)return_value);
927 }
928 /* }}} */
929
930 /*
931 * Local variables:
932 * tab-width: 4
933 * c-basic-offset: 4
934 * End:
935 * vim600: noet sw=4 ts=4 fdm=marker
936 * vim<600: noet sw=4 ts=4
937 */
938