00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <HttpServletResponseImpl.h>
00021 #include <servlet/IllegalStateException.h>
00022 #include <servlet/ServletException.h>
00023
00024 #include <sstream>
00025
00026 namespace container {
00027
00028 HttpServletResponseImpl::HttpServletResponseImpl(Connection& con, const std::string& mimeType, const std::string& charEnc)
00029 : m_req(0)
00030 , m_contentLength(-1)
00031 , m_contentType(mimeType)
00032 , m_characterEncoding(charEnc)
00033 , m_outputStream(con,*this)
00034 , m_committed(false)
00035 , m_statusCode(SC_OK)
00036 {
00037 }
00038
00039
00040 HttpServletResponseImpl::~HttpServletResponseImpl()
00041 {
00042 }
00043
00050 void HttpServletResponseImpl::sendHeaders(Connection& c)
00051 {
00052 std::ostream con(&c);
00053 std::string ct = getContentType();
00054 if(!getCharacterEncoding().empty())
00055 ct+="; charset="+getCharacterEncoding();
00056 setHeader(std::string("content-type"),ct);
00057
00058 con<<"Status: "<<m_statusCode<<'\n';
00059 if(m_contentLength!=-1)
00060 con<<"Content-length: "<<m_contentLength<<'\n';
00061 for(util::mparam_t::iterator cur=m_headers.begin(); cur!=m_headers.end(); cur++)
00062 con<<cur->first<<": "<<cur->second<<'\n';
00063
00064 for(cookielist_t::iterator curC=m_cookies.begin(); curC!=m_cookies.end(); curC++){
00065 std::stringstream cookieStr;
00066 time_t maxAge=curC->getMaxAge();
00067 cookieStr<<curC->getName()<<'='<<quoteString(curC->getValue());
00068 if(!curC->getDomain().empty())
00069 cookieStr<<"; Domain="<<quoteString(curC->getDomain());
00070 if(!curC->getPath().empty())
00071 cookieStr<<"; Path="<<quoteString(curC->getPath());
00072 if(curC->getSecure())
00073 cookieStr<<"; Secure;";
00074 if(curC->getVersion()!=0){
00075 cookieStr<<"; Version="<<curC->getVersion();
00076 if(!curC->getComment().empty())
00077 cookieStr<<"; Comment="<<quoteString(curC->getComment());
00078 if(maxAge>=0)
00079 cookieStr<<"; Max-Age="<<maxAge;
00080 }else{
00081 if(maxAge>=0) {
00082 char date[32];
00083 struct tm exp;
00084 maxAge=maxAge?maxAge+::time(0):1;
00085 ::gmtime_r(&maxAge, &exp);
00086 ::strftime(date, sizeof(date), "\"%a, %d-%m-%Y %H:%M:%S %Z\"", &exp);
00087 cookieStr<<"; Expires="<<date;
00088 }
00089 }
00090 con<<"Set-Cookie: "<<cookieStr.str()<<'\n';
00091 std::cerr<<"Set-Cookie: "<<cookieStr.str()<<std::endl;
00092 }
00093 con<<'\n';
00094 m_committed=true;
00095 }
00096
00097 std::string HttpServletResponseImpl::quoteString(const std::string& in)
00098 {
00099 std::string out;
00100 if(in.empty())
00101 out="\"\"";
00102 else if(in.find_first_of(",; \"")!=std::string::npos)
00103 {
00104 out.reserve(in.length()+2);
00105 out+='"';
00106 for(std::string::size_type i=0; i<in.length(); i++)
00107 {
00108 if(in[i]=='"')
00109 out+="\\\"";
00110 else
00111 out+=in[i];
00112 }
00113 out+='"';
00114 }
00115 else
00116 out.assign(in);
00117 return out;
00118 }
00119
00120 }
00121
00125 void container::HttpServletResponseImpl::flushBuffer()
00126 {
00127 getOutputStream().flush();
00128 }
00129
00130
00134 void container::HttpServletResponseImpl::reset()
00135 {
00136 resetBuffer();
00137 m_headers.clear();
00138 m_cookies.clear();
00139 setContentType("text/html");
00141 }
00142
00143
00151 void container::HttpServletResponseImpl::resetBuffer()
00152 {
00153 if(isCommitted())
00154 throw servlet::IllegalStateException();
00156 }
00157
00158
00162 void container::HttpServletResponseImpl::addHeader(const std::string& name, const std::string& value)
00163 {
00164 if(isCommitted())
00165 throw servlet::IllegalStateException();
00166
00167 std::string lname(name);
00168 std::transform(lname.begin(),lname.end(),lname.begin(),::tolower);
00169 m_headers.insert(util::nvpair(lname,value));
00170 }
00171
00172 void container::HttpServletResponseImpl::setHeader(const std::string& name, const std::string& value)
00173 {
00174 if(isCommitted())
00175 throw servlet::IllegalStateException();
00176
00177 std::string lname(name);
00178 std::transform(lname.begin(),lname.end(),lname.begin(),::tolower);
00179 m_headers.erase(m_headers.lower_bound(lname),m_headers.upper_bound(lname));
00180 m_headers.insert(util::nvpair(name,value));
00181 }
00182
00186 bool container::HttpServletResponseImpl::containsHeader(const std::string& name) const
00187 {
00188 std::string lname(name);
00189 std::transform(lname.begin(),lname.end(),lname.begin(),::tolower);
00190 return m_headers.find(lname)!=m_headers.end();
00191 }
00192
00193
00197 void container::HttpServletResponseImpl::setStatus(int sc)
00198 {
00199 if(isCommitted())
00200 throw servlet::IllegalStateException();
00201
00202 m_statusCode=sc;
00203 }
00204
00205
00209 void container::HttpServletResponseImpl::sendRedirect(const std::string& location)
00210 {
00211 if(isCommitted())
00212 throw servlet::IllegalStateException();
00213
00214 sendError(SC_SEE_OTHER);
00215 addHeader("Location",location);
00216
00217 getOutputStream()<<"\n";
00218 }
00219
00220
00224 void container::HttpServletResponseImpl::sendError(int sc)
00225 {
00226 if(isCommitted())
00227 throw servlet::IllegalStateException();
00228
00229 m_statusMsg.clear();
00230 m_statusCode=sc;
00231 }
00232
00233
00237 void container::HttpServletResponseImpl::sendError(int sc, const std::string& msg)
00238 {
00239 if(isCommitted())
00240 throw servlet::IllegalStateException();
00241
00242 m_statusCode=sc;
00243 m_statusMsg=msg;
00244 }
00245
00246
00250 std::string container::HttpServletResponseImpl::getStatusMessage()
00251 {
00252 if(!m_statusMsg.empty())
00253 return m_statusMsg;
00254 switch(m_statusCode){
00255 case SC_OK:
00256 return std::string("OK");
00257 case SC_NOT_FOUND:
00258 return std::string("Servlet is not defined");
00259 default:
00260 return std::string("No message");
00261 }
00262 }
00263
00264
00268 void container::HttpServletResponseImpl::addCookie(const servlet::Cookie& cookie)
00269 {
00270 if(isCommitted()){
00271 throw servlet::IllegalStateException();
00272 }
00273 m_cookies.push_back(cookie);
00274 }
00275
00276 namespace container
00277 {
00278 std::string HttpServletResponseImpl::getCharacterEncoding()
00279 {
00280 return m_characterEncoding;
00281 }
00282 std::string HttpServletResponseImpl::getContentType()
00283 {
00284 return m_contentType;
00285 }
00286 std::ostream& HttpServletResponseImpl::getOutputStream()
00287 {
00288 return m_outputStream;
00289 }
00290 void HttpServletResponseImpl::setCharacterEncoding(const std::string& charset)
00291 {
00292 if(isCommitted()){
00293 throw servlet::IllegalStateException();
00294 }
00295 m_characterEncoding = charset;
00296 }
00297 void HttpServletResponseImpl::setContentLength(int len)
00298 {
00299 if(isCommitted()){
00300 throw servlet::IllegalStateException();
00301 }
00302 m_contentLength = len;
00303 }
00304 void HttpServletResponseImpl::setContentType(const std::string& type)
00305 {
00306 if(isCommitted()){
00307 throw servlet::IllegalStateException();
00308 }
00309 m_contentType = type;
00310 }
00311 void HttpServletResponseImpl::setBufferSize(int size)
00312 {
00313 m_outputStream.setBufferSize(size);
00314 }
00315 int HttpServletResponseImpl::getBufferSize()
00316 {
00317 return m_outputStream.getBufferSize();
00318 }
00319 bool HttpServletResponseImpl::isCommitted()
00320 {
00321 return m_committed;
00322 }
00323
00325 std::string HttpServletResponseImpl::encodeURL(const std::string& url)
00326 {
00327
00328 return url;
00329 }
00330 std::string HttpServletResponseImpl::encodeRedirectURL(const std::string& url)
00331 {
00332
00333 return url;
00334 }
00335 void HttpServletResponseImpl::setDateHeader(const std::string& name, long date)
00336 {
00337 struct tm out;
00338 gmtime_r(&date, &out);
00339 char str[32];
00340 strftime(str, sizeof(str), "%a, %d %b %Y %H:%M:%S GMT", &out);
00341 setHeader(name, str);
00342 }
00343 void HttpServletResponseImpl::addDateHeader(const std::string& name, long date)
00344 {
00345 struct tm out;
00346 gmtime_r(&date, &out);
00347 char str[32];
00348 strftime(str, sizeof(str), "%a, %d %b %Y %H:%M:%S GMT", &out);
00349 addHeader(name, str);
00350 }
00351 void HttpServletResponseImpl::setIntHeader(const std::string& name, int value)
00352 {
00353 std::stringstream val;
00354 val<<value;
00355 setHeader(name, val.str());
00356 }
00357 void HttpServletResponseImpl::addIntHeader(const std::string& name, int value)
00358 {
00359 std::stringstream val;
00360 val<<value;
00361 addHeader(name, val.str());
00362 }
00363 }