Go to the documentation of this file.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 "DcResponse.h"
00027
00028
00029 CdcResponse::CdcResponse (CdcSocket* psock, CdcBuffersList& bflst)
00030 :aBody (bflst)
00031 {
00032 if (psock == NULL)
00033 throw (CdcException ("Socket pointer is null"));
00034
00035 pSocket = psock;
00036
00037 Restart ();
00038 }
00039
00040 void CdcResponse::Clear ()
00041 {
00042 aBody.Clear ();
00043 mHeaderFields.clear ();
00044 mCookies.clear ();
00045 }
00046
00047 void CdcResponse::Restart ()
00048 {
00049 Clear ();
00050
00051 CdcHttpTime time;
00052 SetHeaderField ("Accept-Ranges", "None");
00053 SetHeaderField ("Allow", "GET, POST, HEAD");
00054 SetHeaderField ("Date", time.FormatGmt (TIME_FORMAT));
00055 SetHeaderField ("Server", SERVER_NAME);
00056 SetHeaderField ("Connection", "Keep-Alive");
00057
00058 SetVersion (PROTOCOL11_VRS);
00059 nStatusCode = 200;
00060 sStatusPhrase = EMPTY_STR;
00061
00062 isHeaderSent = false;
00063 }
00064
00065 CdcString CdcResponse::GetStatusPhrase (int code) const
00066 {
00067 switch (code)
00068 {
00069 case 100: return CdcString ("Continue");
00070 case 101: return CdcString ("Switching Protocols");
00071 case 200: return CdcString ("OK");
00072 case 201: return CdcString ("Created");
00073 case 202: return CdcString ("Accepted");
00074 case 203: return CdcString ("Non-Authoritative Information");
00075 case 204: return CdcString ("No Content");
00076 case 205: return CdcString ("Reset Content");
00077 case 206: return CdcString ("Partial Content");
00078 case 300: return CdcString ("Multiple Choices");
00079 case 301: return CdcString ("Moved Permanently");
00080 case 302: return CdcString ("Found");
00081 case 303: return CdcString ("See Other");
00082 case 304: return CdcString ("Not Modified");
00083 case 305: return CdcString ("Use Proxy");
00084 case 307: return CdcString ("Temporary Redirect");
00085 case 400: return CdcString ("Bad Request");
00086 case 401: return CdcString ("Unauthorized");
00087 case 402: return CdcString ("Payment Required");
00088 case 403: return CdcString ("Forbidden");
00089 case 404: return CdcString ("Not Found");
00090 case 405: return CdcString ("Method Not Allowed");
00091 case 406: return CdcString ("Not Acceptable");
00092 case 407: return CdcString ("Proxy Authentication Required");
00093 case 408: return CdcString ("Request Time-out");
00094 case 409: return CdcString ("Conflict");
00095 case 410: return CdcString ("Gone");
00096 case 411: return CdcString ("Length Required");
00097 case 412: return CdcString ("Precondition Failed");
00098 case 413: return CdcString ("Request Entity Too Large");
00099 case 414: return CdcString ("Request-URI Too Large");
00100 case 415: return CdcString ("Unsupported Media Type");
00101 case 416: return CdcString ("Requested range not satisfiable");
00102 case 417: return CdcString ("Expectation Failed");
00103 case 500: return CdcString ("Internal Server Error");
00104 case 501: return CdcString ("Not Implemented");
00105 case 502: return CdcString ("Bad Gateway");
00106 case 503: return CdcString ("Service Unavailable");
00107 case 504: return CdcString ("Gateway Time-out");
00108 case 505: return CdcString ("HTTP Version not supported");
00109 }
00110 return CdcString ("Unknown code");
00111 }
00112
00113 int CdcResponse::HeaderToBuffer (CdcBuffer& buff) const
00114 {
00115
00116 buff.RemoveAll ();
00117
00118
00119 buff.Append (sVersion);
00120 buff.Append (' ');
00121 buff.Append (nStatusCode);
00122 buff.Append (' ');
00123 buff.Append (sStatusPhrase);
00124 buff.Append (CRLF);
00125
00126
00127 CdcString name, val;
00128 bool length_header = false;
00129 t_map::const_iterator pos;
00130 for (pos = mHeaderFields.begin ();
00131 pos != mHeaderFields.end (); ++pos)
00132 {
00133 name = (*pos).first;
00134 val = (*pos).second;
00135 if (name.CompareNoCase ("Content-Length") == 0)
00136 length_header = true;
00137 buff.Append (name);
00138 buff.Append (": ");
00139 buff.Append (val);
00140 buff.Append (CRLF);
00141 }
00142
00143
00144 for ( pos = mCookies.begin (); pos != mCookies.end (); ++pos)
00145 {
00146 name = (*pos).first;
00147 val = (*pos).second;
00148 buff.Append ("Set-Cookie: ");
00149 buff.Append (name);
00150 buff.Append (val);
00151 buff.Append (CRLF);
00152 }
00153
00154
00155 if (length_header == false && GetHeaderField ("Transfer-Encoding").IsEmpty ())
00156 {
00157 buff.Append ("Content-Length: ");
00158 buff.Append (aBody.GetDataSize ());
00159 buff.Append (CRLF);
00160 }
00161
00162
00163 buff.Append (CRLF);
00164
00165 return buff.GetDataSize ();
00166 }
00167
00168
00169 int CdcResponse::SendHeader () throw (CdcException)
00170 {
00171 if (isHeaderSent) return 0;
00172
00173 CdcBuffer buff;
00174 int lng = HeaderToBuffer (buff);
00175
00176 lng = pSocket->Write (buff.GetPointer (), lng);
00177 isHeaderSent = true;
00178 return lng;
00179 }
00180
00181 int CdcResponse::SendResponse () throw (CdcException)
00182 {
00183
00184
00185 int lng = 0;
00186 if (nStatusCode == 0 || (lng = SendHeader ()) > 0)
00187 {
00188 bool ret = aBody.SeekFirst ();
00189 while (ret)
00190 {
00191 lng += pSocket->Write (aBody.GetPointer (), aBody.GetLength ());
00192 ret = aBody.SeekNext ();
00193 }
00194 }
00195 else
00196 {
00197 lng += Flush (EMPTY_STR.c_str ());
00198
00199 CdcString tmp = "0 ";
00200 tmp += CRLFCRLF;
00201 lng += pSocket->Write (tmp.GetBuffer (), tmp.GetLength ());
00202 }
00203 return lng;
00204 }
00205
00206
00207
00208 int CdcResponse::Flush (BufferHolder buff) throw (int)
00209 {
00210 int lng = 0;
00211 try
00212 {
00213 if (nStatusCode > 0 && isHeaderSent == false)
00214 {
00215 SetHeaderField ("Transfer-Encoding", "chunked");
00216 lng = SendHeader ();
00217 }
00218
00219 bool ret = aBody.SeekFirst ();
00220 CdcString cnk_hdr;
00221 while (ret)
00222 {
00223 if (nStatusCode > 0)
00224 {
00225 cnk_hdr = CdcString::IntToString (aBody.GetLength (), "%X ") + CRLF;
00226 lng += pSocket->Write (cnk_hdr.GetBuffer (), cnk_hdr.GetLength ());
00227 }
00228 lng += pSocket->Write (aBody.GetPointer (), aBody.GetLength ());
00229 if (nStatusCode > 0)
00230 lng += pSocket->Write (CRLF, CRLF_SIZE);
00231 ret = aBody.SeekNext ();
00232 }
00233
00234 if (buff.empty () == false)
00235 {
00236 if (nStatusCode > 0)
00237 {
00238 cnk_hdr = CdcString::IntToString (buff.size, "%X ") + CRLF;
00239 lng += pSocket->Write (cnk_hdr.GetBuffer (), cnk_hdr.GetLength ());
00240 }
00241 lng += pSocket->Write (buff.pointer, buff.size);
00242 if (nStatusCode > 0)
00243 lng += pSocket->Write (CRLF, CRLF_SIZE);
00244 }
00245
00246 Clear ();
00247 }
00248 catch (CdcException& e)
00249 {
00250 throw e.GetExpCode ();
00251 }
00252 return lng;
00253 }
00254
00255
00256 void CdcResponse::SetCookie (const CdcString& name,
00257 const CdcString& val,
00258 int days, const CdcString& path)
00259 {
00260 CdcString cookie = "=" + val + "; path=" + path + "; expires=";
00261 CdcHttpTime time;
00262 time.AddDays (days);
00263 cookie += time.FormatGmt ("%a, %d-%b-%Y %H:%M:%S GMT");
00264 mCookies [name] = cookie;
00265 }
00266
00267
00268
00269 void CdcResponse::SetVersion (const CdcString& vrs)
00270 {
00271 sVersion = vrs;
00272 }
00273
00274 void CdcResponse::SetStatus (int code)
00275 {
00276 nStatusCode = code;
00277 sStatusPhrase = GetStatusPhrase (nStatusCode);
00278 }
00279
00280 void CdcResponse::SetHeaderField (const CdcString& name, const CdcString& value)
00281 {
00282 if (name == BN_SET_STATUS)
00283 SetStatus (atoi (value.GetBuffer ()));
00284 else
00285 mHeaderFields [name] = value;
00286 }
00287
00288 CdcString CdcResponse::GetHeaderField (CdcString& name)
00289 {
00290 if (name == BN_SET_STATUS)
00291 return CdcString::IntToString (nStatusCode);
00292 else
00293 return mHeaderFields [name];
00294 }
00295