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