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

Web服务器

开发平台:

Unix_Linux

  1. /*
  2. ** http.c
  3. **
  4. ** Copyright (c) 1994-1997 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 <unistd.h>
  22. #include <string.h>
  23. #include <errno.h>
  24. #include <stdarg.h>
  25. #include <limits.h>
  26. #include <time.h>
  27. #include <syslog.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30. #define IN_DNS_C
  31. #include "phttpd.h"
  32. int phttpd_call(const char *module,
  33. struct connectioninfo *cip)
  34. {
  35.     struct modinfo *mp;
  36.     void *mkey;
  37.     int status;
  38.     char buf[2048];
  39.     
  40.     
  41.     while (*module && *module == '/')
  42. ++module;
  43.     s_strcpy(buf, sizeof(buf), modules_home);
  44.     s_strcat(buf, sizeof(buf), "/");
  45.     s_strcat(buf, sizeof(buf), module);
  46.     
  47.     mp = md_load(buf, &mkey);
  48.     if (mp == NULL)
  49.     {
  50. return http_error(cip, 500,
  51.   "A system error occured while loading module <B>%s</B>:<BR><PRE>%s</PRE>",
  52.   module, md_error());
  53.     }
  54.     status = mp->pm_request(cip);
  55.     
  56.     md_release(mkey);
  57.     return status;
  58. }
  59. int phttpd_request(struct connectioninfo *cip)
  60. {
  61.     const char *handler;
  62.     
  63.     if (cip->hip == NULL)
  64. return -1;
  65.     
  66.     handler = url_gethandler(cip->hip->url);
  67.     if (handler == NULL)
  68. return -1;
  69.     return phttpd_call(handler, cip);
  70. }
  71. void http_sendlastmodified(int fd, time_t ct)
  72. {
  73.     char buf[64];
  74.     
  75.     fd_puts("Last-Modified: ", fd);
  76.     fd_puts(http_time_r(&ct, buf, sizeof(buf)), fd);
  77. }
  78. char *http_sendheaders(int fd,
  79.        struct connectioninfo *cip,
  80.        int code,
  81.        char *type)
  82. {
  83.     char buf[256];
  84.     time_t ct;
  85.     int keepalive;
  86.     
  87.     ct = cip->cn_time;
  88.     if (cip->hip && cip->hip->mip)
  89. keepalive = cip->hip->mip->connection_flags & MCF_KEEPALIVE;
  90.     else
  91. keepalive = 0;
  92.     
  93.     if (ct == 0)
  94. time(&ct);
  95.     if (type == NULL)
  96. switch (code)
  97. {
  98.   case 200:
  99.     type = "OK";
  100.     break;
  101.   case 201:
  102.     type = "Created";
  103.     break;
  104.   case 202:
  105.     type = "Accepted";
  106.     break;
  107.   case 203:
  108.     type = "Provisional Information";
  109.     break;
  110.   case 204:
  111.     type = "No Content";
  112.     break;
  113.   case 206:
  114.     type = "Partial Content";
  115.     break;
  116.   case 300:
  117.     type = "Multiple Choices";
  118.     break;
  119.   case 301:
  120.     type = "Moved Permanently";
  121.     break;
  122.     
  123.   case 302:
  124.     type = "Moved Temporarily";
  125.     break;
  126.   case 303:
  127.     type = "Method";
  128.     break;
  129.     
  130.   case 304:
  131.     type = "Not Modified";
  132.     break;
  133.   case 400:
  134.     type = "Bad Request";
  135.     break;
  136.   case 401:
  137.     type = "Unauthorized";
  138.     break;
  139.   case 402:
  140.     type = "Payment Forbidden";
  141.     break;
  142.   case 403:
  143.     type = "Forbidden";
  144.     break;
  145.   case 404:
  146.     type = "Not Found";
  147.     break;
  148.   case 405:
  149.     type = "Method Not Allowed";
  150.     break;
  151.   case 406:
  152.     type = "None Acceptable";
  153.     break;
  154.     
  155.   case 407:
  156.     type = "Proxy Authentication Required";
  157.     break;
  158.     
  159.   case 408:
  160.     type = "Request Timeout";
  161.     break;
  162.     
  163.   case 409:
  164.     type = "Conflict";
  165.     break;
  166.     
  167.   case 410:
  168.     type = "Gone";
  169.     break;
  170.   case 412:
  171.     type = "Precondition Failed";
  172.     break;
  173.     
  174.   case 500:
  175.     type = "Internal Server Error";
  176.     break;
  177.   case 501:
  178.     type = "Not Implemented";
  179.     break;
  180.     
  181.   case 502:
  182.     type = "Bad Gateway";
  183.     break;
  184.     
  185.   case 503:
  186.     type = "Service Unavailable";
  187.     break;
  188.     
  189.   case 504:
  190.     type = "Gateway Timeout";
  191.     break;
  192.     
  193.   default:
  194.     type = "?";
  195. }
  196.     if ( strcasecmp(cip->hip->version,"HTTP/1.1")!=0)
  197.       fd_puts("HTTP/1.0 ", fd);
  198.     else
  199.       fd_puts("HTTP/1.1 ", fd);
  200.     fd_puti(code, fd);
  201.     fd_putc(' ', fd);
  202.     fd_puts(type, fd);
  203.     fd_putc('n', fd);
  204.     
  205.     fd_puts("MIME-Version: 1.0n", fd);
  206.     fd_puts("Date: ", fd);
  207.     fd_puts(http_time_r(&ct, buf, sizeof(buf)), fd);
  208.     
  209.     fd_puts("Server: phttpd/", fd);
  210.     fd_puts(server_version, fd);
  211.     fd_putc('n', fd);
  212.     if (keepalive && (keepalive_timeout > 0 || keepalive_maxreq > 0))
  213.     {
  214. fd_puts("Connection: Keep-Alive", fd);
  215. if (keepalive_timeout > 0)
  216.     fd_printf(fd, ", timeout=%d", keepalive_timeout);
  217. if (keepalive_maxreq > 0)
  218.     fd_printf(fd, ", maxreq=%d", keepalive_maxreq);
  219. fd_putc('n', fd);
  220.     }
  221.     
  222.     return type;
  223. }    
  224. int http_unauthorized(struct connectioninfo *cip, const char *realm)
  225. {
  226.     int result;
  227.     int fd = cip->fd;
  228.     struct httpinfo *hip = cip->hip;
  229.     
  230.     if (debug > 1)
  231. fprintf(stderr, "      Sent UNAUTHORIZED messagen");
  232.     result = 401;
  233.     if (hip->mip != NULL)
  234.     {
  235. http_sendheaders(fd, cip, result, NULL);
  236. fd_printf(fd, "WWW-Authenticate: Basic realm="%s"n", realm);
  237. fd_putc('n', fd);
  238.     }
  239.     if(strcasecmp(hip->method, "HEAD") == 0)
  240.        return result;
  241.     html_sysheader(fd, "H2", "Unauthorized");
  242.     fd_printf(fd, "Please send authorization codes for realm "%s".n",
  243.       realm);
  244.     html_sysfooter(fd);
  245.     
  246.     return result;
  247. }
  248. int http_forbidden(struct connectioninfo *cip)
  249. {
  250.     int result;
  251.     int fd = cip->fd;
  252.     struct httpinfo *hip = cip->hip;
  253.     
  254.     if (debug > 1)
  255. fprintf(stderr, "      Sent FORBIDDEN messagen");
  256.     result = 403;
  257.     if (hip->mip != NULL)
  258.     {
  259. http_sendheaders(fd, cip, result, NULL);
  260. fd_putc('n', fd);
  261.     }
  262.     
  263.     if(strcasecmp(hip->method, "HEAD") == 0)
  264.        return result;
  265.     html_sysheader(fd, "H2", "Access Denied");
  266.     fd_printf(fd, "Your request to ");
  267.     if (hip->orig_url == NULL)
  268. fd_printf(fd, "[null]");
  269.     else
  270. html_href(fd, hip->orig_url, hip->orig_url);
  271.     
  272.     fd_printf(fd, " was denied.n");
  273.     html_sysfooter(fd);
  274.     
  275.     return result;
  276. }
  277. int http_authenticate(struct connectioninfo *cip,
  278.       const char *path,
  279.       const char *realm,
  280.       char *request)
  281. {
  282.     if (!access_auth(cip->hip, path))
  283. return http_unauthorized(cip, realm);
  284.     return 0;
  285. }
  286. int http_access(struct connectioninfo *cip,
  287. const char *auth_path,
  288. char *request)
  289. {
  290.     if (!access_check(auth_path, cip))
  291. return error_access(cip);
  292.     return 0;
  293. }
  294. /*
  295.  *  Extract the request (the part after the first '?') in URL and add
  296.  *  it to the beginning of *REQUESTP.
  297.  */
  298. void
  299. http_extract_request(char *url, char **requestp)
  300. {
  301.     char *cp;
  302.     if (url == NULL)
  303. return;
  304.     
  305.     cp = strchr(url, '?');
  306.     if (cp != NULL)
  307.     {
  308. *cp++ = '';
  309. if (requestp == NULL)
  310.     return;
  311. if (!*requestp)
  312. {
  313.     *requestp = s_strdup(cp);
  314. }
  315. else
  316. {
  317.     char *oldrequest = *requestp;
  318.     size_t oldlen = strlen(oldrequest);
  319.     size_t addlen = strlen(cp);
  320.     *requestp = s_malloc(oldlen + 1 + addlen + 1);
  321.     memcpy(*requestp, oldrequest, oldlen);
  322.     *(*requestp + oldlen) = '?';
  323.     memcpy(*requestp + oldlen + 1, cp, addlen);
  324.     *(*requestp + oldlen + 1 + addlen) = '';
  325.     s_free(oldrequest);
  326. }
  327.     }
  328. }
  329. int http_get_request(struct connectioninfo *cip,
  330.      int *keepalive)
  331. {
  332.     char buf[2048], *lastcp, *url, *req, *rawurl;
  333.     struct httpinfo *hip = NULL;
  334.     int result = -1;
  335.     int headerbytes;
  336.     ucentry_t *ucp;
  337.     urlinfo_t *uip;
  338.     char *realm;
  339.     int len;
  340.     char *mvsxy,*svpath;
  341.     char *slash = "/";
  342.     
  343.     ucp = NULL;
  344.     uip = NULL;
  345.     
  346.     if (debug > 1)
  347. fprintf(stderr, "http_get_request(), fd=%dn", cip->fd);
  348.     
  349.     if ((req = fd_gets(NULL, maxurlsize, cip->fd)) == NULL)
  350.     {
  351. if (debug > 2)
  352.     fprintf(stderr, "t->Returning failed (fd=%d)n", cip->fd);
  353. return -1;
  354.     }
  355.     
  356.     hip = s_malloc(sizeof(struct httpinfo));
  357.     headerbytes=strlen(req);
  358.    
  359.     hip->svsname = NULL;
  360.     hip->method = strtok_r(req, " tnr", &lastcp);
  361.     if (hip->method == NULL)
  362.     {
  363. s_free(hip);
  364. return -1;
  365.     }
  366.     
  367.     url = strtok_r(NULL, " tnr", &lastcp);
  368.     if (url)
  369. hip->version = s_strdup(strtok_r(NULL, " tnr", &lastcp));
  370.     if (url == NULL)
  371.     {
  372. s_free(hip->method);
  373. s_free(hip);
  374. return -1;
  375.     }
  376. /* Clear setup.... */
  377.     hip->prelen=0;
  378. /* Added for Multi-Virtual-Server RK */
  379. /* Some how ugly, might be a nicer way to code this, but it works ! */
  380. /* Maybe one should create differnt global accept code, depending on the
  381. ** mode, we are running. This may look nicer, but more code to maintain. 
  382. ** 23.11.97 rk@netuse.de
  383. */
  384.     if ( rkmultimode != 0 ) /* We are in MULTIMODE */
  385. {
  386.     if ( debug >6 )
  387. fprintf(stderr,"MVS-RK: Adding prefixn");
  388.     len = strlen(url)+10;
  389.     mvsxy=s_malloc(len);
  390.     if ( url[0]=='/' )
  391. s_sprintf(mvsxy, len, "/%08lx%s", cip->server->sin.sin_addr.s_addr, url);
  392.     else
  393. s_sprintf(mvsxy, len, "/%08lx/%s", cip->server->sin.sin_addr.s_addr, url);
  394.     
  395.     /* lenght of prefix is 8 + 1 (+1) (still fix !) */
  396.             hip->prelen=9;
  397.     if ( debug >6 )
  398. fprintf(stderr,"MVS-RK: calling freen");
  399.     
  400.     url[strlen(mvsxy)]=0x00; /* wg.logfile */
  401.     s_strcpy(url,strlen(url)+11, mvsxy);
  402.     
  403.     s_free(mvsxy);
  404.     if ( debug >6 )
  405. fprintf(stderr,"MVS-RK: prefix donen");
  406. }
  407.     if ( softvirtserver!=0 && hip->version != NULL )
  408.     { /* working here.......... 1.1 */
  409.       if ( hip->prelen != 0 ) len=hip->prelen+1;
  410.       else len=0;
  411.       if ( debug >6 ) fprintf(stderr,"SVS-http: %s (%d)n",url,len);
  412.       if (    strncasecmp(url+len,"http://",7)== 0 
  413. /* Disabled, since common broser send a HTTP/1.0 and SVS-Information :-( */
  414.         /*   && strcasecmp(hip->version,"HTTP/1.1")==0  */
  415.    && strlen(url+len) > 7 )
  416.       { /* we got CMD http://host/path HTTP/1.x */
  417. rawurl=url;
  418. url=url+len+7;
  419. svpath=strchr(url,'/'); /* add : */
  420.         if ( svpath != NULL ) len=svpath-url;
  421. else                { len=strlen(url); svpath=slash; }
  422.         hip->svsname=s_strndup(url,len);
  423. str_to_lower(hip->svsname);
  424. /* check for :port and DROP !! */
  425. mvsxy=strchr(hip->svsname,':');
  426. if ( mvsxy != NULL ) *mvsxy=0x00;
  427. if ( debug >6 ) fprintf(stderr,"SVS-Host: %s (%d) n",hip->svsname,len);
  428. len = strlen(rawurl);
  429. mvsxy=s_malloc(len);
  430.         if ( rkmultimode )
  431.            s_sprintf(mvsxy, len, "%.9s/%s%s",rawurl,hip->svsname,svpath);
  432.         else
  433.             s_sprintf(mvsxy, len, "/%s%s",hip->svsname,svpath);
  434.         
  435. hip->prelen=hip->prelen+strlen(hip->svsname)+1;
  436.         if (debug > 6 ) fprintf(stderr, "SVS1: NEWURL: %s (%d)n",mvsxy,hip->prelen);
  437. hip->svstype=SVSINGET;
  438.         s_strcpy(url,strlen(mvsxy)+1, mvsxy);
  439.  
  440.         url[strlen(mvsxy)]=0x00; /* wg.logfile */
  441.         s_free(mvsxy);
  442.       } /* we have softvirtserver set, but no information about that was sent.... */
  443.       else
  444.       if ( debug >6 ) fprintf(stderr,"SVS-Host: -not-1.1-n");
  445.     }
  446.     /* END RK */
  447.     
  448.     if (debug > 4)
  449. fprintf(stderr, "Method = %s, URL = %s PL = %dn",
  450. hip->method, url ? url : "<null>", hip->prelen);
  451.     
  452.     cip->hip = hip;
  453. #if 1
  454.     hip->orig_url = s_strdup(url);
  455.     hip->orig_request = NULL;
  456.     url_unquote(url, 0);
  457. #else
  458.     http_extract_request(url, &hip->request);
  459.     hip->orig_url = s_strdup(url);
  460.     hip->orig_request = s_strdup(hip->request);
  461.     url_unquote(url, 0);
  462.     if (debug > 2)
  463. fprintf(stderr, "url=%snorig_url=%snreq=%snorig_req=%sn",
  464. url ? url : "<null>",
  465. hip->orig_url ? hip->orig_url : "<null>",
  466. hip->request ? hip->request : "<null>",
  467. hip->orig_request ? hip->orig_request : "<null>");
  468. #endif
  469.     
  470.     if (hip->version != NULL)
  471.     {
  472. hip->mip = mime_getheaders(cip->fd);
  473. if (hip->mip == NULL)
  474. {
  475.     error_bad_request(cip, "Invalid MIME headers");
  476.     goto End;
  477. }
  478. hip->mip->headerbytes=hip->mip->headerbytes+headerbytes;
  479. if (keepalive && hip->mip &&
  480.     (hip->mip->connection_flags & MCF_KEEPALIVE))
  481.     *keepalive = 1;
  482. /* Get the client-supplied authentication information */
  483. hip->aip = auth_get(hip);
  484.     }
  485. /* softvirtserver added here rk */
  486.     if ( softvirtserver!=0 && hip->svsname == NULL ) 
  487.     {
  488.    
  489.        hip->svsname=s_strdup(mime_getheader(hip->mip,"HOST",1));
  490.        if ( hip->svsname == NULL )
  491.          {
  492.    if ( rkmultimode )
  493.    {
  494.      hip->svsname=s_strdup(dns_lookup_servername(cip->server));
  495.      if ( hip->svsname == NULL ) 
  496. hip->svsname=s_strdup(server_host);
  497.    }
  498.    else
  499.      hip->svsname=s_strdup(server_host);
  500.  }
  501.   str_to_lower(hip->svsname);
  502.           /* check for :port and DROP !! */
  503.           mvsxy=strchr(hip->svsname,':');
  504.           if ( mvsxy != NULL ) *mvsxy=0x00;
  505.           if (debug > 6 ) fprintf(stderr, "SVS: Found: %sn",hip->svsname);
  506.           len = strlen(url)+strlen(hip->svsname)+2;
  507.   mvsxy=s_malloc(len);
  508.           if ( rkmultimode )
  509.     s_sprintf(mvsxy, len, "%.9s/%s/%s",url,hip->svsname,url+10);
  510.   else
  511.             if ( url[0]=='/' )
  512.       s_sprintf(mvsxy, len, "/%s%s",hip->svsname,url);
  513.     else
  514.       s_sprintf(mvsxy, len, "/%s/%s",hip->svsname,url);
  515.   hip->prelen=hip->prelen+strlen(hip->svsname)+1;
  516. /*
  517. ** if (debug > 6 ) fprintf(stderr, "SVS2: NEWURL: %s (%d)n",mvsxy,hip->prelen);
  518. */
  519.           hip->svstype=SVSMIMEHOST;
  520.           s_strcpy(url,strlen(mvsxy)+1, mvsxy);
  521.           url[strlen(mvsxy)]=0x00; /* wg.logfile */
  522.           s_free(mvsxy);
  523.       
  524.     } /* end of softvirtserver! */
  525.     if (strcasecmp(hip->method, "PING") == 0)
  526.     {
  527. if (hip->mip)
  528. {
  529.     http_sendheaders(cip->fd, cip, 200, NULL);
  530.     result = 200;
  531.     fd_putc('n', cip->fd);
  532. }
  533. fd_puts("PONGn", cip->fd);
  534. goto End;
  535.     }
  536.     
  537.     if (hip->mip && (hip->mip->pragma_flags & MPF_NOCACHE))
  538. ucp = urlcache_lookup(url, UCF_ALL+UCF_RELOAD);
  539.     else
  540. ucp = urlcache_lookup(url, UCF_ALL);
  541.       
  542.     if (ucp == NULL)
  543. goto End;
  544. /*  XXXX url is now split into url and request part XXXX */
  545.     
  546.     uip = ucp->uip;
  547.     if (uip == NULL)
  548.     {
  549. urlcache_release(ucp);
  550. goto End;
  551.     }
  552.     hip->url = s_strdup(uip->rewrite.url);
  553.     
  554.     if (uip->rewrite.request)
  555.     {
  556. if (hip->request)
  557.     s_free(hip->request);
  558. hip->request = s_strdup(uip->rewrite.request);
  559.     }
  560.     
  561.     if (uip->redirect.url)
  562.     {
  563. result = http_redirect(cip,
  564.        uip->redirect.url,
  565.        uip->redirect.request,
  566.           hip->request,
  567.        302);
  568. goto End;
  569.     }
  570.     
  571.     if (uip->predirect.url)
  572.     {
  573. result = http_redirect(cip,
  574.        uip->predirect.url,
  575.        uip->predirect.request,
  576.           hip->request,
  577.        301);
  578. goto End;
  579.     }
  580.     
  581.     if (uip->access.path)
  582.     {
  583. result = http_access(cip, uip->access.path, hip->request);
  584. if (result != 0)
  585.     goto End;
  586.     }
  587.     
  588.     /* ADDED by RK */
  589.     if (debug > 4)
  590. fprintf(stderr,"Check write ACCESSn");
  591.     
  592.     if (write_needs_auth && 
  593. (strcasecmp(hip->method, "PUT")==0 ||
  594.  strcasecmp(hip->method, "DELETE")==0))
  595.     {
  596. if (debug > 4)
  597.     fprintf(stderr,"We have a write CMD...n");
  598.       if (write_getauthenticate(url, buf, sizeof(buf))) 
  599.       {
  600.           uip->auth.source=s_strdup(buf);
  601.           realm = uip->auth.source;
  602.           if (realm)
  603.           {   
  604.               while (*realm && !s_isspace(*realm))
  605.   ++realm;
  606.               if (s_isspace(*realm))
  607.   *realm++ = '';
  608.               while (*realm && s_isspace(*realm))
  609.   ++realm;
  610.           }
  611.           uip->auth.realm = realm;
  612.           uip->flags |= UCF_AUTH;
  613.   if ( debug > 4 )
  614.       fprintf(stderr,"Using auth for...%sn",uip->auth.source);
  615.       }
  616.       else
  617.       {
  618.           uip->auth.source=NULL;
  619.   result = -403;
  620.   goto End;
  621.       }
  622.     } /* end of write_needs_auth */
  623.     if (uip->auth.source)
  624.     {
  625. result = http_authenticate(cip,
  626.    uip->auth.source,
  627.    uip->auth.realm,
  628.    hip->request);
  629. if (result != 0)
  630.     goto End;
  631.     }
  632.     if (uip->handler)
  633. result = phttpd_call(uip->handler, cip);
  634.     if (debug > 3)
  635. fprintf(stderr, "MAIN-RETURN: Result=%dn", result);
  636.     
  637.   End:
  638.     if (result < 0)
  639. switch (result)
  640. {
  641.   case -1:
  642.     result = error_not_found(cip);
  643.     break;
  644.   case -403:
  645.     result = error_access(cip);
  646.     break;
  647.     
  648.   case -405:
  649.     result = error_method_denied(cip);
  650.     break;
  651.     
  652.   default:
  653.     result = error_bad_request(cip, hip->method);
  654.     syslog(LOG_NOTICE, "bad HTTP request (#%d) method: %s",
  655.    cip->request_no,
  656.    hip->method);
  657. }
  658.     if (ucp)
  659. urlcache_release(ucp);
  660.     
  661.     if (hip->length == 0)
  662. *keepalive = 0;
  663.     
  664.     if (debug > 1)
  665. fprintf(stderr, "http_get_request(), fd=%d, returning %dn",
  666. cip->fd, result);
  667.     
  668.     return result;
  669. }
  670. void http_freeinfo(struct httpinfo *hip)
  671. {
  672.     if (hip == NULL)
  673. return;
  674.     
  675.     s_free(hip->method);
  676.     s_free(hip->url);
  677.     s_free(hip->request);
  678.     s_free(hip->orig_url);
  679.     s_free(hip->orig_request);
  680.     s_free(hip->version);
  681.     s_free(hip->svsname);
  682.     
  683.     if (hip->mip) mime_freeheaders(hip->mip);
  684.     auth_free(hip->aip);
  685.     
  686.     s_free(hip);
  687. }
  688. int http_error(struct connectioninfo *cip,
  689.        int code,
  690.        const char *format,
  691.        ...)
  692. {
  693.     va_list ap;
  694.     char *type, buf[256];
  695.     struct httpinfo *hip = cip->hip;
  696.     
  697.     if (hip->mip != NULL)
  698.     {
  699. type = http_sendheaders(cip->fd, cip, code, NULL);
  700. fd_puts("Content-Type: text/htmln", cip->fd);
  701. fd_putc('n', cip->fd);
  702.     }
  703.     else
  704.     {
  705.         int blen;
  706.       
  707.         blen = s_strcpy(buf, sizeof(buf), "Error Code #");
  708. s_sprintf(buf+blen, sizeof(buf)-blen, "%d", code);
  709. type = buf;
  710.     }
  711.     if (strcasecmp(hip->method, "HEAD") == 0)
  712. return code;
  713.     
  714.     va_start(ap, format);
  715.     
  716.     html_error(cip->fd, type, format, ap);
  717.     
  718.     va_end(ap);
  719.     hip->length = fd_written(cip->fd);
  720.     
  721.     return code;
  722. }
  723. void http_sendlang(int fd, const char *url)
  724. {
  725.     int i;
  726.     char **pair;
  727.     if(content_language_table == NULL)
  728.         return;
  729.     for(i = 0; i < content_language_table->length; ++i)
  730.     {
  731.         pair = content_language_table->value[i];
  732. if(strmatch(url, pair[0]))
  733. {
  734.     fd_puts("Content-Language: ", fd);
  735.     fd_puts(pair[1], fd);
  736.     fd_putc('n', fd);
  737.     break;
  738. }
  739.     }
  740. }
  741. /* Send a redirect pointer */
  742. int http_redirect(struct connectioninfo *cip,
  743.   const char *url,
  744.   const char *request,
  745.   const char *orig_req,
  746.   int code)
  747. {
  748.     char buf1[2048], buf2[2048], buf3[2048];
  749.     int result, len;
  750.     int fd = cip->fd;
  751.     struct httpinfo *hip = cip->hip;
  752.     url = url_quote(url, buf1, sizeof(buf1), "?", 0);
  753.     if (url == NULL)
  754. return -1;
  755.     
  756.     if (request)
  757.     {
  758. request = url_quote(request, buf2, sizeof(buf2), """, 1);
  759. if (request == NULL)
  760.     return -1;
  761.     }
  762.     if (orig_req)
  763.     {
  764. orig_req = url_quote(orig_req, buf3, sizeof(buf3), """, 1);
  765. if (orig_req == NULL)
  766.     return -1;
  767.     }
  768.     
  769.     if (debug > 1)
  770. fprintf(stderr, "      Sent URL REDIRECT (%s -> %s)n",
  771. hip->url, url);
  772.     result = code;
  773.     
  774.     if (hip->mip != NULL)
  775.     {
  776. http_sendheaders(fd, cip, result, NULL);
  777. fd_printf(fd, "Location: %s%s%s%sn",
  778.   url,
  779.   (orig_req || request) ? "?" : "",
  780.   orig_req ? orig_req : "",
  781.   request ? request : "");
  782.   
  783. http_sendlastmodified(fd, cip->cn_time);
  784. fd_puts("Content-Type: text/htmlnn", fd);
  785.     }
  786.     
  787.     if (strcasecmp(hip->method, "HEAD") == 0)
  788. return result;
  789.     
  790.     len = fd_written(fd);
  791.     html_sysheader(fd, "H2", "Document moved");
  792.     
  793.     fd_puts("The document has moved to this URL:<P>n", fd);
  794.     fd_puts("<UL>n", fd);
  795.     
  796.     fd_printf(fd, "<B><A HREF="%s%s%s%s">%s%s%s%s</A></B>.n",
  797.       url,
  798.       (orig_req || request) ? "?" : "",
  799.       orig_req ? orig_req : "",
  800.       request ? request : "",
  801.       url,
  802.       (orig_req || request) ? "?" : "",
  803.       orig_req ? orig_req : "",
  804.       request ? request : "");
  805.     
  806.     fd_puts("</UL>n", fd);
  807.     
  808.     html_sysfooter(fd);
  809.     if (logheadervolume)
  810. hip->length = fd_written(fd);
  811.     else
  812. hip->length = fd_written(fd) - len; 
  813.     return result;
  814. }
  815. /* Send a 'Not Modified' message */
  816. int http_not_modified(struct connectioninfo *cip)
  817. {
  818.     int result;
  819.     int fd = cip->fd;
  820.     struct httpinfo *hip = cip->hip;
  821.     
  822.     if (debug > 1)
  823. fprintf(stderr, "      Sent NOT MODIFIED messagen");
  824.     result = 304;
  825.     if (hip->mip != NULL)
  826.     {
  827. http_sendheaders(fd, cip, result, NULL);
  828. fd_putc('n', fd);
  829.     }
  830.     hip->length = fd_written(fd);
  831.     return result;
  832. }
  833. /* Send a 'Precondition Failed' message */
  834. int http_precondition_failed(struct connectioninfo *cip)
  835. {
  836.     int result;
  837.     int fd = cip->fd;
  838.     struct httpinfo *hip = cip->hip;
  839.     
  840.     if (debug > 1)
  841. fprintf(stderr, "      Sent PRECONDITION FAILED messagen");
  842.     result = 412;
  843.     if (hip->mip != NULL)
  844.     {
  845. http_sendheaders(fd, cip, result, NULL);
  846. fd_putc('n', fd);
  847.     }
  848.     
  849.     if(strcasecmp(hip->method, "HEAD") == 0)
  850.        return result;
  851.     html_sysheader(fd, "H2", "Precondition Failed");
  852.     fd_printf(fd, "The entity which lives at ");
  853.     if (hip->orig_url == NULL)
  854. fd_printf(fd, "[null]");
  855.     else
  856. html_href(fd, hip->orig_url, hip->orig_url);
  857.     
  858.     fd_printf(fd, " was changed.n");
  859.     html_sysfooter(fd);
  860.     hip->length = fd_written(fd);
  861.     
  862.     return result;
  863. }
  864. static const char *const weekday[] =
  865. {
  866.     "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  867. };
  868. static const char *const month[] =
  869. {
  870.     "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  871.     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  872. };
  873. char *http_time_r(const time_t *btp, char *buf, int bufsize)
  874. {
  875.     struct tm tpb;
  876.     
  877.     if (bufsize < 31)
  878. return NULL;
  879.     
  880.     if (gmtime_r(btp, &tpb) == NULL)
  881. return NULL;
  882.     s_sprintf(buf, bufsize, "%s, %02d %s %d %02d:%02d:%02d GMTn",
  883.     weekday[tpb.tm_wday],
  884.     tpb.tm_mday,
  885.     month[tpb.tm_mon],
  886.     tpb.tm_year + 1900,
  887.     tpb.tm_hour,
  888.     tpb.tm_min,
  889.     tpb.tm_sec);
  890.     return buf;
  891. }