Logo Search packages:      
Sourcecode: xawtv version File versions  Download package

request.c

#include "config.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <syslog.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include "httpd.h"

/* ---------------------------------------------------------------------- */

void
read_request(struct REQUEST *req, int pipelined)
{
    int             rc;
    char            *h;

 restart:
    rc = read(req->fd, req->hreq + req->hdata, MAX_HEADER - req->hdata);
    switch (rc) {
    case -1:
      if (errno == EAGAIN) {
          if (pipelined)
            break; /* check if there is already a full request */
          else
            return;
      }
      if (errno == EINTR)
          goto restart;
      xperror(LOG_INFO,"read",req->peerhost);
      /* fall through */
    case 0:
      req->state = STATE_CLOSE;
      return;
    default:
      req->hdata += rc;
      req->hreq[req->hdata] = 0;
    }

    /* check if this looks like a http request after
       the first few bytes... */
    if (req->hdata < 5)
      return;
    if (strncmp(req->hreq,"GET ",4)  != 0  &&
      strncmp(req->hreq,"PUT ",4)  != 0  &&
      strncmp(req->hreq,"HEAD ",5) != 0  &&
      strncmp(req->hreq,"POST ",5) != 0) {
      mkerror(req,400,0);
      return;
    }
    
    /* header complete ?? */
    if (NULL != (h = strstr(req->hreq,"\r\n\r\n")) ||
      NULL != (h = strstr(req->hreq,"\n\n"))) {
      if (*h == '\r') {
          h += 4;
          *(h-2) = 0;
      } else {
          h += 2;
          *(h-1) = 0;
      }
      req->lreq  = h - req->hreq;
      req->state = STATE_PARSE_HEADER;
      return;
    }

    if (req->hdata == MAX_HEADER) {
      /* oops: buffer full, but found no complete request ... */
      mkerror(req,400,0);
      return;
    }
    return;
}

/* ---------------------------------------------------------------------- */

static int
unhex(unsigned char c)
{
    if (c < '@')
      return c - '0';
    return (c & 0x0f) + 9;
}

static void
unquote(unsigned char *dst, unsigned char *src)
{
    int i,j,q,n=strlen(src);

    q=0;
    for (i=0, j=0; i<n; i++, j++) {
      if (src[i] == '?')
          q = 1;
      if (q && src[i] == '+') {
          dst[j] = ' ';
      } else if (src[i] == '%') {
          dst[j] = (unhex(src[i+1]) << 4) | unhex(src[i+2]);
          i += 2;
      } else {
          dst[j] = src[i];
      }
    }
    dst[j] = 0;
}

void
parse_request(struct REQUEST *req)
{
    char filename[2048], proto[5], *h;
    int  port;
    
    if (debug > 2)
      fprintf(stderr,"%s\n",req->hreq);

    /* parse request. Hehe, scanf is powerfull :-) */
    if (4 != sscanf(req->hreq, "%4[A-Z] %255[^ \t\r\n] HTTP/%d.%d",
                req->type,filename,&(req->major),&(req->minor))) {
      mkerror(req,400,0);
      return;
    }
    if (filename[0] == '/') {
      strcpy(req->uri,filename);
    } else {
      port = 0;
      *proto = 0;
      if (4 != sscanf(filename,"%4[a-zA-Z]://%64[a-zA-Z0-9.-]:%d%255[^ \t\r\n]",
                  proto,req->hostname,&port,req->uri) &&
          3 != sscanf(filename,"%4[a-zA-Z]://%64[a-zA-Z0-9.-]%255[^ \t\r\n]",
                  proto,req->hostname,req->uri)) {
          mkerror(req,400,0);
          return;
      }
      if (*proto != 0 && 0 != strcasecmp(proto,"http")) {
          mkerror(req,400,0);
          return;
      }
    }

    unquote(req->path,req->uri);    
    if (debug)
      fprintf(stderr,"%03d: %s \"%s\" HTTP/%d.%d\n",
            req->fd, req->type, req->path, req->major, req->minor);

    if (0 != strcmp(req->type,"GET") &&
      0 != strcmp(req->type,"HEAD")) {
      mkerror(req,501,0);
      return;
    }

    if (0 == strcmp(req->type,"HEAD")) {
      req->head_only = 1;
    }

    /* checks */
    if (req->path[0] != '/') {
      mkerror(req,400,0);
      return;
    }

    /* parse header lines */
    req->keep_alive = req->minor;
    for (h = req->hreq; h - req->hreq < req->lreq;) {
      h = strchr(h,'\n');
      if (NULL == h)
          break;
      h++;

      if (0 == strncasecmp(h,"Connection: ",12)) {
          req->keep_alive = (0 == strncasecmp(h+12,"Keep-Alive",10));

      } else if (0 == strncasecmp(h,"Host: ",6)) {
          sscanf(h+6,"%64[a-zA-Z0-9.-]",req->hostname);
      }
    }

    /* make sure we have a hostname */
    if (req->hostname[0] == '\0' || canonicalhost)
      strncpy(req->hostname,server_host,64);

    /* lowercase hostname */
    for (h = req->hostname; *h != 0; h++) {
      if (*h < 'A' || *h > 'Z')
          continue;
      *h += 32;
    }

    /* handle request (more to come) */
    buildpage(req);
    return;
}

Generated by  Doxygen 1.6.0   Back to index