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

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