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

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