Annotation of embedaddon/php/ext/pspell/pspell.c, revision 1.1.1.2

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: 
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>