Back to index

courier  0.68.2
Functions | Variables
sqispell.c File Reference
#include "config.h"
#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 "newmsg.h"
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>

Go to the source code of this file.

Functions

void output_form (const char *)
void output_attrencoded (const char *)
static void spelladd (const char *)
static int search_spell (const char *, unsigned, unsigned)
int spell_start (const char *c)
static struct rfc2045findtext (struct rfc2045 *)
static char * spell_check (const char *, unsigned, unsigned, const char *, const char *, const char *, int *)
static int spellignore (const char *)
static char * spellreplace (const char *)
static void showfunc (const char *p, size_t n, void *dummy)
static void show_part (const char *ptr, size_t cnt)
void spell_show ()
static FILE * opendict (const char *mode)
void spell_check_continue ()
void ispell_cleanup ()

Variables

const char * sqwebmail_content_charset
const char * sqwebmail_content_ispelldict
static struct ispellispellptr
static char * ispellline = 0
static unsigned paragraph

Function Documentation

static struct rfc2045 * findtext ( struct rfc2045 rfcp) [static, read]

Definition at line 262 of file sqispell.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void ispell_cleanup ( )

Definition at line 673 of file sqispell.c.

Here is the caller graph for this function:

static FILE* opendict ( const char *  mode) [static]

Definition at line 562 of file sqispell.c.

{
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);
}

Here is the caller graph for this function:

void output_attrencoded ( const char *  )

Definition at line 259 of file sqwebmail.c.

{
       output_attrencoded_fp(p, stdout);
}

Here is the call graph for this function:

void output_form ( const char *  )

Definition at line 796 of file sqwebmail.c.

{
       FILE   *f;

#ifdef GZIP
       int    dogzip;
       int    pipefd[2];
       pid_t  pid= -1;
#endif

       noimages= auth_getoptionenvint("wbnoimages");

       f=do_open_form(formname, 1);

       sqwebmail_formname=formname;

       if (!f)       error("Can't open form template.");

       /*
       ** Except for the dummy frame window (and the tiny empty frame),
       ** and the window containing the print preview of the message,
       ** expire everything.
       */

       if (strcmp(formname, "index.html") && strcmp(formname, "empty.html") &&
              strcmp(formname, "print.html"))
              cginocache();

#ifdef GZIP

       dogzip=0;
       if (strcmp(formname, "readmsg.html") == 0 ||
           strcmp(formname, "folder.html") == 0 ||
           strcmp(formname, "folders.html") == 0 ||
           strcmp(formname, "gpg.html") == 0)
       {
       const char *p=getenv("HTTP_ACCEPT_ENCODING");

              if (p)
              {
              char   *q=strdup(p), *r;

                     if (!q)       enomem();
                     for (r=q; *r; r++)
                            *r= tolower((int)(unsigned char)*r);
                     for (r=q; (r=strtok(r, ", ")) != 0; r=0)
                            if (strcmp(r, "gzip") == 0)
                            {
                                   dogzip=1;
                                   if (pipe(pipefd))
                                          enomem();
                            }
                     free(q);
              }
       }
#endif

       /* Do not send a Vary header for attachment downloads */

       if (*cgi("download") == 0)
              printf("Vary: Accept-Language\n");

#ifdef GZIP
       if (dogzip)
              printf("Content-Encoding: gzip\n");
#endif

       printf("Content-Type: text/html");

       if (sqwebmail_content_charset)
              printf("; charset=%s", sqwebmail_content_charset);

       printf("\n\n");

#ifdef GZIP
       if (dogzip)
       {
              fflush(stdout);
              while ((pid=fork()) == -1)
                     sleep(5);
              if (pid == 0)
              {
                     dup2(pipefd[0], 0);
                     close(pipefd[0]);
                     close(pipefd[1]);
                     execl(GZIP, "gzip", "-c", (char *)0);
                     fprintf(stderr, 
                            "ERR: Cannot execute " GZIP ": %s\n",
                            strerror(errno));
                     exit(1);
              }

              gzip_save_fd=dup(1);
              dup2(pipefd[1], 1);
              close(pipefd[1]);
              close(pipefd[0]);
       }
#endif
       fix_xml_header(f);
       do_output_form_loop(f);
       do_close_form();

#ifdef GZIP
       if (pid > 0)
       {
       int    waitstat;
       pid_t  p2;

              /* Restore original stdout */

              fflush(stdout);
              dup2(gzip_save_fd, 1);
              close(gzip_save_fd);
              gzip_save_fd= -1;
              while ((p2=wait(&waitstat)) >= 0 && p2 != pid)
                     ;
       }
#endif
}

Here is the call graph for this function:

static int search_spell ( const char *  filename,
unsigned  parnum,
unsigned  pos 
) [static]

Definition at line 54 of file sqispell.c.

{
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(&current_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(&current_line, c);
                     continue;
              }
              buf_append(&current_line, '\0');
              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, '\0');
                                   buf_cpy(&current_line, tempbuf.ptr);
                                   buf_append(&current_line, '\0');
                                   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,
                                    NEWMSG_SQISPELL);

              if (p) free(p);

              if (*cgi("error"))
              {
                     has_misspelling=0;   /* Abort spell checking */
              }
       }

       buf_free(&newtext);
       buf_free(&current_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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void show_part ( const char *  ptr,
size_t  cnt 
) [static]

Definition at line 389 of file sqispell.c.

{
       unicode_char *uc;
       size_t ucsize;
       int conv_err;

       if (libmail_u_convert_tou_tobuf(ptr, cnt,
                                   sqwebmail_content_charset,
                                   &uc,
                                   &ucsize,
                                   &conv_err) == 0)
       {
              if (conv_err)
              {
                     free(uc);
                     uc=NULL;
              }
       }


       if (uc)
       {

              struct filter_info info;

              filter_start(&info, sqwebmail_content_charset,
                          &showfunc, NULL);
              filter(&info, uc, ucsize);
              filter_end(&info);

              free(uc);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void showfunc ( const char *  p,
size_t  n,
void *  dummy 
) [static]

Definition at line 376 of file sqispell.c.

{
       while (n)
       {
              if (*p == ' ')
                     printf("&nbsp;");
              else if (*p != '\n')
                     putchar(*p);
              p++;
              --n;
       }
}

Here is the caller graph for this function:

static char * spell_check ( const char *  line,
unsigned  pnum,
unsigned  pos,
const char *  ignoreword,
const char *  replacefrom,
const char *  replaceto,
int *  hasmisspelled 
) [static]

Definition at line 303 of file sqispell.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 646 of file sqispell.c.

{
const char *filename=cgi("draftmessage");
unsigned parnum=atol(cgi("row"));
unsigned pos=atol(cgi("col"));
char   *draftfilename;

       CHECKFILENAME(filename);
       draftfilename=maildir_find(INBOX "." 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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void spell_show ( )

Definition at line 423 of file sqispell.c.

{
const char *draftmessage=cgi("draftmessage");
struct ispell_misspelled *msp;
struct ispell_suggestion *isps;
size_t p, l=strlen(ispellline), n;
const char *ignorelab=getarg("IGNORE");
const char *ignorealllab=getarg("IGNOREALL");
const char *replacelab=getarg("REPLACE");
const char *replacealllab=getarg("REPLACEALL");
const char *insertlab=getarg("INSERT");
const char *continuelab=getarg("CONTINUE");
const char *finishlab=getarg("FINISH");

       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\" cellpadding=\"1\" "
              "class=\"box-small-outer\"><tr><td>");
       printf("<table border=\"0\" cellspacing=\"0\" class=\"spellcheck-background\"><tr><td>");

       printf("<table border=\"1\" cellspacing=\"0\" cellpadding=\"8\" class=\"spellcheck-excerpt\"><tr><td align=\"center\"><span style=\"color: #000000\" class=\"spellcheck-excerpt\">");

       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("...&nbsp;");
       }
       else
              p=0;


       show_part(ispellline+p, msp->word_pos-p);
       printf("<strong>");
       show_part(ispellline+msp->word_pos, strlen(msp->misspelled_word));
       printf("</strong>");

       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;
       }

       show_part(ispellline+p, n);

       if (n != l-p)
              printf("&nbsp;...");
       printf("</span></td></tr></table><br />");
       printf("<table border=\"1\" cellpadding=\"8\" class=\"spellcheck-main\"><tr><td>");

       printf("<table border=\"0\">");
       for (isps=msp->first_suggestion; isps; isps=isps->next)
       {
              printf("<tr><td>%s</td><td><input 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 type=\"radio\" name=\"REPLACE\" value=\"#other\" /></td><td><input type=\"text\" name=\"OTHER\" size=\"20\" /></td></tr>\n",
              replacelab);
       printf("<tr><td> </td><td><input type=\"radio\" name=\"REPLACE\" value=\"#insert\" /></td><td>%s</td></tr>\n",
              insertlab);

       printf("<tr><td> </td><td><input 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 type=\"radio\" name=\"REPLACE\" value=\"#ignore\" /></td><td>%s</td></tr>\n",
              ignorelab);
       printf("<tr><td> </td><td><input type=\"radio\" name=\"REPLACE\" value=\"#ignoreall\" /></td><td>%s</td></tr>\n",
              ignorealllab);
       printf("</table>");
       printf("</td></tr></table><br />");
       printf("<table border=\"1\" cellpadding=\"8\" class=\"spellcheck-continue\"><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");
       printf("</td></tr></table>\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int spell_start ( const char *  c)

Definition at line 33 of file sqispell.c.

{
char   *filename=maildir_find(INBOX "." DRAFTS, c);

       if (!c)       return (-1);

       if (search_spell(filename, 0, 0) == 0)
              return (-1);

       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void spelladd ( const char *  word) [static]

Definition at line 612 of file sqispell.c.

{
FILE   *fp=opendict("a");

       if (fp)
       {
              fprintf(fp, "%s\n", word);
              fclose(fp);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int spellignore ( const char *  word) [static]

Definition at line 577 of file sqispell.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char * spellreplace ( const char *  word) [static]

Definition at line 623 of file sqispell.c.

{
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);
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

char* ispellline = 0 [static]

Definition at line 297 of file sqispell.c.

struct ispell* ispellptr [static]

Definition at line 296 of file sqispell.c.

unsigned paragraph [static]

Definition at line 298 of file sqispell.c.

Definition at line 39 of file gpg.c.

Definition at line 128 of file sqwebmail.c.