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

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** gopher_proxy.c
  3. **
  4. ** Copyright (c) 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. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <alloca.h>
  23. #include "phttpd.h"
  24. int pm_init(const char **argv)
  25. {
  26.     const char *name = argv[0];
  27.     
  28.     if (debug > 1)
  29. fprintf(stderr, "gopher_proxy: pm_init("%s")n", name);
  30.     return 0;
  31. }
  32. void pm_exit(void)
  33. {
  34.     if (debug > 1)
  35. fprintf(stderr, "gopher_proxy: pm_exit()n");
  36. }
  37. static int get_rq(char *in_url,
  38.   char **host,
  39.   char **port,
  40.   char **out_url)
  41. {
  42.     char *cp;
  43.     
  44.     if (strncmp(in_url, "gopher://", 9) != 0)
  45. return -1;
  46.     cp = in_url+9;
  47.     *host = cp;
  48.     while (*cp && !(*cp == '/' || *cp == ':'))
  49. ++cp;
  50.     if (*cp == 0)
  51. return 1;
  52.     if (*cp == ':')
  53.     {
  54. *cp++ = '';
  55. *port = cp;
  56. while (*cp && *cp != '/')
  57.     ++cp;
  58. if (*cp == 0)
  59.     return 2;
  60.     }
  61.     
  62.     *cp++ = '';
  63.     *out_url = cp;
  64.     return 3;
  65. }
  66. void send_href(int fd,
  67.       char *prot,
  68.       char *host,
  69.       char *port,
  70.       char seltype,
  71.       char *selector,
  72.       char *label,
  73.       char *append)
  74. {
  75.     char seltag[2];
  76.     char buf[1024];
  77.     
  78.     seltag[0] = seltype,
  79.     seltag[1] = '';
  80.     
  81.     if (port && strcmp(prot, "gopher") == 0 &&
  82. strcmp(port, "70") == 0)
  83. port = NULL;
  84.     
  85.     fd_printf(fd, "<LI> <A HREF="%s://%s%s%s/%s%s">%s%s</A>n",
  86.       prot,
  87.       host ? host : "",
  88.       port ? ":" : "",
  89.       port ? port : "",
  90.       seltag, url_quote(selector, buf, sizeof(buf), "?", 0),
  91.       label,
  92.       append ? append : "");
  93. }
  94. void send_telnet(int fd,
  95.       char *prot,
  96.       char *host,
  97.       char *port,
  98.       char *selector,
  99.       char *label,
  100.       char *append)
  101. {
  102.     char buf[1024];
  103.     if (port && strcmp(prot, "telnet") == 0 &&
  104. strcmp(port, "23") == 0)
  105. port = NULL;
  106.     
  107.     fd_printf(fd, "<LI> <A HREF="%s://%s%s%s%s%s/">%s%s</A>n",
  108.       prot,
  109.       selector ? url_quote(selector, buf, sizeof(buf), "?", 0) : "",
  110.       selector ? "@" : "",
  111.       host ? host : "",
  112.       port ? ":" : "",
  113.       port ? port : "",
  114.       label,
  115.       append ? append : "");
  116. }
  117. int pm_request(struct connectioninfo *cip)
  118. {
  119.     struct httpinfo *hip;
  120.     char *tmp, *host, *port, *url, buf[1024];
  121.     int sock_fd, result, fd, tmpsize;
  122.     fd = cip->fd;
  123.     host = port = url = NULL;
  124.     
  125.     hip = cip->hip;
  126.      
  127.     if (debug > 1)
  128.     {
  129. fprintf(stderr, "gopher_proxy: pm_request()n");
  130. fprintf(stderr, "thip->method = %sn", hip->method);
  131. fprintf(stderr, "thip->url = %sn", hip->url);
  132.     }
  133.     tmpsize = strlen(hip->url)+1;
  134.     tmp = (char *) alloca(tmpsize);
  135.     s_strcpy(tmp, tmpsize, hip->url);
  136.     
  137.     if (get_rq(tmp, &host, &port, &url) < 0)
  138. goto Fail;
  139.     if (debug > 2)
  140. fprintf(stderr, "get_rq(), host=%s, port=%s, url=%sn",
  141. host ? host : "<null>",
  142. port ? port : "<null>",
  143. url ? url : "<null>");
  144. /* XXX should probably check if this is ourself we are connecting to... */
  145.     
  146.     sock_fd = fd_sconnect(host, port ? port : "70");
  147.     if (sock_fd < 0)
  148.     {
  149. if (debug > 2)
  150.     fprintf(stderr, "fd_sconnect("%s") failedn", host);
  151. goto Fail;
  152.     }
  153.     if (debug > 4)
  154. fprintf(stderr, "Gopher query: %sn", url+1);
  155.     result = 200;
  156.     if (hip->mip)
  157. http_sendheaders(fd, cip, result, NULL);
  158.     switch (url[0])
  159.     {
  160.       case '7':
  161. {
  162.     char **argv, *request, *full_url;
  163.     int i, fusize;
  164.     fusize = i = strlen(hip->url);
  165.     full_url = alloca(fusize);
  166.     s_strncpy(full_url, fusize, hip->url, i-1);
  167.     full_url[i-1] = '';
  168.     
  169.     if (debug > 4)
  170. fprintf(stderr, "Gopher query.n");
  171.     if (hip->request)
  172.     {
  173.            int reqsize = strlen(hip->request)+1;
  174. request = (char *) alloca(reqsize);
  175. s_strcpy(request, reqsize, hip->request);
  176.     }
  177.     else
  178. request = NULL;
  179.     
  180.     if (request == NULL ||
  181. *request == '' ||
  182. (argv = strsplit(request, '&', 2)) == NULL)
  183.     {
  184. fd_puts("Content-Type: text/htmlnn", fd);
  185. fd_puts("<HTML><HEAD>n", fd);
  186. fd_printf(fd, "<TITLE>Gopher Search of %s</TITLE>n",
  187.   full_url);
  188. fd_puts("</HEAD><BODY>n", fd);
  189. fd_printf(fd, "<H2 ALIGN=CENTER>Gopher Search of %s</H2>n",
  190.   full_url);
  191. fd_printf(fd, "<ISINDEX>n");
  192. fd_puts("</BODY></HTML>n", fd);
  193. break;
  194.     }
  195.     fd_puts(url+1, sock_fd);
  196.     fd_putc('t', sock_fd);
  197.     
  198.     for (i = 0; argv[i]; i++)
  199.     {
  200. fd_puts(argv[i], sock_fd);
  201. if (argv[i+1])
  202.     fd_putc(' ', sock_fd);
  203.     }
  204.     fd_putc('n', sock_fd);
  205.     fd_flush(sock_fd);
  206. }
  207.       case '':
  208.       case '1':
  209. if (url[0] != '7')
  210. {
  211.     if (debug > 4)
  212. fprintf(stderr, "Gopher menu.n");
  213.     
  214.     if (url[0])
  215. fd_printf(sock_fd, "%sn", url+1);
  216.     else
  217. fd_puts("n", sock_fd);
  218.     fd_flush(sock_fd);
  219. }
  220. fd_puts("Content-Type: text/htmlnn", fd);
  221. html_sysheader(fd, "H2", "Gopher Menu:");
  222. fd_puts("<OL>n", fd);
  223. while (fd_gets(buf, sizeof(buf), sock_fd))
  224. {
  225.     char *label, *selector, *host, *port, *extra;
  226.     
  227.     
  228.     label = buf+1;
  229.     host = port = NULL;
  230.     
  231.     selector = strchr(label, 't');
  232.     if (selector)
  233.     {
  234. *selector++ = '';
  235. host = strchr(selector, 't');
  236. if (host)
  237. {
  238.     *host++ = '';
  239.     
  240.     port = strchr(host, 't');
  241.     if (port)
  242.     {
  243. *port++ = '';
  244. extra = strchr(port, 't');
  245. if (extra)
  246.     *extra++ = '';
  247.     }
  248. }
  249.     }
  250.     switch (buf[0])
  251.     {
  252.       case '.':
  253. break;
  254.       case 'i':
  255. fd_printf(fd, "<LI> %sn", label);
  256. break;
  257.       case '3':
  258. fd_printf(fd, "<B>%s</B>n", label);
  259. break;
  260.       case '0':
  261.       case '2':
  262.       case '4':
  263.       case '5':
  264.       case '6':
  265.       case '7':
  266.       case '9':
  267.       case 'g':
  268.       case 'I':
  269.       case 's':
  270.       case ';':
  271. send_href(fd, "gopher", host, port, buf[0], selector, label, NULL);
  272. break;
  273.       case '1':
  274. send_href(fd, "gopher", host, port, buf[0], selector, label, "/");
  275. break;
  276.       case '8':
  277. send_telnet(fd, "telnet", host, port, selector, label, NULL);
  278. break;
  279.       case 'T':
  280. send_telnet(fd, "tn3270", host, port, selector, label, NULL);
  281. break;
  282.       default:
  283. fd_printf(fd, "<LI> ? type='%c' (%d), label=%s",
  284.   buf[0], (int) buf[0], label);
  285. if (selector)
  286.     fd_printf(fd, ", selector=%s", selector);
  287. if (host)
  288.     fd_printf(fd, ", host=%s", host);
  289. if (port)
  290.     fd_printf(fd, ", port=%s", port);
  291. fd_putc('n', fd);
  292.     }
  293. }
  294. fd_puts("</OL>n", fd);
  295. html_sysfooter(fd);
  296. break;
  297.       case '0':
  298. if (url[0])
  299.     fd_printf(sock_fd, "%sn", url+1);
  300. else
  301.     fd_puts("n", sock_fd);
  302. fd_flush(sock_fd);
  303. if (debug > 4)
  304.     fprintf(stderr, "Gopher text.n");
  305. fd_puts("Content-Type: text/plainnn", fd);
  306. fd_relay(sock_fd, fd, 0);
  307. break;
  308.       case '2':
  309. {
  310.     char **argv, *request, *url;
  311.     int i;
  312.     url = alloca(i = strlen(hip->url));
  313.     s_strncpy(url, i, hip->url, i-1);
  314.     url[i-1] = '';
  315.     
  316.     if (hip->request)
  317.     {
  318.         int reqsize = strlen(hip->request)+1;
  319. request = (char *) alloca(reqsize);
  320. s_strcpy(request, reqsize, hip->request);
  321.     }
  322.     else
  323. request = NULL;
  324.     
  325.     if (request == NULL ||
  326. *request == '' ||
  327. (argv = strsplit(request, '&', 2)) == NULL)
  328.     {
  329. fd_puts("Content-Type: text/htmlnn", fd);
  330. fd_puts("<HTML><HEAD>n", fd);
  331. fd_printf(fd, "<TITLE>CSO Search of %s</TITLE>n",
  332.   url);
  333. fd_puts("</HEAD><BODY>n", fd);
  334. fd_printf(fd, "<H2 ALIGN=CENTER>CSO Search of %s</H2>n",
  335.   url);
  336. fd_printf(fd, "<ISINDEX>n");
  337. fd_puts("</BODY></HTML>n", fd);
  338. break;
  339.     }
  340.     fd_puts("query", sock_fd);
  341.     for (i = 0; argv[i]; i++)
  342. fd_printf(sock_fd, " %s", argv[i]);
  343.     
  344.     fd_putc('n', sock_fd);
  345.     fd_flush(sock_fd);
  346.     fd_puts("quitn", sock_fd);
  347.     fd_shutdown(sock_fd, 1);
  348.     fd_puts("Content-Type: text/plainnn", fd);
  349.     fd_relay(sock_fd, fd, 0);
  350. }
  351. break;
  352.       case '4':
  353. if (url[0])
  354.     fd_printf(sock_fd, "%sn", url+1);
  355. else
  356.     fd_puts("n", sock_fd);
  357. fd_flush(sock_fd);
  358. if (debug > 4)
  359.     fprintf(stderr, "Gopher macbinhex.n");
  360. fd_puts("Content-Type: application/binhexnn", fd);
  361. fd_relay(sock_fd, fd, 0);
  362. break;
  363.       case '5':
  364. if (debug > 4)
  365.     fprintf(stderr, "Gopher pcbinary.n");
  366. if (url[0])
  367.     fd_printf(sock_fd, "%sn", url+1);
  368. else
  369.     fd_puts("n", sock_fd);
  370. fd_flush(sock_fd);
  371. fd_puts("Content-Type: application/octet-streamnn", fd);
  372. fd_relay(sock_fd, fd, 0);
  373. break;
  374.       case '6':
  375. if (debug > 4)
  376.     fprintf(stderr, "Gopher uuencoded.n");
  377. if (url[0])
  378.     fd_printf(sock_fd, "%sn", url+1);
  379. else
  380.     fd_puts("n", sock_fd);
  381. fd_flush(sock_fd);
  382. fd_puts("Content-Type: application/uuencodednn", fd);
  383. fd_relay(sock_fd, fd, 0);
  384. break;
  385.       case '9':
  386. if (debug > 4)
  387.     fprintf(stderr, "Gopher binary.n");
  388. if (url[0])
  389.     fd_printf(sock_fd, "%sn", url+1);
  390. else
  391.     fd_puts("n", sock_fd);
  392. fd_flush(sock_fd);
  393. fd_puts("Content-Type: application/octet-streamnn", fd);
  394. fd_relay(sock_fd, fd, 0);
  395. break;
  396.       case 'g':
  397.       case 'I':
  398. if (debug > 4)
  399.     fprintf(stderr, "Gopher GIF.n");
  400. if (url[0])
  401.     fd_printf(sock_fd, "%sn", url+1);
  402. else
  403.     fd_puts("n", sock_fd);
  404. fd_flush(sock_fd);
  405. fd_puts("Content-Type: image/gifnn", fd);
  406. fd_relay(sock_fd, fd, 0);
  407. break;
  408.       case 's':
  409. if (debug > 4)
  410.     fprintf(stderr, "Gopher Sound.n");
  411. if (url[0])
  412.     fd_printf(sock_fd, "%sn", url+1);
  413. else
  414.     fd_puts("n", sock_fd);
  415. fd_flush(sock_fd);
  416. fd_puts("Content-Type: audio/unknownnn", fd);
  417. fd_relay(sock_fd, fd, 0);
  418. break;
  419.       case ';':
  420. if (debug > 4)
  421.     fprintf(stderr, "Gopher MPEG.n");
  422. if (url[0])
  423.     fd_printf(sock_fd, "%sn", url+1);
  424. else
  425.     fd_puts("n", sock_fd);
  426. fd_flush(sock_fd);
  427. fd_puts("Content-Type: vide/mpegnn", fd);
  428. fd_relay(sock_fd, fd, 0);
  429. break;
  430.       default:
  431. fd_puts("Content-Type: text/htmlnn", fd);
  432. html_sysheader(fd, "H2", "Gopher Menu:");
  433. fd_printf(fd, "Unknown gopher query type: '%c'n", url[1]);
  434. html_sysfooter(fd);
  435.     }
  436.     
  437.     
  438.     if (debug > 4)
  439. fprintf(stderr, "gopher_proxy: closing downn");
  440.     
  441.     fd_close(sock_fd);
  442.     return 200;
  443.     
  444.   Fail:
  445.     return -1;
  446. }