#include #include #include #include #include #include "global.h" #include "manhat-lib/shared_util.h" #include "manhat-lib/shared_file_util.h" #include "manhat-lib/shared_survey_string.h" #include "manhat-lib/shared_cs_util.h" #include "manhat-lib/shared_server_string.h" #define DEBUG 0 /* if set to 1, you'll see the output of the aspell command in your browser ** This is useful when you are first getting aspell/ispell to work, but ** should be shut off for normal operation. */ #define NULL_DEV "/dev/null" /* If DEBUG is 0, aspell/ispell errors will be redirected here. ** This is the standard Null device for Un*x systems? */ typedef struct word { char *err_word; char *sugg_word_list; struct word *next; }WORD; typedef struct word_list { WORD *head; WORD *current; }WORD_LIST; int htoi(char *s) { int value; int c; c = s[0]; if (isupper(c)) c = tolower(c); value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16; c = s[1]; if (isupper(c)) c = tolower(c); value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10; return (value); } int url_decode(char *str, int len) { #define ISPELL_SPECIAL_CHARS "*&@+-~#!^" char *dest = str; char *data = str; while (len--) { if(strchr(ISPELL_SPECIAL_CHARS,*data)) *dest = ' '; else if (*data == '%') { if ( (len >= 2) && isxdigit((int) *(data + 1)) && isxdigit((int) *(data + 2))) { *dest = (char) htoi(data + 1); if((*dest == '%') || strchr(ISPELL_SPECIAL_CHARS,*dest)) *dest = ' '; data += 2; len -= 2; } else *dest = ' '; } else *dest = *data; data++; dest++; } *dest = '\0'; return dest - str; #undef ISPELL_SPECIAL_CHARS } void free_word_list(WORD_LIST *list) { WORD *ptr; while(list->head) { ptr = list->head->next; if(list->head->err_word) free(list->head->err_word); if(list->head->sugg_word_list) free(list->head->sugg_word_list); free(list->head); list->head = ptr; } } WORD_LIST * initialize_word_list(WORD_LIST *list_words) { list_words = (WORD_LIST *)malloc(sizeof(WORD_LIST)); list_words->head =0; list_words->current =0; return list_words; } void write_file(const char *text, char *filename) { int fd; FILE *fp; char *decode_text; decode_text = malloc_str(text); url_decode(decode_text, strlen(decode_text)); snprintf (filename, MAX_PATH + 1, "%sCGI_DATA_spell_XXXXXX", TMP_PATH); fd = mkstemp (filename); if(fd == -1) cs_critical_error (ERR_MKSTEMP_FAILED, ""); close(fd); change_mkstemp_permission(filename); /*shared_file_util.c */ fp = fopen (filename, "w"); if(!fp) cs_critical_error (ERR_FOPEN_WRITE_FAILED, filename); fprintf(fp, "%s", decode_text); fclose(fp); if(decode_text) free(decode_text); } void report_aspell_error(const char *error_path) { FILE *fp; char *buf; struct stat file_stat; if(DEBUG) /* then show the error file */ { if(stat(error_path, &file_stat)) cs_critical_error(ERR_STAT_FAILED, error_path); buf = (char*)malloc(sizeof(char) * file_stat.st_size +1); if(!buf) cs_critical_error(ERR_MALLOC_FAILED, "report_aspell_error()"); fp = fopen(error_path,"r"); if(fp) { fread( buf, file_stat.st_size ,1, fp); fclose(fp); unlink(error_path); *(buf + file_stat.st_size) = '\0'; cs_set_value("error_content", buf); free(buf); } } else cs_critical_error(ERR_GENERAL_ERROR,"spell checker failed"); exit(1); } void spell_checker(const char *filename, char *result) { char cmd[MAX_PATH +1]; int fd; char error_file[MAX_PATH + 1]; snprintf (result, MAX_PATH + 1, "%sCGI_DATA_result_XXXXXX", TMP_PATH); fd = mkstemp (result); if(fd == -1) cs_critical_error (ERR_MKSTEMP_FAILED, result); close(fd); change_mkstemp_permission(result); /* shared_file_util.c */ if(DEBUG) /* then create an error file in Manhattan's 'tmp' directory */ { snprintf (error_file, MAX_PATH + 1, "%sCGI_DATA_aspellerror_XXXXXX", TMP_PATH); fd = mkstemp (error_file); if(fd == -1) cs_critical_error (ERR_MKSTEMP_FAILED, error_file); close(fd); change_mkstemp_permission(error_file); /* shared_file_util.c */ } else snprintf(error_file, MAX_PATH + 1, NULL_DEV); /* otherwise errors are redirected to /dev/null */ /** ASPELL_PATH and ASPELL_ARGS are #defined in custom.h **/ snprintf(cmd, MAX_PATH +1, "%s %s < %s > %s 2>%s", ASPELL_PATH, ASPELL_ARGS, filename, result, error_file); if(system(cmd)) /* something failed */ { unlink(filename); unlink(result); report_aspell_error(error_file); } else { if(DEBUG) unlink(error_file); unlink(filename); } } char * read_parameters() { char *text, *return_text; text = hdf_get_value(global_cgi->hdf, "Query.checktext", " "); return_text = malloc_str(text); return return_text; } void write_js_text( char *text) { cs_set_value("text", text); } int count_sugg_words(const char *sugg_word) { int count =0; int i; int len; len = strlen(sugg_word); for(i =0; i < len; i++) { if(sugg_word[i] == ',') count++; } return count; } WORD * process_sugg_words(WORD *new_word, const char *sugg_word) { int i, j=0, count, total, len; count = count_sugg_words(sugg_word); total = (count +1)*2 + 2 + strlen(sugg_word); new_word->sugg_word_list = (char*)malloc(sizeof(char)*total +1); new_word->sugg_word_list[j] = '['; j++; new_word->sugg_word_list[j] = '\''; j++; for(i = 0, len = strlen(sugg_word); i < len; i++) { if(sugg_word[i] == ',') { new_word->sugg_word_list[j]='\''; j++; new_word->sugg_word_list[j]=sugg_word[i]; /* this is , */ j++; i++; new_word->sugg_word_list[j]=sugg_word[i]; /* this is white space */ j++; new_word->sugg_word_list[j]='\''; j++; } else { new_word->sugg_word_list[j]=sugg_word[i]; j++; } } new_word->sugg_word_list[j] = '\''; j++; new_word->sugg_word_list[j] = ']'; j++; new_word->sugg_word_list[j] = '\0'; return new_word; } WORD_LIST * insert_word(char *line_buffer, WORD_LIST *list_word) { char *ptr, *ptr2, *ptr3; WORD *new_word; ptr = strchr(line_buffer, ' '); if(ptr) /* if a space was found */ { *ptr = '\0'; ptr3 = ptr; ptr++; ptr2 = strchr(ptr, ' '); if(ptr2) /* if second space found */ { *ptr2 = '\0'; new_word = (WORD*)malloc(sizeof(WORD)); new_word->err_word = malloc_str(ptr); new_word->sugg_word_list =0; new_word->next = 0; *ptr3 = ' '; *ptr2 = ' '; ptr2++; ptr = strchr(ptr2, ':'); if(ptr) /* colon was found this means there are suggs words*/ { ptr++; *ptr = '\0'; ptr2 = ptr; ptr++; new_word = process_sugg_words(new_word, ptr); *ptr2 = ' '; } if(!list_word->head) list_word->head = new_word; else list_word->current->next = new_word; list_word->current = new_word; } } return list_word; } WORD_LIST * read_from_file(const char *filename, WORD_LIST *list_words) { FILE *fp; char *buffer, *line_buffer; int i, j, big_buffer = 400, line_flag =0; int len; struct stat buf; if(stat(filename, &buf)) cs_critical_error(ERR_STAT_FAILED, filename); /* allocate space for holding spell check data */ buffer = (char*)malloc(sizeof(char) * (buf.st_size +1)); fp = fopen(filename, "r"); if(!fp) cs_critical_error(ERR_FOPEN_READ_FAILED, filename); if(fread(buffer, buf.st_size, 1, fp) != 1) cs_critical_error(ERR_FREAD_FAILED, filename); fclose(fp); unlink(filename); *(buffer+buf.st_size) = '\0'; line_buffer = (char*)malloc(sizeof(char) * (big_buffer +1)); *line_buffer = '\0'; for(j =0, len=strlen(buffer); j < len; j++) { i=0; line_flag =0; while(buffer[j] != '\n') { if( (buffer[j] == '&' && i ==0) || (buffer[j] == '#' && i ==0 && buffer[j+1] != ')')) line_flag = 1; if(line_flag) /* then this word is spelled wrong */ { if((int)strlen(line_buffer) >= big_buffer) { line_buffer = realloc(line_buffer, big_buffer*2 +1); big_buffer = big_buffer *2; } if(buffer[j] == '\'') /* escape single quote */ { line_buffer[i] = '\\'; i++; line_buffer[i] = '\''; line_buffer[i+1] = '\0'; i++; } else { line_buffer[i] = buffer[j]; line_buffer[i+1] = '\0'; i++; } } j++; } /* done processing one line */ if(line_flag) { list_words = insert_word(line_buffer, list_words); memset(line_buffer, 0, strlen(line_buffer)); } } if(buffer) free(buffer); if(line_buffer) free(line_buffer); return list_words; } void print_check_result(WORD_LIST *list_words) { #define MAX_TMP_NAME 30 int i =0; char name[MAX_TMP_NAME]; for(list_words->current=list_words->head; list_words->current; list_words->current = list_words->current->next) { snprintf(name, MAX_TMP_NAME, "list.%d.index", i); cs_set_int_value(name, i); snprintf(name, MAX_TMP_NAME, "list.%d.word", i); cs_set_value(name, list_words->current->err_word); snprintf(name, MAX_TMP_NAME, "list.%d.suggs", i); if(list_words->current->sugg_word_list) cs_set_value(name, list_words->current->sugg_word_list); else cs_set_value(name, "\'\'"); i++; } #undef MAX_TMP_NAME } void print_page( char *text, WORD_LIST *list_words) { char server_string[MAX_PATH +1]; get_server_string(server_string, MAX_PATH); /* shared_server_string.c */ cs_set_value("server_name", server_string); write_js_text(text); print_check_result(list_words); } int main() { char *text; char filename[MAX_PATH +1]; char result[MAX_PATH +1]; WORD_LIST *list_words =0; cs_cgi_init(); list_words = initialize_word_list(list_words); text = read_parameters(); write_file(text, filename); spell_checker(filename, result); read_from_file(result, list_words); print_page(text, list_words); if(text) free(text); free_word_list(list_words); if(list_words) free(list_words); cs_cgi_display("spellchecker", 1); cs_cgi_destroy(); return 0; }