abyss_bool ResponseWriteStart(TSession * const sessionP) { /*---------------------------------------------------------------------------- Begin the process of sending the response for an HTTP transaction (i.e. Abyss session). As part of this, send the entire HTTP header for the response. -----------------------------------------------------------------------------*/ struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP; assert(!sessionP->responseStarted); if (sessionP->status == 0) { /* Handler hasn't set status. That's an error */ TraceMsg("Abyss client called ResponseWriteStart() on " "a session for which he has not set the request status " "('status' member of TSession). Using status 500\n"); sessionP->status = 500; } sessionP->responseStarted = TRUE; { const char * const reason = HTTPReasonByStatus(sessionP->status); const char * line; abyss_bool ret = TRUE; xmlrpc_asprintf(&line,"HTTP/1.1 %u %s\r\n", sessionP->status, reason); ret = ConnWrite(sessionP->connP, line, strlen(line)); xmlrpc_strfree(line); if (!ret) return FALSE; } addConnectionHeaderFld(sessionP); if (sessionP->chunkedwrite && sessionP->chunkedwritemode) ResponseAddField(sessionP, "Transfer-Encoding", "chunked"); addDateHeaderFld(sessionP); if (srvP->advertise) addServerHeaderFld(sessionP); /* Note that sessionP->responseHeaderFields is defined to contain syntactically but not necessarily semantically valid header field names and values. */ if (sendHeader(sessionP->connP, sessionP->responseHeaderFields)) if (ConnWrite(sessionP->connP, "\r\n", 2)) return TRUE; return FALSE; }
static void addConnectionHeaderFld(TSession * const sessionP) { struct _TServer * const srvP = ConnServer(sessionP->connP)->srvP; if (HTTPKeepalive(sessionP)) { const char * keepaliveValue; ResponseAddField(sessionP, "Connection", "Keep-Alive"); xmlrpc_asprintf(&keepaliveValue, "timeout=%u, max=%u", srvP->keepalivetimeout, srvP->keepalivemaxconn); ResponseAddField(sessionP, "Keep-Alive", keepaliveValue); xmlrpc_strfree(keepaliveValue); } else ResponseAddField(sessionP, "Connection", "close"); }
static abyss_bool ServerDefaultHandlerFunc(TSession * const sessionP) { struct _TServer * const srvP = ConnServer(sessionP->conn)->srvP; char *p; char z[4096]; TFileStat fs; unsigned int i; abyss_bool endingslash=FALSE; if (!RequestValidURIPath(sessionP)) { ResponseStatus(sessionP, 400); return TRUE; } /* Must check for * (asterisk uri) in the future */ if (sessionP->request_info.method == m_options) { ResponseAddField(sessionP, "Allow", "GET, HEAD"); ResponseContentLength(sessionP, 0); ResponseStatus(sessionP, 200); return TRUE; } if ((sessionP->request_info.method != m_get) && (sessionP->request_info.method != m_head)) { ResponseAddField(sessionP, "Allow", "GET, HEAD"); ResponseStatus(sessionP, 405); return TRUE; } strcpy(z, srvP->filespath); strcat(z, sessionP->request_info.uri); p = z + strlen(z) - 1; if (*p == '/') { endingslash = TRUE; *p = '\0'; } #ifdef WIN32 p = z; while (*p) { if ((*p) == '/') *p= '\\'; ++p; } #endif /* WIN32 */ if (!FileStat(z, &fs)) { ResponseStatusErrno(sessionP); return TRUE; } if (fs.st_mode & S_IFDIR) { /* Redirect to the same directory but with the ending slash ** to avoid problems with some browsers (IE for examples) when ** they generate relative urls */ if (!endingslash) { strcpy(z, sessionP->request_info.uri); p = z+strlen(z); *p = '/'; *(p+1) = '\0'; ResponseAddField(sessionP, "Location", z); ResponseStatus(sessionP, 302); ResponseWrite(sessionP); return TRUE; } *p = DIRECTORY_SEPARATOR[0]; ++p; i = srvP->defaultfilenames.size; while (i-- > 0) { *p = '\0'; strcat(z, (srvP->defaultfilenames.item[i])); if (FileStat(z, &fs)) { if (!(fs.st_mode & S_IFDIR)) return ServerFileHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); } } *(p-1) = '\0'; if (!FileStat(z, &fs)) { ResponseStatusErrno(sessionP); return TRUE; } return ServerDirectoryHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); } else return ServerFileHandler(sessionP, z, fs.st_mtime, srvP->mimeTypeP); }