[2286] | 1 | /**********************************************************************
|
---|
| 2 | *
|
---|
| 3 | * httpreq.cpp
|
---|
| 4 | * Copyright (C) 1996
|
---|
| 5 | *
|
---|
| 6 | * A component of the fnord webserver written by [email protected].
|
---|
| 7 | *
|
---|
| 8 | * Altered for use with the Greenstone digital library software by the
|
---|
| 9 | * New Zealand Digital Library Project at the University of Waikato,
|
---|
| 10 | * New Zealand.
|
---|
| 11 | *
|
---|
| 12 | * This program is free software; you can redistribute it and/or modify
|
---|
| 13 | * it under the terms of the GNU General Public License as published by
|
---|
| 14 | * the Free Software Foundation; either version 2 of the License, or
|
---|
| 15 | * (at your option) any later version.
|
---|
| 16 | *
|
---|
| 17 | * This program is distributed in the hope that it will be useful,
|
---|
| 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 20 | * GNU General Public License for more details.
|
---|
| 21 | *
|
---|
| 22 | * You should have received a copy of the GNU General Public License
|
---|
| 23 | * along with this program; if not, write to the Free Software
|
---|
| 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
---|
| 25 | *
|
---|
| 26 | *********************************************************************/
|
---|
[611] | 27 |
|
---|
| 28 | #include <windows.h>
|
---|
| 29 | #include <stdlib.h>
|
---|
| 30 | #include <stdio.h>
|
---|
| 31 | #include <string.h>
|
---|
| 32 | #include <memory.h>
|
---|
[3810] | 33 | #include "httpreq.h"
|
---|
[611] | 34 | #include "parse.h"
|
---|
| 35 | #include "netio.h"
|
---|
| 36 | #include "settings.h"
|
---|
| 37 | #include "httpsrv.h"
|
---|
| 38 | #include "httpsend.h"
|
---|
| 39 | #include "cgiwrapper.h"
|
---|
[2353] | 40 | #include "d_winsock.h"
|
---|
[611] | 41 |
|
---|
| 42 | /*
|
---|
| 43 | Implementation Notes:
|
---|
| 44 |
|
---|
| 45 | HTTP field names, method and version strings are converted to upper case
|
---|
| 46 | right after being read from the client in order to allow case insensitive
|
---|
| 47 | string comparisons to be done on them. Since these fields are worked with a
|
---|
| 48 | lot, this should help performance.
|
---|
| 49 | */
|
---|
| 50 |
|
---|
| 51 | //Private Data and declarations
|
---|
| 52 | #define IO_BUFFER_SIZE 16384 //16K IO Buffer
|
---|
| 53 | #define MAX_HTTP_LINE_LEN 1024 //Max length of line in a header of 1024
|
---|
| 54 |
|
---|
| 55 | //Private Function Declarations with Return Contstants
|
---|
| 56 |
|
---|
| 57 | /*
|
---|
| 58 | Function Name: DispatchRequest
|
---|
| 59 | Purpose: Manages having the request parsed, then sent to the right function
|
---|
| 60 | to send a response or handle an error.
|
---|
| 61 | Parameters:
|
---|
| 62 | ClientSocket - Socket the client is on
|
---|
| 63 | ClientSockAddr - Address of client
|
---|
| 64 | AddrLen - Length of address of client
|
---|
| 65 | IOBuffer - Pointer to buffer allocated for IO operations
|
---|
| 66 | ThreadNum - Number of thread that called this function for debugging purposes
|
---|
| 67 | Notes: I'm still playing with the keep alive support. I commented out
|
---|
| 68 | the stuff for giving a client a timeout because I was unable to detect
|
---|
| 69 | disconnects.
|
---|
| 70 | More Notes: Not sure if this organization will allow me to easily add support
|
---|
| 71 | for ISAPI filter DLLs.
|
---|
| 72 | */
|
---|
| 73 | void DispatchRequest(SOCKET ClientSocket, SOCKADDR_IN ClientSockAddr, int AddrLen, BYTE *IOBuffer);
|
---|
| 74 |
|
---|
| 75 | /*
|
---|
| 76 | Function Name: Get HTTP Headers
|
---|
| 77 | Purpose: Manages having the request parsed, then sent to the right function
|
---|
| 78 | to send a response or handle an error.
|
---|
| 79 | Parameters:
|
---|
| 80 | RequestInfo - Request information structure (see httpreq.h)
|
---|
| 81 | RequestFields - HTTP request fields structure (see httpreq.h)
|
---|
| 82 | Returns: GH_ERROR on error (diconnect, bad data, Windows in a bad mood, etc.)
|
---|
| 83 | GH_UNKNOWN_VERSION if the version number is not HTTP/0.9 or HTTP/1.x
|
---|
| 84 | GH_SIMPLE_REQUEST on a properly formated HTTP/0.9 request
|
---|
| 85 | GH_10_REQUEST on a properly formated HTTP/1.x request
|
---|
| 86 | */
|
---|
| 87 | int GetHTTPHeaders(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields);
|
---|
[3017] | 88 | #define GH_BAD_METHOD -2
|
---|
[611] | 89 | #define GH_ERROR -1
|
---|
| 90 | #define GH_UNKNOWN_VERSION 0
|
---|
| 91 | #define GH_SIMPLE_REQUEST 1
|
---|
| 92 | #define GH_10_REQUEST 2
|
---|
| 93 |
|
---|
| 94 | /*
|
---|
| 95 | Function Name: Clean Up HTTP Headers
|
---|
| 96 | Purpose: Cleans up memory dynamicly allocated for headers
|
---|
| 97 | Parameters:
|
---|
| 98 | RequestInfo - Request information structure (see httpreq.h)
|
---|
| 99 | RequestFields - HTTP request fields structure (see httpreq.h)
|
---|
| 100 | Returns: Nothing
|
---|
| 101 | */
|
---|
| 102 | void CleanUpHTTPHeaders(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields);
|
---|
| 103 |
|
---|
| 104 | /*
|
---|
| 105 | Function Name: Split Query
|
---|
| 106 | Purpose: Splits the file and query part of a URI. In other words, it
|
---|
| 107 | puts the parts before and after the "?" in differnet strings.
|
---|
| 108 | Parameters:
|
---|
| 109 | URIStr - The requested URI
|
---|
| 110 | FileStr - String to contain the name of the path + file part of the URI
|
---|
| 111 | QueryStr - String to contain the query part of the URI
|
---|
| 112 | Returns: TRUE if there is a query, else FALSE
|
---|
| 113 | */
|
---|
| 114 | BOOL SplitQuery(char *URIStr, char *FileStr, char *QueryStr, int ThreadNum);
|
---|
| 115 |
|
---|
| 116 | /*
|
---|
| 117 | Function Name: Get File
|
---|
| 118 | Purpose: Attempts to find a given file, including looking for index.html.
|
---|
| 119 | Updates the given URI string so it points to the true document location
|
---|
| 120 | Parameters:
|
---|
| 121 | FilePath - Path of file, may be modified to best reflect the retrived file
|
---|
| 122 | or directory
|
---|
| 123 | URIStr - URI string, minus the query
|
---|
| 124 | Returns: GF_ERROR on error
|
---|
| 125 | GF_FILE_FOUND on success
|
---|
| 126 | GF_INDEX_FOUND if file is a directory with an index.html file in it
|
---|
| 127 | GF_DIRECTORY if file is a directory
|
---|
| 128 | GF_FILE_NOT_FOUND if file was found
|
---|
| 129 | */
|
---|
| 130 |
|
---|
| 131 | /*
|
---|
| 132 | Function Name: Process Simple Request
|
---|
| 133 | Purpose: Sends a reply to a HTTP 0.9 "simple" request
|
---|
| 134 | Parameters:
|
---|
| 135 | ClientSocket - Socket the client is on
|
---|
| 136 | RequestInfo - Structure storing the parsed headers
|
---|
| 137 | IOBuffer - Pointer to buffer allocated for IO operations
|
---|
| 138 | TheadNum - Number of calling thread for debugging
|
---|
| 139 | Notes: I should really test this and see if it works...
|
---|
| 140 | */
|
---|
| 141 | void ProcessSimpleRequest(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields);
|
---|
| 142 |
|
---|
| 143 | //Public Functions
|
---|
| 144 | /******************************************************************************/
|
---|
| 145 | void RequestThread(RequestThreadMessageT *Parameters) {
|
---|
| 146 | SOCKADDR_IN ClientSockAddr;
|
---|
| 147 | SOCKET ClientSocket;
|
---|
| 148 | int AddrLen;
|
---|
| 149 | //Allocate an IO buffer for this thread
|
---|
| 150 | BYTE *IOBuffer = new BYTE[IO_BUFFER_SIZE];
|
---|
| 151 |
|
---|
| 152 | //Get the parameters for the request
|
---|
| 153 | ClientSocket = Parameters->ClientSocket;
|
---|
| 154 | ClientSockAddr = Parameters->ClientSockAddr;
|
---|
| 155 | AddrLen = Parameters->AddrLen;
|
---|
| 156 | DispatchRequest(ClientSocket, ClientSockAddr, AddrLen, IOBuffer);
|
---|
| 157 | }
|
---|
| 158 | /******************************************************************************/
|
---|
| 159 |
|
---|
| 160 | //Private Functions
|
---|
| 161 |
|
---|
| 162 | /******************************************************************************/
|
---|
| 163 | void DispatchRequest(SOCKET ClientSocket, SOCKADDR_IN ClientSockAddr, int AddrLen, BYTE *IOBuffer) {
|
---|
| 164 | RequestInfoT RequestInfo;
|
---|
| 165 | RequestFieldsT RequestFields;
|
---|
| 166 |
|
---|
| 167 | // TrayAddConnection();
|
---|
| 168 |
|
---|
| 169 | //Setup the RequestInfo structure
|
---|
| 170 | memset(&RequestInfo, 0, sizeof(RequestInfoT));
|
---|
| 171 | RequestInfo.ThreadNum = 0;
|
---|
| 172 | RequestInfo.IOBuffer = IOBuffer;
|
---|
| 173 | RequestInfo.IOBufferSize = IO_BUFFER_SIZE;
|
---|
| 174 | RequestInfo.ClientSocket = ClientSocket;
|
---|
| 175 | RequestInfo.ClientSockAddr = ClientSockAddr;
|
---|
| 176 | RequestInfo.AddrLen = AddrLen;
|
---|
| 177 | RequestInfo.KeepAlive = FALSE;
|
---|
| 178 |
|
---|
| 179 | int GetHeadersResult;
|
---|
| 180 | do {
|
---|
| 181 | //Get Headers
|
---|
| 182 | GetHeadersResult = GetHTTPHeaders(RequestInfo, RequestFields);
|
---|
[2353] | 183 |
|
---|
[611] | 184 | //Figure out what version we're dealing with and deal with it
|
---|
| 185 | switch (GetHeadersResult) {
|
---|
| 186 | case GH_SIMPLE_REQUEST :
|
---|
| 187 | SendHTTPError(400, "HTTP Request not supported", "Only 1.x requests supported", RequestInfo, RequestFields);
|
---|
| 188 | // TrayIncNumServed();
|
---|
| 189 | break;
|
---|
| 190 | case GH_10_REQUEST :
|
---|
| 191 | ExamineURIStr(RequestFields.URIStr,&RequestInfo,&RequestFields);
|
---|
| 192 | // TrayIncNumServed();
|
---|
| 193 | break;
|
---|
| 194 | case GH_UNKNOWN_VERSION :
|
---|
| 195 | SendHTTPError(400, "HTTP Version not supported", "Only 1.x requests supported", RequestInfo, RequestFields);
|
---|
| 196 | // TrayIncNumServed();
|
---|
| 197 | break;
|
---|
[3017] | 198 | /* added Feb 2002 to handle stupid MS behaviour */
|
---|
| 199 | case GH_BAD_METHOD :
|
---|
| 200 | SendHTTPError(501, "Not implemented", "Only GET and POST currently implemented", RequestInfo, RequestFields);
|
---|
| 201 | break;
|
---|
[611] | 202 | case GH_ERROR:
|
---|
| 203 | //Disconnect
|
---|
| 204 | RequestInfo.KeepAlive = FALSE;
|
---|
| 205 | break;
|
---|
| 206 | }
|
---|
| 207 | CleanUpHTTPHeaders(RequestInfo, RequestFields);
|
---|
| 208 | } while (0/*RequestInfo.KeepAlive == TRUE*/);
|
---|
| 209 | //Close connection
|
---|
| 210 | CloseSocket(RequestInfo.ClientSocket);
|
---|
| 211 | // TrayRemoveConnection();
|
---|
| 212 | }
|
---|
| 213 |
|
---|
| 214 | /******************************************************************************/
|
---|
| 215 | int GetHTTPHeaders(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields) {
|
---|
| 216 | //Parsing and IO buffers
|
---|
[3810] | 217 | text_t CurLine;
|
---|
| 218 | text_t NextLine;
|
---|
| 219 | text_t FieldNameStr;
|
---|
| 220 | text_t FieldValStr;
|
---|
[611] | 221 |
|
---|
| 222 | //Parsing and IO working vars
|
---|
| 223 | int ReadBufferIndex;
|
---|
| 224 | int DataInBuffer;
|
---|
[3810] | 225 | text_t::const_iterator next;
|
---|
| 226 | text_t::const_iterator end;
|
---|
[611] | 227 |
|
---|
| 228 | //Clear all the fields
|
---|
| 229 | memset(&RequestFields, 0, sizeof(RequestFieldsT));
|
---|
| 230 |
|
---|
| 231 | ReadBufferIndex = 0;
|
---|
| 232 | DataInBuffer = 0;
|
---|
| 233 |
|
---|
| 234 | //Get First Line
|
---|
| 235 | if (GetLine(CurLine, RequestInfo.ClientSocket, RequestInfo.IOBuffer,
|
---|
| 236 | RequestInfo.IOBufferSize, ReadBufferIndex, DataInBuffer,
|
---|
| 237 | RequestInfo.ThreadNum) != 0) return GH_ERROR;
|
---|
| 238 | do {//Get Next Line, append it if the first charactor is space
|
---|
| 239 | if(GetLine(NextLine, RequestInfo.ClientSocket, RequestInfo.IOBuffer,
|
---|
| 240 | RequestInfo.IOBufferSize, ReadBufferIndex, DataInBuffer,
|
---|
| 241 | RequestInfo.ThreadNum) != 0) return GH_ERROR;
|
---|
[3810] | 242 | if ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t')) {
|
---|
| 243 | CurLine += NextLine;
|
---|
| 244 | }
|
---|
| 245 | } while ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t'));
|
---|
[611] | 246 | //Method String (first word)
|
---|
[3810] | 247 | GetWord(RequestFields.MethodStr, CurLine.begin(), CurLine.end(), next);
|
---|
| 248 | uc(RequestFields.MethodStr);
|
---|
[3017] | 249 |
|
---|
| 250 | /* Added Feb 2002 - IE since about version 5 send stupid frontpage requests
|
---|
| 251 | for MS Document formats eg "GET /_vti_inf.html" */
|
---|
[3810] | 252 | if (RequestFields.MethodStr == "OPTIONS") {
|
---|
| 253 | return GH_BAD_METHOD;
|
---|
[3017] | 254 | }
|
---|
[611] | 255 | //Version String (last word)
|
---|
[3810] | 256 | GetLastWord(RequestFields.VersionStr, CurLine.begin(), CurLine.end(), end);
|
---|
| 257 | uc(RequestFields.VersionStr);
|
---|
| 258 | text_t::const_iterator versionbegin = RequestFields.VersionStr.begin();
|
---|
[611] | 259 |
|
---|
[3810] | 260 | if ((RequestFields.VersionStr.size() > 5) && (substr(versionbegin, versionbegin+5) != "HTTP/")) {
|
---|
[611] | 261 | //No version, assume simple request
|
---|
| 262 | //part after method is URI
|
---|
[3810] | 263 | RequestFields.URIStr = CurLine;
|
---|
[611] | 264 | return GH_SIMPLE_REQUEST;
|
---|
| 265 | }
|
---|
| 266 |
|
---|
| 267 | //URI String (in between End of first and Start of last)
|
---|
| 268 | //<Method> <WhiteSpace> <URI> <WhiteSpace> <Version> <CRLF>
|
---|
[3810] | 269 | // next^ end^
|
---|
[2280] | 270 | text_t spacebuffer;
|
---|
[3810] | 271 | text_t::const_iterator here = next;
|
---|
| 272 | while (here != end) {
|
---|
[2280] | 273 | // do this to remove trailing space
|
---|
[3810] | 274 | if (*here == ' ' || *here == '\t') {
|
---|
| 275 | spacebuffer.push_back(*here);
|
---|
[2280] | 276 | } else {
|
---|
| 277 | if (!spacebuffer.empty()) {
|
---|
| 278 | RequestFields.URIStr += spacebuffer;
|
---|
| 279 | spacebuffer.clear();
|
---|
| 280 | }
|
---|
[3810] | 281 | RequestFields.URIStr.push_back(*here);
|
---|
[2280] | 282 | }
|
---|
[9598] | 283 | ++here;
|
---|
[2280] | 284 | }
|
---|
[2353] | 285 |
|
---|
[611] | 286 | //Only accept requests from HTTP/0.9 or HTTP/1.X clients, we'll
|
---|
| 287 | //assume that anything else will require an upgrade or patch
|
---|
[3810] | 288 | if ((RequestFields.VersionStr.size() > 7) && (substr(versionbegin, versionbegin+7) != "HTTP/1.")) {
|
---|
[611] | 289 | return GH_UNKNOWN_VERSION;
|
---|
[3810] | 290 | }
|
---|
[611] | 291 |
|
---|
| 292 | //Get the rest of the lines
|
---|
[3810] | 293 | CurLine = NextLine;
|
---|
[611] | 294 |
|
---|
[3810] | 295 | while (!CurLine.empty()) {//Blank Line, we're done
|
---|
[611] | 296 | do {//Get Next Line, append it if the first charactor is space
|
---|
| 297 | if (GetLine(NextLine, RequestInfo.ClientSocket, RequestInfo.IOBuffer,
|
---|
| 298 | RequestInfo.IOBufferSize, ReadBufferIndex, DataInBuffer,
|
---|
| 299 | RequestInfo.ThreadNum) != 0)
|
---|
| 300 | return GH_ERROR;
|
---|
[11259] | 301 | if (NextLine.empty())
|
---|
| 302 | break;
|
---|
[3810] | 303 | if ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t')) {
|
---|
| 304 | CurLine += NextLine;
|
---|
| 305 | }
|
---|
| 306 | } while ((*(NextLine.begin()) == ' ') || (*(NextLine.begin()) == '\t'));
|
---|
[611] | 307 |
|
---|
[3810] | 308 | GetWord(FieldNameStr, CurLine.begin(), CurLine.end(), next);
|
---|
| 309 | uc(FieldNameStr);
|
---|
[611] | 310 |
|
---|
[3810] | 311 | FieldValStr = substr(next, CurLine.end());
|
---|
[611] | 312 |
|
---|
| 313 | //Process it
|
---|
| 314 | //In order of expected commonality
|
---|
| 315 | //All constants are in canonized, thus in upper case and case sensitive
|
---|
| 316 | //comparisons are used
|
---|
[3810] | 317 |
|
---|
[611] | 318 | //--Just About Always--
|
---|
[3810] | 319 | if (FieldNameStr == "ACCEPT:") {
|
---|
| 320 | if (!RequestFields.AcceptStr.empty()) {
|
---|
| 321 | RequestFields.AcceptStr += ", ";
|
---|
[611] | 322 | }
|
---|
[3810] | 323 | RequestFields.AcceptStr += FieldValStr;
|
---|
[611] | 324 | }
|
---|
[3810] | 325 | else if (FieldNameStr == "DATE:") {
|
---|
| 326 | RequestFields.DateStr = FieldValStr;
|
---|
[611] | 327 | }
|
---|
[3810] | 328 | else if (FieldNameStr == "USER-AGENT:") {
|
---|
| 329 | RequestFields.UserAgentStr = FieldValStr;
|
---|
[611] | 330 | }
|
---|
[3810] | 331 | else if (FieldNameStr == "CONNECTION:") {
|
---|
| 332 | RequestFields.ConnectionStr = FieldValStr;
|
---|
[611] | 333 | }
|
---|
| 334 | //--Sometimes--
|
---|
[3810] | 335 | else if (FieldNameStr == "ACCEPT-LANGUAGE:") {
|
---|
| 336 | RequestFields.AcceptLangStr = FieldValStr;
|
---|
[611] | 337 | }
|
---|
[3810] | 338 | else if (FieldNameStr == "REFERER:") {
|
---|
| 339 | RequestFields.RefererStr = FieldValStr;
|
---|
[611] | 340 | }
|
---|
[3810] | 341 | else if (FieldNameStr == "IF-MODIFIED-SINCE:") {
|
---|
| 342 | RequestFields.IfModSinceStr = FieldValStr;
|
---|
[611] | 343 | }
|
---|
| 344 | //--Uncommon--
|
---|
[3810] | 345 | else if (FieldNameStr == "FROM:") {
|
---|
| 346 | RequestFields.FromStr = FieldValStr;
|
---|
[611] | 347 | }
|
---|
[3810] | 348 | else if (FieldNameStr == "MIME-VERSION:") {
|
---|
| 349 | RequestFields.MIMEVerStr = FieldValStr;
|
---|
[611] | 350 | }
|
---|
[3810] | 351 | else if (FieldNameStr == "PRAGMA:") {
|
---|
| 352 | RequestFields.PragmaStr = FieldValStr;
|
---|
[611] | 353 | }
|
---|
| 354 | //--Special case--
|
---|
[3810] | 355 | else if (FieldNameStr == "AUTHORIZATION:") {
|
---|
| 356 | RequestFields.AuthorizationStr = FieldValStr;
|
---|
[611] | 357 | }
|
---|
[3810] | 358 | else if (FieldNameStr == "CONTENT-LENGTH:") {
|
---|
| 359 | RequestFields.ContentLengthStr = FieldValStr;
|
---|
[611] | 360 | }
|
---|
[3810] | 361 | else if (FieldNameStr == "CONTENT-TYPE:") {
|
---|
| 362 | RequestFields.ContentTypeStr = FieldValStr;
|
---|
[611] | 363 | }
|
---|
[3810] | 364 | else if (FieldNameStr == "CONTENT-ENCODING:") {
|
---|
| 365 | RequestFields.ContentEncodingStr = FieldValStr;
|
---|
[611] | 366 | }
|
---|
[3810] | 367 | else if (!FieldNameStr.empty()) {
|
---|
[611] | 368 | //Add it to the other headers
|
---|
[3810] | 369 |
|
---|
| 370 | //Remove the colon
|
---|
| 371 | if (*(FieldNameStr.end()-1) == ':') {
|
---|
| 372 | FieldNameStr.pop_back();
|
---|
[611] | 373 | }
|
---|
[3810] | 374 | RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Var = FieldNameStr;
|
---|
| 375 | RequestFields.OtherHeaders[RequestFields.NumOtherHeaders].Val = FieldValStr;
|
---|
[9598] | 376 | ++RequestFields.NumOtherHeaders;
|
---|
[611] | 377 | }
|
---|
[3810] | 378 | CurLine = NextLine;
|
---|
[611] | 379 | }
|
---|
| 380 |
|
---|
[3810] | 381 | if (!RequestFields.ContentLengthStr.empty()) { //Do we have attached data?
|
---|
[611] | 382 | unsigned int NumRecv;
|
---|
| 383 |
|
---|
[3810] | 384 | RequestFields.ContentLength = RequestFields.ContentLengthStr.getint();
|
---|
[611] | 385 | if (RequestFields.ContentLength > 0) {
|
---|
[2353] | 386 |
|
---|
[611] | 387 | //Allocate memory
|
---|
| 388 | RequestFields.Content = new BYTE[RequestFields.ContentLength];
|
---|
| 389 |
|
---|
| 390 | //Get rest of data from get lines
|
---|
| 391 | NumRecv = DataInBuffer - ReadBufferIndex;
|
---|
| 392 |
|
---|
| 393 | if (NumRecv >RequestFields.ContentLength) {
|
---|
| 394 | //Overflow, only read what they said they'd send
|
---|
| 395 | NumRecv = RequestFields.ContentLength;
|
---|
| 396 | }
|
---|
| 397 | memcpy(RequestFields.Content, RequestInfo.IOBuffer + ReadBufferIndex,
|
---|
| 398 | NumRecv);
|
---|
| 399 |
|
---|
| 400 | while (NumRecv < RequestFields.ContentLength) {
|
---|
[2353] | 401 | NumRecv += GetData(RequestInfo.ClientSocket,
|
---|
| 402 | RequestFields.Content + NumRecv,
|
---|
| 403 | RequestFields.ContentLength - NumRecv,
|
---|
| 404 | RequestInfo.ThreadNum);
|
---|
[611] | 405 | if (NumRecv < 0) return GH_ERROR;
|
---|
| 406 | }
|
---|
[2353] | 407 |
|
---|
| 408 | // It seems to be important on NT that all available data was read
|
---|
| 409 | // from the socket before the socket is closed (otherwise netscape
|
---|
| 410 | // throws a "connection reset by peer" error). Since netscape seems
|
---|
| 411 | // to send a few extra bytes in certain situations we'll make sure we
|
---|
| 412 | // slurp it all up here.
|
---|
[9636] | 413 | char *tmpbuffer = new char[100]; // this had new char(100)????
|
---|
[3056] | 414 | // unsigned long int nonblockmode=1;
|
---|
| 415 | // ioctlsocket(RequestInfo.ClientSocket, FIONBIO, &nonblockmode);
|
---|
[2353] | 416 | d_recv(RequestInfo.ClientSocket, tmpbuffer, 100, 0);
|
---|
[9636] | 417 | delete []tmpbuffer;
|
---|
[2353] | 418 |
|
---|
[611] | 419 | }
|
---|
| 420 | else {
|
---|
| 421 | RequestFields.Content = NULL;
|
---|
| 422 | RequestFields.ContentLength = 0;
|
---|
| 423 | }
|
---|
| 424 | }
|
---|
| 425 | else {
|
---|
| 426 | RequestFields.Content = NULL;
|
---|
| 427 | RequestFields.ContentLength = 0;
|
---|
| 428 | }
|
---|
| 429 |
|
---|
| 430 | return GH_10_REQUEST;
|
---|
| 431 | }
|
---|
| 432 |
|
---|
| 433 | /******************************************************************************/
|
---|
| 434 | void CleanUpHTTPHeaders(RequestInfoT &RequestInfo, RequestFieldsT &RequestFields) {
|
---|
| 435 | //Clean up memory allocated for the Content
|
---|
[3810] | 436 | if (RequestFields.Content != NULL) {
|
---|
[611] | 437 | delete[] RequestFields.Content;
|
---|
| 438 | }
|
---|
| 439 |
|
---|
| 440 | // clean up memory allocated for the IOBuffer
|
---|
| 441 | if (RequestInfo.IOBuffer != NULL) {
|
---|
| 442 | delete[] RequestInfo.IOBuffer;
|
---|
| 443 | RequestInfo.IOBuffer = NULL;
|
---|
| 444 | }
|
---|
| 445 | }
|
---|