00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "DcRequest.h"
00027
00028 CdcRequest::CdcRequest (CdcSocket* psock)
00029 {
00030 if (psock == NULL)
00031 throw (CdcException ("Socket pointer is null"));
00032 pSocket = psock;
00033 sBuffer.reserve (1024);
00034 }
00035
00036
00037 void CdcRequest::ReadNextRequest ()
00038 {
00039 int place;
00040 ResetRequestFields ();
00041 pSocket->StartNewRequest ();
00042
00043 while ((place = sBuffer.Find (CRLFCRLF)) == -1)
00044 pSocket->Read (sBuffer);
00045 place += CRLFCRLF_SIZE;
00046
00047 ParseHeader (sBuffer.Left (place));
00048
00049 if (place < sBuffer.GetLength ())
00050 sBuffer = sBuffer.Mid (place);
00051 else
00052 sBuffer = EMPTY_STR;
00053
00054 if (sMethod != POST) return;
00055
00056 Handle100Continue ();
00057
00058 CdcString ste = GetHeaderField ("Transfer-Encoding");
00059 ste.MakeLower ();
00060 CdcString msg_body;
00061 if (ste.Find ("chunked") != -1)
00062 DoChunkRequest (msg_body);
00063 else
00064 {
00065 CdcString slng = GetHeaderField ("Content-Length");
00066 if (slng.IsEmpty ())
00067 throw (CdcExceptionParse ("Cannot find the message length",
00068 DC_PARSE_EXP));
00069
00070 int lng = atoi (slng.GetBuffer ());
00071 while (sBuffer.GetLength () < lng)
00072 pSocket->Read (sBuffer);
00073
00074 msg_body = sBuffer.Left (lng);
00075
00076 if (lng < sBuffer.GetLength ())
00077 sBuffer = sBuffer.Mid (lng);
00078 else
00079 sBuffer = EMPTY_STR;
00080 }
00081
00082
00083 SetVariable ("BN_Body", msg_body);
00084 try { ParseQueryLine (msg_body); }
00085 catch (CdcExceptionParse& e) {e.GetExpCode ();}
00086 }
00087
00088
00089 void CdcRequest::Handle100Continue ()
00090 {
00091
00092 if (sVersion == PROTOCOL10_VRS)
00093 return;
00094
00095 if (GetHeaderField ("Expect") == "100-continue")
00096 {
00097 pSocket->Write (CONTINUE_MSG, strlen (CONTINUE_MSG));
00098 pSocket->Write (CRLFCRLF, CRLFCRLF_SIZE);
00099 }
00100 return;
00101 }
00102
00103 void CdcRequest::DoChunkRequest (CdcString& msg_body) throw (CdcException)
00104 {
00105 PrintString ("Chunked Request", PS_DBG);
00106 int place = 0, lng;
00107
00108 while (sBuffer.Find (CRLFCRLF) == -1)
00109 pSocket->Read (sBuffer);
00110
00111 lng = strtoul (sBuffer.GetBuffer (), NULL, 16);
00112 place = sBuffer.Find (CRLF, place) + CRLF_SIZE;
00113 if (place == -1)
00114 throw (CdcExceptionParse ("Bad format of chuncked request",
00115 DC_CNT_PRS_CNK_EXP));
00116
00117 while (lng > 0)
00118 {
00119 if (sBuffer.GetLength () - place < lng)
00120 throw (CdcExceptionParse ("Bad format of chuncked request",
00121 DC_CNT_PRS_CNK_EXP));
00122
00123 msg_body += sBuffer.Mid (place, lng);
00124 place += lng + CRLF_SIZE;
00125
00126 if (sBuffer.GetLength () < place)
00127 throw (CdcExceptionParse ("Bad format of chuncked request",
00128 DC_CNT_PRS_CNK_EXP));
00129 lng = strtoul (sBuffer.Mid (place).GetBuffer (), NULL, 16);
00130 place = sBuffer.Find (CRLF, place) + CRLF_SIZE;
00131 if (place == -1)
00132 throw (CdcExceptionParse ("Bad format of chuncked request",
00133 DC_CNT_PRS_CNK_EXP));
00134 }
00135
00136 while (1)
00137 {
00138 lng = sBuffer.Find (CRLF, place) - place;
00139 if (lng < 0 || sBuffer.GetLength () - place < lng)
00140 throw (CdcExceptionParse ("Bad format of chuncked request",
00141 DC_CNT_PRS_CNK_EXP));
00142 if (lng == place)
00143 break;
00144 ParseHeaderLine (sBuffer.Mid (place, lng - place));
00145 place = lng + CRLF_SIZE;
00146 }
00147 }
00148
00149
00150 void CdcRequest::FindHost () throw (CdcException)
00151 {
00152
00153 sHost = "Default-Host";
00154 sReqHost = EMPTY_STR;
00155 if (sVersion == PROTOCOL10_VRS) return;
00156
00157 sReqHost = GetHeaderField ("Host");
00158 if (sReqHost.IsEmpty ()) throw (CdcExceptionParse (
00159 "HTTP 1.1 request MUST include the Host: header", DC_PARSE_EXP));
00160
00161 int place = sReqHost.Find (':');
00162 if (place != -1) sReqHost = sReqHost.Left (place);
00163
00164 CdcString tmp = sReqHost;
00165 while (1)
00166 {
00167 sHost = CdcParameters::GetParam ("Server->Aliases->" + tmp);
00168 if (sHost.IsEmpty () == false) return;
00169 if (tmp == "*") break;
00170 if (tmp[0] == '*' && tmp[1] == '.')
00171 tmp = tmp.Mid (2);
00172 place = tmp.Find (".");
00173 if (place != -1)
00174 tmp = "*." + tmp.Mid (place + 1);
00175 else
00176 tmp = '*';
00177 }
00178 throw (CdcExceptionParse (
00179 "Wrong host name in the Host: header.", DC_PARSE_EXP));
00180 }
00181
00182
00183 void CdcRequest::ResetRequestFields ()
00184 {
00185 mHeaderFields.clear ();
00186 mVariables.clear ();
00187
00188 sMethod = EMPTY_STR;
00189 sURL = EMPTY_STR;
00190 sVersion = EMPTY_STR;
00191
00192
00193 SetVariable ("BN_ClinetIP", pSocket->GetClientAddress ());
00194 SetVariable ("BN_AppPath", CdcFileUtil::GetProgramPath ());
00195 SetVariable ("BN_Server", SERVER_NAME);
00196 SetVariable ("BN_Port", CdcParameters::GetParam ("Server->Port"));
00197 }
00198
00199
00200
00201 void CdcRequest::ParseHeader (CdcString& msg) throw (CdcException)
00202 {
00203 int endline, place;
00204
00205 place = msg.Find (CRLF);
00206 if (place == -1)
00207 throw (CdcExceptionParse ("Cannot parse the Request message",
00208 DC_CNT_PRS_REQ_EXP));
00209 ParseRequsetLine (msg.Left (place));
00210
00211 place += CRLF_SIZE;
00212 while ((endline = msg.Find (CRLF, place)) > place)
00213 {
00214 CdcString header = msg.Mid (place, endline - place);
00215 if (header.Left (6).CompareNoCase ("Cookie") == 0)
00216 ParseCookiesHeader (header);
00217 ParseHeaderLine (header);
00218 place = endline + CRLF_SIZE;
00219 }
00220 if (endline == -1)
00221 throw (CdcExceptionParse ("Cannot parse the Request message",
00222 DC_CNT_PRS_REQ_EXP));
00223
00224 FindHost ();
00225
00226 SetVariable ("BN_RootPath", CdcFileUtil::GetWorkPath (
00227 CdcParameters::GetParam ("Server->Hosts->" + sHost + "->Root")));
00228 SetVariable ("BN_Host", sHost);
00229 SetVariable ("BN_Alias", sReqHost);
00230 SetVariable ("BN_Version", sVersion);
00231 SetVariable ("BN_Method", sMethod);
00232 SetVariable ("BN_Protocol", sProtocol);
00233 SetVariable ("BN_URL", sURL);
00234 SetVariable ("BN_FullURL", sFullURL);
00235 SetVariable ("BN_Address", sProtocol + "://" + sReqHost + sFullURL);
00236 }
00237
00238
00239 void CdcRequest::ParseRequsetLine (CdcString& line) throw (CdcException)
00240 {
00241 int place;
00242
00243 place = line.Find (' ');
00244 if (place == -1)
00245 throw (CdcExceptionParse ("Cannot find the url part of request line",
00246 DC_CNT_PRS_REQ_LINE_EXP));
00247 sMethod = line.Left (place);
00248 sMethod.TrimLeft ();
00249
00250 if (!(sMethod == GET || sMethod == POST || sMethod == HEAD))
00251 throw (CdcExceptionParse ("Method not Implemented", DC_NOT_SUPPORT));
00252
00253 line = line.Mid (place + 1);
00254 place = line.Find (' ');
00255 if (place == -1)
00256 throw (CdcExceptionParse ("Cannot find the version part of request line",
00257 DC_CNT_PRS_REQ_LINE_EXP));
00258 sFullURL = line.Left (place);
00259 sVersion = line.Mid (place + 1);
00260 sVersion.TrimLeft ();
00261
00262
00263
00264 place = sFullURL.Find ("://");
00265 if (place == -1)
00266 place = -3;
00267 place += 3;
00268 if (place > 0 && sFullURL.Left (place) != "http://")
00269 throw (CdcExceptionParse ("Server Support just HTTP protocol",
00270 DC_CNT_PRS_REQ_LINE_EXP));
00271 sProtocol = "http";
00272
00273 place = sFullURL.Find ('/', place);
00274 if (place == -1)
00275 throw (CdcExceptionParse ("Cannot find '/' in the url",
00276 DC_CNT_PRS_REQ_LINE_EXP));
00277 sURL = sFullURL.Mid (place);
00278
00279 place = sURL.Find ('?');
00280 if (place != -1)
00281 {
00282 CdcString tmp = sURL.Mid (place + 1);
00283 SetVariable ("BN_Query", tmp);
00284 ParseQueryLine (tmp);
00285 sURL = sURL.Left (place);
00286 }
00287 }
00288
00289
00290 void CdcRequest::ParseQueryLine (CdcString& line, char limit) throw (CdcException)
00291 {
00292 CdcString name, val;
00293 int place, end;
00294
00295 do
00296 {
00297 place = line.Find ('=');
00298 if (place == -1)
00299 throw (CdcExceptionParse ("Cannot parse the query part of the url.",
00300 DC_CNT_PRS_QUERY_EXP));
00301 name = line.Left (place);
00302 name.TrimLeft ();
00303 name.TrimRight ();
00304 URIDecode (name);
00305 place++;
00306 while (place < line.GetLength () && line[place] == '=')
00307 ++place;
00308
00309 end = line.Find (limit, place);
00310 if (end == -1)
00311 val = line.Mid (place);
00312 else
00313 val = line.Mid (place, end - place);
00314 val.TrimLeft ();
00315 val.TrimRight ();
00316 URIDecode (val);
00317
00318 if (mVariables.find (name) == mVariables.end ())
00319 mVariables [name] = val;
00320 else
00321 mVariables [name] += ',' + val;
00322
00323
00324 line = line.Mid (end + 1);
00325 }
00326 while (end != -1);
00327 }
00328
00329
00330 void CdcRequest::ParseCookiesHeader (CdcString& line)
00331 {
00332
00333 int place = line.Find (':');
00334 if (place == -1) return;
00335 ++place;
00336
00337 CdcString tmp = line.Mid (place);
00338 SetVariable ("BN_Cookies", tmp);
00339
00340 try
00341 { ParseQueryLine (tmp, ';'); }
00342 catch (CdcExceptionParse& e)
00343 { e.GetExpCode (); }
00344 }
00345
00346 void CdcRequest::URIDecode (CdcString& str)
00347 {
00348 char* stop;
00349 CdcString new_str;
00350 int place, old_place = 0;
00351
00352 str.Replace ('+', ' ');
00353 while (1)
00354 {
00355 place = str.Find ('%', old_place);
00356 if (place == -1)
00357 {
00358 new_str += str.Mid (old_place);
00359 str = new_str;
00360 return;
00361 }
00362 else
00363 {
00364 new_str += str.Mid (old_place, place - old_place);
00365 new_str += (char) strtol (str.Mid (place + 1, 2), &stop, 16);
00366 old_place = place + 3;
00367 }
00368 }
00369 }
00370
00371
00372 void CdcRequest::ParseHeaderLine (CdcString& line) throw (CdcException)
00373 {
00374 int place = line.Find (':');
00375 if (place == -1)
00376 throw (CdcExceptionParse ("Cannot parse the header field",
00377 DC_CNT_PRS_HEADER_EXP));
00378
00379 CdcString name = line.Left (place);
00380 name.TrimLeft ();
00381 name.TrimRight ();
00382 name.MakeLower ();
00383
00384 CdcString val = line.Mid (place + 1);
00385 val.TrimLeft ();
00386 val.TrimRight ();
00387
00388 mHeaderFields [name] = val;
00389 }
00390
00391 void CdcRequest::EraseHeaderField (const CdcString& name)
00392 {
00393 CdcString temp = name;
00394 temp.MakeLower ();
00395 mHeaderFields.erase (temp);
00396 }
00397
00398 const string& CdcRequest::__GetHeaderField (const CdcString& name) const
00399 {
00400 CdcString temp = name;
00401 temp.MakeLower ();
00402 t_const_itr itr = mHeaderFields.find (temp);
00403 if (itr == mHeaderFields.end ())
00404 return EMPTY_STR;
00405 return itr->second;
00406 }
00407
00408 const string& CdcRequest::__GetVariable (const CdcString& name) const
00409 {
00410 t_const_itr itr = mVariables.find (name);
00411 if (itr == mVariables.end ())
00412 return EMPTY_STR;
00413 return itr->second;
00414 }
00415
00416 BufferHolder CdcRequest::GetRequestVarsNamesList (BufferHolder sep)
00417 {
00418 sVarList.clear ();
00419 CdcString s_sep (sep);
00420 t_map* pmap;
00421 t_map::const_iterator pos;
00422
00423 if (s_sep[0] == 'H')
00424 {
00425 pmap = &mHeaderFields;
00426 s_sep = s_sep.Mid (1);
00427 }
00428 else
00429 pmap = &mVariables;
00430
00431 for (pos = pmap->begin ();
00432 pos != pmap->end (); ++pos)
00433 {
00434 if (sVarList.empty () == false)
00435 sVarList += s_sep;
00436 sVarList += pos->first;
00437 }
00438
00439 return BufferHolder (sVarList.c_str ());
00440 }
00441