sqispell.c
上传用户:s81996212
上传日期:2007-01-04
资源大小:722k
文件大小:14k
- /*
- ** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for
- ** distribution information.
- */
- /*
- ** $Id: sqispell.c,v 1.13 2000/03/14 18:58:35 mrsam Exp $
- */
- #include "sqwebmail.h"
- #include "maildir.h"
- #include "folder.h"
- #include "cgi/cgi.h"
- #include "rfc2045/rfc2045.h"
- #include "maildir/maildirmisc.h"
- #include "buf.h"
- #include "ispell.h"
- #include "filter.h"
- #include <stdio.h>
- #include <string.h>
- #include <fcntl.h>
- #include <ctype.h>
- extern void output_form(const char *);
- extern char form_args[];
- extern const char *sqwebmail_content_ispelldict;
- extern void output_attrencoded(const char *);
- extern char *newmsg_createdraft_do(const char *, const char *, int);
- static void spelladd(const char *);
- static int search_spell(const char *, unsigned, unsigned);
- int spell_start(const char *c)
- {
- char *filename=maildir_find(DRAFTS, c);
- if (!c) return (-1);
- if (search_spell(filename, 0, 0) == 0)
- return (-1);
- return (0);
- }
- /*
- ** Search for misspelled words.
- */
- static struct rfc2045 *findtext(struct rfc2045 *);
- static char *spell_check(const char *, unsigned, unsigned,
- const char *, const char *, const char *, int *);
- static int search_spell(const char *filename, unsigned parnum, unsigned pos)
- {
- struct rfc2045 *rfcp, *textp;
- struct buf newtext, current_line;
- off_t start_pos, end_pos, start_body;
- int made_replacements, has_misspelling;
- char *new_line;
- unsigned paragraph;
- const char *ignoreword="";
- const char *replacefrom="";
- const char *replaceto="";
- int checked=0;
- off_t dummy;
- FILE *fp=0;
- int x;
- x=maildir_safeopen(filename, O_RDONLY, 0);
- if (x >= 0)
- if ((fp=fdopen(x, "r")) == 0)
- close(x);
- if (!fp) return (0);
- rfcp=rfc2045_fromfp(fp);
- if (!rfcp) enomem();
- textp=findtext(rfcp);
- if (!textp)
- {
- rfc2045_free(rfcp);
- fclose(fp);
- return (0);
- }
- buf_init(&newtext);
- buf_init(¤t_line);
- rfc2045_mimepos(textp, &start_pos, &end_pos, &start_body,
- &dummy, &dummy);
- if (fseek(fp, start_body, SEEK_SET) == -1)
- enomem();
- made_replacements=0;
- has_misspelling=0;
- paragraph=0;
- for ( ; start_body < end_pos; start_body++)
- {
- int c=getc(fp);
- if (c < 0) enomem();
- if (c != 'n')
- {
- buf_append(¤t_line, c);
- continue;
- }
- buf_append(¤t_line, ' ');
- if (parnum)
- {
- --parnum;
- buf_cat(&newtext, current_line.ptr);
- buf_cat(&newtext, "n");
- current_line.cnt=0;
- ++paragraph;
- continue;
- }
- if (!checked)
- {
- int l;
- checked=1;
- if ((l=strlen(cgi("word"))) > 0)
- {
- /* Ok, what should we do? */
- const char *newword=cgi("REPLACE");
- if (!*newword || strcmp(newword, "#other") == 0)
- newword=cgi("OTHER");
- /*
- ** Perhaps they entered the word without
- ** checking this checkmark.
- */
- else if (*newword == '#')
- newword="";
- if (*newword && pos + l <= strlen(current_line.ptr))
- {
- struct buf tempbuf;
- buf_init(&tempbuf);
- buf_cpyn(&tempbuf, current_line.ptr,
- pos);
- buf_cat(&tempbuf, newword);
- buf_cat(&tempbuf,
- current_line.ptr+pos+l);
- pos += strlen(newword);
- if (*cgi("REPLACEALL"))
- {
- replacefrom=cgi("word");
- replaceto=newword;
- }
- buf_append(&tempbuf, ' ');
- buf_cpy(¤t_line, tempbuf.ptr);
- buf_append(¤t_line, ' ');
- buf_free(&tempbuf);
- made_replacements=1;
- }
- else
- {
- pos += l;
- if (strcmp(cgi("REPLACE"),
- "#ignoreall") == 0)
- ignoreword=cgi("word");
- }
- if (strcmp(cgi("REPLACE"),
- "#insert") == 0)
- {
- spelladd(cgi("word"));
- }
- }
- }
- if (*current_line.ptr == '>')
- {
- buf_cat(&newtext, current_line.ptr);
- buf_cat(&newtext, "n");
- pos=0;
- current_line.cnt=0;
- ++paragraph;
- continue;
- }
- if (!has_misspelling)
- {
- new_line=spell_check(current_line.ptr, paragraph, pos,
- ignoreword, replacefrom, replaceto,
- &has_misspelling);
- if (new_line)
- {
- buf_cat(&newtext, new_line);
- free(new_line);
- made_replacements=1;
- }
- else buf_cat(&newtext, current_line.ptr);
- }
- else buf_cat(&newtext, current_line.ptr);
- buf_cat(&newtext, "n");
- pos=0;
- current_line.cnt=0;
- ++paragraph;
- }
- if (current_line.cnt)
- buf_cat(&newtext, "n");
- rfc2045_free(rfcp);
- fclose(fp);
- if (made_replacements)
- {
- char *p=newmsg_createdraft_do(filename, newtext.ptr, 1);
- if (p) free(p);
- if (*cgi("error"))
- {
- has_misspelling=0; /* Abort spell checking */
- }
- }
- buf_free(&newtext);
- buf_free(¤t_line);
- if (*ignoreword)
- {
- static char *p=0;
- if (p) free(p);
- p=malloc(strlen(cgi("globignore")) + 2 + strlen(ignoreword));
- if (!p) enomem();
- strcpy(p, cgi("globignore"));
- if (*p) strcat(p, ":");
- strcat(p, ignoreword);
- cgi_put("globignore", p);
- }
- if (*replacefrom)
- {
- static char *p=0;
- if (p) free(p);
- p=malloc(strlen(cgi("globreplace"))+3
- +strlen(replacefrom)+strlen(replaceto));
- if (!p) enomem();
- strcpy(p, cgi("globreplace"));
- if (*p) strcat(p, ":");
- strcat(strcat(strcat(p, replacefrom), ":"), replaceto);
- cgi_put("globreplace", p);
- free(p);
- }
- if (has_misspelling) return (1);
- return (0);
- }
- static struct rfc2045 *findtext(struct rfc2045 *rfcp)
- {
- struct rfc2045 *textp;
- const char *content_type;
- const char *content_transfer_encoding;
- const char *charset;
- rfc2045_mimeinfo(rfcp, &content_type,
- &content_transfer_encoding, &charset);
- if (strncmp(content_type, "text/", 5) == 0)
- textp=rfcp;
- else
- {
- for (textp=rfcp->firstpart; textp; textp=textp->next)
- {
- if (textp->isdummy) continue;
- rfc2045_mimeinfo(textp, &content_type,
- &content_transfer_encoding, &charset);
- if (strncmp(content_type, "text/", 5) == 0)
- break;
- }
- }
- return (textp);
- }
- /*
- ** Ok, check a single paragraph, starting at position #pos.
- **
- ** If some replacements were made due to previous saved 'replace all' words,
- ** return the text of the modified line. Otherwise return NULL.
- **
- ** Set *hasmisspelled to 1 if there are some misspellings in this line.
- */
- static struct ispell *ispellptr;
- static char *ispellline=0;
- static unsigned paragraph;
- static int spellignore(const char *);
- static char *spellreplace(const char *);
- static char *spell_check(const char *line, unsigned pnum, unsigned pos,
- const char *ignoreword,
- const char *replacefrom,
- const char *replaceto,
- int *hasmisspelled)
- {
- struct ispell_misspelled *msp, *np;
- char *newline=0;
- const char *newword;
- char *w;
- if (strlen(line) <= pos) return (0); /* Sanity check */
- ispellptr=ispell_run(sqwebmail_content_ispelldict, line+pos);
- if (!ispellptr) enomem();
- for (msp=ispellptr->first_misspelled; msp; msp=msp->next)
- if (msp->misspelled_word)
- msp->word_pos += pos;
- for (msp=ispellptr->first_misspelled; msp; msp=msp->next)
- {
- if ((*ignoreword &&
- strcmp(msp->misspelled_word, ignoreword) == 0)
- || spellignore(msp->misspelled_word))
- {
- msp->misspelled_word=0;
- continue;
- }
- newword=0;
- if ( *replacefrom &&
- strcmp(msp->misspelled_word, replacefrom) == 0)
- newword=replaceto;
- w=0;
- if (newword ||
- (newword=w=spellreplace(msp->misspelled_word)) != 0)
- {
- char *p=malloc(strlen(newline ? newline:line)+strlen(newword)+1);
- if (!p) enomem();
- memcpy(p, (newline ? newline:line), msp->word_pos);
- strcpy(p+msp->word_pos, newword);
- strcat(p, (newline ? newline:line)+msp->word_pos+
- strlen(msp->misspelled_word));
- if (newline) free(newline);
- newline=p;
- for (np=msp; (np=np->next) != 0; )
- np->word_pos += strlen(newword)-strlen(msp->misspelled_word);
- msp->misspelled_word=0;
- if (w)
- free(w);
- continue;
- }
- *hasmisspelled=1;
- paragraph=pnum;
- break;
- }
- if (!hasmisspelled)
- {
- ispell_free(ispellptr);
- ispellptr=0;
- }
- else
- {
- if (ispellline) free(ispellline);
- if ((ispellline=malloc(strlen( newline ? newline:line)+1)) == 0)
- enomem();
- strcpy(ispellline, newline ? newline:line);
- }
- return (newline);
- }
- static void showfunc(const char *p, size_t n)
- {
- while (n)
- {
- if (*p == ' ')
- printf(" ");
- else if (*p != 'n')
- putchar(*p);
- p++;
- --n;
- }
- }
- void spell_show()
- {
- const char *draftmessage=cgi("draftmessage");
- struct ispell_misspelled *msp;
- struct ispell_suggestion *isps;
- size_t p, l=strlen(ispellline), n;
- char *ignorelab=strtok(form_args, "|");
- char *ignorealllab=strtok(NULL, "|");
- char *replacelab=strtok(NULL, "|");
- char *replacealllab=strtok(NULL, "|");
- char *insertlab=strtok(NULL, "|");
- char *continuelab=strtok(NULL, "|");
- char *finishlab=strtok(NULL, "|");
- if (!ispellptr) enomem();
- if (!ignorelab) ignorelab="";
- if (!ignorealllab) ignorealllab="";
- if (!replacelab) replacelab="";
- if (!replacealllab) replacealllab="";
- if (!continuelab) continuelab="";
- if (!finishlab) finishlab="";
- for (msp=ispellptr->first_misspelled; msp; msp=msp->next)
- if (msp->misspelled_word) break;
- if (!msp) enomem();
- CHECKFILENAME(draftmessage);
- printf("<INPUT TYPE=HIDDEN NAME=form VALUE="spellchk">n");
- printf("<INPUT TYPE=HIDDEN NAME=pos VALUE="%s">n", cgi("pos"));
- if (*cgi("globignore"))
- {
- printf("<INPUT TYPE=HIDDEN NAME=globignore VALUE="");
- output_attrencoded(cgi("globignore"));
- printf("">n");
- }
- if (*cgi("globreplace"))
- {
- printf("<INPUT TYPE=HIDDEN NAME=globreplace VALUE="");
- output_attrencoded(cgi("globreplace"));
- printf("">n");
- }
- printf("<INPUT TYPE=HIDDEN NAME=draftmessage VALUE="");
- output_attrencoded(draftmessage);
- printf("">");
- printf("<INPUT TYPE=HIDDEN NAME=row VALUE="%u"><INPUT TYPE=HIDDEN NAME=col VALUE="%u"><INPUT TYPE=HIDDEN NAME=word VALUE="",
- (unsigned)paragraph,
- (unsigned)msp->word_pos);
- output_attrencoded(msp->misspelled_word);
- printf(""><TABLE BORDER=0 CELLSPACING=0><TR><TD>");
- printf("<TABLE BORDER=1 WIDTH="100%%" BGCOLOR="#EEEEEE" CELLSPACING=0 CELLPADDING=8><TR><TD ALIGN=CENTER><TT><FONT COLOR="#000000">");
- if (msp->word_pos > 30)
- {
- p=msp->word_pos-30;
- for (n=p; n<msp->word_pos; n++)
- if (ispellline[n] == ' ')
- {
- while (n < p && ispellline[n] == ' ')
- ++n;
- p=n;
- break;
- }
- printf("... ");
- }
- else
- p=0;
- filter_start(FILTER_FOR_DISPLAY, &showfunc);
- filter(ispellline+p, msp->word_pos-p);
- filter_end();
- printf("<B>");
- filter_start(FILTER_FOR_DISPLAY, &showfunc);
- filter(ispellline+msp->word_pos, strlen(msp->misspelled_word));
- filter_end();
- printf("</B>");
- p=msp->word_pos+strlen(msp->misspelled_word);
- if (l-p < 30)
- {
- n=l-p;
- }
- else n=30;
- while (n)
- {
- if (ispellline[n+p] != ' ')
- {
- --n;
- continue;
- }
- while (n && ispellline[n+p-1] == ' ')
- --n;
- break;
- }
- filter_start(FILTER_FOR_DISPLAY, &showfunc);
- filter(ispellline+p, n);
- filter_end();
- if (n != l-p)
- printf(" ...");
- printf("</FONT></TT></TD></TR></TABLE><BR>");
- printf("<TABLE BORDER=1 BGCOLOR="#FFFFC0" CELLPADDING=8><TR><TD>");
- printf("<TABLE BORDER=0 WIDTH="100%%"><TR><TD>");
- for (isps=msp->first_suggestion; isps; isps=isps->next)
- {
- printf("<TR><TD>%s</TD><TD><INPUT BORDER=0 TYPE=RADIO NAME=REPLACE VALUE="%s"></TD><TD>%s</TD></TR>n",
- replacelab,
- isps->suggested_word,
- isps->suggested_word);
- replacelab=" ";
- }
- printf("<TR><TD>%s</TD><TD><INPUT BORDER=0 TYPE=RADIO NAME=REPLACE VALUE="#other"></TD><TD><INPUT TYPE=TEXT NAME=OTHER WIDTH=20></TD></TR>n",
- replacelab);
- printf("<TR><TD> </TD><TD><INPUT BORDER=0 TYPE=RADIO NAME=REPLACE VALUE="#insert"></TD><TD>%s</TD></TR>n",
- insertlab);
- printf("<TR><TD> </TD><TD><INPUT BORDER=0 TYPE=CHECKBOX NAME=REPLACEALL></TD><TD>%s</TD></TR>n",
- replacealllab);
- printf("<TR><TD> </TD><TD COLSPAN=2><HR WIDTH="100%%"></TD></TR>n");
- printf("<TR><TD> </TD><TD><INPUT BORDER=0 TYPE=RADIO NAME=REPLACE VALUE="#ignore"></TD><TD>%s</TD></TR>n",
- ignorelab);
- printf("<TR><TD> </TD><TD><INPUT BORDER=0 TYPE=RADIO NAME=REPLACE VALUE="#ignoreall"></TD><TD>%s</TD></TR>n",
- ignorealllab);
- printf("</TABLE>");
- printf("</TR></TD></TABLE><BR>");
- printf("<TABLE BORDER=1 CELLPADDING=8 BGCOLOR="#EEEEEE" WIDTH="100%%"><TR><TD>");
- printf("<INPUT TYPE=SUBMIT NAME="continue" VALUE="%s">n",
- continuelab);
- printf("<INPUT TYPE=SUBMIT NAME="finish" VALUE="%s">n",
- finishlab);
- printf("</TD></TR></TABLE>n");
- printf("</TD></TR></TABLE>n");
- }
- static FILE *opendict(const char *mode)
- {
- FILE *fp;
- char *p=malloc(sqwebmail_content_ispelldict ?
- strlen(sqwebmail_content_ispelldict)+20:20);
- if (!p) enomem();
- strcat(strcpy(p, sqwebmail_content_ispelldict ?
- "sqwebmail-dict-":"sqwebmail-dict"),
- sqwebmail_content_ispelldict ? sqwebmail_content_ispelldict:"");
- fp=fopen(p, mode);
- free(p);
- return (fp);
- }
- static int spellignore(const char *word)
- {
- char buf[100];
- const char *c;
- char *p, *q;
- FILE *fp=opendict("r");
- if (!fp) return (0);
- while (fgets(buf, sizeof(buf), fp) != NULL)
- {
- if ((p=strchr(buf, 'n')) != 0) *p=0;
- if (strcmp(word, buf) == 0)
- {
- fclose(fp);
- return (1);
- }
- }
- fclose(fp);
- c=cgi("globignore");
- p=malloc(strlen(c)+1);
- if (!p) enomem();
- strcpy(p, c);
- for (q=p; (q=strtok(q, ":")) != 0; q=0)
- if (strcmp(q, word) == 0)
- {
- free(p);
- return (1);
- }
- return (0);
- }
- static void spelladd(const char *word)
- {
- FILE *fp=opendict("a");
- if (fp)
- {
- fprintf(fp, "%sn", word);
- fclose(fp);
- }
- }
- static char *spellreplace(const char *word)
- {
- char *p, *q, *r;
- const char *c=cgi("globreplace");
- p=malloc(strlen(c)+1);
- if (!p) enomem();
- strcpy(p, c);
- for (q=p; (q=strtok(q, ":")) != 0 && (r=strtok(0, ":")) != 0; q=0)
- {
- if (strcmp(q, word) == 0)
- {
- q=malloc(strlen(r)+1);
- if (!q) enomem();
- strcpy(q, r);
- free(p);
- return (q);
- }
- }
- free(p);
- return (0);
- }
- void spell_check_continue()
- {
- const char *filename=cgi("draftmessage");
- unsigned parnum=atol(cgi("row"));
- unsigned pos=atol(cgi("col"));
- char *draftfilename;
- CHECKFILENAME(filename);
- draftfilename=maildir_find(DRAFTS, filename);
- if (!draftfilename)
- {
- output_form("folder.html");
- return;
- }
- if (search_spell(draftfilename, parnum, pos) &&
- *cgi("continue"))
- output_form("spellchk.html");
- else
- {
- cgi_put("draft", cgi("draftmessage"));
- cgi_put("previewmsg","SPELLCHK");
- output_form("newmsg.html");
- }
- free(draftfilename);
- }
- void ispell_cleanup()
- {
- if(ispellline) free(ispellline);
- ispellline=NULL;
- }