[BACK]Return to bozohttpd.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / httpd

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/libexec/httpd/bozohttpd.c between version 1.3 and 1.3.2.3

version 1.3, 2007/10/17 18:48:00 version 1.3.2.3, 2008/03/23 00:41:24
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      bozohttpd.c,v 1.3.2.2 2007/11/06 23:12:02 matt Exp      */
   
 /*      $eterna: bozohttpd.c,v 1.137 2006/05/17 08:37:36 mrg Exp $      */  /*      $eterna: bozohttpd.c,v 1.142 2008/03/03 03:36:11 mrg Exp $      */
   
 /*  /*
  * Copyright (c) 1997-2006 Matthew R. Green   * Copyright (c) 1997-2008 Matthew R. Green
  * All rights reserved.   * All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
Line 96 
Line 96 
  *   *
  *      - 14.5/14.16/14.35: we don't do ranges.  from section 14.35.2   *      - 14.5/14.16/14.35: we don't do ranges.  from section 14.35.2
  *        `A server MAY ignore the Range header'.  but it might be nice.   *        `A server MAY ignore the Range header'.  but it might be nice.
    *        since 20080301 we support simple range headers.
  *   *
  *      - 14.9: we aren't a cache.   *      - 14.9: we aren't a cache.
  *   *
Line 110 
Line 111 
 #define INDEX_HTML              "index.html"  #define INDEX_HTML              "index.html"
 #endif  #endif
 #ifndef SERVER_SOFTWARE  #ifndef SERVER_SOFTWARE
 #define SERVER_SOFTWARE         "bozohttpd/20060517"  #define SERVER_SOFTWARE         "bozohttpd/20080303"
 #endif  #endif
 #ifndef DIRECT_ACCESS_FILE  #ifndef DIRECT_ACCESS_FILE
 #define DIRECT_ACCESS_FILE      ".bzdirect"  #define DIRECT_ACCESS_FILE      ".bzdirect"
Line 374  main(int argc, char **argv)
Line 375  main(int argc, char **argv)
                         break;                          break;
 #else /* NO_DAEMON_MODE */  #else /* NO_DAEMON_MODE */
                 case 'b':                  case 'b':
                   case 'e':
                   case 'f':
                 case 'i':                  case 'i':
                 case 'I':                  case 'I':
                         error(1, "Daemon mode is not enabled");                          error(1, "Daemon mode is not enabled");
Line 425  main(int argc, char **argv)
Line 428  main(int argc, char **argv)
                         uflag = 1;                          uflag = 1;
                         break;                          break;
 #else  #else
                 case 'u':  
                 case 'p':                  case 'p':
                   case 't':
                   case 'u':
                         error(1, "User support is not enabled");                          error(1, "User support is not enabled");
                         /* NOTREACHED */                          /* NOTREACHED */
 #endif /* NO_USER_SUPPORT */  #endif /* NO_USER_SUPPORT */
Line 563  parse_request(char *in, char **method, c
Line 567  parse_request(char *in, char **method, c
         *method = *url = *proto = NULL;         /* set them up */          *method = *url = *proto = NULL;         /* set them up */
   
         len = (ssize_t)strlen(in);          len = (ssize_t)strlen(in);
         val = strnsep(&in, " \t\n\r", &len);          val = bozostrnsep(&in, " \t\n\r", &len);
         if (len < 1 || val == NULL)          if (len < 1 || val == NULL)
                 return;                  return;
         *method = val;          *method = val;
         while (*in == ' ' || *in == '\t')          while (*in == ' ' || *in == '\t')
                 in++;                  in++;
         val = strnsep(&in, " \t\n\r", &len);          val = bozostrnsep(&in, " \t\n\r", &len);
         if (len < 1) {          if (len < 1) {
                 if (len == 0)                  if (len == 0)
                         *url = val;                          *url = val;
Line 625  read_request(void)
Line 629  read_request(void)
         memset(request, 0, sizeof *request);          memset(request, 0, sizeof *request);
         request->hr_allow = request->hr_host = NULL;          request->hr_allow = request->hr_host = NULL;
         request->hr_content_type = request->hr_content_length = NULL;          request->hr_content_type = request->hr_content_length = NULL;
           request->hr_range = NULL;
           request->hr_last_byte_pos = -1;
   
         slen = sizeof(ss);          slen = sizeof(ss);
         if (getpeername(0, (struct sockaddr *)&ss, &slen) < 0)          if (getpeername(0, (struct sockaddr *)&ss, &slen) < 0)
Line 668  read_request(void)
Line 674  read_request(void)
         sigaction(SIGALRM, &sa, NULL);  /* XXX */          sigaction(SIGALRM, &sa, NULL);  /* XXX */
   
         alarm(MAX_WAIT_TIME);          alarm(MAX_WAIT_TIME);
         while ((str = dgetln(STDIN_FILENO, &len, bozoread)) != NULL) {          while ((str = bozodgetln(STDIN_FILENO, &len, bozoread)) != NULL) {
                 alarm(0);                  alarm(0);
                 if (alarmhit)                  if (alarmhit)
                         http_error(408, NULL, "request timed out");                          http_error(408, NULL, "request timed out");
Line 709  read_request(void)
Line 715  read_request(void)
                         if (*str == '\0')                          if (*str == '\0')
                                 break;                                  break;
   
                         val = strnsep(&str, ":", &len);                          val = bozostrnsep(&str, ":", &len);
                         debug((DEBUG_EXPLODING,                          debug((DEBUG_EXPLODING,
                             "read_req2: after strnsep: str ``%s'' val ``%s''",                              "read_req2: after bozostrnsep: str ``%s'' val ``%s''",
                             str, val));                              str, val));
                         if (val == NULL || len == -1)                          if (val == NULL || len == -1)
                                 http_error(404, request, "no header");                                  http_error(404, request, "no header");
                         while (*str == ' ' || *str == '\t')                          while (*str == ' ' || *str == '\t')
                                 len--, str++;                                  len--, str++;
                           while (*val == ' ' || *val == '\t')
                                   val++;
   
                         if (auth_check_headers(request, val, str, len))                          if (auth_check_headers(request, val, str, len))
                                 goto next_header;                                  goto next_header;
Line 735  read_request(void)
Line 743  read_request(void)
                         else if (strcasecmp(hdr->h_header, "referrer") == 0 ||                          else if (strcasecmp(hdr->h_header, "referrer") == 0 ||
                                  strcasecmp(hdr->h_header, "referer") == 0)                                   strcasecmp(hdr->h_header, "referer") == 0)
                                 request->hr_referrer = hdr->h_value;                                  request->hr_referrer = hdr->h_value;
                           else if (strcasecmp(hdr->h_header, "range") == 0)
                                   request->hr_range = hdr->h_value;
   
                         debug((DEBUG_FAT, "adding header %s: %s",                          debug((DEBUG_FAT, "adding header %s: %s",
                             hdr->h_header, hdr->h_value));                              hdr->h_header, hdr->h_value));
Line 755  next_header:
Line 765  next_header:
         if (request->hr_proto == http_11 && request->hr_host == NULL)          if (request->hr_proto == http_11 && request->hr_host == NULL)
                 http_error(400, request, "missing Host header");                  http_error(400, request, "missing Host header");
   
           if (request->hr_range != NULL) {
                   debug((DEBUG_FAT, "hr_range: %s", request->hr_range));
                   /* support only simple ranges %d- and %d-%d */
                   if (strchr(request->hr_range, ',') == NULL) {
                           const char *rstart, *dash;
   
                           rstart = strchr(request->hr_range, '=');
                           if (rstart != NULL) {
                                   rstart++;
                                   dash = strchr(rstart, '-');
                                   if (dash != NULL && dash != rstart) {
                                           dash++;
                                           request->hr_have_range = 1;
                                           request->hr_first_byte_pos =
                                               strtoll(rstart, NULL, 10);
                                           if (request->hr_first_byte_pos < 0)
                                                   request->hr_first_byte_pos = 0;
                                           if (*dash != '\0') {
                                                   request->hr_last_byte_pos =
                                                       strtoll(dash, NULL, 10);
                                                   if (request->hr_last_byte_pos < 0)
                                                           request->hr_last_byte_pos = -1;
                                           }
                                   }
                           }
                   }
           }
   
         debug((DEBUG_FAT, "read_request returns url %s in request", request->hr_url));          debug((DEBUG_FAT, "read_request returns url %s in request", request->hr_url));
         return (request);          return (request);
 }  }
Line 847  process_request(http_req *request)
Line 885  process_request(http_req *request)
                 /* NOTREACHED */                  /* NOTREACHED */
         /* XXX RFC1945 10.9 If-Modified-Since (http code 304) */          /* XXX RFC1945 10.9 If-Modified-Since (http code 304) */
   
         bozoprintf("%s 200 OK\r\n", request->hr_proto);          /* validate requested range */
           if (request->hr_last_byte_pos == -1 ||
               request->hr_last_byte_pos >= sb.st_size)
                   request->hr_last_byte_pos = sb.st_size - 1;
           if (request->hr_have_range &&
               request->hr_first_byte_pos > request->hr_last_byte_pos) {
                   request->hr_have_range = 0;     /* punt */
                   request->hr_first_byte_pos = 0;
                   request->hr_last_byte_pos = sb.st_size - 1;
           }
           debug((DEBUG_FAT, "have_range %d first_pos %qd last_pos %qd",
               request->hr_have_range,
               request->hr_first_byte_pos, request->hr_last_byte_pos));
           if (request->hr_have_range)
                   bozoprintf("%s 206 Partial Content\r\n", request->hr_proto);
           else
                   bozoprintf("%s 200 OK\r\n", request->hr_proto);
   
         if (request->hr_proto != http_09) {          if (request->hr_proto != http_09) {
                 type = content_type(request, file);                  type = content_type(request, file);
Line 861  process_request(http_req *request)
Line 915  process_request(http_req *request)
         if (request->hr_method != HTTP_HEAD) {          if (request->hr_method != HTTP_HEAD) {
                 char *addr;                  char *addr;
                 void *oaddr;                  void *oaddr;
                 off_t sz = sb.st_size;                  size_t mappedsz;
                   size_t sz;
   
                 oaddr = addr = mmap(0, (size_t)sz, PROT_READ,                  sz = mappedsz = request->hr_last_byte_pos - request->hr_first_byte_pos + 1;
                     MAP_SHARED, fd, 0);                  oaddr = addr = mmap(0, mappedsz, PROT_READ,
                       MAP_SHARED, fd, request->hr_first_byte_pos);
                 if (addr == (char *)-1)                  if (addr == (char *)-1)
                         error(1, "mmap failed: %s", strerror(errno));                          error(1, "mmap failed: %s", strerror(errno));
   
Line 874  process_request(http_req *request)
Line 930  process_request(http_req *request)
                 while (sz > WRSZ) {                  while (sz > WRSZ) {
                         if (bozowrite(STDOUT_FILENO, addr, WRSZ) != WRSZ)                          if (bozowrite(STDOUT_FILENO, addr, WRSZ) != WRSZ)
                                 error(1, "write failed: %s", strerror(errno));                                  error(1, "write failed: %s", strerror(errno));
                           debug((DEBUG_OBESE, "wrote %d bytes", WRSZ));
                         sz -= WRSZ;                          sz -= WRSZ;
                         addr += WRSZ;                          addr += WRSZ;
                 }                  }
                 if (sz && bozowrite(STDOUT_FILENO, addr, sz) != sz)                  if (sz && bozowrite(STDOUT_FILENO, addr, sz) != sz)
                         error(1, "final write failed: %s", strerror(errno));                          error(1, "final write failed: %s", strerror(errno));
                 if (munmap(oaddr, (size_t)sb.st_size) < 0)                  debug((DEBUG_OBESE, "wrote %d bytes", (int)sz));
                   if (munmap(oaddr, mappedsz) < 0)
                         warning("munmap failed");                          warning("munmap failed");
         }          }
         /* If SSL enabled cleanup SSL structure. */          /* If SSL enabled cleanup SSL structure. */
Line 1260  void
Line 1318  void
 print_header(http_req *request, struct stat *sbp, const char *type,  print_header(http_req *request, struct stat *sbp, const char *type,
              const char *encoding)               const char *encoding)
 {  {
           off_t len;
   
         bozoprintf("Date: %s\r\n", http_date());          bozoprintf("Date: %s\r\n", http_date());
         bozoprintf("Server: %s\r\n", server_software);          bozoprintf("Server: %s\r\n", server_software);
           bozoprintf("Accept-Ranges: bytes\r\n");
         if (sbp) {          if (sbp) {
                 char filedate[40];                  char filedate[40];
                 struct  tm *tm;                  struct  tm *tm;
Line 1275  print_header(http_req *request, struct s
Line 1336  print_header(http_req *request, struct s
                 bozoprintf("Content-Type: %s\r\n", type);                  bozoprintf("Content-Type: %s\r\n", type);
         if (encoding && *encoding)          if (encoding && *encoding)
                 bozoprintf("Content-Encoding: %s\r\n", encoding);                  bozoprintf("Content-Encoding: %s\r\n", encoding);
         if (sbp)          if (sbp) {
                 bozoprintf("Content-Length: %qd\r\n", (long long)sbp->st_size);                  if (request->hr_have_range) {
                           len = request->hr_last_byte_pos - request->hr_first_byte_pos +1;
                           bozoprintf("Content-Range: bytes %qd-%qd/%qd\r\n",
                               (long long) request->hr_first_byte_pos,
                               (long long) request->hr_last_byte_pos,
                               (long long) sbp->st_size);
                   }
                   else
                           len = sbp->st_size;
                   bozoprintf("Content-Length: %qd\r\n", (long long)len);
           }
         if (request && request->hr_proto == http_11)          if (request && request->hr_proto == http_11)
                 bozoprintf("Connection: close\r\n");                  bozoprintf("Connection: close\r\n");
         bozoflush(stdout);          bozoflush(stdout);
Line 1334  escape_html(http_req *request)
Line 1405  escape_html(http_req *request)
         tmp[j] = 0;          tmp[j] = 0;
   
         /*          /*
          * XXX original "url" is a substring of an allocation, so we           * original "url" is a substring of an allocation, so we
          * can't touch it.  so, ignore it and replace the request.           * can't touch it.  so, ignore it and replace the request.
          */           */
         request->hr_url = tmp;          request->hr_url = tmp;
Line 1379  fix_url_percent(http_req *request)
Line 1450  fix_url_percent(http_req *request)
                 buf[2] = '\0';                  buf[2] = '\0';
                 s++;                  s++;
                 *t = (char)strtol(buf, NULL, 16);                  *t = (char)strtol(buf, NULL, 16);
                 debug((DEBUG_EXPLODING, "fu_%%: strtol put %c into *t", *t));                  debug((DEBUG_EXPLODING, "fu_%%: strtol put '%c' into *t", *t));
                 if (*t++ == '\0')                  if (*t++ == '\0')
                         http_error(400, request, "percent hack got a 0 back");                          http_error(400, request, "percent hack got a 0 back");
   
                 while (*s && *s != '%') {                  while (*s && *s != '%') {
                         if (s >= end)                          if (end && s >= end)
                                 break;                                  break;
                         *t++ = *s++;                          *t++ = *s++;
                 }                  }
Line 1553  http_error(int code, http_req *request, 
Line 1624  http_error(int code, http_req *request, 
                 error(1, "http_error() failed (short = %p, long = %p)",                  error(1, "http_error() failed (short = %p, long = %p)",
                     header, reason);                      header, reason);
   
         if (request && request->hr_serverport && strcmp(request->hr_serverport, "80") != 0)          if (request && request->hr_serverport &&
               strcmp(request->hr_serverport, "80") != 0)
                 snprintf(portbuf, sizeof(portbuf), ":%s", request->hr_serverport);                  snprintf(portbuf, sizeof(portbuf), ":%s", request->hr_serverport);
         else          else
                 portbuf[0] = '\0';                  portbuf[0] = '\0';
Line 1597  static struct errors_map {
Line 1669  static struct errors_map {
 } errors_map[] = {  } errors_map[] = {
         { 400,  "400 Bad Request",      "The request was not valid", },          { 400,  "400 Bad Request",      "The request was not valid", },
         { 401,  "401 Unauthorized",     "No authorization", },          { 401,  "401 Unauthorized",     "No authorization", },
         { 403,  "403 Forbidden",        "Access to this item has been denied", },          { 403,  "403 Forbidden",        "Access to this item has been denied",},
         { 404,  "404 Not Found",        "This item has not been found", },          { 404,  "404 Not Found",        "This item has not been found", },
         { 408,  "408 Request Timeout",  "This request took too long", },          { 408,  "408 Request Timeout",  "This request took too long", },
         { 417,  "417 Expectation Failed","Expectations not available", },          { 417,  "417 Expectation Failed","Expectations not available", },
Line 1638  http_errors_long(int code)
Line 1710  http_errors_long(int code)
  * correctly passed in.   * correctly passed in.
  */   */
 char *  char *
 strnsep(char **strp, const char *delim, ssize_t *lenp)  bozostrnsep(char **strp, const char *delim, ssize_t     *lenp)
 {  {
         char    *s;          char    *s;
         const   char *spanp;          const   char *spanp;
Line 1672  strnsep(char **strp, const char *delim, 
Line 1744  strnsep(char **strp, const char *delim, 
  * terminate the string.   * terminate the string.
  */   */
 char *  char *
 dgetln(int fd, ssize_t *lenp, ssize_t (*readfn)(int, void *, size_t))  bozodgetln(int fd, ssize_t *lenp, ssize_t (*readfn)(int, void *, size_t))
 {  {
         static  char *buffer;          static  char *buffer;
         static  ssize_t buflen = 0;          static  ssize_t buflen = 0;
Line 1698  dgetln(int fd, ssize_t *lenp, ssize_t (*
Line 1770  dgetln(int fd, ssize_t *lenp, ssize_t (*
          * the program           * the program
          */           */
         for (; readfn(fd, &c, 1) == 1; ) {          for (; readfn(fd, &c, 1) == 1; ) {
                 debug((DEBUG_EXPLODING, "dgetln read %c", c));                  debug((DEBUG_EXPLODING, "bozodgetln read %c", c));
   
                 if (len >= buflen - 1) {                  if (len >= buflen - 1) {
                         buflen *= 2;                          buflen *= 2;
                         debug((DEBUG_EXPLODING,                          debug((DEBUG_EXPLODING, "bozodgetln: "
                             "dgetln: reallocating buffer to buflen %d", buflen));                              "reallocating buffer to buflen %zu", buflen));
                         nbuffer = realloc(buffer, buflen);                          nbuffer = realloc(buffer, buflen);
                         if (nbuffer == NULL) {                          if (nbuffer == NULL) {
                                 free(buffer);                                  free(buffer);
Line 1735  dgetln(int fd, ssize_t *lenp, ssize_t (*
Line 1807  dgetln(int fd, ssize_t *lenp, ssize_t (*
   
         }          }
         buffer[len] = '\0';          buffer[len] = '\0';
         debug((DEBUG_OBESE, "dgetln returns: ``%s'' with len %d", buffer, len));          debug((DEBUG_OBESE, "bozodgetln returns: ``%s'' with len %d",
                  buffer, len));
         *lenp = len;          *lenp = len;
         return (buffer);          return (buffer);
 }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.3.2.3

CVSweb <webmaster@jp.NetBSD.org>