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: Vlad Krupin <phpdevel@echospace.com> |
14 +----------------------------------------------------------------------+
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "php.h"
22
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <stdio.h>
26
27 #ifdef HAVE_PSPELL
28
29 /* this will enforce compatibility in .12 version (broken after .11.2) */
30 #define USE_ORIGINAL_MANAGER_FUNCS
31
32 #include "php_pspell.h"
33 #include <pspell.h>
34 #include "ext/standard/info.h"
35 #include "pspell_arginfo.h"
36
37 #define PSPELL_FAST 1L
38 #define PSPELL_NORMAL 2L
39 #define PSPELL_BAD_SPELLERS 3L
40 #define PSPELL_SPEED_MASK_INTERNAL 3L
41 #define PSPELL_RUN_TOGETHER 8L
42
43 /* Largest ignored word can be 999 characters (this seems sane enough),
44 * and it takes 3 bytes to represent that (see pspell_config_ignore)
45 */
46 #define PSPELL_LARGEST_WORD 3
47
48 static PHP_MINIT_FUNCTION(pspell);
49 static PHP_MINFO_FUNCTION(pspell);
50
51 static int le_pspell, le_pspell_config;
52
53 zend_module_entry pspell_module_entry = {
54 STANDARD_MODULE_HEADER,
55 "pspell", ext_functions, PHP_MINIT(pspell), NULL, NULL, NULL, PHP_MINFO(pspell), PHP_PSPELL_VERSION, STANDARD_MODULE_PROPERTIES
56 };
57
58 #ifdef COMPILE_DL_PSPELL
ZEND_GET_MODULE(pspell)59 ZEND_GET_MODULE(pspell)
60 #endif
61
62 static void php_pspell_close(zend_resource *rsrc)
63 {
64 PspellManager *manager = (PspellManager *)rsrc->ptr;
65
66 delete_pspell_manager(manager);
67 }
68
php_pspell_close_config(zend_resource * rsrc)69 static void php_pspell_close_config(zend_resource *rsrc)
70 {
71 PspellConfig *config = (PspellConfig *)rsrc->ptr;
72
73 delete_pspell_config(config);
74 }
75
76 #define PSPELL_FETCH_CONFIG do { \
77 zval *res = zend_hash_index_find(&EG(regular_list), conf); \
78 if (res == NULL || Z_RES_P(res)->type != le_pspell_config) { \
79 zend_throw_error(NULL, "%s(): " ZEND_LONG_FMT " is not a PSPELL config index", get_active_function_name(), conf); \
80 RETURN_THROWS(); \
81 } \
82 config = (PspellConfig *)Z_RES_P(res)->ptr; \
83 } while (0)
84
85 #define PSPELL_FETCH_MANAGER do { \
86 zval *res = zend_hash_index_find(&EG(regular_list), scin); \
87 if (res == NULL || Z_RES_P(res)->type != le_pspell) { \
88 zend_throw_error(NULL, "%s(): " ZEND_LONG_FMT " is not a PSPELL result index", get_active_function_name(), scin); \
89 RETURN_THROWS(); \
90 } \
91 manager = (PspellManager *)Z_RES_P(res)->ptr; \
92 } while (0);
93
94 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(pspell)95 static PHP_MINIT_FUNCTION(pspell)
96 {
97 REGISTER_LONG_CONSTANT("PSPELL_FAST", PSPELL_FAST, CONST_PERSISTENT | CONST_CS);
98 REGISTER_LONG_CONSTANT("PSPELL_NORMAL", PSPELL_NORMAL, CONST_PERSISTENT | CONST_CS);
99 REGISTER_LONG_CONSTANT("PSPELL_BAD_SPELLERS", PSPELL_BAD_SPELLERS, CONST_PERSISTENT | CONST_CS);
100 REGISTER_LONG_CONSTANT("PSPELL_RUN_TOGETHER", PSPELL_RUN_TOGETHER, CONST_PERSISTENT | CONST_CS);
101 le_pspell = zend_register_list_destructors_ex(php_pspell_close, NULL, "pspell", module_number);
102 le_pspell_config = zend_register_list_destructors_ex(php_pspell_close_config, NULL, "pspell config", module_number);
103 return SUCCESS;
104 }
105 /* }}} */
106
107 /* {{{ Load a dictionary */
PHP_FUNCTION(pspell_new)108 PHP_FUNCTION(pspell_new)
109 {
110 char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
111 size_t language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
112 zend_long mode = Z_L(0), speed = Z_L(0);
113 int argc = ZEND_NUM_ARGS();
114 zval *ind;
115
116 #ifdef PHP_WIN32
117 TCHAR aspell_dir[200];
118 TCHAR data_dir[220];
119 TCHAR dict_dir[220];
120 HKEY hkey;
121 DWORD dwType,dwLen;
122 #endif
123
124 PspellCanHaveError *ret;
125 PspellManager *manager;
126 PspellConfig *config;
127
128 if (zend_parse_parameters(argc, "s|sssl", &language, &language_len, &spelling, &spelling_len,
129 &jargon, &jargon_len, &encoding, &encoding_len, &mode) == FAILURE) {
130 RETURN_THROWS();
131 }
132
133 config = new_pspell_config();
134
135 #ifdef PHP_WIN32
136 /* If aspell was installed using installer, we should have a key
137 * pointing to the location of the dictionaries
138 */
139 if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
140 LONG result;
141 dwLen = sizeof(aspell_dir) - 1;
142 result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
143 RegCloseKey(hkey);
144 if (result == ERROR_SUCCESS) {
145 strlcpy(data_dir, aspell_dir, sizeof(data_dir));
146 strlcat(data_dir, "\\data", sizeof(data_dir));
147 strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
148 strlcat(dict_dir, "\\dict", sizeof(dict_dir));
149
150 pspell_config_replace(config, "data-dir", data_dir);
151 pspell_config_replace(config, "dict-dir", dict_dir);
152 }
153 }
154 #endif
155
156 pspell_config_replace(config, "language-tag", language);
157
158 if (spelling_len) {
159 pspell_config_replace(config, "spelling", spelling);
160 }
161
162 if (jargon_len) {
163 pspell_config_replace(config, "jargon", jargon);
164 }
165
166 if (encoding_len) {
167 pspell_config_replace(config, "encoding", encoding);
168 }
169
170 if (mode) {
171 speed = mode & PSPELL_SPEED_MASK_INTERNAL;
172
173 /* First check what mode we want (how many suggestions) */
174 if (speed == PSPELL_FAST) {
175 pspell_config_replace(config, "sug-mode", "fast");
176 } else if (speed == PSPELL_NORMAL) {
177 pspell_config_replace(config, "sug-mode", "normal");
178 } else if (speed == PSPELL_BAD_SPELLERS) {
179 pspell_config_replace(config, "sug-mode", "bad-spellers");
180 }
181
182 /* Then we see if run-together words should be treated as valid components */
183 if (mode & PSPELL_RUN_TOGETHER) {
184 pspell_config_replace(config, "run-together", "true");
185 }
186 }
187
188 ret = new_pspell_manager(config);
189 delete_pspell_config(config);
190
191 if (pspell_error_number(ret) != 0) {
192 php_error_docref(NULL, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
193 delete_pspell_can_have_error(ret);
194 RETURN_FALSE;
195 }
196
197 manager = to_pspell_manager(ret);
198 ind = zend_list_insert(manager, le_pspell);
199 RETURN_LONG(Z_RES_HANDLE_P(ind));
200 }
201 /* }}} */
202
203 /* {{{ Load a dictionary with a personal wordlist*/
PHP_FUNCTION(pspell_new_personal)204 PHP_FUNCTION(pspell_new_personal)
205 {
206 char *personal, *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
207 size_t personal_len, language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
208 zend_long mode = Z_L(0), speed = Z_L(0);
209 int argc = ZEND_NUM_ARGS();
210 zval *ind;
211
212 #ifdef PHP_WIN32
213 TCHAR aspell_dir[200];
214 TCHAR data_dir[220];
215 TCHAR dict_dir[220];
216 HKEY hkey;
217 DWORD dwType,dwLen;
218 #endif
219
220 PspellCanHaveError *ret;
221 PspellManager *manager;
222 PspellConfig *config;
223
224 if (zend_parse_parameters(argc, "ps|sssl", &personal, &personal_len, &language, &language_len,
225 &spelling, &spelling_len, &jargon, &jargon_len, &encoding, &encoding_len, &mode) == FAILURE) {
226 RETURN_THROWS();
227 }
228
229 config = new_pspell_config();
230
231 #ifdef PHP_WIN32
232 /* If aspell was installed using installer, we should have a key
233 * pointing to the location of the dictionaries
234 */
235 if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
236 LONG result;
237 dwLen = sizeof(aspell_dir) - 1;
238 result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
239 RegCloseKey(hkey);
240 if (result == ERROR_SUCCESS) {
241 strlcpy(data_dir, aspell_dir, sizeof(data_dir));
242 strlcat(data_dir, "\\data", sizeof(data_dir));
243 strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
244 strlcat(dict_dir, "\\dict", sizeof(dict_dir));
245
246 pspell_config_replace(config, "data-dir", data_dir);
247 pspell_config_replace(config, "dict-dir", dict_dir);
248 }
249 }
250 #endif
251
252 if (php_check_open_basedir(personal)) {
253 delete_pspell_config(config);
254 RETURN_FALSE;
255 }
256
257 pspell_config_replace(config, "personal", personal);
258 pspell_config_replace(config, "save-repl", "false");
259
260 pspell_config_replace(config, "language-tag", language);
261
262 if (spelling_len) {
263 pspell_config_replace(config, "spelling", spelling);
264 }
265
266 if (jargon_len) {
267 pspell_config_replace(config, "jargon", jargon);
268 }
269
270 if (encoding_len) {
271 pspell_config_replace(config, "encoding", encoding);
272 }
273
274 if (mode) {
275 speed = mode & PSPELL_SPEED_MASK_INTERNAL;
276
277 /* First check what mode we want (how many suggestions) */
278 if (speed == PSPELL_FAST) {
279 pspell_config_replace(config, "sug-mode", "fast");
280 } else if (speed == PSPELL_NORMAL) {
281 pspell_config_replace(config, "sug-mode", "normal");
282 } else if (speed == PSPELL_BAD_SPELLERS) {
283 pspell_config_replace(config, "sug-mode", "bad-spellers");
284 }
285
286 /* Then we see if run-together words should be treated as valid components */
287 if (mode & PSPELL_RUN_TOGETHER) {
288 pspell_config_replace(config, "run-together", "true");
289 }
290 }
291
292 ret = new_pspell_manager(config);
293 delete_pspell_config(config);
294
295 if (pspell_error_number(ret) != 0) {
296 php_error_docref(NULL, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
297 delete_pspell_can_have_error(ret);
298 RETURN_FALSE;
299 }
300
301 manager = to_pspell_manager(ret);
302 ind = zend_list_insert(manager, le_pspell);
303 RETURN_LONG(Z_RES_HANDLE_P(ind));
304 }
305 /* }}} */
306
307 /* {{{ Load a dictionary based on the given config */
PHP_FUNCTION(pspell_new_config)308 PHP_FUNCTION(pspell_new_config)
309 {
310 zend_long conf;
311 zval *ind;
312 PspellCanHaveError *ret;
313 PspellManager *manager;
314 PspellConfig *config;
315
316 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &conf) == FAILURE) {
317 RETURN_THROWS();
318 }
319
320 PSPELL_FETCH_CONFIG;
321
322 ret = new_pspell_manager(config);
323
324 if (pspell_error_number(ret) != 0) {
325 php_error_docref(NULL, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
326 delete_pspell_can_have_error(ret);
327 RETURN_FALSE;
328 }
329
330 manager = to_pspell_manager(ret);
331 ind = zend_list_insert(manager, le_pspell);
332 RETURN_LONG(Z_RES_HANDLE_P(ind));
333 }
334 /* }}} */
335
336 /* {{{ Returns true if word is valid */
PHP_FUNCTION(pspell_check)337 PHP_FUNCTION(pspell_check)
338 {
339 size_t word_len;
340 zend_long scin;
341 char *word;
342 PspellManager *manager;
343
344 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
345 RETURN_THROWS();
346 }
347
348 PSPELL_FETCH_MANAGER;
349
350 if (pspell_manager_check(manager, word)) {
351 RETURN_TRUE;
352 } else {
353 RETURN_FALSE;
354 }
355 }
356 /* }}} */
357
358 /* {{{ Returns array of suggestions */
PHP_FUNCTION(pspell_suggest)359 PHP_FUNCTION(pspell_suggest)
360 {
361 zend_long scin;
362 char *word;
363 size_t word_len;
364 PspellManager *manager;
365 const PspellWordList *wl;
366 const char *sug;
367
368 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
369 RETURN_THROWS();
370 }
371
372 PSPELL_FETCH_MANAGER;
373
374 array_init(return_value);
375
376 wl = pspell_manager_suggest(manager, word);
377 if (wl) {
378 PspellStringEmulation *els = pspell_word_list_elements(wl);
379 while ((sug = pspell_string_emulation_next(els)) != 0) {
380 add_next_index_string(return_value,(char *)sug);
381 }
382 delete_pspell_string_emulation(els);
383 } else {
384 php_error_docref(NULL, E_WARNING, "PSPELL had a problem. details: %s", pspell_manager_error_message(manager));
385 RETURN_FALSE;
386 }
387 }
388 /* }}} */
389
390 /* {{{ Notify the dictionary of a user-selected replacement */
PHP_FUNCTION(pspell_store_replacement)391 PHP_FUNCTION(pspell_store_replacement)
392 {
393 size_t miss_len, corr_len;
394 zend_long scin;
395 char *miss, *corr;
396 PspellManager *manager;
397
398 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lss", &scin, &miss, &miss_len, &corr, &corr_len) == FAILURE) {
399 RETURN_THROWS();
400 }
401
402 PSPELL_FETCH_MANAGER;
403
404 pspell_manager_store_replacement(manager, miss, corr);
405 if (pspell_manager_error_number(manager) == 0) {
406 RETURN_TRUE;
407 } else {
408 php_error_docref(NULL, E_WARNING, "pspell_store_replacement() gave error: %s", pspell_manager_error_message(manager));
409 RETURN_FALSE;
410 }
411 }
412 /* }}} */
413
414 /* {{{ Adds a word to a personal list */
PHP_FUNCTION(pspell_add_to_personal)415 PHP_FUNCTION(pspell_add_to_personal)
416 {
417 size_t word_len;
418 zend_long scin;
419 char *word;
420 PspellManager *manager;
421
422 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
423 RETURN_THROWS();
424 }
425
426 PSPELL_FETCH_MANAGER;
427
428 /*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
429 if (word_len == 0) {
430 RETURN_FALSE;
431 }
432
433 pspell_manager_add_to_personal(manager, word);
434 if (pspell_manager_error_number(manager) == 0) {
435 RETURN_TRUE;
436 } else {
437 php_error_docref(NULL, E_WARNING, "pspell_add_to_personal() gave error: %s", pspell_manager_error_message(manager));
438 RETURN_FALSE;
439 }
440 }
441 /* }}} */
442
443 /* {{{ Adds a word to the current session */
PHP_FUNCTION(pspell_add_to_session)444 PHP_FUNCTION(pspell_add_to_session)
445 {
446 size_t word_len;
447 zend_long scin;
448 char *word;
449 PspellManager *manager;
450
451 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ls", &scin, &word, &word_len) == FAILURE) {
452 RETURN_THROWS();
453 }
454
455 PSPELL_FETCH_MANAGER;
456
457 /*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
458 if (word_len == 0) {
459 RETURN_FALSE;
460 }
461
462 pspell_manager_add_to_session(manager, word);
463 if (pspell_manager_error_number(manager) == 0) {
464 RETURN_TRUE;
465 } else {
466 php_error_docref(NULL, E_WARNING, "pspell_add_to_session() gave error: %s", pspell_manager_error_message(manager));
467 RETURN_FALSE;
468 }
469 }
470 /* }}} */
471
472 /* {{{ Clears the current session */
PHP_FUNCTION(pspell_clear_session)473 PHP_FUNCTION(pspell_clear_session)
474 {
475 zend_long scin;
476 PspellManager *manager;
477
478 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &scin) == FAILURE) {
479 RETURN_THROWS();
480 }
481
482 PSPELL_FETCH_MANAGER;
483
484 pspell_manager_clear_session(manager);
485 if (pspell_manager_error_number(manager) == 0) {
486 RETURN_TRUE;
487 } else {
488 php_error_docref(NULL, E_WARNING, "pspell_clear_session() gave error: %s", pspell_manager_error_message(manager));
489 RETURN_FALSE;
490 }
491 }
492 /* }}} */
493
494 /* {{{ Saves the current (personal) wordlist */
PHP_FUNCTION(pspell_save_wordlist)495 PHP_FUNCTION(pspell_save_wordlist)
496 {
497 zend_long scin;
498 PspellManager *manager;
499
500 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &scin) == FAILURE) {
501 RETURN_THROWS();
502 }
503
504 PSPELL_FETCH_MANAGER;
505
506 pspell_manager_save_all_word_lists(manager);
507
508 if (pspell_manager_error_number(manager) == 0) {
509 RETURN_TRUE;
510 } else {
511 php_error_docref(NULL, E_WARNING, "pspell_save_wordlist() gave error: %s", pspell_manager_error_message(manager));
512 RETURN_FALSE;
513 }
514
515 }
516 /* }}} */
517
518 /* {{{ Create a new config to be used later to create a manager */
PHP_FUNCTION(pspell_config_create)519 PHP_FUNCTION(pspell_config_create)
520 {
521 char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
522 size_t language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
523 zval *ind;
524 PspellConfig *config;
525
526 #ifdef PHP_WIN32
527 TCHAR aspell_dir[200];
528 TCHAR data_dir[220];
529 TCHAR dict_dir[220];
530 HKEY hkey;
531 DWORD dwType,dwLen;
532 #endif
533
534 if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|sss", &language, &language_len, &spelling, &spelling_len,
535 &jargon, &jargon_len, &encoding, &encoding_len) == FAILURE) {
536 RETURN_THROWS();
537 }
538
539 config = new_pspell_config();
540
541 #ifdef PHP_WIN32
542 /* If aspell was installed using installer, we should have a key
543 * pointing to the location of the dictionaries
544 */
545 if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
546 LONG result;
547 dwLen = sizeof(aspell_dir) - 1;
548 result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
549 RegCloseKey(hkey);
550 if (result == ERROR_SUCCESS) {
551 strlcpy(data_dir, aspell_dir, sizeof(data_dir));
552 strlcat(data_dir, "\\data", sizeof(data_dir));
553 strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
554 strlcat(dict_dir, "\\dict", sizeof(dict_dir));
555
556 pspell_config_replace(config, "data-dir", data_dir);
557 pspell_config_replace(config, "dict-dir", dict_dir);
558 }
559 }
560 #endif
561
562 pspell_config_replace(config, "language-tag", language);
563
564 if (spelling_len) {
565 pspell_config_replace(config, "spelling", spelling);
566 }
567
568 if (jargon_len) {
569 pspell_config_replace(config, "jargon", jargon);
570 }
571
572 if (encoding_len) {
573 pspell_config_replace(config, "encoding", encoding);
574 }
575
576 /* By default I do not want to write anything anywhere because it'll try to write to $HOME
577 which is not what we want */
578 pspell_config_replace(config, "save-repl", "false");
579
580 ind = zend_list_insert(config, le_pspell_config);
581 RETURN_LONG(Z_RES_HANDLE_P(ind));
582 }
583 /* }}} */
584
585 /* {{{ Consider run-together words as valid components */
PHP_FUNCTION(pspell_config_runtogether)586 PHP_FUNCTION(pspell_config_runtogether)
587 {
588 zend_long conf;
589 zend_bool runtogether;
590 PspellConfig *config;
591
592 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lb", &conf, &runtogether) == FAILURE) {
593 RETURN_THROWS();
594 }
595
596 PSPELL_FETCH_CONFIG;
597
598 pspell_config_replace(config, "run-together", runtogether ? "true" : "false");
599
600 RETURN_TRUE;
601 }
602 /* }}} */
603
604 /* {{{ Select mode for config (PSPELL_FAST, PSPELL_NORMAL or PSPELL_BAD_SPELLERS) */
PHP_FUNCTION(pspell_config_mode)605 PHP_FUNCTION(pspell_config_mode)
606 {
607 zend_long conf, mode;
608 PspellConfig *config;
609
610 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &conf, &mode) == FAILURE) {
611 RETURN_THROWS();
612 }
613
614 PSPELL_FETCH_CONFIG;
615
616 /* First check what mode we want (how many suggestions) */
617 if (mode == PSPELL_FAST) {
618 pspell_config_replace(config, "sug-mode", "fast");
619 } else if (mode == PSPELL_NORMAL) {
620 pspell_config_replace(config, "sug-mode", "normal");
621 } else if (mode == PSPELL_BAD_SPELLERS) {
622 pspell_config_replace(config, "sug-mode", "bad-spellers");
623 }
624
625 RETURN_TRUE;
626 }
627 /* }}} */
628
629 /* {{{ Ignore words <= n chars */
PHP_FUNCTION(pspell_config_ignore)630 PHP_FUNCTION(pspell_config_ignore)
631 {
632 char ignore_str[MAX_LENGTH_OF_LONG + 1];
633 zend_long conf, ignore = 0L;
634 PspellConfig *config;
635
636 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &conf, &ignore) == FAILURE) {
637 RETURN_THROWS();
638 }
639
640 PSPELL_FETCH_CONFIG;
641
642 snprintf(ignore_str, sizeof(ignore_str), ZEND_LONG_FMT, ignore);
643
644 pspell_config_replace(config, "ignore", ignore_str);
645 RETURN_TRUE;
646 }
647 /* }}} */
648
pspell_config_path(INTERNAL_FUNCTION_PARAMETERS,char * option)649 static void pspell_config_path(INTERNAL_FUNCTION_PARAMETERS, char *option)
650 {
651 zend_long conf;
652 char *value;
653 size_t value_len;
654 PspellConfig *config;
655
656 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lp", &conf, &value, &value_len) == FAILURE) {
657 RETURN_THROWS();
658 }
659
660 PSPELL_FETCH_CONFIG;
661
662 if (php_check_open_basedir(value)) {
663 RETURN_FALSE;
664 }
665
666 pspell_config_replace(config, option, value);
667
668 RETURN_TRUE;
669 }
670
671 /* {{{ Use a personal dictionary for this config */
PHP_FUNCTION(pspell_config_personal)672 PHP_FUNCTION(pspell_config_personal)
673 {
674 pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "personal");
675 }
676 /* }}} */
677
678 /* {{{ location of the main word list */
PHP_FUNCTION(pspell_config_dict_dir)679 PHP_FUNCTION(pspell_config_dict_dir)
680 {
681 pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "dict-dir");
682 }
683 /* }}} */
684
685 /* {{{ location of language data files */
PHP_FUNCTION(pspell_config_data_dir)686 PHP_FUNCTION(pspell_config_data_dir)
687 {
688 pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "data-dir");
689 }
690 /* }}} */
691
692 /* {{{ Use a personal dictionary with replacement pairs for this config */
PHP_FUNCTION(pspell_config_repl)693 PHP_FUNCTION(pspell_config_repl)
694 {
695 zend_long conf;
696 char *repl;
697 size_t repl_len;
698 PspellConfig *config;
699
700 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lp", &conf, &repl, &repl_len) == FAILURE) {
701 RETURN_THROWS();
702 }
703
704 PSPELL_FETCH_CONFIG;
705
706 pspell_config_replace(config, "save-repl", "true");
707
708 if (php_check_open_basedir(repl)) {
709 RETURN_FALSE;
710 }
711
712 pspell_config_replace(config, "repl", repl);
713
714 RETURN_TRUE;
715 }
716 /* }}} */
717
718 /* {{{ Save replacement pairs when personal list is saved for this config */
PHP_FUNCTION(pspell_config_save_repl)719 PHP_FUNCTION(pspell_config_save_repl)
720 {
721 zend_long conf;
722 zend_bool save;
723 PspellConfig *config;
724
725 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lb", &conf, &save) == FAILURE) {
726 RETURN_THROWS();
727 }
728
729 PSPELL_FETCH_CONFIG;
730
731 pspell_config_replace(config, "save-repl", save ? "true" : "false");
732
733 RETURN_TRUE;
734 }
735 /* }}} */
736
737 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(pspell)738 static PHP_MINFO_FUNCTION(pspell)
739 {
740 php_info_print_table_start();
741 php_info_print_table_row(2, "PSpell Support", "enabled");
742 php_info_print_table_end();
743 }
744 /* }}} */
745
746 #endif
747