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

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** ph.c
  3. **
  4. ** Copyright (c) 1994,1995 Peter Eriksson <pen@signum.se>
  5. **
  6. ** This program is free software; you can redistribute it and/or modify
  7. ** it under the terms of the GNU General Public License as published by
  8. ** the Free Software Foundation; either version 2 of the License, or
  9. ** (at your option) any later version.
  10. **
  11. ** This program is distributed in the hope that it will be useful,
  12. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. ** GNU General Public License for more details.
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #define IFM_SPECIAL
  20. #include <stdio.h>
  21. #include <alloca.h>
  22. #include <time.h>
  23. #include <string.h>
  24. #include <errno.h>
  25. #include <unistd.h>
  26. #include <stdlib.h>
  27. #include "phttpd.h"
  28. static char *default_page = NULL;
  29. static char *default_server = NULL;
  30. static struct table *ph_labels = NULL;
  31. static int n_labels = 0;
  32. static char *include_header_file = NULL;
  33. static char *include_footer_file = NULL;
  34. #ifdef IFM_SPECIAL
  35. static char *email_href_path = NULL;
  36. static hashtable_t email_href_table;
  37. #endif
  38. static int phl_create(char *cmd,
  39.       char *line,
  40.       void *var)
  41. {
  42.     char **pair;
  43.     
  44.     pair = s_malloc(2* sizeof(char *));
  45.     
  46.     pair[0] = s_strdup(cmd);
  47.     pair[1] = s_strdup(line);
  48.     * (char ***) var = pair;
  49.     return 1;
  50. }
  51. static void phl_free(void *var)
  52. {
  53.     char **pair;
  54.     pair = (char **) var;
  55.     if (pair[0])
  56. s_free(pair[0]);
  57.     if (pair[1])
  58. s_free(pair[1]);
  59.     
  60.     s_free(pair);
  61. }
  62. static struct options ph_cfg_table[] =
  63. {
  64.     { "default-page",     T_STRING, &default_page,       NULL },
  65.     { "default-server",   T_STRING, &default_server,     NULL },
  66.     { "footer-file",   T_STRING, &include_footer_file, NULL },
  67.     { "header-file",   T_STRING, &include_header_file, NULL },
  68. #ifdef IFM_SPECIAL
  69.     { "email-href-db",    T_STRING, &email_href_path,    NULL },
  70. #endif
  71.     
  72.     { "ph-labels",        T_TABLE,  &ph_labels,          phl_create },
  73.     { NULL,               -1,       NULL,                NULL }
  74. };
  75. void load_href_db(char *path,
  76.   hashtable_t *tp)
  77. {
  78.     int fd;
  79.     char buf[1024];
  80.     ht_init(tp, 0, NULL);
  81.     
  82.     fd = fd_open(path, O_RDONLY);
  83.     if (fd < 0)
  84. return;
  85.     while (fd_gets(buf, sizeof(buf), fd))
  86.     {
  87. char *cp, *key, *value;
  88. cp = buf;
  89. key = value = NULL;
  90. while (*cp && s_isspace(*cp))
  91.     ++cp;
  92. if (*cp == '#' || *cp == 0)
  93.     continue;
  94. key = cp;
  95. while (*cp && !s_isspace(*cp))
  96.     ++cp;
  97. if (*cp == 0)
  98.     continue;
  99. *cp++ = '';
  100. while (*cp && s_isspace(*cp))
  101.     ++cp;
  102. value = cp;
  103. cp = value + strlen(value)-1;
  104. while (cp > value && s_isspace(*cp))
  105.     --cp;
  106. *++cp = '';
  107. if (debug > 2)
  108.     fprintf(stderr, "Inserting key=%s, value=%sn", key, value);
  109. ht_insert(tp, key, 0, s_strdup(value), 0, s_free);
  110.     }
  111.     fd_close(fd);
  112. }
  113. int pm_init(const char **argv)
  114. {
  115.     char *cfg_path, *cp;
  116.     const char *name;
  117.     int cfg_size;
  118.     
  119.     name = argv[0];
  120.     
  121.     if (debug > 1)
  122. fprintf(stderr, "*** libph/pm_init("%s") called ***n", name);
  123.     cfg_path = s_strxdup(name, 6, &cfg_size);
  124.     
  125.     cp = strrchr(cfg_path, '.');
  126.     if (cp && strcmp(cp, ".so") == 0)
  127. *cp = '';
  128.     
  129.     s_strcat(cfg_path, cfg_size, ".conf");
  130.     if (config_parse_file(cfg_path, ph_cfg_table, 0) < 0)
  131. return -1;
  132.     if (config_parse_argv(argv+1, ph_cfg_table) < 0)
  133. return -1;
  134.     if (ph_labels)
  135. n_labels = ph_labels->length;
  136.     if (email_href_path)
  137. load_href_db(email_href_path, &email_href_table);
  138.     return 0;
  139. }
  140. void pm_exit(void)
  141. {
  142.     if (debug > 1)
  143. fprintf(stderr, "*** libph/pm_exit() called ***n");
  144.     if (default_page)
  145. s_free(default_page);
  146.     if (default_server)
  147. s_free(default_server);
  148.     if (ph_labels)
  149. tbl_free(ph_labels, phl_free);
  150.     if (email_href_path)
  151.     {
  152. ht_destroy(&email_href_table);
  153. s_free(email_href_path);
  154.     }
  155. }
  156. static void send_head(int fd,
  157.       char *header_type,
  158.       char *title)
  159. {
  160.     fscentry_t *fep = NULL;
  161.     fsinfo_t *fip = NULL;
  162.     if (include_header_file)
  163.     {
  164. fep = fscache_lookup(include_header_file, FSCF_GETDATA);
  165. if (fep != NULL && (fip = fep->fip) != NULL)
  166. {
  167.     fd_write(fd, fip->data.file.content, fip->sb.st_size);
  168. }
  169. fscache_release(fep);
  170.     }
  171.     
  172.     if (fip == NULL)
  173.     {
  174. fd_puts("<HTML>n", fd);
  175. fd_puts("<HEAD>n", fd);
  176. fd_printf(fd, "<TITLE>Query Results</TITLE>n");
  177. fd_puts("</HEAD>n", fd);
  178. fd_puts("<BODY>n", fd);
  179.     }
  180.     
  181.     fd_printf(fd, "<%s>%s</%s>n", header_type, title, header_type);
  182. }
  183. static void send_tail(int fd)
  184. {
  185.     fscentry_t *fep = NULL;
  186.     fsinfo_t *fip = NULL;
  187.     if (include_footer_file)
  188.     {
  189. fep = fscache_lookup(include_footer_file, FSCF_GETDATA);
  190. if (fep != NULL && (fip = fep->fip) != NULL)
  191. {
  192.     fd_write(fd, fip->data.file.content, fip->sb.st_size);
  193. }
  194. fscache_release(fep);
  195.     }
  196.     if (fip == NULL)
  197. html_sysfooter(fd);
  198.     
  199.     fd_puts("</BODY>n", fd);
  200.     fd_puts("</HTML>n", fd);
  201. }
  202. static int error(int fd,
  203.  char *header,
  204.  char *msg,
  205.  ...)
  206. {
  207.     va_list ap;
  208.     
  209.     va_start(ap, msg);
  210.     
  211.     send_head(fd, "H2", header);
  212.     fd_vprintf(fd, msg, ap);
  213.     send_tail(fd);
  214.     va_end(ap);
  215.     return 200;
  216. }
  217. static int get_idx(char *label, char **prompt)
  218. {
  219.     int i;
  220.     
  221.     for (i = 0; i < n_labels; i++)
  222.     {
  223. char **pair = ph_labels->value[i];
  224. if (strcmp(label, pair[0]) == 0)
  225. {
  226.     if (prompt)
  227. *prompt = pair[1];
  228.     return i;
  229. }
  230.     }
  231.     return -1;
  232. }
  233. struct resvinfo
  234. {
  235.     int len;
  236.     char **resv;
  237. };
  238. static struct table *get_results(int fd)
  239. {
  240.     int code, num, pos, nidx;
  241.     struct table *tp;
  242.     char buf[2048], label[2048], value[2048];
  243.     struct resvinfo *rp;
  244.     
  245.     tp = tbl_create(0);
  246.     
  247.     pos = 0;
  248.     rp = NULL;
  249.     
  250.     while (fd_gets(buf, sizeof(buf), fd))
  251.     {
  252. if (sscanf(buf, "%d : %d : %[^ t:] : %[^nr]",
  253.    &code, &num, label, value) == 4)
  254. {
  255.     if (code != -200)
  256. break;
  257.     if (pos != num)
  258.     {
  259. if (rp != NULL)
  260.     tbl_append(tp, rp);
  261. rp = s_malloc(sizeof(struct resvinfo));
  262. rp->len = n_labels;
  263. rp->resv = s_malloc(rp->len * sizeof(char *));
  264. pos = num;
  265.     }
  266.     nidx = get_idx(label, NULL);
  267.     if (nidx < 0)
  268.     {
  269. char *cp, **pair;
  270. pair = s_malloc(2 * sizeof(char *));
  271. pair[0] = s_strdup(label);
  272. pair[1] = s_strdup(label);
  273. cp = pair[1];
  274. if (s_islower(*cp))
  275.     *cp = s_toupper(*cp);
  276. while (*cp)
  277. {
  278.     if (*cp == '_')
  279. *cp = ' ';
  280.     ++cp;
  281. }
  282. nidx = n_labels;
  283. if (ph_labels == NULL)
  284.     ph_labels = tbl_create(0);
  285. n_labels = rp->len = tbl_append(ph_labels, pair);
  286. rp->resv = s_realloc(rp->resv,
  287.     rp->len * sizeof(char *));
  288.      }
  289.     rp->resv[nidx] = s_strdup(value);
  290. }
  291.     }
  292.     if (rp != NULL)
  293. tbl_append(tp, rp);
  294.     return tp;
  295. }
  296. static void rp_free(void *val)
  297. {
  298.     struct resvinfo *rip;
  299.     int i;
  300.     
  301.     rip = (struct resvinfo *) val;
  302.     for (i = 0; i < rip->len; i++)
  303. if (rip->resv[i])
  304.     s_free(rip->resv[i]);
  305.     s_free(rip);
  306. }
  307. static int find_label(char *label)
  308. {
  309.     int i;
  310.     for (i = 0; i < n_labels; i++)
  311.     {
  312. char **pair = ph_labels->value[i];
  313. if (strcmp(pair[0], label) == 0)
  314.     return i;
  315.     }
  316.     return -1;
  317. }
  318. static char *get_label(int idx)
  319. {
  320.     if (idx >= 0 && idx < n_labels)
  321.     {
  322. char **pair = ph_labels->value[idx];
  323. return pair[0];
  324.     }
  325.     return NULL;
  326. }
  327. static int get_url_pointer(char *email,
  328.    char *buf,
  329.    int size)
  330. {
  331.     if (email_href_path)
  332.     {
  333. hashentry_t *hep;
  334. hep = ht_lookup(&email_href_table, email, 0);
  335. if (hep == NULL)
  336.     return 0;
  337. s_strcpy(buf, size, hep->data);
  338. ht_release(hep);
  339. return 1;
  340.     }
  341.     else
  342.     {
  343. if (strcmp(email, "peter@ifm.liu.se") == 0)
  344. {
  345.     s_strcpy(buf, size, "http://www.ifm.liu.se/~peter/");
  346.     return 1;
  347. }
  348. else if (strcmp(email, "johan@lysator.liu.se") == 0)
  349. {
  350.     s_strcpy(buf, size, "http://www.lysator.liu.se/~johan/");
  351.     return 1;
  352. }
  353.     }
  354.     return 0;
  355. }
  356. static int get_href(struct resvinfo *rip,
  357.     int idx,
  358.     char *value,
  359.     char *qvalue,
  360.     char *buf,
  361.     int size)
  362. {
  363.     char *label;
  364.     label = get_label(idx);
  365.     if (label == NULL)
  366. return 0;
  367.     if (strcmp(label, "email") == 0)
  368.     {
  369. s_strcpy(buf, size, "mailto:");
  370. s_strcat(buf, size, qvalue);
  371. return 1;
  372.     }
  373. #ifdef IFM_SPECIAL
  374.     else if (strcmp(label, "name") == 0)
  375.     {
  376. int email_idx;
  377. char *email;
  378. email_idx = find_label("email");
  379. if (email_idx >= 0 && email_idx < rip->len &&
  380.     (email = rip->resv[email_idx]) != NULL)
  381. {
  382.     if (get_url_pointer(email, buf, size))
  383. return 1;
  384. }
  385.     }
  386.     
  387.     else if (strcmp(label, "department") == 0)
  388.     {
  389. if (strncmp(value, "IFM", 3) == 0)
  390. {
  391.     s_strcpy(buf, size, "http://www.ifm.liu.se/");
  392.     return 1;
  393. }
  394. else if (strncmp(value, "ISY", 3) == 0)
  395. {
  396.     s_strcpy(buf, size, "http://www.isy.liu.se/");
  397.     return 1;
  398. }
  399. else if (strncmp(value, "IDA", 3) == 0)
  400. {
  401.     s_strcpy(buf, size, "http://www.ida.liu.se/");
  402.     return 1;
  403. }
  404. else if (strncmp(value, "IKP", 3) == 0)
  405. {
  406.     s_strcpy(buf, size, "http://www.ikp.liu.se/");
  407.     return 1;
  408. }
  409. else if (strncmp(value, "MAI", 3) == 0)
  410. {
  411.     s_strcpy(buf, size, "http://www.math.liu.se/");
  412.     return 1;
  413. }
  414.     }
  415. #endif
  416.     return 0;
  417. }
  418. static void send_results(int fd,
  419.  struct table *tp)
  420. {
  421.     int i, j, len;
  422.     int *field_width;
  423.     char buf[1024], buf2[1024];
  424.     
  425.     field_width = (int *) alloca(n_labels * sizeof(int));
  426.     if (field_width == NULL)
  427. s_abort();
  428.     for (i = 0; i < n_labels; i++)
  429. field_width[i] = 0;
  430.     for (i = 0; i < tp->length; i++)
  431.     {
  432. struct resvinfo *rip = tp->value[i];
  433. for (j = 0; j < rip->len; j++)
  434.     if (rip->resv[j])
  435.     {
  436. if ((len = strlen(rip->resv[j])) > field_width[j])
  437.     field_width[j] = len;
  438.     }
  439.     }
  440.     for (i = 0; i < n_labels; i++)
  441.     {
  442. char **pair = ph_labels->value[i];
  443. int len = strlen(pair[1]);
  444. if (field_width[i] > 0 && len > field_width[i])
  445.     field_width[i] = len;
  446.     }
  447.     
  448.     fd_puts("<PRE><TABLE CELLSPACING=3 WIDTH=100%>n", fd);
  449.     fd_puts("<TR>", fd);
  450.     for (i = 0; i < n_labels; i++)
  451.     {
  452. char **pair = ph_labels->value[i];
  453. if (field_width[i] == 0)
  454.     continue;
  455.        
  456. html_strquote(pair[1], buf, sizeof(buf));
  457. fd_printf(fd, " <TH ALIGN=LEFT> %-*s", field_width[i], buf);
  458.     }
  459.     fd_printf(fd, "n<TR> <TD COLSPAN=%d> <HR>n", n_labels);
  460.     
  461.     for (i = 0; i < tp->length; i++)
  462.     {
  463. struct resvinfo *rip = tp->value[i];
  464. fd_puts("<TR>", fd);
  465. for (j = 0; j < rip->len; j++)
  466. {
  467.     if (field_width[j] == 0)
  468. continue;
  469.     
  470.     fd_puts(" <TD> ", fd);
  471.     if (rip->resv[j] != NULL)
  472.     {
  473. int have_anchor = 0;
  474. len = strlen(rip->resv[j]);
  475. html_strquote(rip->resv[j], buf, sizeof(buf));
  476. have_anchor = get_href(rip, j, rip->resv[j], buf,
  477.        buf2, sizeof(buf2));
  478. if (have_anchor < 0)
  479.     return;
  480. if (have_anchor)
  481.     fd_printf(fd, "<A HREF="%s">", buf2);
  482. fd_puts(buf, fd);
  483. if (have_anchor)
  484.     fd_puts("</A>", fd);
  485. if (field_width[j]-len > 0)
  486.     fd_printf(fd, "%-*s",
  487.       field_width[j]-len,
  488.       "");
  489.     }
  490.     else
  491. fd_printf(fd, "%-*s", 
  492.   field_width[j], "");
  493. }
  494. fd_putc('n', fd);
  495.     }
  496.     
  497.     fd_printf(fd, "n<TR> <TD COLSPAN=%d> <HR>n", n_labels);
  498.     fd_puts("</TABLE></PRE>n", fd);
  499. }
  500. static void get_list(int fd, int ph_fd)
  501. {
  502.     struct table *tp;
  503.     
  504.     tp = get_results(ph_fd);
  505.     send_results(fd, tp);
  506.     tbl_free(tp, rp_free);
  507. }
  508. static int http_get(struct connectioninfo *cip)
  509. {
  510.     char buf[1024], *cp, *cp2, *code_s, buf2[256], **argv, *request;
  511.     int code, fd_length, sock_fd, result, i, len;
  512.     
  513.     int fd = cip->fd;
  514.     struct httpinfo *hip = cip->hip;
  515.     
  516.     
  517.     
  518.     if (debug > 1)
  519. fprintf(stderr, "*** libph/http_get() called ***n");
  520.     
  521.     result = 200;
  522.     sock_fd = -1;
  523.     argv = NULL;
  524.     
  525.     if (hip->request)
  526.     {
  527.         int reqsize = strlen(hip->request)+1;
  528. request = (char *) alloca(reqsize);
  529. s_strcpy(request, reqsize, hip->request);
  530.     }
  531.     else
  532. request = NULL;
  533.     
  534.     
  535.     if (request == NULL ||
  536. request[0] == '' ||
  537. (argv = strsplit(request, '&', 2)) == NULL)
  538.     {
  539. if (default_page)
  540.     return http_redirect(cip, default_page, NULL, NULL, 302);
  541. else
  542. {
  543.     if (hip->mip != NULL)
  544.     {
  545. http_sendheaders(fd, cip, result, NULL);
  546. fd_puts("Content-Type: text/htmln", fd);
  547. fd_putc('n', fd);
  548.     }
  549.     
  550.     fd_length = fd_written(fd);
  551.     
  552.     result = error(fd, "Error", "No question asked");
  553.     goto End;
  554. }
  555.     }
  556.     
  557.     if (hip->mip != NULL)
  558.     {
  559. http_sendheaders(fd, cip, result, NULL);
  560. fd_puts("Content-Type: text/htmln", fd);
  561. fd_putc('n', fd);
  562.     }
  563.     
  564.     fd_length = fd_written(fd);
  565.     
  566.     cp = strchr(hip->url+1, '/');
  567.     if (cp == NULL)
  568. cp = default_server;
  569.     else
  570. ++cp;
  571.     
  572.     if (cp == NULL || *cp == '')
  573.     {
  574. result = error(fd, "Error", "No PH server specified");
  575. goto End;
  576.     }
  577.     
  578.     cp2 = strchr(cp, ':');
  579.     if (cp2 == NULL)
  580. cp2 = "105";
  581.     else
  582. *cp2++ = '';
  583.     
  584.     if (debug > 4)
  585. fprintf(stderr, "Before fd_sconnect("%s", "%s")n",
  586. cp, cp2);
  587.     
  588.     sock_fd = fd_sconnect(cp, cp2);
  589.     if (sock_fd < 0)
  590.     {
  591. result = error(fd, "Error", "Can not connect to NS service at %s", cp);
  592. goto End;
  593.     }
  594.     
  595.     if (debug > 4)
  596. fprintf(stderr, "tGot fd#%dn", sock_fd);
  597.     
  598.     fd_printf(sock_fd, "query");
  599.     for (i = 0; argv[i]; i++)
  600.     {
  601. char *cp, *last, *obj;
  602. cp = strchr(argv[i], '=');
  603. if (cp == NULL || cp[1] == '')
  604.     continue;
  605. #if 0
  606. fd_printf(sock_fd, " %s", argv[i]);
  607. #else
  608. *cp++ = '';
  609. obj = strtok_r(cp, " t", &last);
  610. while (obj)
  611. {
  612.     fd_printf(sock_fd, " %s=%s", argv[i], obj);
  613.     obj = strtok_r(NULL, " t", &last);
  614. }
  615. #endif
  616.     }
  617.     fd_putc('n', sock_fd);
  618.     fd_flush(sock_fd);
  619.     
  620.     fd_puts("quitn", sock_fd);
  621.     fd_shutdown(sock_fd, 1);
  622.     if (debug > 4)
  623. fprintf(stderr, "Sent reply, waiting for answern");
  624.     
  625.     if (fd_gets(buf, sizeof(buf), sock_fd) == NULL)
  626.     {
  627. result = error(fd, "Error", "Premature end of transmission");
  628. goto End;
  629.     }
  630.     if (debug > 4)
  631. fprintf(stderr, "t->Got one linen");
  632.     
  633.     cp = buf;
  634.     code_s = strtok_r(buf, ":", &cp);
  635.     if (code_s == NULL)
  636.     {
  637. result = error(fd, "Error", "protocol error: <PRE>%s</PRE>", buf);
  638. goto End;
  639.     }
  640.     
  641.     code = atoi(code_s);
  642.     switch (code)
  643.     {
  644.       case 102:
  645. send_head(fd, "H2", "Query Results");
  646. get_list(fd, sock_fd);
  647. send_tail(fd);
  648. break;
  649.       default:
  650. len = s_strcpy(buf2, sizeof(buf2), "Error #");
  651. s_sprintf(buf2+len, sizeof(buf2)-len, "%d", code);
  652. result = error(fd, buf2, cp);
  653.     }
  654.   End:
  655.     if (debug > 4)
  656. fprintf(stderr, "All done, beginnig cleanupn");
  657.     if (argv)
  658. s_free(argv);
  659.     
  660.     if (sock_fd >= 0)
  661. fd_close(sock_fd);
  662.     if (debug > 4)
  663. fprintf(stderr, "Exiting.n");
  664.     return result;
  665. }
  666. int pm_request(struct connectioninfo *cip)
  667. {
  668.     struct httpinfo *hip = cip->hip;
  669.     
  670.     if (strcasecmp(hip->method, "GET") == 0)
  671. return http_get(cip);
  672.     else
  673. return -1;
  674. }