00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <sys/types.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include <unistd.h>
00014 #include <errno.h>
00015 #include <signal.h>
00016
00017 #include "http.h"
00018 #include "utility.h"
00019 #include "net.h"
00020 #include "config.h"
00021
00022 #define SERVER "Server: "VERSION
00023
00024 _PROTOTYPE(static void GotAlarm, (int sig));
00025 _PROTOTYPE(static int sendout, (char *data));
00026
00027 static void GotAlarm(sig)
00028 int sig;
00029 {
00030 }
00031
00032 static int sendout(data)
00033 char *data;
00034 {
00035 if(strlen(data) > 0)
00036 write(1, data, strlen(data));
00037 write(1, "\r\n", 2);
00038 if(dbglog != (FILE *)NULL) {
00039 fprintf(dbglog, "REPLY: %s\n", data);
00040 fflush(dbglog);
00041 }
00042
00043 return(0);
00044 }
00045
00046 int sendreply(rp, rq)
00047 struct http_reply *rp;
00048 struct http_request *rq;
00049 {
00050 int s;
00051 int s2;
00052 int e;
00053 static char buffer[8192];
00054
00055 if(rq->type != HTTP_REQUEST_TYPE_PROXY)
00056
00057 if(rq->method == HTTP_METHOD_POST ||
00058 (rq->method == HTTP_METHOD_PUT && rp->status == HTTP_STATUS_OK)) {
00059 if(rq->type != HTTP_REQUEST_TYPE_FULL)
00060 return(0);
00061 if(rq->method == HTTP_METHOD_PUT)
00062 rp->status = HTTP_STATUS_CREATED;
00063 else
00064 rp->status = HTTP_STATUS_OK;
00065 while(rq->size != 0) {
00066 s = read(0, buffer, (rq->size > sizeof(buffer)) ? sizeof(buffer) : rq->size);
00067 if(s <= 0) {
00068 rp->status = HTTP_STATUS_SERVER_ERROR;
00069 strcpy(rp->statusmsg, strerror(errno));
00070 close(rp->fd);
00071 close(rp->ofd);
00072 break;
00073 }
00074 rq->size -= s;
00075 s2 = write(rp->ofd, buffer, s);
00076 if(s2 != s) break;
00077 }
00078 }
00079
00080 if(rp->status != HTTP_STATUS_OK && rp->status != HTTP_STATUS_CREATED &&
00081 rp->status != HTTP_STATUS_NOT_MODIFIED)
00082 rp->keepopen = 0;
00083
00084 if(rp->status == HTTP_STATUS_NOT_MODIFIED) {
00085 sprintf(buffer, "<h2>Error %03d %s</h2>",
00086 rp->status, rp->statusmsg);
00087 rp->size = strlen(buffer);
00088 rp->keepopen = rq->keepopen;
00089 }
00090
00091 if(!rp->headers) {
00092
00093 if((rq->type == HTTP_REQUEST_TYPE_PROXY && rp->status != HTTP_STATUS_OK) ||
00094 rq->type == HTTP_REQUEST_TYPE_FULL) {
00095 sprintf(buffer, "HTTP/%d.%d %03d %s",
00096 rq->vmajor, rq->vminor, rp->status, rp->statusmsg);
00097 sendout(buffer);
00098 sendout(SERVER);
00099 if(rp->status == HTTP_STATUS_MOVED_PERM ||
00100 rp->status == HTTP_STATUS_MOVED_TEMP) {
00101 #if 1
00102 sprintf(buffer, "Location: %s", rq->url);
00103 #else
00104 sprintf(buffer, "Location: http://%s%s", myhostname, rq->url);
00105 #endif
00106 sendout(buffer);
00107 }
00108 if(rp->keepopen)
00109 sendout("Connection: Keep-Alive");
00110 else
00111 sendout("Connection: Close");
00112 if(rp->status == HTTP_STATUS_UNAUTHORIZED && rp->auth != NULL) {
00113 sprintf(buffer, "WWW-Authenticate: Basic realm=\"%s\"", rp->auth->desc);
00114 sendout(buffer);
00115 }
00116 if(rp->status == HTTP_STATUS_PROXY_AUTH_REQRD && proxyauth != NULL) {
00117 sprintf(buffer, "Proxy-Authenticate: Basic realm=\"%s\"", proxyauth->desc);
00118 sendout(buffer);
00119 }
00120 if(rp->modtime != (time_t) -1) {
00121 sprintf(buffer, "Last-Modified: %s", httpdate(&rp->modtime));
00122 sendout(buffer);
00123 }
00124 if(rp->size != 0) {
00125 sprintf(buffer, "Content-Length: %lu", rp->size);
00126 sendout(buffer);
00127 }
00128 if(rp->status == HTTP_STATUS_OK) {
00129 sprintf(buffer, "Content-Type: %s", rp->mtype);
00130 sendout(buffer);
00131 } else
00132 sendout("Content-Type: text/html");
00133 if(!rp->headers)
00134 sendout("");
00135 } else
00136 if(rp->status != HTTP_STATUS_OK)
00137 return(0);
00138 }
00139
00140 if(rp->status != HTTP_STATUS_OK && rp->status != HTTP_STATUS_CREATED) {
00141 sprintf(buffer, "<h2>Error %03d %s</h2>",
00142 rp->status, rp->statusmsg);
00143 sendout(buffer);
00144 return(0);
00145 }
00146
00147 if(rq->type == HTTP_REQUEST_TYPE_PROXY) {
00148 proxy(rq, rp);
00149 return(0);
00150 }
00151
00152
00153 if(rq->method == HTTP_METHOD_GET || rq->method == HTTP_METHOD_POST) {
00154 errno = 0;
00155 while(1) {
00156 alarm(0);
00157 signal(SIGALRM, GotAlarm);
00158 alarm(10);
00159 s = read(rp->fd, buffer, sizeof(buffer));
00160 e = errno;
00161 alarm(0);
00162 if(s > 0) {
00163 s2 = write(1, buffer, s);
00164 e = errno;
00165 if(s2 != s) break;
00166 continue;
00167 }
00168 if(s == 0) break;
00169 if(s < 0 && e != EINTR) break;
00170 signal(SIGALRM, GotAlarm);
00171 alarm(2);
00172 s = read(0, buffer, 1);
00173 e = errno;
00174 alarm(0);
00175 if(s < 0 && e != EINTR) break;
00176 }
00177 }
00178
00179 close(rp->fd);
00180 rp->fd = -1;
00181 if(rp->ofd != -1)
00182 close(rp->ofd);
00183 if(rp->pid != 0 && e != 0) {
00184 kill(-rp->pid, SIGHUP);
00185 rp->pid = 0;
00186 }
00187
00188 return(0);
00189 }