1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.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: Vlad Krupin <phpdevel@echospace.com> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: pspell.c 276986 2009-03-10 23:40:06Z helly $ */
20 :
21 : #define IS_EXT_MODULE
22 :
23 : #ifdef HAVE_CONFIG_H
24 : #include "config.h"
25 : #endif
26 :
27 : #include "php.h"
28 :
29 : #include <stdlib.h>
30 : #include <ctype.h>
31 : #include <stdio.h>
32 :
33 : #if HAVE_PSPELL
34 :
35 : /* this will enforce compatibility in .12 version (broken after .11.2) */
36 : #define USE_ORIGINAL_MANAGER_FUNCS
37 :
38 : #include "php_pspell.h"
39 : #include <pspell.h>
40 : #include "ext/standard/info.h"
41 :
42 : #define PSPELL_FAST 1L
43 : #define PSPELL_NORMAL 2L
44 : #define PSPELL_BAD_SPELLERS 3L
45 : #define PSPELL_SPEED_MASK_INTERNAL 3L
46 : #define PSPELL_RUN_TOGETHER 8L
47 :
48 : /* Largest ignored word can be 999 characters (this seems sane enough),
49 : * and it takes 3 bytes to represent that (see pspell_config_ignore)
50 : */
51 : #define PSPELL_LARGEST_WORD 3
52 :
53 : static PHP_MINIT_FUNCTION(pspell);
54 : static PHP_MINFO_FUNCTION(pspell);
55 : static PHP_FUNCTION(pspell_new);
56 : static PHP_FUNCTION(pspell_new_personal);
57 : static PHP_FUNCTION(pspell_new_config);
58 : static PHP_FUNCTION(pspell_check);
59 : static PHP_FUNCTION(pspell_suggest);
60 : static PHP_FUNCTION(pspell_store_replacement);
61 : static PHP_FUNCTION(pspell_add_to_personal);
62 : static PHP_FUNCTION(pspell_add_to_session);
63 : static PHP_FUNCTION(pspell_clear_session);
64 : static PHP_FUNCTION(pspell_save_wordlist);
65 : static PHP_FUNCTION(pspell_config_create);
66 : static PHP_FUNCTION(pspell_config_runtogether);
67 : static PHP_FUNCTION(pspell_config_mode);
68 : static PHP_FUNCTION(pspell_config_ignore);
69 : static PHP_FUNCTION(pspell_config_personal);
70 : static PHP_FUNCTION(pspell_config_dict_dir);
71 : static PHP_FUNCTION(pspell_config_data_dir);
72 : static PHP_FUNCTION(pspell_config_repl);
73 : static PHP_FUNCTION(pspell_config_save_repl);
74 :
75 : /* {{{ arginfo */
76 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_new, 0, 0, 1)
77 : ZEND_ARG_INFO(0, language)
78 : ZEND_ARG_INFO(0, spelling)
79 : ZEND_ARG_INFO(0, jargon)
80 : ZEND_ARG_INFO(0, encoding)
81 : ZEND_ARG_INFO(0, mode)
82 : ZEND_END_ARG_INFO()
83 :
84 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_new_personal, 0, 0, 2)
85 : ZEND_ARG_INFO(0, personal)
86 : ZEND_ARG_INFO(0, language)
87 : ZEND_ARG_INFO(0, spelling)
88 : ZEND_ARG_INFO(0, jargon)
89 : ZEND_ARG_INFO(0, encoding)
90 : ZEND_ARG_INFO(0, mode)
91 : ZEND_END_ARG_INFO()
92 :
93 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_new_config, 0, 0, 1)
94 : ZEND_ARG_INFO(0, config)
95 : ZEND_END_ARG_INFO()
96 :
97 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_check, 0, 0, 2)
98 : ZEND_ARG_INFO(0, pspell)
99 : ZEND_ARG_INFO(0, word)
100 : ZEND_END_ARG_INFO()
101 :
102 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_suggest, 0, 0, 2)
103 : ZEND_ARG_INFO(0, pspell)
104 : ZEND_ARG_INFO(0, word)
105 : ZEND_END_ARG_INFO()
106 :
107 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_store_replacement, 0, 0, 3)
108 : ZEND_ARG_INFO(0, pspell)
109 : ZEND_ARG_INFO(0, misspell)
110 : ZEND_ARG_INFO(0, correct)
111 : ZEND_END_ARG_INFO()
112 :
113 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_add_to_personal, 0, 0, 2)
114 : ZEND_ARG_INFO(0, pspell)
115 : ZEND_ARG_INFO(0, word)
116 : ZEND_END_ARG_INFO()
117 :
118 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_add_to_session, 0, 0, 2)
119 : ZEND_ARG_INFO(0, pspell)
120 : ZEND_ARG_INFO(0, word)
121 : ZEND_END_ARG_INFO()
122 :
123 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_clear_session, 0, 0, 1)
124 : ZEND_ARG_INFO(0, pspell)
125 : ZEND_END_ARG_INFO()
126 :
127 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_save_wordlist, 0, 0, 1)
128 : ZEND_ARG_INFO(0, pspell)
129 : ZEND_END_ARG_INFO()
130 :
131 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_create, 0, 0, 1)
132 : ZEND_ARG_INFO(0, language)
133 : ZEND_ARG_INFO(0, spelling)
134 : ZEND_ARG_INFO(0, jargon)
135 : ZEND_ARG_INFO(0, encoding)
136 : ZEND_END_ARG_INFO()
137 :
138 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_runtogether, 0, 0, 2)
139 : ZEND_ARG_INFO(0, conf)
140 : ZEND_ARG_INFO(0, runtogether)
141 : ZEND_END_ARG_INFO()
142 :
143 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_mode, 0, 0, 2)
144 : ZEND_ARG_INFO(0, conf)
145 : ZEND_ARG_INFO(0, mode)
146 : ZEND_END_ARG_INFO()
147 :
148 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_ignore, 0, 0, 2)
149 : ZEND_ARG_INFO(0, conf)
150 : ZEND_ARG_INFO(0, ignore)
151 : ZEND_END_ARG_INFO()
152 :
153 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_personal, 0, 0, 2)
154 : ZEND_ARG_INFO(0, conf)
155 : ZEND_ARG_INFO(0, personal)
156 : ZEND_END_ARG_INFO()
157 :
158 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_dict_dir, 0, 0, 2)
159 : ZEND_ARG_INFO(0, conf)
160 : ZEND_ARG_INFO(0, directory)
161 : ZEND_END_ARG_INFO()
162 :
163 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_data_dir, 0, 0, 2)
164 : ZEND_ARG_INFO(0, conf)
165 : ZEND_ARG_INFO(0, directory)
166 : ZEND_END_ARG_INFO()
167 :
168 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_repl, 0, 0, 2)
169 : ZEND_ARG_INFO(0, conf)
170 : ZEND_ARG_INFO(0, repl)
171 : ZEND_END_ARG_INFO()
172 :
173 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pspell_config_save_repl, 0, 0, 2)
174 : ZEND_ARG_INFO(0, conf)
175 : ZEND_ARG_INFO(0, save)
176 : ZEND_END_ARG_INFO()
177 : /* }}} */
178 :
179 : /* {{{ pspell_functions[]
180 : */
181 : static const zend_function_entry pspell_functions[] = {
182 : PHP_FE(pspell_new, arginfo_pspell_new)
183 : PHP_FE(pspell_new_personal, arginfo_pspell_new_personal)
184 : PHP_FE(pspell_new_config, arginfo_pspell_new_config)
185 : PHP_FE(pspell_check, arginfo_pspell_check)
186 : PHP_FE(pspell_suggest, arginfo_pspell_suggest)
187 : PHP_FE(pspell_store_replacement, arginfo_pspell_store_replacement)
188 : PHP_FE(pspell_add_to_personal, arginfo_pspell_add_to_personal)
189 : PHP_FE(pspell_add_to_session, arginfo_pspell_add_to_session)
190 : PHP_FE(pspell_clear_session, arginfo_pspell_clear_session)
191 : PHP_FE(pspell_save_wordlist, arginfo_pspell_save_wordlist)
192 : PHP_FE(pspell_config_create, arginfo_pspell_config_create)
193 : PHP_FE(pspell_config_runtogether, arginfo_pspell_config_runtogether)
194 : PHP_FE(pspell_config_mode, arginfo_pspell_config_mode)
195 : PHP_FE(pspell_config_ignore, arginfo_pspell_config_ignore)
196 : PHP_FE(pspell_config_personal, arginfo_pspell_config_personal)
197 : PHP_FE(pspell_config_dict_dir, arginfo_pspell_config_dict_dir)
198 : PHP_FE(pspell_config_data_dir, arginfo_pspell_config_data_dir)
199 : PHP_FE(pspell_config_repl, arginfo_pspell_config_repl)
200 : PHP_FE(pspell_config_save_repl, arginfo_pspell_config_save_repl)
201 : {NULL, NULL, NULL}
202 : };
203 : /* }}} */
204 :
205 : static int le_pspell, le_pspell_config;
206 :
207 : zend_module_entry pspell_module_entry = {
208 : STANDARD_MODULE_HEADER,
209 : "pspell", pspell_functions, PHP_MINIT(pspell), NULL, NULL, NULL, PHP_MINFO(pspell), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
210 : };
211 :
212 : #ifdef COMPILE_DL_PSPELL
213 : ZEND_GET_MODULE(pspell)
214 : #endif
215 :
216 : static void php_pspell_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
217 13 : {
218 13 : PspellManager *manager = (PspellManager *)rsrc->ptr;
219 :
220 13 : delete_pspell_manager(manager);
221 13 : }
222 :
223 : static void php_pspell_close_config(zend_rsrc_list_entry *rsrc TSRMLS_DC)
224 4 : {
225 4 : PspellConfig *config = (PspellConfig *)rsrc->ptr;
226 :
227 4 : delete_pspell_config(config);
228 4 : }
229 :
230 : #define PSPELL_FETCH_CONFIG \
231 : config = (PspellConfig *) zend_list_find(conf, &type); \
232 : if (config == NULL || type != le_pspell_config) { \
233 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "%ld is not a PSPELL config index", conf); \
234 : RETURN_FALSE; \
235 : } \
236 :
237 : #define PSPELL_FETCH_MANAGER \
238 : manager = (PspellManager *) zend_list_find(scin, &type); \
239 : if (!manager || type != le_pspell) { \
240 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "%ld is not a PSPELL result index", scin); \
241 : RETURN_FALSE; \
242 : } \
243 :
244 : /* {{{ PHP_MINIT_FUNCTION
245 : */
246 : static PHP_MINIT_FUNCTION(pspell)
247 17007 : {
248 17007 : REGISTER_LONG_CONSTANT("PSPELL_FAST", PSPELL_FAST, CONST_PERSISTENT | CONST_CS);
249 17007 : REGISTER_LONG_CONSTANT("PSPELL_NORMAL", PSPELL_NORMAL, CONST_PERSISTENT | CONST_CS);
250 17007 : REGISTER_LONG_CONSTANT("PSPELL_BAD_SPELLERS", PSPELL_BAD_SPELLERS, CONST_PERSISTENT | CONST_CS);
251 17007 : REGISTER_LONG_CONSTANT("PSPELL_RUN_TOGETHER", PSPELL_RUN_TOGETHER, CONST_PERSISTENT | CONST_CS);
252 17007 : le_pspell = zend_register_list_destructors_ex(php_pspell_close, NULL, "pspell", module_number);
253 17007 : le_pspell_config = zend_register_list_destructors_ex(php_pspell_close_config, NULL, "pspell config", module_number);
254 17007 : return SUCCESS;
255 : }
256 : /* }}} */
257 :
258 : /* {{{ proto int pspell_new(string language [, string spelling [, string jargon [, string encoding [, int mode]]]])
259 : Load a dictionary */
260 : static PHP_FUNCTION(pspell_new)
261 7 : {
262 7 : char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
263 7 : int language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
264 7 : long mode = 0L, speed = 0L;
265 7 : int argc = ZEND_NUM_ARGS();
266 : int ind;
267 :
268 : #ifdef PHP_WIN32
269 : TCHAR aspell_dir[200];
270 : TCHAR data_dir[220];
271 : TCHAR dict_dir[220];
272 : HKEY hkey;
273 : DWORD dwType,dwLen;
274 : #endif
275 :
276 : PspellCanHaveError *ret;
277 : PspellManager *manager;
278 : PspellConfig *config;
279 :
280 7 : if (zend_parse_parameters(argc TSRMLS_CC, "s|sssl", &language, &language_len, &spelling, &spelling_len,
281 : &jargon, &jargon_len, &encoding, &encoding_len, &mode) == FAILURE) {
282 0 : return;
283 : }
284 :
285 7 : config = new_pspell_config();
286 :
287 : #ifdef PHP_WIN32
288 : /* If aspell was installed using installer, we should have a key
289 : * pointing to the location of the dictionaries
290 : */
291 : if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
292 : LONG result;
293 : dwLen = sizeof(aspell_dir) - 1;
294 : result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
295 : RegCloseKey(hkey);
296 : if (result == ERROR_SUCCESS) {
297 : strlcpy(data_dir, aspell_dir, sizeof(data_dir));
298 : strlcat(data_dir, "\\data", sizeof(data_dir));
299 : strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
300 : strlcat(dict_dir, "\\dict", sizeof(dict_dir));
301 :
302 : pspell_config_replace(config, "data-dir", data_dir);
303 : pspell_config_replace(config, "dict-dir", dict_dir);
304 : }
305 : }
306 : #endif
307 :
308 7 : pspell_config_replace(config, "language-tag", language);
309 :
310 7 : if (argc > 1) {
311 2 : if (spelling_len > 0) {
312 0 : pspell_config_replace(config, "spelling", spelling);
313 : }
314 : }
315 :
316 7 : if (argc > 2) {
317 2 : if (jargon_len > 0) {
318 0 : pspell_config_replace(config, "jargon", jargon);
319 : }
320 : }
321 :
322 7 : if (argc > 3) {
323 2 : if (encoding_len > 0) {
324 0 : pspell_config_replace(config, "encoding", encoding);
325 : }
326 : }
327 :
328 7 : if (argc > 4) {
329 2 : speed = mode & PSPELL_SPEED_MASK_INTERNAL;
330 :
331 : /* First check what mode we want (how many suggestions) */
332 2 : if (speed == PSPELL_FAST) {
333 2 : pspell_config_replace(config, "sug-mode", "fast");
334 0 : } else if (speed == PSPELL_NORMAL) {
335 0 : pspell_config_replace(config, "sug-mode", "normal");
336 0 : } else if (speed == PSPELL_BAD_SPELLERS) {
337 0 : pspell_config_replace(config, "sug-mode", "bad-spellers");
338 : }
339 :
340 : /* Then we see if run-together words should be treated as valid components */
341 2 : if (mode & PSPELL_RUN_TOGETHER) {
342 2 : pspell_config_replace(config, "run-together", "true");
343 : }
344 : }
345 :
346 7 : ret = new_pspell_manager(config);
347 7 : delete_pspell_config(config);
348 :
349 7 : if (pspell_error_number(ret) != 0) {
350 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
351 0 : delete_pspell_can_have_error(ret);
352 0 : RETURN_FALSE;
353 : }
354 :
355 7 : manager = to_pspell_manager(ret);
356 7 : ind = zend_list_insert(manager, le_pspell);
357 7 : RETURN_LONG(ind);
358 : }
359 : /* }}} */
360 :
361 : /* {{{ proto int pspell_new_personal(string personal, string language [, string spelling [, string jargon [, string encoding [, int mode]]]])
362 : Load a dictionary with a personal wordlist*/
363 : static PHP_FUNCTION(pspell_new_personal)
364 2 : {
365 2 : char *personal, *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
366 2 : int personal_len, language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
367 2 : long mode = 0L, speed = 0L;
368 2 : int argc = ZEND_NUM_ARGS();
369 : int ind;
370 :
371 : #ifdef PHP_WIN32
372 : TCHAR aspell_dir[200];
373 : TCHAR data_dir[220];
374 : TCHAR dict_dir[220];
375 : HKEY hkey;
376 : DWORD dwType,dwLen;
377 : #endif
378 :
379 : PspellCanHaveError *ret;
380 : PspellManager *manager;
381 : PspellConfig *config;
382 :
383 2 : if (zend_parse_parameters(argc TSRMLS_CC, "ss|sssl", &personal, &personal_len, &language, &language_len,
384 : &spelling, &spelling_len, &jargon, &jargon_len, &encoding, &encoding_len, &mode) == FAILURE) {
385 0 : return;
386 : }
387 :
388 2 : config = new_pspell_config();
389 :
390 : #ifdef PHP_WIN32
391 : /* If aspell was installed using installer, we should have a key
392 : * pointing to the location of the dictionaries
393 : */
394 : if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
395 : LONG result;
396 : dwLen = sizeof(aspell_dir) - 1;
397 : result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
398 : RegCloseKey(hkey);
399 : if (result == ERROR_SUCCESS) {
400 : strlcpy(data_dir, aspell_dir, sizeof(data_dir));
401 : strlcat(data_dir, "\\data", sizeof(data_dir));
402 : strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
403 : strlcat(dict_dir, "\\dict", sizeof(dict_dir));
404 :
405 : pspell_config_replace(config, "data-dir", data_dir);
406 : pspell_config_replace(config, "dict-dir", dict_dir);
407 : }
408 : }
409 : #endif
410 :
411 2 : if (php_check_open_basedir(personal TSRMLS_CC)) {
412 0 : delete_pspell_config(config);
413 0 : RETURN_FALSE;
414 : }
415 :
416 2 : pspell_config_replace(config, "personal", personal);
417 2 : pspell_config_replace(config, "save-repl", "false");
418 2 : pspell_config_replace(config, "language-tag", language);
419 :
420 2 : if (argc > 2) {
421 0 : if (spelling_len > 0) {
422 0 : pspell_config_replace(config, "spelling", spelling);
423 : }
424 : }
425 :
426 2 : if (argc > 3) {
427 0 : if (jargon_len > 0) {
428 0 : pspell_config_replace(config, "jargon", jargon);
429 : }
430 : }
431 :
432 2 : if (argc > 4) {
433 0 : if (encoding_len > 0) {
434 0 : pspell_config_replace(config, "encoding", encoding);
435 : }
436 : }
437 :
438 2 : if (argc > 5) {
439 0 : speed = mode & PSPELL_SPEED_MASK_INTERNAL;
440 :
441 : /* First check what mode we want (how many suggestions) */
442 0 : if (speed == PSPELL_FAST) {
443 0 : pspell_config_replace(config, "sug-mode", "fast");
444 0 : } else if (speed == PSPELL_NORMAL) {
445 0 : pspell_config_replace(config, "sug-mode", "normal");
446 0 : } else if (speed == PSPELL_BAD_SPELLERS) {
447 0 : pspell_config_replace(config, "sug-mode", "bad-spellers");
448 : }
449 :
450 : /* Then we see if run-together words should be treated as valid components */
451 0 : if (mode & PSPELL_RUN_TOGETHER) {
452 0 : pspell_config_replace(config, "run-together", "true");
453 : }
454 : }
455 :
456 2 : ret = new_pspell_manager(config);
457 2 : delete_pspell_config(config);
458 :
459 2 : if (pspell_error_number(ret) != 0) {
460 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
461 1 : delete_pspell_can_have_error(ret);
462 1 : RETURN_FALSE;
463 : }
464 :
465 1 : manager = to_pspell_manager(ret);
466 1 : ind = zend_list_insert(manager, le_pspell);
467 1 : RETURN_LONG(ind);
468 : }
469 : /* }}} */
470 :
471 : /* {{{ proto int pspell_new_config(int config)
472 : Load a dictionary based on the given config */
473 : static PHP_FUNCTION(pspell_new_config)
474 6 : {
475 : int type, ind;
476 : long conf;
477 : PspellCanHaveError *ret;
478 : PspellManager *manager;
479 : PspellConfig *config;
480 :
481 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &conf) == FAILURE) {
482 0 : return;
483 : }
484 :
485 6 : PSPELL_FETCH_CONFIG;
486 :
487 6 : ret = new_pspell_manager(config);
488 :
489 6 : if (pspell_error_number(ret) != 0) {
490 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
491 1 : delete_pspell_can_have_error(ret);
492 1 : RETURN_FALSE;
493 : }
494 :
495 5 : manager = to_pspell_manager(ret);
496 5 : ind = zend_list_insert(manager, le_pspell);
497 5 : RETURN_LONG(ind);
498 : }
499 : /* }}} */
500 :
501 : /* {{{ proto bool pspell_check(int pspell, string word)
502 : Returns true if word is valid */
503 : static PHP_FUNCTION(pspell_check)
504 88 : {
505 : int type, word_len;
506 : long scin;
507 : char *word;
508 : PspellManager *manager;
509 :
510 88 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
511 1 : return;
512 : }
513 :
514 87 : PSPELL_FETCH_MANAGER;
515 :
516 86 : if (pspell_manager_check(manager, word)) {
517 79 : RETURN_TRUE;
518 : } else {
519 7 : RETURN_FALSE;
520 : }
521 : }
522 : /* }}} */
523 :
524 : /* {{{ proto array pspell_suggest(int pspell, string word)
525 : Returns array of suggestions */
526 : static PHP_FUNCTION(pspell_suggest)
527 2 : {
528 : long scin;
529 : char *word;
530 : int word_len;
531 : PspellManager *manager;
532 : int type;
533 : const PspellWordList *wl;
534 : const char *sug;
535 :
536 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
537 0 : return;
538 : }
539 :
540 2 : PSPELL_FETCH_MANAGER;
541 :
542 2 : array_init(return_value);
543 :
544 2 : wl = pspell_manager_suggest(manager, word);
545 2 : if (wl) {
546 2 : PspellStringEmulation *els = pspell_word_list_elements(wl);
547 49 : while ((sug = pspell_string_emulation_next(els)) != 0) {
548 45 : add_next_index_string(return_value,(char *)sug,1);
549 : }
550 2 : delete_pspell_string_emulation(els);
551 : } else {
552 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL had a problem. details: %s", pspell_manager_error_message(manager));
553 0 : RETURN_FALSE;
554 : }
555 : }
556 : /* }}} */
557 :
558 : /* {{{ proto bool pspell_store_replacement(int pspell, string misspell, string correct)
559 : Notify the dictionary of a user-selected replacement */
560 : static PHP_FUNCTION(pspell_store_replacement)
561 0 : {
562 : int type, miss_len, corr_len;
563 : long scin;
564 : char *miss, *corr;
565 : PspellManager *manager;
566 :
567 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lss", &scin, &miss, &miss_len, &corr, &corr_len) == FAILURE) {
568 0 : return;
569 : }
570 :
571 0 : PSPELL_FETCH_MANAGER;
572 :
573 0 : pspell_manager_store_replacement(manager, miss, corr);
574 0 : if (pspell_manager_error_number(manager) == 0) {
575 0 : RETURN_TRUE;
576 : } else {
577 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_store_replacement() gave error: %s", pspell_manager_error_message(manager));
578 0 : RETURN_FALSE;
579 : }
580 : }
581 : /* }}} */
582 :
583 : /* {{{ proto bool pspell_add_to_personal(int pspell, string word)
584 : Adds a word to a personal list */
585 : static PHP_FUNCTION(pspell_add_to_personal)
586 1 : {
587 : int type, word_len;
588 : long scin;
589 : char *word;
590 : PspellManager *manager;
591 :
592 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
593 0 : return;
594 : }
595 :
596 1 : PSPELL_FETCH_MANAGER;
597 :
598 : /*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
599 1 : if (word_len == 0) {
600 0 : RETURN_FALSE;
601 : }
602 :
603 1 : pspell_manager_add_to_personal(manager, word);
604 1 : if (pspell_manager_error_number(manager) == 0) {
605 1 : RETURN_TRUE;
606 : } else {
607 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_add_to_personal() gave error: %s", pspell_manager_error_message(manager));
608 0 : RETURN_FALSE;
609 : }
610 : }
611 : /* }}} */
612 :
613 : /* {{{ proto bool pspell_add_to_session(int pspell, string word)
614 : Adds a word to the current session */
615 : static PHP_FUNCTION(pspell_add_to_session)
616 2 : {
617 : int type, word_len;
618 : long scin;
619 : char *word;
620 : PspellManager *manager;
621 :
622 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
623 0 : return;
624 : }
625 :
626 2 : PSPELL_FETCH_MANAGER;
627 :
628 : /*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
629 2 : if (word_len == 0) {
630 1 : RETURN_FALSE;
631 : }
632 :
633 1 : pspell_manager_add_to_session(manager, word);
634 1 : if (pspell_manager_error_number(manager) == 0) {
635 1 : RETURN_TRUE;
636 : } else {
637 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_add_to_session() gave error: %s", pspell_manager_error_message(manager));
638 0 : RETURN_FALSE;
639 : }
640 : }
641 : /* }}} */
642 :
643 : /* {{{ proto bool pspell_clear_session(int pspell)
644 : Clears the current session */
645 : static PHP_FUNCTION(pspell_clear_session)
646 2 : {
647 : int type;
648 : long scin;
649 : PspellManager *manager;
650 :
651 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &scin) == FAILURE) {
652 1 : return;
653 : }
654 :
655 1 : PSPELL_FETCH_MANAGER;
656 :
657 1 : pspell_manager_clear_session(manager);
658 1 : if (pspell_manager_error_number(manager) == 0) {
659 1 : RETURN_TRUE;
660 : } else {
661 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_clear_session() gave error: %s", pspell_manager_error_message(manager));
662 0 : RETURN_FALSE;
663 : }
664 : }
665 : /* }}} */
666 :
667 : /* {{{ proto bool pspell_save_wordlist(int pspell)
668 : Saves the current (personal) wordlist */
669 : static PHP_FUNCTION(pspell_save_wordlist)
670 1 : {
671 : int type;
672 : long scin;
673 : PspellManager *manager;
674 :
675 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &scin) == FAILURE) {
676 0 : return;
677 : }
678 :
679 1 : PSPELL_FETCH_MANAGER;
680 :
681 1 : pspell_manager_save_all_word_lists(manager);
682 :
683 1 : if (pspell_manager_error_number(manager) == 0) {
684 1 : RETURN_TRUE;
685 : } else {
686 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_save_wordlist() gave error: %s", pspell_manager_error_message(manager));
687 0 : RETURN_FALSE;
688 : }
689 :
690 : }
691 : /* }}} */
692 :
693 : /* {{{ proto int pspell_config_create(string language [, string spelling [, string jargon [, string encoding]]])
694 : Create a new config to be used later to create a manager */
695 : static PHP_FUNCTION(pspell_config_create)
696 4 : {
697 4 : char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
698 4 : int language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
699 : int ind;
700 : PspellConfig *config;
701 :
702 : #ifdef PHP_WIN32
703 : TCHAR aspell_dir[200];
704 : TCHAR data_dir[220];
705 : TCHAR dict_dir[220];
706 : HKEY hkey;
707 : DWORD dwType,dwLen;
708 : #endif
709 :
710 4 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss", &language, &language_len, &spelling, &spelling_len,
711 : &jargon, &jargon_len, &encoding, &encoding_len) == FAILURE) {
712 0 : return;
713 : }
714 :
715 4 : config = new_pspell_config();
716 :
717 : #ifdef PHP_WIN32
718 : /* If aspell was installed using installer, we should have a key
719 : * pointing to the location of the dictionaries
720 : */
721 : if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
722 : LONG result;
723 : dwLen = sizeof(aspell_dir) - 1;
724 : result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
725 : RegCloseKey(hkey);
726 : if (result == ERROR_SUCCESS) {
727 : strlcpy(data_dir, aspell_dir, sizeof(data_dir));
728 : strlcat(data_dir, "\\data", sizeof(data_dir));
729 : strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
730 : strlcat(dict_dir, "\\dict", sizeof(dict_dir));
731 :
732 : pspell_config_replace(config, "data-dir", data_dir);
733 : pspell_config_replace(config, "dict-dir", dict_dir);
734 : }
735 : }
736 : #endif
737 :
738 4 : pspell_config_replace(config, "language-tag", language);
739 :
740 4 : if (spelling_len) {
741 3 : pspell_config_replace(config, "spelling", spelling);
742 : }
743 :
744 4 : if (jargon_len) {
745 0 : pspell_config_replace(config, "jargon", jargon);
746 : }
747 :
748 4 : if (encoding_len) {
749 3 : pspell_config_replace(config, "encoding", encoding);
750 : }
751 :
752 : /* By default I do not want to write anything anywhere because it'll try to write to $HOME
753 : which is not what we want */
754 4 : pspell_config_replace(config, "save-repl", "false");
755 :
756 4 : ind = zend_list_insert(config, le_pspell_config);
757 4 : RETURN_LONG(ind);
758 : }
759 : /* }}} */
760 :
761 : /* {{{ proto bool pspell_config_runtogether(int conf, bool runtogether)
762 : Consider run-together words as valid components */
763 : static PHP_FUNCTION(pspell_config_runtogether)
764 3 : {
765 : int type;
766 : long conf;
767 : zend_bool runtogether;
768 : PspellConfig *config;
769 :
770 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &conf, &runtogether) == FAILURE) {
771 0 : return;
772 : }
773 :
774 3 : PSPELL_FETCH_CONFIG;
775 :
776 3 : pspell_config_replace(config, "run-together", runtogether ? "true" : "false");
777 :
778 3 : RETURN_TRUE;
779 : }
780 : /* }}} */
781 :
782 : /* {{{ proto bool pspell_config_mode(int conf, long mode)
783 : Select mode for config (PSPELL_FAST, PSPELL_NORMAL or PSPELL_BAD_SPELLERS) */
784 : static PHP_FUNCTION(pspell_config_mode)
785 1 : {
786 : int type;
787 : long conf, mode;
788 : PspellConfig *config;
789 :
790 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &conf, &mode) == FAILURE) {
791 0 : return;
792 : }
793 :
794 1 : PSPELL_FETCH_CONFIG;
795 :
796 : /* First check what mode we want (how many suggestions) */
797 1 : if (mode == PSPELL_FAST) {
798 0 : pspell_config_replace(config, "sug-mode", "fast");
799 1 : } else if (mode == PSPELL_NORMAL) {
800 0 : pspell_config_replace(config, "sug-mode", "normal");
801 1 : } else if (mode == PSPELL_BAD_SPELLERS) {
802 1 : pspell_config_replace(config, "sug-mode", "bad-spellers");
803 : }
804 :
805 1 : RETURN_TRUE;
806 : }
807 : /* }}} */
808 :
809 : /* {{{ proto bool pspell_config_ignore(int conf, int ignore)
810 : Ignore words <= n chars */
811 : static PHP_FUNCTION(pspell_config_ignore)
812 2 : {
813 : int type;
814 : char ignore_str[MAX_LENGTH_OF_LONG + 1];
815 2 : long conf, ignore = 0L;
816 : PspellConfig *config;
817 :
818 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &conf, &ignore) == FAILURE) {
819 0 : return;
820 : }
821 :
822 2 : PSPELL_FETCH_CONFIG;
823 :
824 2 : snprintf(ignore_str, sizeof(ignore_str), "%ld", ignore);
825 :
826 2 : pspell_config_replace(config, "ignore", ignore_str);
827 2 : RETURN_TRUE;
828 : }
829 : /* }}} */
830 :
831 : static void pspell_config_path(INTERNAL_FUNCTION_PARAMETERS, char *option)
832 1 : {
833 : int type;
834 : long conf;
835 : char *value;
836 : int value_len;
837 : PspellConfig *config;
838 :
839 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &conf, &value, &value_len) == FAILURE) {
840 0 : return;
841 : }
842 :
843 1 : PSPELL_FETCH_CONFIG;
844 :
845 1 : if (php_check_open_basedir(value TSRMLS_CC)) {
846 0 : RETURN_FALSE;
847 : }
848 :
849 1 : pspell_config_replace(config, option, value);
850 :
851 1 : RETURN_TRUE;
852 : }
853 :
854 : /* {{{ proto bool pspell_config_personal(int conf, string personal)
855 : Use a personal dictionary for this config */
856 : static PHP_FUNCTION(pspell_config_personal)
857 1 : {
858 1 : pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "personal");
859 1 : }
860 : /* }}} */
861 :
862 : /* {{{ proto bool pspell_config_dict_dir(int conf, string directory)
863 : location of the main word list */
864 : static PHP_FUNCTION(pspell_config_dict_dir)
865 0 : {
866 0 : pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "dict-dir");
867 0 : }
868 : /* }}} */
869 :
870 : /* {{{ proto bool pspell_config_data_dir(int conf, string directory)
871 : location of language data files */
872 : static PHP_FUNCTION(pspell_config_data_dir)
873 0 : {
874 0 : pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "data-dir");
875 0 : }
876 : /* }}} */
877 :
878 : /* {{{ proto bool pspell_config_repl(int conf, string repl)
879 : Use a personal dictionary with replacement pairs for this config */
880 : static PHP_FUNCTION(pspell_config_repl)
881 0 : {
882 : int type;
883 : long conf;
884 : char *repl;
885 : int repl_len;
886 : PspellConfig *config;
887 :
888 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &conf, &repl, &repl_len) == FAILURE) {
889 0 : return;
890 : }
891 :
892 0 : PSPELL_FETCH_CONFIG;
893 :
894 0 : pspell_config_replace(config, "save-repl", "true");
895 :
896 0 : if (php_check_open_basedir(repl TSRMLS_CC)) {
897 0 : RETURN_FALSE;
898 : }
899 :
900 0 : pspell_config_replace(config, "repl", repl);
901 :
902 0 : RETURN_TRUE;
903 : }
904 : /* }}} */
905 :
906 : /* {{{ proto bool pspell_config_save_repl(int conf, bool save)
907 : Save replacement pairs when personal list is saved for this config */
908 : static PHP_FUNCTION(pspell_config_save_repl)
909 0 : {
910 : int type;
911 : long conf;
912 : zend_bool save;
913 : PspellConfig *config;
914 :
915 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &conf, &save) == FAILURE) {
916 0 : return;
917 : }
918 :
919 0 : PSPELL_FETCH_CONFIG;
920 :
921 0 : pspell_config_replace(config, "save-repl", save ? "true" : "false");
922 :
923 0 : RETURN_TRUE;
924 : }
925 : /* }}} */
926 :
927 : /* {{{ PHP_MINFO_FUNCTION
928 : */
929 : static PHP_MINFO_FUNCTION(pspell)
930 43 : {
931 43 : php_info_print_table_start();
932 43 : php_info_print_table_row(2, "PSpell Support", "enabled");
933 43 : php_info_print_table_end();
934 43 : }
935 : /* }}} */
936 :
937 : #endif
938 :
939 : /*
940 : * Local variables:
941 : * tab-width: 4
942 : * c-basic-offset: 4
943 : * End:
944 : * vim600: sw=4 ts=4 fdm=marker
945 : * vim<600: sw=4 ts=4
946 : */
|