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

proc.c

/* Anti-Web HTTPD */
/* Hardcore Software */
/*
This software is Copyright (C) 2001-2004 By Hardcore Software and
others. The software is distributed under the terms of the GNU General
Public License. See the file 'COPYING' for more details.
*/


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

#include "aw3.h"




// Returns 1 if elems should continue being read, 0 otherwise
int procheadelem(struct connstruct *cn, char *buf) {

  char *words[10];

  split(buf, words, 10, ' ');

  if (words[0] == NULL) return 0;

  if (strcmp(words[0], "GET")==0 ||
      strcmp(words[0], "HEAD")==0 ||
      strcmp(words[0], "POST")==0) {
    char *segs[4];

    if (*words[0] == 'H') cn->reqtype = TYPE_HEAD;
    else if (*words[0] == 'P') cn->reqtype = TYPE_POST;

    urldecode(segs[0]);
    split(words[1], segs, 4, '?');

    if (segs[0] == NULL) return 0;

    // Inserted for Bibledit. 
    // Here we notice a command after the ?.
    // Convert the %20-style stuff.
    // Write the command to a file.
    if (segs[1]) {
      urldecode(segs[1]);
      char * filename = malloc (1024);
      filename[0] = 0;
      filename = strncat (filename, getenv ("HOME"), 900);
      filename = strcat (filename, "/.bibledit_temp/bibledit.httpd.request");
      int filefd = open (filename, O_CREAT | O_WRONLY | O_TRUNC, 0644);
      if (filefd > 0) {
        write (filefd, segs[1], strlen (segs[1]));
        close (filefd);
      }
      free (filename);
    }
    // End of insert.
    
    urldecode(segs[0]);

    if (sanitizefile(segs[0]) == 0) {
      send404(cn);
      removeconnection(cn);
      return 0;
    }

    strncpy(cn->filereq, segs[0], MAXREQUESTLENGTH);

    if (segs[1] != NULL) strncpy(cn->cgiargs, segs[1], MAXREQUESTLENGTH);

  } else if (strcmp(words[0], "Host:")==0) {

    if (words[1] == NULL) return 0;

    if (sanitizehost(words[1]) == 0) {
      send404(cn);
      removeconnection(cn);
      return 0;
    }

    strncpy(cn->virtualhostreq, words[1], MAXREQUESTLENGTH);
  } else if (strcmp(words[0], "Range:")==0) {

    cn->offset = -1;

    if (strchr(words[1], '-') == NULL) return 1;

    if (strchr(words[1], '=') != NULL) {
      while(*words[1] != '=') words[1]++;
      words[1]++;
    }

    if (isdigit(*words[1]) == 0) return 1;

    cn->offset = atoi(words[1]);

  }

  return 1;

}



void procdirlisting(struct connstruct *cn) {

  char buf[MAXREQUESTLENGTH];

  if (allowdirectorylisting == 0) {
    send404(cn);
    removeconnection(cn);
    return;
  }

  if (cn->reqtype == TYPE_HEAD) {
    snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n");
    write(cn->networkdesc, buf, strlen(buf));

    removeconnection(cn);
    return;
  }

  cn->dirp = opendir(cn->actualfile);
  if (cn->dirp == NULL) {
    send404(cn);
    removeconnection(cn);
    return;
  }

  // Get rid of the "."
  readdir(cn->dirp);

  // If the browser doesn't specify a virtual host, the client will
  // see "http://default/thedir/" instead of "http://thehost.com/thedir/"
  // Consider this punishment for using such an old browser.
  snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nContent-Type: text/html\n\n<HTML><BODY>\n<TITLE>Directory Listing</TITLE>\n<H2>Directory listing of http://%s%s</H2><BR>\n", cn->virtualhostreq, cn->filereq);
  write(cn->networkdesc, buf, strlen(buf));

  cn->state = STATE_DOING_DIR;

  return;


}



void procdodir(struct connstruct *cn) {

  struct dirent *dp;
  char buf[MAXREQUESTLENGTH];
  char encbuf[sizeof(dp->d_name)*3+1];
  int putslash;

  do {

    if ((dp = readdir(cn->dirp)) == NULL) {
      snprintf(buf, sizeof(buf), "<BR><BR>End of Anti-Web directory listing.</BODY></HTML>\n");
      write(cn->networkdesc, buf, strlen(buf));
      removeconnection(cn);
      return;
    }

    if (cn->filereq[0] == '/' && cn->filereq[1] == '\0' &&
        strcmp(dp->d_name, "..") == 0) continue;

    snprintf(buf, sizeof(buf), "%s%s", cn->actualfile, dp->d_name);
    putslash = isdir(buf);

    urlencode(dp->d_name, encbuf);
    snprintf(buf, sizeof(buf), "<A HREF=\"%s%s\">%s%s</A><BR>\n",
           encbuf, putslash ? "/" : "", dp->d_name, putslash ? "/" : "");
    write(cn->networkdesc, buf, strlen(buf));

  } while (issockwriteable(cn->networkdesc));

  return;
}




void procreadhead(struct connstruct *cn) {

  char buf[MAXREQUESTLENGTH*4], *tp, *next;
  int rv;

  rv = read(cn->networkdesc, buf, sizeof(buf)-1);
  if (rv == 0 || rv == -1) {
    removeconnection(cn);
    return;
  }

  buf[rv] = '\0';

  next = tp = buf;
  
  // Inserted code for Bibledit: Write the request to a named pipe.
  // Umm, this was so before, but the code was moved, but now leaving this 
  // remaining code out crashes the server. So just left it.
  char * filename = malloc (1024);
  free (filename);

  // Split up lines and send to procheadelem()
  while(*next != '\0') {

    // If we have a blank line, advance to next stage!
    if (*next == '\r' || *next == '\n') {
      buildactualfile(cn);

      cn->state = STATE_WANT_TO_SEND_HEAD;
      return;
    }

    while(*next != '\r' && *next != '\n' && *next != '\0') next++;
    if (*next == '\r') {
      *next = '\0';
      next+=2;
    }
    else if (*next == '\n') *next++ = '\0';

    if (procheadelem(cn, tp) == 0) return;

    tp = next;
  }
  
  return;

}



/* In this function we assume that the file has been checked for
 * maliciousness (".."s, etc) and has been decoded
 */
void procsendhead(struct connstruct *cn) {

  char buf[1024];
  struct stat stbuf;


  if (stat(cn->actualfile, &stbuf) == -1) {
    send404(cn);
    removeconnection(cn);
    return;
  }

  if (iscgi(cn->actualfile)) {
    // Set up CGI script
    if (allowcgi == 0 ||
        access(cn->actualfile, X_OK) != 0 ||
        isdir(cn->actualfile)) {
      send404(cn);
      removeconnection(cn);
      return;
    }

    proccgi(cn);
    return;
  }


  if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
    if (cn->filereq[strlen(cn->filereq)-1] != '/') {
      send301(cn);
      removeconnection(cn);
      return;
    }

    // Check to see if this dir has an index file
    if (procindex(cn, &stbuf) == 0) {
      // If not, we do a directory listing of it
      procdirlisting(cn);
      return;
    }

    // If the index is a CGI file, handle it like any other CGI
    if (iscgi(cn->actualfile)) {
      // Set up CGI script
      if (allowcgi == 0 ||
          access(cn->actualfile, X_OK) != 0 ||
          isdir(cn->actualfile)) {
        send404(cn);
        removeconnection(cn);
        return;
      }

      proccgi(cn);
      return;
    }
    // If the index isn't a CGI, we continue on with the index file

  }

  if (cn->offset == -1 || cn->offset >= stbuf.st_size) {
    cn->offset = -1;

    snprintf(buf, sizeof(buf), "HTTP/1.1 200 OK\nServer: Anti-Web V%s (%s)\nContent-Type: %s\nContent-Length: %ld\nLast-Modified: %s\n",
               VERSION,
               quote,
               getmimetype(cn->actualfile),
               (long) stbuf.st_size,
               ctime(&(stbuf.st_mtime))); // ctime() has a \n on the end
  } else {
    snprintf(buf, sizeof(buf), "HTTP/1.1 206 OK\nServer: Anti-Web V%s (%s)\nContent-Type: %s\nContent-Range: %ld-%ld/%ld\nContent-Length: %ld\nLast-Modified: %s\n",
               VERSION,
               quote,
               getmimetype(cn->actualfile),
               cn->offset,
               (long) stbuf.st_size-1,
               (long) stbuf.st_size,
               (long) stbuf.st_size - cn->offset,
               ctime(&(stbuf.st_mtime))); // ctime() has a \n on the end
  }

  write(cn->networkdesc, buf, strlen(buf));

  if (cn->reqtype == TYPE_HEAD) {
    removeconnection(cn);
    return;
  } else {

    cn->filedesc = open(cn->actualfile, O_RDONLY);
    if (cn->filedesc == -1) {
      send404(cn);
      removeconnection(cn);
      return;
    }

    if (cn->offset != -1) {
      lseek(cn->filedesc, cn->offset, SEEK_SET);
    }

    cn->state = STATE_WANT_TO_READ_FILE;
    return;
  }

}



void procreadfile(struct connstruct *cn) {

  int rv;

  rv = read(cn->filedesc, cn->databuf, BLOCKSIZE);

  if (rv == 0 || rv == -1) {
    removeconnection(cn);
    return;
  }

  cn->numbytes = rv;
  cn->state = STATE_WANT_TO_SEND_FILE;

  return;
}



void procsendfile(struct connstruct *cn) {

  int rv;

  rv = write(cn->networkdesc, cn->databuf, cn->numbytes);

  if (rv == -1) {
    removeconnection(cn);
    return;
  }

  cn->state = STATE_WANT_TO_READ_FILE;

  return;

}

Generated by  Doxygen 1.6.0   Back to index