Annotation of embedaddon/php/ext/pspell/pspell.c, revision 1.1.1.4
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.4 ! misho 5: | Copyright (c) 1997-2014 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 19: /* $Id$ */
1.1 misho 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: PHP_FE_END
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: {
218: PspellManager *manager = (PspellManager *)rsrc->ptr;
219:
220: delete_pspell_manager(manager);
221: }
222:
223: static void php_pspell_close_config(zend_rsrc_list_entry *rsrc TSRMLS_DC)
224: {
225: PspellConfig *config = (PspellConfig *)rsrc->ptr;
226:
227: delete_pspell_config(config);
228: }
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: {
248: REGISTER_LONG_CONSTANT("PSPELL_FAST", PSPELL_FAST, CONST_PERSISTENT | CONST_CS);
249: REGISTER_LONG_CONSTANT("PSPELL_NORMAL", PSPELL_NORMAL, CONST_PERSISTENT | CONST_CS);
250: REGISTER_LONG_CONSTANT("PSPELL_BAD_SPELLERS", PSPELL_BAD_SPELLERS, CONST_PERSISTENT | CONST_CS);
251: REGISTER_LONG_CONSTANT("PSPELL_RUN_TOGETHER", PSPELL_RUN_TOGETHER, CONST_PERSISTENT | CONST_CS);
252: le_pspell = zend_register_list_destructors_ex(php_pspell_close, NULL, "pspell", module_number);
253: le_pspell_config = zend_register_list_destructors_ex(php_pspell_close_config, NULL, "pspell config", module_number);
254: 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: {
262: char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
263: int language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
264: long mode = 0L, speed = 0L;
265: 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: 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: return;
283: }
284:
285: 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: pspell_config_replace(config, "language-tag", language);
309:
310: if (spelling_len) {
311: pspell_config_replace(config, "spelling", spelling);
312: }
313:
314: if (jargon_len) {
315: pspell_config_replace(config, "jargon", jargon);
316: }
317:
318: if (encoding_len) {
319: pspell_config_replace(config, "encoding", encoding);
320: }
321:
322: if (argc > 4) {
323: speed = mode & PSPELL_SPEED_MASK_INTERNAL;
324:
325: /* First check what mode we want (how many suggestions) */
326: if (speed == PSPELL_FAST) {
327: pspell_config_replace(config, "sug-mode", "fast");
328: } else if (speed == PSPELL_NORMAL) {
329: pspell_config_replace(config, "sug-mode", "normal");
330: } else if (speed == PSPELL_BAD_SPELLERS) {
331: pspell_config_replace(config, "sug-mode", "bad-spellers");
332: }
333:
334: /* Then we see if run-together words should be treated as valid components */
335: if (mode & PSPELL_RUN_TOGETHER) {
336: pspell_config_replace(config, "run-together", "true");
337: }
338: }
339:
340: ret = new_pspell_manager(config);
341: delete_pspell_config(config);
342:
343: if (pspell_error_number(ret) != 0) {
344: php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
345: delete_pspell_can_have_error(ret);
346: RETURN_FALSE;
347: }
348:
349: manager = to_pspell_manager(ret);
1.1.1.2 misho 350: ind = zend_list_insert(manager, le_pspell TSRMLS_CC);
1.1 misho 351: RETURN_LONG(ind);
352: }
353: /* }}} */
354:
355: /* {{{ proto int pspell_new_personal(string personal, string language [, string spelling [, string jargon [, string encoding [, int mode]]]])
356: Load a dictionary with a personal wordlist*/
357: static PHP_FUNCTION(pspell_new_personal)
358: {
359: char *personal, *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
360: int personal_len, language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
361: long mode = 0L, speed = 0L;
362: int argc = ZEND_NUM_ARGS();
363: int ind;
364:
365: #ifdef PHP_WIN32
366: TCHAR aspell_dir[200];
367: TCHAR data_dir[220];
368: TCHAR dict_dir[220];
369: HKEY hkey;
370: DWORD dwType,dwLen;
371: #endif
372:
373: PspellCanHaveError *ret;
374: PspellManager *manager;
375: PspellConfig *config;
376:
1.1.1.2 misho 377: if (zend_parse_parameters(argc TSRMLS_CC, "ps|sssl", &personal, &personal_len, &language, &language_len,
1.1 misho 378: &spelling, &spelling_len, &jargon, &jargon_len, &encoding, &encoding_len, &mode) == FAILURE) {
379: return;
380: }
381:
382: config = new_pspell_config();
383:
384: #ifdef PHP_WIN32
385: /* If aspell was installed using installer, we should have a key
386: * pointing to the location of the dictionaries
387: */
388: if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
389: LONG result;
390: dwLen = sizeof(aspell_dir) - 1;
391: result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
392: RegCloseKey(hkey);
393: if (result == ERROR_SUCCESS) {
394: strlcpy(data_dir, aspell_dir, sizeof(data_dir));
395: strlcat(data_dir, "\\data", sizeof(data_dir));
396: strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
397: strlcat(dict_dir, "\\dict", sizeof(dict_dir));
398:
399: pspell_config_replace(config, "data-dir", data_dir);
400: pspell_config_replace(config, "dict-dir", dict_dir);
401: }
402: }
403: #endif
404:
405: if (php_check_open_basedir(personal TSRMLS_CC)) {
406: delete_pspell_config(config);
407: RETURN_FALSE;
408: }
409:
410: pspell_config_replace(config, "personal", personal);
411: pspell_config_replace(config, "save-repl", "false");
412:
413: pspell_config_replace(config, "language-tag", language);
414:
415: if (spelling_len) {
416: pspell_config_replace(config, "spelling", spelling);
417: }
418:
419: if (jargon_len) {
420: pspell_config_replace(config, "jargon", jargon);
421: }
422:
423: if (encoding_len) {
424: pspell_config_replace(config, "encoding", encoding);
425: }
426:
427: if (argc > 5) {
428: speed = mode & PSPELL_SPEED_MASK_INTERNAL;
429:
430: /* First check what mode we want (how many suggestions) */
431: if (speed == PSPELL_FAST) {
432: pspell_config_replace(config, "sug-mode", "fast");
433: } else if (speed == PSPELL_NORMAL) {
434: pspell_config_replace(config, "sug-mode", "normal");
435: } else if (speed == PSPELL_BAD_SPELLERS) {
436: pspell_config_replace(config, "sug-mode", "bad-spellers");
437: }
438:
439: /* Then we see if run-together words should be treated as valid components */
440: if (mode & PSPELL_RUN_TOGETHER) {
441: pspell_config_replace(config, "run-together", "true");
442: }
443: }
444:
445: ret = new_pspell_manager(config);
446: delete_pspell_config(config);
447:
448: if (pspell_error_number(ret) != 0) {
449: php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
450: delete_pspell_can_have_error(ret);
451: RETURN_FALSE;
452: }
453:
454: manager = to_pspell_manager(ret);
1.1.1.2 misho 455: ind = zend_list_insert(manager, le_pspell TSRMLS_CC);
1.1 misho 456: RETURN_LONG(ind);
457: }
458: /* }}} */
459:
460: /* {{{ proto int pspell_new_config(int config)
461: Load a dictionary based on the given config */
462: static PHP_FUNCTION(pspell_new_config)
463: {
464: int type, ind;
465: long conf;
466: PspellCanHaveError *ret;
467: PspellManager *manager;
468: PspellConfig *config;
469:
470: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &conf) == FAILURE) {
471: return;
472: }
473:
474: PSPELL_FETCH_CONFIG;
475:
476: ret = new_pspell_manager(config);
477:
478: if (pspell_error_number(ret) != 0) {
479: php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL couldn't open the dictionary. reason: %s", pspell_error_message(ret));
480: delete_pspell_can_have_error(ret);
481: RETURN_FALSE;
482: }
483:
484: manager = to_pspell_manager(ret);
1.1.1.2 misho 485: ind = zend_list_insert(manager, le_pspell TSRMLS_CC);
1.1 misho 486: RETURN_LONG(ind);
487: }
488: /* }}} */
489:
490: /* {{{ proto bool pspell_check(int pspell, string word)
491: Returns true if word is valid */
492: static PHP_FUNCTION(pspell_check)
493: {
494: int type, word_len;
495: long scin;
496: char *word;
497: PspellManager *manager;
498:
499: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
500: return;
501: }
502:
503: PSPELL_FETCH_MANAGER;
504:
505: if (pspell_manager_check(manager, word)) {
506: RETURN_TRUE;
507: } else {
508: RETURN_FALSE;
509: }
510: }
511: /* }}} */
512:
513: /* {{{ proto array pspell_suggest(int pspell, string word)
514: Returns array of suggestions */
515: static PHP_FUNCTION(pspell_suggest)
516: {
517: long scin;
518: char *word;
519: int word_len;
520: PspellManager *manager;
521: int type;
522: const PspellWordList *wl;
523: const char *sug;
524:
525: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
526: return;
527: }
528:
529: PSPELL_FETCH_MANAGER;
530:
531: array_init(return_value);
532:
533: wl = pspell_manager_suggest(manager, word);
534: if (wl) {
535: PspellStringEmulation *els = pspell_word_list_elements(wl);
536: while ((sug = pspell_string_emulation_next(els)) != 0) {
537: add_next_index_string(return_value,(char *)sug,1);
538: }
539: delete_pspell_string_emulation(els);
540: } else {
541: php_error_docref(NULL TSRMLS_CC, E_WARNING, "PSPELL had a problem. details: %s", pspell_manager_error_message(manager));
542: RETURN_FALSE;
543: }
544: }
545: /* }}} */
546:
547: /* {{{ proto bool pspell_store_replacement(int pspell, string misspell, string correct)
548: Notify the dictionary of a user-selected replacement */
549: static PHP_FUNCTION(pspell_store_replacement)
550: {
551: int type, miss_len, corr_len;
552: long scin;
553: char *miss, *corr;
554: PspellManager *manager;
555:
556: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lss", &scin, &miss, &miss_len, &corr, &corr_len) == FAILURE) {
557: return;
558: }
559:
560: PSPELL_FETCH_MANAGER;
561:
562: pspell_manager_store_replacement(manager, miss, corr);
563: if (pspell_manager_error_number(manager) == 0) {
564: RETURN_TRUE;
565: } else {
566: php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_store_replacement() gave error: %s", pspell_manager_error_message(manager));
567: RETURN_FALSE;
568: }
569: }
570: /* }}} */
571:
572: /* {{{ proto bool pspell_add_to_personal(int pspell, string word)
573: Adds a word to a personal list */
574: static PHP_FUNCTION(pspell_add_to_personal)
575: {
576: int type, word_len;
577: long scin;
578: char *word;
579: PspellManager *manager;
580:
581: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
582: return;
583: }
584:
585: PSPELL_FETCH_MANAGER;
586:
587: /*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
588: if (word_len == 0) {
589: RETURN_FALSE;
590: }
591:
592: pspell_manager_add_to_personal(manager, word);
593: if (pspell_manager_error_number(manager) == 0) {
594: RETURN_TRUE;
595: } else {
596: php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_add_to_personal() gave error: %s", pspell_manager_error_message(manager));
597: RETURN_FALSE;
598: }
599: }
600: /* }}} */
601:
602: /* {{{ proto bool pspell_add_to_session(int pspell, string word)
603: Adds a word to the current session */
604: static PHP_FUNCTION(pspell_add_to_session)
605: {
606: int type, word_len;
607: long scin;
608: char *word;
609: PspellManager *manager;
610:
611: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &scin, &word, &word_len) == FAILURE) {
612: return;
613: }
614:
615: PSPELL_FETCH_MANAGER;
616:
617: /*If the word is empty, we have to return; otherwise we'll segfault! ouch!*/
618: if (word_len == 0) {
619: RETURN_FALSE;
620: }
621:
622: pspell_manager_add_to_session(manager, word);
623: if (pspell_manager_error_number(manager) == 0) {
624: RETURN_TRUE;
625: } else {
626: php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_add_to_session() gave error: %s", pspell_manager_error_message(manager));
627: RETURN_FALSE;
628: }
629: }
630: /* }}} */
631:
632: /* {{{ proto bool pspell_clear_session(int pspell)
633: Clears the current session */
634: static PHP_FUNCTION(pspell_clear_session)
635: {
636: int type;
637: long scin;
638: PspellManager *manager;
639:
640: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &scin) == FAILURE) {
641: return;
642: }
643:
644: PSPELL_FETCH_MANAGER;
645:
646: pspell_manager_clear_session(manager);
647: if (pspell_manager_error_number(manager) == 0) {
648: RETURN_TRUE;
649: } else {
650: php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_clear_session() gave error: %s", pspell_manager_error_message(manager));
651: RETURN_FALSE;
652: }
653: }
654: /* }}} */
655:
656: /* {{{ proto bool pspell_save_wordlist(int pspell)
657: Saves the current (personal) wordlist */
658: static PHP_FUNCTION(pspell_save_wordlist)
659: {
660: int type;
661: long scin;
662: PspellManager *manager;
663:
664: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &scin) == FAILURE) {
665: return;
666: }
667:
668: PSPELL_FETCH_MANAGER;
669:
670: pspell_manager_save_all_word_lists(manager);
671:
672: if (pspell_manager_error_number(manager) == 0) {
673: RETURN_TRUE;
674: } else {
675: php_error_docref(NULL TSRMLS_CC, E_WARNING, "pspell_save_wordlist() gave error: %s", pspell_manager_error_message(manager));
676: RETURN_FALSE;
677: }
678:
679: }
680: /* }}} */
681:
682: /* {{{ proto int pspell_config_create(string language [, string spelling [, string jargon [, string encoding]]])
683: Create a new config to be used later to create a manager */
684: static PHP_FUNCTION(pspell_config_create)
685: {
686: char *language, *spelling = NULL, *jargon = NULL, *encoding = NULL;
687: int language_len, spelling_len = 0, jargon_len = 0, encoding_len = 0;
688: int ind;
689: PspellConfig *config;
690:
691: #ifdef PHP_WIN32
692: TCHAR aspell_dir[200];
693: TCHAR data_dir[220];
694: TCHAR dict_dir[220];
695: HKEY hkey;
696: DWORD dwType,dwLen;
697: #endif
698:
699: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss", &language, &language_len, &spelling, &spelling_len,
700: &jargon, &jargon_len, &encoding, &encoding_len) == FAILURE) {
701: return;
702: }
703:
704: config = new_pspell_config();
705:
706: #ifdef PHP_WIN32
707: /* If aspell was installed using installer, we should have a key
708: * pointing to the location of the dictionaries
709: */
710: if (0 == RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Aspell", &hkey)) {
711: LONG result;
712: dwLen = sizeof(aspell_dir) - 1;
713: result = RegQueryValueEx(hkey, "", NULL, &dwType, (LPBYTE)&aspell_dir, &dwLen);
714: RegCloseKey(hkey);
715: if (result == ERROR_SUCCESS) {
716: strlcpy(data_dir, aspell_dir, sizeof(data_dir));
717: strlcat(data_dir, "\\data", sizeof(data_dir));
718: strlcpy(dict_dir, aspell_dir, sizeof(dict_dir));
719: strlcat(dict_dir, "\\dict", sizeof(dict_dir));
720:
721: pspell_config_replace(config, "data-dir", data_dir);
722: pspell_config_replace(config, "dict-dir", dict_dir);
723: }
724: }
725: #endif
726:
727: pspell_config_replace(config, "language-tag", language);
728:
729: if (spelling_len) {
730: pspell_config_replace(config, "spelling", spelling);
731: }
732:
733: if (jargon_len) {
734: pspell_config_replace(config, "jargon", jargon);
735: }
736:
737: if (encoding_len) {
738: pspell_config_replace(config, "encoding", encoding);
739: }
740:
741: /* By default I do not want to write anything anywhere because it'll try to write to $HOME
742: which is not what we want */
743: pspell_config_replace(config, "save-repl", "false");
744:
1.1.1.2 misho 745: ind = zend_list_insert(config, le_pspell_config TSRMLS_CC);
1.1 misho 746: RETURN_LONG(ind);
747: }
748: /* }}} */
749:
750: /* {{{ proto bool pspell_config_runtogether(int conf, bool runtogether)
751: Consider run-together words as valid components */
752: static PHP_FUNCTION(pspell_config_runtogether)
753: {
754: int type;
755: long conf;
756: zend_bool runtogether;
757: PspellConfig *config;
758:
759: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &conf, &runtogether) == FAILURE) {
760: return;
761: }
762:
763: PSPELL_FETCH_CONFIG;
764:
765: pspell_config_replace(config, "run-together", runtogether ? "true" : "false");
766:
767: RETURN_TRUE;
768: }
769: /* }}} */
770:
771: /* {{{ proto bool pspell_config_mode(int conf, long mode)
772: Select mode for config (PSPELL_FAST, PSPELL_NORMAL or PSPELL_BAD_SPELLERS) */
773: static PHP_FUNCTION(pspell_config_mode)
774: {
775: int type;
776: long conf, mode;
777: PspellConfig *config;
778:
779: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &conf, &mode) == FAILURE) {
780: return;
781: }
782:
783: PSPELL_FETCH_CONFIG;
784:
785: /* First check what mode we want (how many suggestions) */
786: if (mode == PSPELL_FAST) {
787: pspell_config_replace(config, "sug-mode", "fast");
788: } else if (mode == PSPELL_NORMAL) {
789: pspell_config_replace(config, "sug-mode", "normal");
790: } else if (mode == PSPELL_BAD_SPELLERS) {
791: pspell_config_replace(config, "sug-mode", "bad-spellers");
792: }
793:
794: RETURN_TRUE;
795: }
796: /* }}} */
797:
798: /* {{{ proto bool pspell_config_ignore(int conf, int ignore)
799: Ignore words <= n chars */
800: static PHP_FUNCTION(pspell_config_ignore)
801: {
802: int type;
803: char ignore_str[MAX_LENGTH_OF_LONG + 1];
804: long conf, ignore = 0L;
805: PspellConfig *config;
806:
807: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &conf, &ignore) == FAILURE) {
808: return;
809: }
810:
811: PSPELL_FETCH_CONFIG;
812:
813: snprintf(ignore_str, sizeof(ignore_str), "%ld", ignore);
814:
815: pspell_config_replace(config, "ignore", ignore_str);
816: RETURN_TRUE;
817: }
818: /* }}} */
819:
820: static void pspell_config_path(INTERNAL_FUNCTION_PARAMETERS, char *option)
821: {
822: int type;
823: long conf;
824: char *value;
825: int value_len;
826: PspellConfig *config;
827:
1.1.1.2 misho 828: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lp", &conf, &value, &value_len) == FAILURE) {
1.1 misho 829: return;
830: }
831:
832: PSPELL_FETCH_CONFIG;
833:
834: if (php_check_open_basedir(value TSRMLS_CC)) {
835: RETURN_FALSE;
836: }
837:
838: pspell_config_replace(config, option, value);
839:
840: RETURN_TRUE;
841: }
842:
843: /* {{{ proto bool pspell_config_personal(int conf, string personal)
844: Use a personal dictionary for this config */
845: static PHP_FUNCTION(pspell_config_personal)
846: {
847: pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "personal");
848: }
849: /* }}} */
850:
851: /* {{{ proto bool pspell_config_dict_dir(int conf, string directory)
852: location of the main word list */
853: static PHP_FUNCTION(pspell_config_dict_dir)
854: {
855: pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "dict-dir");
856: }
857: /* }}} */
858:
859: /* {{{ proto bool pspell_config_data_dir(int conf, string directory)
860: location of language data files */
861: static PHP_FUNCTION(pspell_config_data_dir)
862: {
863: pspell_config_path(INTERNAL_FUNCTION_PARAM_PASSTHRU, "data-dir");
864: }
865: /* }}} */
866:
867: /* {{{ proto bool pspell_config_repl(int conf, string repl)
868: Use a personal dictionary with replacement pairs for this config */
869: static PHP_FUNCTION(pspell_config_repl)
870: {
871: int type;
872: long conf;
873: char *repl;
874: int repl_len;
875: PspellConfig *config;
876:
1.1.1.2 misho 877: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lp", &conf, &repl, &repl_len) == FAILURE) {
1.1 misho 878: return;
879: }
880:
881: PSPELL_FETCH_CONFIG;
882:
883: pspell_config_replace(config, "save-repl", "true");
884:
885: if (php_check_open_basedir(repl TSRMLS_CC)) {
886: RETURN_FALSE;
887: }
888:
889: pspell_config_replace(config, "repl", repl);
890:
891: RETURN_TRUE;
892: }
893: /* }}} */
894:
895: /* {{{ proto bool pspell_config_save_repl(int conf, bool save)
896: Save replacement pairs when personal list is saved for this config */
897: static PHP_FUNCTION(pspell_config_save_repl)
898: {
899: int type;
900: long conf;
901: zend_bool save;
902: PspellConfig *config;
903:
904: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lb", &conf, &save) == FAILURE) {
905: return;
906: }
907:
908: PSPELL_FETCH_CONFIG;
909:
910: pspell_config_replace(config, "save-repl", save ? "true" : "false");
911:
912: RETURN_TRUE;
913: }
914: /* }}} */
915:
916: /* {{{ PHP_MINFO_FUNCTION
917: */
918: static PHP_MINFO_FUNCTION(pspell)
919: {
920: php_info_print_table_start();
921: php_info_print_table_row(2, "PSpell Support", "enabled");
922: php_info_print_table_end();
923: }
924: /* }}} */
925:
926: #endif
927:
928: /*
929: * Local variables:
930: * tab-width: 4
931: * c-basic-offset: 4
932: * End:
933: * vim600: sw=4 ts=4 fdm=marker
934: * vim<600: sw=4 ts=4
935: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>