static void handleDirectory(TSession *const sessionP, const char *const dirName, time_t const fileModTime, MIMEType *const mimeTypeP) { bool text; bool ascending; uint16_t sort; /* 1=by name, 2=by date */ const char *error; determineSortType(sessionP->requestInfo.query, &ascending, &sort, &text, &error); if (error) { ResponseStatus(sessionP, 400); xmlrpc_strfree(error); } else if (notRecentlyModified(sessionP, fileModTime)) { ResponseStatus(sessionP, 304); ResponseWriteStart(sessionP); } else { TPool pool; bool succeeded; succeeded = PoolCreate(&pool, 1024); if (!succeeded) ResponseStatus(sessionP, 500); else { TList list; uint16_t responseStatus; const char *error; generateListing(&list, dirName, sessionP->requestInfo.uri, &pool, &error, &responseStatus); if (error) { ResponseStatus(sessionP, responseStatus); xmlrpc_strfree(error); } else { ResponseStatus(sessionP, 200); ResponseContentType(sessionP, text ? "text/plain" : "text/html"); addLastModifiedHeader(sessionP, fileModTime); ResponseChunked(sessionP); ResponseWriteStart(sessionP); if (sessionP->requestInfo.method != m_head) sendDirectoryDocument(&list, ascending, sort, text, sessionP->requestInfo.uri, mimeTypeP, sessionP); HTTPWriteEndChunk(sessionP); ListFree(&list); } PoolFree(&pool); } } }
static void handleFile(TSession *const sessionP, const char *const fileName, time_t const fileModTime, MIMEType *const mimeTypeP) { /*---------------------------------------------------------------------------- This is an HTTP request handler for a GET. It does the classic web server thing: send the file named in the URL to the client. -----------------------------------------------------------------------------*/ TFile *fileP; bool success; success = FileOpen(&fileP, fileName, O_BINARY | O_RDONLY); if (!success) ResponseStatusErrno(sessionP); else { if (notRecentlyModified(sessionP, fileModTime)) { ResponseStatus(sessionP, 304); ResponseWriteStart(sessionP); } else sendFileAsResponse(sessionP, fileP, fileName, fileModTime, mimeTypeP); FileClose(fileP); } }
static void sendFileAsResponse(TSession *const sessionP, TFile *const fileP, const char *const fileName, time_t const fileModTime, MIMEType *const mimeTypeP) { uint64_t const filesize = FileSize(fileP); const char *const mediatype = MIMETypeGuessFromFile2(mimeTypeP, fileName); uint64_t start; /* Defined only if session has one range */ uint64_t end; /* Defined only if session has one range */ switch (sessionP->ranges.size) { case 0: ResponseStatus(sessionP, 200); break; case 1: { bool decoded; decoded = RangeDecode((char *) (sessionP->ranges.item[0]), filesize, &start, &end); if (!decoded) { ListFree(&sessionP->ranges); ResponseStatus(sessionP, 200); } else { const char *contentRange; xmlrpc_asprintf(&contentRange, "bytes %" PRIu64 "-%" PRIu64 "/%" PRIu64, start, end, filesize); ResponseAddField(sessionP, "Content-range", contentRange); xmlrpc_strfree(contentRange); ResponseContentLength(sessionP, end - start + 1); ResponseStatus(sessionP, 206); } } break; default: ResponseContentType(sessionP, "multipart/ranges; boundary=" BOUNDARY); ResponseStatus(sessionP, 206); break; } if (sessionP->ranges.size == 0) { ResponseContentLength(sessionP, filesize); ResponseContentType(sessionP, mediatype); } addLastModifiedHeader(sessionP, fileModTime); ResponseWriteStart(sessionP); if (sessionP->requestInfo.method != m_head) sendBody(sessionP, fileP, filesize, mediatype, start, end); }
static void sendResponse(xmlrpc_env * const envP, TSession * const abyssSessionP, const char * const body, size_t const len, bool const chunked, ResponseAccessCtl const accessControl) { /*---------------------------------------------------------------------------- Generate an HTTP response containing body 'body' of length 'len' characters. This is meant to run in the context of an Abyss URI handler for Abyss session 'abyssSessionP'. -----------------------------------------------------------------------------*/ const char * http_cookie = NULL; /* This used to set http_cookie to getenv("HTTP_COOKIE"), but that doesn't make any sense -- environment variables are not appropriate for this. So for now, cookie code is disabled. - Bryan 2004.10.03. */ /* Various bugs before Xmlrpc-c 1.05 caused the response to be not chunked in the most basic case, but chunked if the client explicitly requested keepalive. I think it's better not to chunk, because it's simpler, so I removed this in 1.05. I don't know what the purpose of chunking would be, and an original comment suggests the author wasn't sure chunking was a good idea. In 1.06 we added the user option to chunk. */ if (chunked) ResponseChunked(abyssSessionP); ResponseStatus(abyssSessionP, 200); if (http_cookie) /* There's an auth cookie, so pass it back in the response. */ addAuthCookie(envP, abyssSessionP, http_cookie); if ((size_t)(uint32_t)len != len) xmlrpc_faultf(envP, "XML-RPC method generated a response too " "large for Abyss to send"); else { uint32_t const abyssLen = (uint32_t)len; /* See discussion below of quotes around "utf-8" */ ResponseContentType(abyssSessionP, "text/xml; charset=utf-8"); ResponseContentLength(abyssSessionP, abyssLen); ResponseAccessControl(abyssSessionP, accessControl); ResponseWriteStart(abyssSessionP); ResponseWriteBody(abyssSessionP, body, abyssLen); ResponseWriteEnd(abyssSessionP); } }
void AbyssServer::Session::Impl::startWriteResponse() { // Note that ResponseWriteStart() assumes no response has been started; it // asserts that fact. if (this->responseStarted) throwf("Attempt to write multiple responses in same session"); ResponseWriteStart(this->cSessionP); this->responseStarted = true; }
void Answer(TSession *r, uint16_t statuscode, char *buffer) { ResponseChunked(r); ResponseStatus(r,statuscode); ResponseContentType(r,"text/html"); ResponseWriteStart(r); HTTPWrite(r,"<HTML><BODY>",12); HTTPWrite(r,buffer,strlen(buffer)); HTTPWrite(r,"</BODY></HTML>",14); HTTPWriteEnd(r); }
/************************************** * SendResponse * Envia la respuesta de una peticion **************************************/ int XmlRpcServer::SendResponse(TSession *r, short code, const char *msg, int length) { //Chunked output ResponseChunked(r); //POnemos el codigo ResponseStatus(r,code); //El content length ResponseContentLength(r, length); //Escribimos la respuesta ResponseWriteStart(r); //La mandamos ResponseWriteBody(r,(char*)msg,length); //End it ResponseWriteEnd(r); return 1; }
void ResponseError2(TSession * const sessionP, const char * const explanation) { const char * errorDocument; ResponseAddField(sessionP, "Content-type", "text/html"); ResponseWriteStart(sessionP); xmlrpc_asprintf(&errorDocument, "<HTML><HEAD><TITLE>Error %d</TITLE></HEAD>" "<BODY>" "<H1>Error %d</H1>" "<P>%s</P>" SERVER_HTML_INFO "</BODY>" "</HTML>", sessionP->status, sessionP->status, explanation); ConnWrite(sessionP->connP, errorDocument, strlen(errorDocument)); xmlrpc_strfree(errorDocument); }