/* ** Copyright (C) 1994, 1995 Enterprise Integration Technologies Corp. ** VeriFone Inc./Hewlett-Packard. All Rights Reserved. ** Kevin Hughes, kev@kevcom.com 3/11/94 ** Kent Landfield, kent@landfield.com 4/6/97 ** ** This program and library is free software; you can redistribute it and/or ** modify it under the terms of the GNU (Library) General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU (Library) General Public License for more details. ** ** You should have received a copy of the GNU (Library) General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "hypermail.h" #include "setup.h" #include "struct.h" #include "printfile.h" #include "print.h" #include "threadprint.h" #include "config.h" /* Uses threadlist to find the next message after * msgnum in the thread containing msgnum. * Returns NULL if there are no more messages in * the thread. */ struct emailinfo *nextinthread(int msgnum) { struct reply *rp = threadlist; for (rp = threadlist; (rp != NULL) && (rp->msgnum != msgnum); rp = rp->next) { ; } if (rp == NULL) { /* msgnum not found in threadlist */ return NULL; } rp = rp->next; if ((rp == NULL) || (rp->frommsgnum == -1)) { /*end of thread - no next msg */ return NULL; } return rp->data; } /* ** Output a menu line with hyperlinks for table display ** ** All parameters are inputs only. Parameters: ** fp : HTML output file pointer ** idx : Type of page this menu is for. ** archives : "" or else the URL of more hypermail archives. ** currentid: "" or else the id of the "current" message. ** cursub : "" or else the subject of the "current" message. ** pos : Called at the top or bottom of the page. */ void fprint_menu(FILE *fp, mindex_t idx, char *archives, char *currentid, char *cursub, int pos) { char *ptr; fprintf(fp, "
| %s | \n", ptr ? ptr : "", lang[MSG_NEW_MESSAGE]); if (ptr) free(ptr); if ((currentid != NULL && currentid[0] != '\0') || (cursub != NULL && cursub[0] != '\0')) { ptr = makemailcommand(set_mailcommand, set_hmail, currentid, cursub); fprintf(fp, "%s | \n", ptr ? ptr : "", lang[MSG_REPLY]); if (ptr) free(ptr); } } } if (set_about && *set_about) fprintf(fp, "%s | \n", set_about, lang[MSG_ABOUT_THIS_LIST]); if (idx != NO_INDEX && !set_reverse) { if (pos == PAGE_TOP) fprintf(fp, "%s | \n", lang[MSG_END_OF_MESSAGES]); else fprintf(fp, "%s | \n", lang[MSG_START_OF_MESSAGES]); } if (idx != DATE_INDEX) fprintf(fp, "%s | \n", datename, lang[MSG_DATE_VIEW]); if (idx != THREAD_INDEX) fprintf(fp, "%s | \n", thrdname, lang[MSG_THREAD_VIEW]); if (idx != SUBJECT_INDEX) fprintf(fp, "%s | \n", subjname, lang[MSG_SUBJECT_VIEW]); if (idx != AUTHOR_INDEX) fprintf(fp, "%s | \n", authname, lang[MSG_AUTHOR_VIEW]); if (archives && *archives) fprintf(fp, "%s | \n", archives, lang[MSG_OTHER_GROUPS]); fprintf(fp, "
|---|
\n"); #endif /* JK: added a
*/ if (set_showhr) fprintf(fp, "
\n");
/*
* Printout the Dates for the Starting and Ending messages
* in the archive, along with a count of the messages.
*/
fprintf(fp, "%s: %s
\n",
lang[MSG_STARTING], getdatestr(firstdatenum));
fprintf(fp, "%s: %s
\n",
lang[MSG_ENDING], getdatestr(lastdatenum));
}
void print_index_footer_links(FILE *fp, int called, int amountmsgs)
{
/*
* Print out the links for
*
* Messages sorted by: [ date ][ subject ][ author ]
* Other mail archives
*
* as appropriate.
*/
char *ptr;
fprintf(fp, "%s: %s
\n",
lang[MSG_LAST_MESSAGE_DATE], getdatestr(lastdatenum));
fprintf(fp, "%s: %s
\n", lang[MSG_ARCHIVED_ON], getlocaltime()); if (set_showhr) fprintf(fp, "
to format the text) have changed so that ** indented text shows up correctly. First, leading spaces become HTML ** non-breaking spaces ( ). In order for this to work, those lines ** must have been preceded by a
or. We accomplish this by checking ** ahead when we print each line... if we determine that the next line ** should be broken before, we do so. */ void printbody(FILE *fp, struct body *bp, char *id, char *subject) { int insig, inblank; #ifdef REMOVED_19991103 int inhtml; #endif char inheader = FALSE; /* we always start in a mail header */ int pre = FALSE; /* JK: added an extra
here */ if (set_showhr) fprintf(fp, "
\n"); printcomment(fp, "body", "start"); if (!set_showhtml) { fprintf(fp, "
\n"); pre = TRUE; } #if DEBUG_PRINTBODY else printf("SHOWHTML is ON\n"); #endif inblank = 1; insig = 0; #ifdef REMOVED_19991103 inhtml = 0; #endif while (bp != NULL) { if (bp->html) { /* already in HTML, don't touch */ if (pre) { fprintf(fp, "\n"); pre = FALSE; } printhtml(fp, bp->line); inheader = FALSE; /* this can't be a header if already in HTML */ bp = bp->next; continue; } if (bp->header) { char head[128]; if (!inheader) { /* @@ JK: I'm not sure why, but I had a !set_showhtml here */ if(!set_showhtml && !pre && set_showheaders) { fprintf(fp, "\n"); pre = TRUE; } inheader = TRUE; } if (sscanf(bp->line, "%127[^:]", head) && set_show_headers && !showheader(head)) { /* the show header keyword has been used, then we skip all those that aren't mentioned! */ if (isalnum(*head) || !set_showheaders) { /* this check is only to make sure that the last line among the headers (the "\n" one) won't be filtered off */ bp = bp->next; continue; } } } else { if (inheader) { if (set_showhtml) { if (pre) { fprintf(fp, "\n"); pre = FALSE; } fprintf(fp, "\n"); } inheader = FALSE; } } #ifdef REMOVED_990310 if (bp->attached && bp->header) { /* only show
if not insince * inmode, the existing newlines are enough! */ fprintf(fp, "%s%s", bp->line, pre ? "" : "
\n"); bp = bp->next; continue; } #endif if (((bp->line)[0] != '\n') && (bp->header && !set_showheaders)) { bp = bp->next; continue; } if (bp->header && set_showheaders && !pre) { fprintf(fp, "\n"); pre = TRUE; } if ((bp->line)[0] == '\n' && inblank) { bp = bp->next; continue; } else inblank = 0; #ifdef REMOVED_19991103 if (!strncasecmp(bp->line, "", 6)) { inhtml = 1; if (!set_showhtml && pre) { fprintf(fp, "\n"); pre = FALSE; } } else if (!strncasecmp(bp->line, "", 7)) { inhtml = 0; if (set_showhtml) fprintf(fp, "%s", bp->line); else { char *ptr; fprintf(fp, "%s
", ptr = convchars(bp->line)); free(ptr); } if (!set_showhtml && !pre) { fprintf(fp, "\n"); pre = TRUE; } bp = bp->next; continue; } if (inhtml) { if (set_showhtml) fprintf(fp, "%s", bp->line); else { char *ptr; fprintf(fp, "%s
", ptr = convchars(bp->line)); free(ptr); } bp = bp->next; continue; } #endif if (set_showhtml) { if (!strcmp(bp->line, "--\n") || !strcmp(bp->line, "-- \n") || !strcmp(bp->line, "----\n") || !strcmp(bp->line, "---\n")) { insig = 1; if (!pre) { fprintf(fp, "\n"); pre = TRUE; } } if (!inheader && (bp->line)[0] == '\n') fprintf(fp, "\n"); fprintf(fp, ""); else { if (insig) { ConvURLs(fp, bp->line, id, subject); } else if (isquote(bp->line)) { fprintf(fp, "%s", (set_iquotes) ? "" : ""); ConvURLs(fp, bp->line, id, subject); fprintf(fp, "%s
\n", (set_iquotes) ? "" : ""); } else if ((bp->line)[0] != '\0') { char *sp; sp = bp->line; while (*sp && (*sp == ' ' || *sp == '\t')) { if (*sp == '\t') fprintf(fp, " "); else fprintf(fp, " "); sp++; } /* JK: avoid converting Message-Id: headers */ if (bp->header && bp->parsedheader && !strncasecmp(bp->line, "Message-Id:", 11) && use_mailcommand) { /* we desactivate it just during this conversion */ use_mailcommand = 0; ConvURLs(fp, sp, id, subject); use_mailcommand = 1; } else ConvURLs(fp, sp, id, subject); /* * Determine whether we should break. * We could check for leading spaces * or quote lines, but in general, * non-alphanumeric lines should be * broken before. */ if ((set_showbr && !bp->header) || ((bp->next != NULL) && !isalnum(bp->next->line[0]))) fprintf(fp, "
"); if (!bp->header) { fprintf(fp, "\n"); } } } } else if ((bp->line)[0] != '\0') { /* JK: avoid converting Message-Id: headers */ if (bp->header && bp->parsedheader && !strncasecmp(bp->line, "Message-Id:", 11) && use_mailcommand) { /* we desactivate it just during this conversion */ use_mailcommand = 0; ConvURLs(fp, bp->line, id, subject); use_mailcommand = 1; } else ConvURLs(fp, bp->line, id, subject); } bp = bp->next; } if (pre) fprintf(fp, ""); printcomment(fp, "body", "end"); if (set_showhr) fprintf(fp, "
\n"); } /* ** Printing...the other main part of this program! ** This writes out the articles, beginning with the number startnum. */ void writearticles(int startnum, int maxnum) { int num, skip, subjmatch, newfile; struct emailinfo *email; struct emailinfo *email2; char filename[MAXFILELEN]; struct body *bp, *status; struct reply *rp; FILE *fp; char *ptr; num = startnum; if (set_showprogress) printf("%s \"%s\"... ", lang[MSG_WRITING_ARTICLES], set_dir); while ((bp = hashnumlookup(num, &email))) { sprintf(filename, "%s%s%.4d.%s", set_dir, (set_dir[strlen(set_dir) - 1] == '/') ? "" : "/", num, set_htmlsuffix); /* * Determine to overwrite files or not */ if (isfile(filename)) newfile = 0; else newfile = 1; skip = 0; if (!newfile && !set_overwrite) { skip = 1; /* is this really necessary with continue ??? */ num++; continue; } else { if ((fp = fopen(filename, "w")) == NULL) { sprintf(errmsg, "%s \"%s\".", lang[MSG_COULD_NOT_WRITE], filename); progerr(errmsg); } } /* * Create the comment fields necessary for incremental updating */ print_msg_header(fp, set_label, email->subject, set_dir, email->name, email->emailaddr, email->msgid, email->charset, filename); printcomment(fp, "received", email->fromdatestr); printcomment(fp, "isoreceived", secs_to_iso(email->fromdate)); printcomment(fp, "sent", email->datestr); printcomment(fp, "isosent", secs_to_iso(email->date)); printcomment(fp, "name", email->name); printcomment(fp, "email", email->emailaddr); printcomment(fp, "subject", ptr = convchars(email->subject)); if (ptr) free(ptr); printcomment(fp, "id", email->msgid); printcomment(fp, "charset", email->charset); printcomment(fp, "inreplyto", ptr = convchars(email->inreplyto)); if (ptr) free(ptr); if (set_usetable) { fprint_menu(fp, NO_INDEX, "", email->msgid, email->subject, PAGE_TOP); fprintf(fp, "\n"); } /* * Print the message's author info and date. */ #if 0 /* JK: removed it because it's redundant with the H1 header */ fprintf(fp, "Subject: %s
\n", email->subject); #endif if (!strcmp(email->name, email->emailaddr)) { if (use_mailcommand) { ptr = makemailcommand(set_mailcommand, email->emailaddr, email->msgid, email->subject); fprintf(fp, "From: ", ptr ? ptr : ""); if (ptr) free(ptr); fprintf(fp, "%s
\n", email->name); } else fprintf(fp, "%s
\n", email->name); } else { if (use_mailcommand) { ptr = makemailcommand(set_mailcommand, email->emailaddr, email->msgid, email->subject); fprintf(fp, "From: %s (", email->name, ptr ? ptr : ""); if (ptr) free(ptr); fprintf(fp, "%s)
\n", email->emailaddr); } else fprintf(fp, "From: %s (%s)
\n", email->name, email->emailaddr); } fprintf(fp, "Date: %s\n\n", getdatestr(email->date)); /* * This is here because it looks better here. The table looks * better before the Author info. This stuff should be in * printfile() so it could be laid out as the user wants... */ /* * Should we print message links ? */ if (set_show_msg_links) { printcomment(fp, "next", "start"); fprintf(fp, "
\n here */ fprintf(fp, "
here */ if (set_showhr) fprintf(fp, "
\n"); } /* * Print out the actual message index lists. Here's the beef. */ if (set_indextable) { fprintf(fp, "
| %s | %s | %s |
\n"); } else { fprintf(fp, "
\n"); } if (!set_usetable) { /* * Print out archive information links at the bottom of the index */ print_index_footer_links(fp, FROM_DATE, amountmsgs); } else { if (set_showhr) fprintf(fp, "
here */ if (set_showhr) fprintf(fp, "
\n"); } if (set_indextable) { fprintf(fp, "
| %s | %s | %s |
\n"); } else { fprintf(fp, "
\n"); } if (!set_usetable) { /* * Print out archive information links at the bottom of the index */ print_index_footer_links(fp, FROM_THREAD, amountmsgs); } else { if (set_showhr) fprintf(fp, "
here */ if (set_showhr) fprintf(fp, "
\n"); } if (set_indextable) { fprintf(fp, "
| %s | %s | %s |
\n"); } else { fprintf(fp, "\n
\n"); } /* * Print out archive information links at the bottom of the index */ if (!set_usetable) print_index_footer_links(fp, FROM_SUBJECT, amountmsgs); else { if (set_showhr) fprintf(fp, "
here */ if (set_showhr) fprintf(fp, "
\n"); } if (set_indextable) { fprintf(fp, "
| %s | %s | %s |
\n"); } else { fprintf(fp, "\n
\n"); } /* * Print out archive information links at the bottom * of the index page */ if (!set_usetable) print_index_footer_links(fp, FROM_AUTHOR, amountmsgs); else { if (set_showhr) fprintf(fp, "