mbox.c.neu
上传用户:ladybrid91
上传日期:2007-01-04
资源大小:287k
文件大小:26k
源码类别:

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** mbox.c
  3. **
  4. ** Copyright (c) 1994-1995 Peter Eriksson <pen@signum.se>
  5. **    Mats 謍rman    <matoh@lysator.liu.se>
  6. **
  7. ** This program is free software; you can redistribute it and/or modify
  8. ** it under the terms of the GNU General Public License as published by
  9. ** the Free Software Foundation; either version 2 of the License, or
  10. ** (at your option) any later version.
  11. **
  12. ** This program is distributed in the hope that it will be useful,
  13. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ** GNU General Public License for more details.
  16. ** You should have received a copy of the GNU General Public License
  17. ** along with this program; if not, write to the Free Software
  18. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20. #include <stdio.h>
  21. #include <time.h>
  22. #include <string.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <errno.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <sys/mman.h>
  29. #include "phttpd.h"
  30. #ifndef MAP_FAILED
  31. #define MAP_FAILED ((caddr_t) -1)
  32. #endif
  33. #ifndef MAP_NORESERVE
  34. #define MAP_NORESERVE 0
  35. #endif
  36. #define SF_ARCHIVE
  37. #define MAX_HDR_LINES 96
  38. #define SEP "From "
  39. #define SEPLEN 5 /* = strlen(SEP) */
  40. typedef struct {
  41.   char *subj;
  42.   char *from;
  43.   char *orgz;
  44.   char *date;
  45.   char *id;
  46. } header_info;
  47. static char *index_top_include = NULL;
  48. static char *index_bottom_include = NULL;
  49. static char *mail_top_include = NULL;
  50. static char *mail_bottom_include = NULL;
  51. static struct options mbox_cfg_table[] =
  52. {
  53.     { "index-top-include", T_STRING, &index_top_include, NULL },
  54.     { "index-bottom-include", T_STRING, &index_bottom_include, NULL },
  55.     { "mail-top-include", T_STRING, &mail_top_include, NULL },
  56.     { "mail-bottom-include", T_STRING, &mail_bottom_include, NULL },
  57.     { NULL,                -1,       NULL,                      NULL }
  58. };
  59. int pm_init(const char **argv)
  60. {
  61.     char *cfg_path, *cp;
  62.     const char *name = argv[0];
  63.     int cfgsize;
  64.     
  65.     if (debug > 1)
  66. fprintf(stderr, "*** mbox/pm_init("%s") called ***n", name);
  67. /* 
  68.     cfgsize = strlen(name)+6;
  69.     cfg_path = s_malloc(cfgsize);
  70.     s_strcpy(cfg_path, cfgsize, name);
  71.  
  72.     cp = strrchr(cfg_path, '.');
  73.     if (cp && strcmp(cp, ".so") == 0)
  74.         *cp = '';
  75.  
  76.     s_strcat(cfg_path, cfgsize, ".conf");
  77.     if (config_parse_file(cfg_path, file_cfg_table, 0) < 0)
  78.         return -1;
  79.  
  80.     if (config_parse_argv(argv+1, file_cfg_table) < 0)
  81.         return -1;
  82.  
  83.     if (default_type == NULL)
  84.         default_type = s_strdup("unknown");
  85. */ 
  86.     return 0;
  87. }
  88. void pm_exit(void)
  89. {
  90.     if (debug > 1)
  91. fprintf(stderr, "*** mbox/pm_exit() called ***n");
  92. }
  93. static int all_digits(char *ptr)
  94. {
  95.   for ( ; *ptr != ''; ptr++)
  96.     if (!s_isdigit(*ptr))
  97.       return 0;
  98.   return -1;
  99. }
  100. static void fd_print_msgid_anchor(int fd_out, char *id)
  101. {
  102.   char *begin;
  103.   char *end;
  104.   int len;
  105.   if ((begin = strchr(id, '<')) == NULL)
  106.     begin = id;
  107.   else 
  108.     begin++;
  109.   if ((end = strrchr(begin, '>')) != NULL)
  110.     len = end - begin;
  111.   else
  112.     len = strlen(begin);
  113.   
  114.   fd_puts("<a name="", fd_out);
  115.   fd_write( fd_out, begin, len);
  116.   fd_puts("">n", fd_out);
  117. }
  118. static void fd_print_msgid_link(int fd_out, char *url, char *id)
  119. {
  120.   char *begin;
  121.   char *end;
  122.   int len;
  123.   if ((begin = strchr(id, '<')) == NULL)
  124.     begin = id;
  125.   else 
  126.     begin++;
  127.   if ((end = strrchr(begin, '>')) != NULL)
  128.     len = end - begin;
  129.   else
  130.     len = strlen(begin);
  131.   
  132.   fd_printf(fd_out, "<a href="%s#", url);
  133.   fd_write( fd_out, begin, len);
  134.   fd_puts("">n", fd_out);
  135. }
  136. static int fd_escape_write(int fd_out, char *start, off_t len)
  137. {
  138.   char *begin;
  139.   char *ptr;
  140.   char *end;
  141.   off_t chunklen;
  142.   int retval;
  143.   begin = start;
  144.   end   = start + len;
  145.   for (ptr = start; ptr < end; ptr++) {
  146.     switch (*ptr) {
  147.     case '&':
  148.       if ((chunklen = ptr - begin) > 0)
  149. if ((retval = fd_write(fd_out, begin, chunklen)) != 0)
  150.   return retval;
  151.       begin = ptr + 1;
  152.       fd_puts("&amp;", fd_out);
  153.       break;
  154.     case '<':
  155.       if ((chunklen = ptr - begin) > 0)
  156. if ((retval = fd_write(fd_out, begin, chunklen)) != 0)
  157.   return retval;
  158.       begin = ptr + 1;
  159.       fd_puts("&lt;", fd_out);
  160.       break;
  161.     case '>':
  162.       if ((chunklen = ptr - begin) > 0)
  163. if ((retval = fd_write(fd_out, begin, chunklen)) != 0)
  164.   return retval;
  165.       begin = ptr + 1;
  166.       fd_puts("&gt;", fd_out);
  167.       break;
  168.     }
  169.   }
  170.   if ((chunklen = ptr - begin) > 0)
  171.     if ((retval = fd_write(fd_out, begin, chunklen)) != 0)
  172.       return retval;
  173.   return 0;
  174. }
  175. static int fd_escape_puts(char *str, int fd_out)
  176. {
  177.   off_t len;
  178.   len = strlen(str);
  179.   return fd_escape_write(fd_out, str, len);
  180. }
  181. static int do_file_copy(char *fname, int fd_out)
  182. {
  183.     int fd;
  184.     fd=s_open(fname,O_RDONLY);
  185. /* RK add filecopy to out here...     */
  186.     s_close(fd);
  187. }
  188. static int letter_head_len(char *start, char *limit)
  189. {
  190.   char *ptr;
  191.   for (ptr = start; ptr < limit; ptr++) {
  192.     if (*ptr != 'n')
  193.       continue;
  194.     ptr++;
  195.     if (ptr >= limit || *ptr == 'n')
  196.       break;
  197.   }
  198.   return ptr - start;
  199. }
  200. static char* malloc_letter_head(char *start,   int len, 
  201. char *lines[], int maxlines)
  202. {
  203.   char *mem;
  204.   int i;
  205.   int nlines;
  206.   if (len <= 0 ||
  207.       (mem = s_malloc(len)) == NULL)
  208.     return NULL;
  209.   
  210.   memcpy(mem, start, len);
  211.   nlines = 0;
  212.   if (nlines < maxlines) 
  213.     lines[nlines++] = mem;
  214.     
  215.   for (i = 0; i < len; i++) {
  216.     if (mem[i] != 'n')
  217.       continue;
  218.     if (i+1 < len && s_isspace(mem[i+1]))
  219.       continue;
  220.     mem[i] = '';
  221.     
  222.     if (nlines < maxlines && i+1 < len) 
  223.       lines[nlines++] = mem + i + 1;
  224.   }
  225.   if (nlines < maxlines) 
  226.     lines[nlines++] = NULL;
  227.   else
  228.     lines[maxlines - 1] = NULL;
  229.   return mem;
  230. }
  231. static char* find_header_val(char *key, char *lines[])
  232. {
  233.   int i;
  234.   int keylen;
  235.   char *ptr;
  236.   keylen=strlen(key);
  237.   for (i = 0; lines[i] != NULL; i++) {
  238.     ptr = lines[i];
  239.     if (strncasecmp(key, ptr, keylen) == 0 &&
  240. ptr[keylen] == ':') {
  241.       ptr += keylen + 1;
  242.       while (s_isspace(*ptr))
  243. ptr++;
  244.       return ptr;
  245.     }
  246.   }
  247.   return NULL;
  248. }
  249. static void set_header_info(header_info *hinf, char *lines[])
  250. {
  251.   hinf->subj = find_header_val("subject", lines);
  252.   hinf->from = find_header_val("from", lines);
  253.   hinf->orgz = find_header_val("organization", lines);
  254.   hinf->date = find_header_val("date", lines);
  255.   hinf->id   = find_header_val("message-id", lines);
  256. }
  257. static void fd_print_subject(int fd_out, char *subj, char *id)
  258. {
  259.   if (id) 
  260.     fd_print_msgid_anchor(fd_out, id);
  261.   if (subj) {
  262.     fd_puts("<strong><font size=+1>", fd_out);
  263.     fd_escape_puts(subj, fd_out);
  264.     fd_puts("</font></strong>n", fd_out);
  265.   }
  266.   if (id)
  267.     fd_puts("</a>n", fd_out);
  268. }
  269. static char *do_letter_head(char *start, char *limit, int fd_out)
  270. {
  271.   char *mem;
  272.   int len;
  273.   char *lines[MAX_HDR_LINES];
  274.   header_info hinf;
  275.   fd_puts("<!-- head -->n", fd_out);
  276.   if (start >= limit || start == NULL) 
  277.     return NULL;
  278.   if ((len = letter_head_len(start, limit)) <= 0 ||
  279.       (mem = malloc_letter_head(start, len, lines, MAX_HDR_LINES)) == NULL)
  280.     return NULL;
  281.  
  282.   set_header_info(&hinf, lines);
  283.   fd_puts("<dt>n", fd_out);
  284.   fd_print_subject(fd_out, hinf.subj, hinf.id);
  285.   fd_puts("<br>", fd_out);
  286.   html_email(fd_out, hinf.from);
  287.   fd_puts("<br>", fd_out);
  288.   if (hinf.orgz) {
  289.     fd_escape_puts(hinf.orgz, fd_out);
  290.     fd_puts("<br>", fd_out);
  291.   }
  292.   if (hinf.date) {
  293.     fd_escape_puts(hinf.date, fd_out);
  294.     fd_puts("<br>", fd_out);
  295.   }
  296.   s_free(mem);
  297.   return start + len;
  298. }
  299. static char *do_index_entry(char *start, char *limit, 
  300.     int fd_out, int num, char *url)
  301. {
  302.   char *mem;
  303.   int len;
  304.   char *lines[MAX_HDR_LINES];
  305.   header_info hinf;
  306.   fd_puts("<!-- index entry -->n", fd_out);
  307.   if (start >= limit || start == NULL) 
  308.     return NULL;
  309.   if ((len = letter_head_len(start, limit)) <= 0 ||
  310.       (mem = malloc_letter_head(start, len, lines, MAX_HDR_LINES)) == NULL)
  311.     return NULL;
  312.   
  313.   set_header_info(&hinf, lines);
  314.   fd_puts("<dt>n", fd_out);
  315.   fd_printf(fd_out, "<a href="%s?%d">n", url, num);
  316.   fd_printf(fd_out, "<strong><font size=+1>%d</font></strong>", num);
  317.   fd_puts("</a>n", fd_out);
  318.   fd_puts("<dd>n", fd_out);
  319.   if (hinf.subj) {
  320.     fd_puts("<strong><font size=+1>", fd_out);
  321.     fd_escape_puts(hinf.subj, fd_out);
  322.     fd_puts("</font></strong><br>n", fd_out);
  323.   }
  324.   if (hinf.from) {
  325. #if 0
  326.     fd_escape_puts(hinf.from, fd_out);
  327. #else
  328.     html_email(fd_out, hinf.from);
  329. #endif
  330.     fd_puts("<br>n", fd_out);
  331.   }
  332.   if (hinf.date) {
  333.     fd_escape_puts(hinf.date, fd_out);
  334.     fd_puts("<br>n", fd_out);
  335.   }
  336.   s_free(mem);
  337.   return start + len;
  338. }
  339. static char *do_rindex_entry(char *start, char *limit, 
  340.     int fd_out, int num, char *url)
  341. {
  342.   char *mem;
  343.   int len;
  344.   char *lines[MAX_HDR_LINES];
  345.   header_info hinf;
  346.   fd_puts("<!-- index entry -->n", fd_out);
  347.   if (start >= limit || start == NULL) 
  348.     return NULL;
  349.   if ((len = letter_head_len(start, limit)) <= 0 ||
  350.       (mem = malloc_letter_head(start, len, lines, MAX_HDR_LINES)) == NULL)
  351.     return NULL;
  352.   
  353.   set_header_info(&hinf, lines);
  354.   fd_puts("<dt>n", fd_out);
  355.   fd_printf(fd_out, "<a href="%s?r%d">n", url, num);
  356.   fd_printf(fd_out, "<strong><font size=+1>%d</font></strong>", num);
  357.   fd_puts("</a>n", fd_out);
  358.   fd_puts("<dd>n", fd_out);
  359.   if (hinf.subj) {
  360.     fd_puts("<strong><font size=+1>", fd_out);
  361.     fd_escape_puts(hinf.subj, fd_out);
  362.     fd_puts("</font></strong><br>n", fd_out);
  363.   }
  364.   if (hinf.from) {
  365. #if 0
  366.     fd_escape_puts(hinf.from, fd_out);
  367. #else
  368.     html_email(fd_out, hinf.from);
  369. #endif
  370.     fd_puts("<br>n", fd_out);
  371.   }
  372.   if (hinf.date) {
  373.     fd_escape_puts(hinf.date, fd_out);
  374.     fd_puts("<br>n", fd_out);
  375.   }
  376.   s_free(mem);
  377.   return start + len;
  378. }
  379. static char *do_id_index_entry(char *start, char *limit, 
  380.        int fd_out, int num, char *url)
  381. {
  382.   char *mem;
  383.   int len;
  384.   char *lines[MAX_HDR_LINES];
  385.   header_info hinf;
  386.   fd_puts("<!-- index entry -->n", fd_out);
  387.   if (start >= limit || start == NULL) 
  388.     return NULL;
  389.   if ((len = letter_head_len(start, limit)) <= 0 ||
  390.       (mem = malloc_letter_head(start, len, lines, MAX_HDR_LINES)) == NULL)
  391.     return NULL;
  392.   
  393.   set_header_info(&hinf, lines);
  394.   fd_puts("<dt>n", fd_out);
  395.   fd_printf(fd_out, "<strong><font size=+1>%d</font></strong>n", num);
  396.   fd_puts("<dd>n", fd_out);
  397.   if (hinf.id)   fd_print_msgid_link(fd_out, url, hinf.id);
  398.   if (hinf.subj) {
  399.     fd_puts("<strong><font size=+1>", fd_out);
  400.     fd_escape_puts(hinf.subj, fd_out);
  401.     fd_puts("</font></strong><br>n", fd_out);
  402.   }
  403.   if (hinf.id)   fd_puts("</a>n", fd_out);
  404.   if (hinf.from) {
  405.     fd_escape_puts(hinf.from, fd_out);
  406.     fd_puts("<br>n", fd_out);
  407.   }
  408.   if (hinf.date) {
  409.     fd_escape_puts(hinf.date, fd_out);
  410.     fd_puts("<br>n", fd_out);
  411.   }
  412.   s_free(mem);
  413.   return start + len;
  414. }
  415. static char *do_letter_body(char *start, char *limit, int fd_out)
  416. {
  417.   char *ptr;
  418.   char *end;
  419.   if (start >= limit || start == NULL) 
  420.     return NULL;
  421.   end = limit - strlen("nFrom ");
  422.   for (ptr = start; ptr < end; ptr++) {
  423.     if (*ptr == 'n') {
  424.       if (strncmp(ptr+1, SEP, SEPLEN) == 0) {
  425. limit = ptr+1;
  426. break;
  427.       }
  428.     }
  429.   }
  430.   fd_puts("<dd>n", fd_out);
  431.   fd_puts("<pre><!-- body -->n", fd_out);
  432.   
  433.   if (fd_escape_write(fd_out, start, limit - start) < 0)
  434.     if (debug) {
  435.       fprintf(stderr, "ERROR:");
  436.       perror("write");
  437.     }
  438.   fd_puts("</pre>n", fd_out);
  439.   return limit;
  440. }
  441. char *skip_letter_forward(int n, char *start, char *limit)
  442. {
  443.   char *ptr;
  444.   char *end;
  445.   if (start >= limit || start == NULL) 
  446.     return NULL;
  447.   if (n < 1)
  448.     return start;
  449.   end   = limit - SEPLEN - 1;
  450.   for (ptr = start; ptr < end; ptr++) {
  451.     if (*ptr == 'n') {
  452.       if (strncmp(ptr+1, SEP, SEPLEN) == 0 &&
  453.   --n <= 0) {
  454. return ptr+1;
  455.       }
  456.     }
  457.   }
  458.   return limit;
  459. }
  460. char *skip_letter_backward(int n, char *start, char *lower_limit)
  461. {
  462.   char *ptr;
  463.   char *begin;
  464.   if (start == NULL || (begin = start - SEPLEN) < lower_limit) 
  465.     return NULL;
  466.   if (n < 1)
  467.     return start;
  468.   for (ptr = begin; ptr >= lower_limit; ptr--) {
  469.     if (*ptr == 'n') {
  470.       if (strncmp(ptr+1, SEP, SEPLEN) == 0 &&
  471.   --n <= 0) {
  472. return ptr+1;
  473.       }
  474.     }
  475.   }
  476.   if (strncmp(lower_limit, SEP, SEPLEN) == 0)
  477.     return lower_limit;
  478.   return NULL;
  479. }
  480. static char *mmap_mbox(int fd_in, off_t size)
  481. {
  482.   char *cp;
  483.   cp = mmap((caddr_t) NULL,
  484.     size,
  485.     PROT_READ,
  486.     MAP_PRIVATE+MAP_NORESERVE,
  487.     fd_in, 0);
  488.   if (cp == (char *) MAP_FAILED) {
  489.     if (debug) {
  490.       fprintf(stderr, "ERROR: ");
  491.       perror("mmap");
  492.     }
  493.   } else {
  494.     madvise(cp, size, MADV_NORMAL);
  495.     madvise(cp, size, MADV_WILLNEED);
  496.   }
  497.   return cp;
  498. }
  499. static void do_letter(int fd_in, int fd_out, off_t size)
  500. {
  501.   char *cp;
  502.   char *ptr;
  503.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  504.     for (ptr = cp; ptr != NULL;) {
  505.       ptr = do_letter_head(ptr, cp+size, fd_out);
  506.       ptr = do_letter_body(ptr, cp+size, fd_out);
  507.     }
  508.     munmap(cp, size);
  509.   }
  510. }
  511. static void do_num_letter(int fd_in, int fd_out, off_t size, int n)
  512. {
  513.   char *cp;
  514.   char *ptr;
  515.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  516.     ptr = skip_letter_forward(n-1, cp, cp+size);
  517.     ptr = do_letter_head(ptr, cp+size, fd_out);
  518.     ptr = do_letter_body(ptr, cp+size, fd_out);
  519.     munmap(cp, size);
  520.   }
  521. }
  522. static void do_rnum_letter(int fd_in, int fd_out, off_t size, int n)
  523. {
  524.   char *cp;
  525.   char *ptr;
  526.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  527.     ptr = skip_letter_backward(n, cp+size, cp);
  528.     ptr = do_letter_head(ptr, cp+size, fd_out);
  529.     ptr = do_letter_body(ptr, cp+size, fd_out);
  530.     munmap(cp, size);
  531.   }
  532. }
  533. static void do_index_entries(int fd_in, int fd_out, off_t size, char *url)
  534. {
  535.   char *cp;
  536.   char *ptr;
  537.   int count;
  538.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  539.     count = 1;
  540.     for (ptr = cp; ptr != NULL;) {
  541.       ptr = do_index_entry(ptr, cp+size, fd_out, count++, url);
  542.       ptr = skip_letter_forward(1, ptr, cp+size);
  543.     }
  544.     munmap(cp, size);
  545.   }
  546. }
  547. static void do_rindex_entries(int fd_in, int fd_out, off_t size, char *url)
  548. {
  549.   char *cp;
  550.   char *ptr;
  551.   int count;
  552.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  553.     count = 1;
  554.     for (ptr = cp + size - 1; ptr != NULL;) {
  555.       ptr = skip_letter_backward(1, ptr, cp);
  556.       do_rindex_entry(ptr, cp+size, fd_out, count++, url);
  557.     }
  558.     munmap(cp, size);
  559.   }
  560. }
  561. static void do_id_index_entries(int fd_in, int fd_out, off_t size, char *url)
  562. {
  563.   char *cp;
  564.   char *ptr;
  565.   int count;
  566.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  567.     count = 1;
  568.     for (ptr = cp; ptr != NULL;) {
  569.       ptr = do_id_index_entry(ptr, cp+size, fd_out, count++, url);
  570.       ptr = skip_letter_forward(1, ptr, cp+size);
  571.     }
  572.     munmap(cp, size);
  573.   }
  574. }
  575. static void do_id_rindex_entries(int fd_in, int fd_out, off_t size, char *url)
  576. {
  577.   char *cp;
  578.   char *ptr;
  579.   int count;
  580.   if ((cp = mmap_mbox(fd_in, size)) != NULL) {
  581.     count = 1;
  582.     for (ptr = cp + size - 1; ptr != NULL;) {
  583.       ptr = skip_letter_backward(1, ptr, cp);
  584.       do_id_index_entry(ptr, cp+size, fd_out, count++, url);
  585.     }
  586.     munmap(cp, size);
  587.   }
  588. }
  589. #ifdef SF_ARCHIVE
  590. static void sf_fix_title(char *title, char *buf, int buflen)
  591. {
  592.   char *begin;
  593.   char *end;
  594.   char *src;
  595.   char *dst;
  596.   char *dstend;
  597.   if ((begin = strrchr(title, '/')) == NULL)
  598.     begin = title;
  599.   else
  600.     begin++;
  601.   if ((end = strrchr(begin, '.')) == NULL ||
  602.       strcmp(end, ".mbox") != 0)
  603.     end = begin + strlen(begin);
  604.   dst = buf; dstend = buf + buflen;
  605.   for (src = begin; src < end; src++) {
  606.     switch (*src) {
  607.     case '':
  608.       *dst = '';
  609.       return;
  610.     case ',':
  611.       if (dst + 2 > dstend) {
  612. *dst = '';
  613. return;
  614.       }
  615.       *dst++ = ',';
  616.       *dst++ = ' ';
  617.       break;
  618.     case '_':
  619.       *dst++ = ' ';
  620.       break;
  621.     default:
  622.       *dst++ = *src;
  623.       break;
  624.     }
  625.     if (dst+1 >= dstend) {
  626.       *dst = '';
  627.       return;
  628.     }
  629.   }
  630. }
  631. static void sf_do_file_head(int fd_out, char *title)
  632. {
  633.   fd_printf(fd_out, "<html>n");
  634.   fd_printf(fd_out, "<!-- SF archive mbox converter -->n");
  635.   fd_printf(fd_out, "<head>n");
  636.   fd_printf(fd_out, "<title>Link鰌ing Science Fiction Archive:%s</title>n", title);
  637.   fd_printf(fd_out, "<link rev="made" href="mailto:matoh@lysator.liu.se">n");
  638.   fd_printf(fd_out, "</head>n");
  639. }
  640. static void sf_do_file_body(int fd_in, int fd_out, off_t size, char *title)
  641. {
  642.   fd_printf(fd_out, "<body background="/sf_archive/background.gif">n");
  643.   fd_printf(fd_out, "<dl>n");
  644.   fd_printf(fd_out, "<dt>n");
  645.   fd_printf(fd_out, "<a href="/sf_archive/sf_main.html">n");
  646.   fd_printf(fd_out, "<img align=top src="/sf_archive/small_logo.gif" alt="[Logotype]" border=0></a>n");
  647.   fd_printf(fd_out, "<cite>The Link鰌ing Science Fiction & Fantasy Archive</cite>n");
  648.   fd_printf(fd_out, "<dd>n");
  649.   fd_printf(fd_out, "<h1>%s</h1>n", title);
  650.   fd_printf(fd_out, "<hr noshade>n");
  651.   fd_printf(fd_out, "<dl>n");
  652.   do_letter(fd_in, fd_out, size);
  653.   fd_printf(fd_out, "</dl>n");
  654.   fd_printf(fd_out, "<hr noshade>n");
  655.   fd_printf(fd_out, "<address>n");
  656.   fd_printf(fd_out, "<a href="/sf_archive/sf_main.html">Link鰌ing SF Archive</a> /n");
  657.   fd_printf(fd_out, "<a href="/sf_archive/matoh.html">Mats 謍rman</a>n");
  658.   fd_printf(fd_out, "</address>n");
  659.   fd_printf(fd_out, "</dl>n");
  660.   fd_printf(fd_out, "</body>n");
  661.   fd_printf(fd_out, "</html>n");
  662. }
  663. static void sf_do_all(int fd_in, int fd_out, char *url, off_t size)
  664. {
  665.   char title[256];
  666.   sf_fix_title(url, title, sizeof(title));
  667.   sf_do_file_head(fd_out, title);
  668.   sf_do_file_body(fd_in, fd_out, size, title);
  669. }
  670. #endif
  671. static void fix_title(char *title, char *buf, int buflen)
  672. {
  673.   char *begin;
  674.   char *end;
  675.   int len;
  676.   int i;
  677.   if ((begin = strrchr(title, '/')) == NULL)
  678.     begin = title;
  679.   else 
  680.     begin++;
  681.   if ((end = strrchr(begin, '.')) == NULL ||
  682.       strcmp(end, ".mbox") != 0)
  683.     len = strlen(begin);
  684.   else
  685.     len = end - begin;
  686.   if (len > buflen - 1)
  687.     len = buflen - 1;
  688.   for (i = 0; i < len; i++) {
  689.     buf[i] = begin[i];
  690.   }
  691.   buf[i] = '';
  692. }
  693. static void do_file_head(int fd_out, char *title, char *url)
  694. {
  695.   fd_puts("<html>n",    fd_out);
  696.   fd_puts("<head>n",    fd_out);
  697. #if 0
  698.   fd_printf(fd_out, "<base href="%s%s">n", server_url, url);
  699. #endif
  700.   fd_puts("<title>",     fd_out);
  701.   fd_escape_puts(title, fd_out);
  702.   fd_puts("</title>n",  fd_out);
  703.   fd_puts("</head>n",   fd_out);
  704.   if ( mail_top_include != NULL ) do_file_copy(mail_top_include, fd_out);
  705. }
  706. static void do_file_body(int fd_in, int fd_out, off_t size, char *title)
  707. {
  708.   fd_printf(fd_out, "<body>n");
  709.   fd_printf(fd_out, "<h1>");
  710.   fd_escape_puts(title, fd_out);
  711.   fd_printf(fd_out, "</h1>n");
  712.   fd_printf(fd_out, "<dl>n");
  713.   do_letter(fd_in, fd_out, size);
  714.   fd_printf(fd_out, "</dl>n");
  715.   if ( mail_bottom_include != NULL ) do_file_copy(mail_bottom_include, fd_out);
  716.   fd_printf(fd_out, "</body>n");
  717.   fd_printf(fd_out, "</html>n");
  718. }
  719. static void do_num_file_body(int fd_in, int fd_out, off_t size, 
  720.     int n, char *title)
  721. {
  722.   fd_printf(fd_out, "<body>n");
  723.   fd_printf(fd_out, "<h1>");
  724.   fd_escape_puts(title, fd_out);
  725.   fd_printf(fd_out, ": %d</h1>n", n);
  726.   fd_printf(fd_out, "<dl>n");
  727.   do_num_letter(fd_in, fd_out, size, n);
  728.   fd_printf(fd_out, "</dl>n");
  729.   fd_printf(fd_out, "</body>n");
  730.   fd_printf(fd_out, "</html>n");
  731. }
  732. static void do_rnum_file_body(int fd_in, int fd_out, off_t size, 
  733.     int n, char *title)
  734. {
  735.   fd_printf(fd_out, "<body>n");
  736.   fd_printf(fd_out, "<h1>");
  737.   fd_escape_puts(title, fd_out);
  738.   fd_printf(fd_out, ": %d</h1>n", n);
  739.   fd_printf(fd_out, "<dl>n");
  740.   do_rnum_letter(fd_in, fd_out, size, n);
  741.   fd_printf(fd_out, "</dl>n");
  742.   fd_printf(fd_out, "</body>n");
  743.   fd_printf(fd_out, "</html>n");
  744. }
  745. static void do_index_body(int fd_in, int fd_out, off_t size, char *title, char *url)
  746. {
  747.   fd_printf(fd_out, "<body>n");
  748.   fd_printf(fd_out, "<h1><a href="%s">", url);
  749.   fd_escape_puts(title, fd_out);
  750.   fd_printf(fd_out, "</a>");
  751.   fd_printf(fd_out, ": Index</h1>n");
  752.   fd_printf(fd_out, "<dl compact>n");
  753.   do_index_entries(fd_in, fd_out, size, url);
  754.   fd_printf(fd_out, "</dl>n");
  755.   fd_printf(fd_out, "</body>n");
  756.   fd_printf(fd_out, "</html>n");
  757. }
  758. static void do_rindex_body(int fd_in, int fd_out, off_t size, char *title, char *url)
  759. {
  760.   fd_printf(fd_out, "<body>n");
  761.   fd_printf(fd_out, "<h1><a href="%s">", url);
  762.   fd_escape_puts(title, fd_out);
  763.   fd_printf(fd_out, "</a>");
  764.   fd_printf(fd_out, ": Reverse Index</h1>n");
  765.   fd_printf(fd_out, "<dl compact>n");
  766.   do_rindex_entries(fd_in, fd_out, size, url);
  767.   fd_printf(fd_out, "</dl>n");
  768.   fd_printf(fd_out, "</body>n");
  769.   fd_printf(fd_out, "</html>n");
  770. }
  771. static void do_id_index_body(int fd_in, int fd_out, off_t size, char *title, char *url)
  772. {
  773.   fd_printf(fd_out, "<body>n");
  774.   fd_printf(fd_out, "<h1><a href="%s">", url);
  775.   fd_escape_puts(title, fd_out);
  776.   fd_printf(fd_out, "</a>");
  777.   fd_printf(fd_out, ": Index</h1>n");
  778.   fd_printf(fd_out, "<dl compact>n");
  779.   do_id_index_entries(fd_in, fd_out, size, url);
  780.   fd_printf(fd_out, "</dl>n");
  781.   fd_printf(fd_out, "</body>n");
  782.   fd_printf(fd_out, "</html>n");
  783. }
  784. static void do_id_rindex_body(int fd_in, int fd_out, off_t size, char *title, char *url)
  785. {
  786.   fd_printf(fd_out, "<body>n");
  787.   fd_printf(fd_out, "<h1><a href="%s">", url);
  788.   fd_escape_puts(title, fd_out);
  789.   fd_printf(fd_out, "</a>");
  790.   fd_printf(fd_out, ": Index</h1>n");
  791.   fd_printf(fd_out, "<dl compact>n");
  792.   do_id_rindex_entries(fd_in, fd_out, size, url);
  793.   fd_printf(fd_out, "</dl>n");
  794.   fd_printf(fd_out, "</body>n");
  795.   fd_printf(fd_out, "</html>n");
  796. }
  797. static void do_all(int fd_in, int fd_out, char *url, off_t size)
  798. {
  799.   char title[256];
  800.   fix_title(url, title, sizeof(title));
  801.   do_file_head(fd_out, title, url);
  802.   do_file_body(fd_in, fd_out, size, title);
  803. }
  804. static void do_index(int fd_in, int fd_out, char *url, off_t size)
  805. {
  806.   char title[256];
  807.   fix_title(url, title, sizeof(title));
  808.   do_file_head(fd_out, title, url);
  809.   do_index_body(fd_in, fd_out, size, title, url);
  810. }
  811. static void do_rindex(int fd_in, int fd_out, char *url, off_t size)
  812. {
  813.   char title[256];
  814.   fix_title(url, title, sizeof(title));
  815.   do_file_head(fd_out, title, url);
  816.   do_rindex_body(fd_in, fd_out, size, title, url);
  817. }
  818. static void do_id_index(int fd_in, int fd_out, char *url, off_t size)
  819. {
  820.   char title[256];
  821.   fix_title(url, title, sizeof(title));
  822.   do_file_head(fd_out, title, url);
  823.   do_id_index_body(fd_in, fd_out, size, title, url);
  824. }
  825. static void do_id_rindex(int fd_in, int fd_out, char *url, off_t size)
  826. {
  827.   char title[256];
  828.   fix_title(url, title, sizeof(title));
  829.   do_file_head(fd_out, title, url);
  830.   do_id_rindex_body(fd_in, fd_out, size, title, url);
  831. }
  832. static void do_num_search(int fd_in, int fd_out, 
  833.   char *num, char *url, off_t size)
  834. {
  835.   char title[256];
  836.   int n;
  837.   n = atoi(num);
  838.   fix_title(url, title, sizeof(title));
  839.   do_file_head(fd_out, title, url);
  840.   do_num_file_body(fd_in, fd_out, size, n, title);
  841. }
  842. static void do_rnum_search(int fd_in, int fd_out, 
  843.   char *num, char *url, off_t size)
  844. {
  845.   char title[256];
  846.   int n;
  847.   n = atoi(num);
  848.   fix_title(url, title, sizeof(title));
  849.   do_file_head(fd_out, title, url);
  850.   do_rnum_file_body(fd_in, fd_out, size, n, title);
  851. }
  852. static int http_get_head(struct connectioninfo *cip)
  853. {
  854.     char buf[256], *s_since;
  855.     char path[1025];
  856.     struct stat sb;
  857.     int fd_in, i, status, result;
  858.     int fd_out = cip->fd;
  859.     struct httpinfo *hip = cip->hip;
  860.     
  861.     
  862.     if (debug > 1)
  863. fprintf(stderr, "*** mbox/pm_get() called ***n");
  864.     if (url_expand(hip->url, path, sizeof(path), &sb, NULL, NULL) == NULL)
  865. return -1;
  866.     
  867.     if (hip->mip &&
  868. (s_since = mime_getheader(hip->mip, "IF-MODIFIED-SINCE", 1)))
  869.     {
  870.         struct tm tm_since;
  871. int t_since;
  872. t_since = atotm(s_since, &tm_since);
  873. if (t_since != -1)
  874. {
  875.     if (sb.st_mtime <= (time_t) t_since)
  876.         return http_not_modified(cip);
  877. }
  878. else
  879. {
  880.     /* Could not parse the date format - do a string compare */
  881.     http_time_r(&sb.st_mtime, buf, sizeof(buf));
  882.     i = strlen(buf);
  883.     buf[i-1] = '';
  884.     
  885.     if (strcmp(s_since, buf) == 0)
  886.         return http_not_modified(cip);
  887. }
  888.     }
  889.     fd_in = s_open(path, O_RDONLY);
  890.     if (fd_in < 0)
  891.     {
  892. if (debug)
  893.     perror("open(path)");
  894. return -1;
  895.     }
  896.     
  897.     result = 200;
  898.     
  899.     if (hip->mip != NULL)
  900.     {
  901. http_sendheaders(fd_out, cip, result, NULL);
  902. http_sendlastmodified(fd_out, sb.st_mtime);
  903. fd_puts("Content-Type: text/htmlnn", fd_out);
  904.     }
  905. #if 0
  906.     hip->length = sb.st_size;
  907. #endif
  908.     
  909.     if (hip->mip != NULL)
  910. fd_putc('n', fd_out);
  911.     if (strcasecmp(hip->method, "HEAD") == 0)
  912.     {
  913. s_close(fd_in);
  914. return result;
  915.     }
  916. #ifdef SF_ARCHIVE
  917.     if (strncmp(hip->url, "/sf_archive/", strlen("/sf_archive/")) == 0) {
  918.       sf_do_all(fd_in, fd_out, hip->url, sb.st_size);
  919.     } else {
  920.       if (hip->request == NULL) {
  921. #if 0
  922. do_all(fd_in, fd_out, hip->url, sb.st_size);
  923. #else
  924. do_rindex(fd_in, fd_out, hip->url, sb.st_size);
  925. #endif
  926.       } else if (strcasecmp(hip->request, "all") == 0) {
  927. do_all(fd_in, fd_out, hip->url, sb.st_size);
  928.       } else if (strcasecmp(hip->request, "index") == 0) {
  929. do_index(fd_in, fd_out, hip->url, sb.st_size);
  930.       } else if (strcasecmp(hip->request, "rindex") == 0) {
  931. do_rindex(fd_in, fd_out, hip->url, sb.st_size);
  932.       } else if (strcasecmp(hip->request, "id_index") == 0) {
  933. do_id_index(fd_in, fd_out, hip->url, sb.st_size);
  934.       } else if (strcasecmp(hip->request, "id_rindex") == 0) {
  935. do_id_rindex(fd_in, fd_out, hip->url, sb.st_size);
  936.       } else if (all_digits(hip->request)) {
  937. do_num_search(fd_in, fd_out, hip->request, hip->url, sb.st_size);
  938.       } else if ((hip->request[0] == 'r' || hip->request[0] == '-' ) && 
  939.  all_digits(hip->request + 1)) {
  940. do_rnum_search(fd_in, fd_out, hip->request+1, hip->url, sb.st_size);
  941.       } else {
  942. #if 0
  943. do_all(fd_in, fd_out, hip->url, sb.st_size);
  944. #else
  945. do_rindex(fd_in, fd_out, hip->url, sb.st_size);
  946. #endif
  947.       }
  948.     }    
  949. #else
  950.     do_all(fd_in, fd_out, hip->url, sb.st_size);
  951. #endif
  952.     status = s_close(fd_in);
  953.     if (status < 0)
  954. if (debug)
  955. {
  956.     fprintf(stderr, "ERROR on #%d: ", cip->request_no);
  957.     perror("close");
  958. }
  959.     if (debug > 2)
  960. fprintf(stderr, "modules/mbox/http_get: Returningn");
  961.     
  962.     return result;
  963. }
  964. int pm_request(struct connectioninfo *cip)
  965. {
  966.     struct httpinfo *hip = cip->hip;
  967.     
  968.     if (strcasecmp(hip->method, "GET") == 0 ||
  969. strcasecmp(hip->method, "HEAD") == 0)
  970. return http_get_head(cip);
  971.     else
  972. return -2;
  973. }