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