Annotation of embedaddon/php/ext/pspell/pspell.c, revision 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>