CPPSERV


Home Projects Jobs Clientele Contact
CPPSERV Documentation Download TODO Mailing lists Bug tracker News RSS Feed Browse source

HttpServletRequestImpl.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2004-2006 by Ilya A. Volynets-Evenbakh                  *
00003  *   ilya@total-knowledge.com                                              *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include <HttpServletRequestImpl.h>
00021 #include <HttpServletResponseImpl.h>
00022 #include <util.h>
00023 #include <servlet/Util.h>
00024 #include <UploadedFileImpl.h>
00025 #include <servlet/ServletException.h>
00026 #include <servlet/NumberFormatException.h>
00027 #include <servlet/IllegalArgumentException.h>
00028 #include <servlet/IllegalStateException.h>
00029 #include <serverconfig/serverconfig.h>
00030 #include <servlet/ServletException.h>
00031 
00032 #include <sstream>
00033 #include <iterator>
00034 #include <algorithm>
00035 
00036 #include <ctype.h>
00037 
00038 #include <iostream>
00039 #include <stdlib.h>
00040 #include <unistd.h>
00041 #include <limits.h>
00042 #include <netdb.h>
00043 #include <sys/types.h>
00044 #include <sys/socket.h>
00045 #include <arpa/inet.h>
00046 
00047 #include <boost/tokenizer.hpp>
00048 
00049 namespace container {
00050 
00051 HttpServletRequestImpl::HttpServletRequestImpl(Connection& con,serverconfig::AppContext* ctx,
00052             const std::string& servletPath, size_t maxRequestSize, size_t maxFileSize)
00053     : m_localPort(0)
00054     , m_remotePort(0)
00055     , m_contentLength(-1)
00056     , m_servletPath(servletPath)
00057     , m_session(0)
00058     , m_maxRequestSize(maxRequestSize)
00059     , m_maxFileSize(maxFileSize)
00060     , m_inputStreamTaken(false)
00061     , m_con(con)
00062     , m_ctx(ctx)
00063     , m_resp(0)
00064     , m_inputStream(&con)
00065 {
00066 }
00067 
00068 void HttpServletRequestImpl::load()
00069 {
00070     m_con.setLimit(m_maxRequestSize);
00071     getHeaders();
00072     getParams();
00073     m_con.setLimit(-1);
00074     if(m_characterEncoding.empty())
00075         m_characterEncoding="ISO-8859-1";
00076 }
00077 
00078 HttpServletRequestImpl::~HttpServletRequestImpl()
00079 {
00080     //delete inputStream;
00081     for(filelist_t::iterator it=m_files.begin(); it!=m_files.end();it++)
00082         delete it->second;
00083     for(cookielist_t::iterator it = m_cookies.begin(); it!= m_cookies.end(); it++)
00084         if(it->second)
00085             delete it->second;
00086 }
00087 
00088 void HttpServletRequestImpl::parseAddr(const std::string& addr, std::string& name, unsigned short& port)
00089 {
00090     std::string::size_type colon=addr.find(':');
00091     if(colon!=std::string::npos){
00092         name=addr.substr(0,colon);
00093         port=atoi(addr.substr(colon+1).c_str());
00094     } else {
00095         name=addr;
00096     }
00097 }
00098 
00099 void HttpServletRequestImpl::addr2host(const std::string& addr, std::string& name)
00100 {
00101     if(addr.empty())
00102         return;
00103     struct in_addr a;
00104     if(inet_pton(AF_INET, addr.c_str(), &a)>0)
00105     {
00106         struct hostent he, *phe;
00107         char buf[1024];
00108         int err;
00109         gethostbyaddr_r(&a, sizeof(a), AF_INET, &he, buf, sizeof(buf), &phe, &err);
00110         if(phe)
00111         {
00112             name = he.h_name;
00113         }
00114     }
00115 }
00116 
00124 void HttpServletRequestImpl::getHeaders()
00125 {
00126 //Use stringstream here to parse...
00127     std::string line;
00128     getline(m_inputStream,line);
00129     std::string::size_type i=line.find(' ');
00130     if(i==std::string::npos)
00131         return;
00132     m_method.assign(line,0,i);
00133     std::transform(m_method.begin(),m_method.end(),m_method.begin(),::toupper);
00134     std::string::size_type j=++i;
00135     i=line.find(' ',i);
00136     if(i==std::string::npos)
00137         return;
00138     m_uri.assign(line, j, i-j);
00139     m_protocol.assign(line, i+1, line.length()-i-1);
00140     i=m_uri.find("://");
00141     if(i==std::string::npos) {
00142         m_scheme="http";
00143         i = 0;
00144     } else {
00145         m_scheme.assign(m_uri,0,i-1);
00146         m_uri=m_uri.substr(i+3);
00147     }
00148     i=m_uri.find('?');
00149     if(i!=std::string::npos){
00150         m_queryString.assign(m_uri.substr(i+1));
00151         m_uri.erase(i);
00152     }
00153     std::string servPath(getServletPath() + '/');
00154     i=m_uri.find(servPath);
00155     if(i!=std::string::npos){
00156         m_pathInfo=m_uri.substr(i + servPath.length());
00157     }
00158     std::transform(m_scheme.begin(),m_scheme.end(),m_scheme.begin(),::tolower);
00159     m_serverPort=80;
00160     if(m_scheme == "https")
00161         m_serverPort=443;
00162     while(getline(m_inputStream,line)){
00163         if(line.empty())
00164             return;
00165         i=line.find(':');
00166         std::string header(line.substr(0,i));
00167         while(line[++i]==' ') i++; // skip white spaces
00168         std::string value(line.substr(i));
00169         std::transform(header.begin(),header.end(),header.begin(),::tolower);
00170         m_headers.insert(util::nvpair(header,value));
00171         if(header=="content-type"){
00172             m_contentType=value;
00173         }else if (header=="content-length"){
00174             m_contentLength=::strtoul(value.c_str(),0,0);
00175         }else if (header=="host" || header=="hostname"){
00176             parseAddr(value, m_serverName, m_serverPort);
00177         }else if(header=="cookie") {
00178             parseCookieHeader(value);
00179         }else if(header=="localaddr") {
00180             parseAddr(value, m_localAddr, m_localPort);
00181         }else if(header=="remoteaddr") {
00182             parseAddr(value, m_remoteAddr, m_remotePort);
00183         }else if(header=="localhost") {
00184             m_localName=value;
00185         }else if(header=="remotehost") {
00186             m_remoteHost=value;
00187         }else if(header=="remoteport") {
00188             m_remotePort=::atoi(value.c_str());
00189         }else if(header=="localport") {
00190             m_localPort=::atoi(value.c_str());
00191         }
00192     }
00193 }
00194 
00195 
00203 void HttpServletRequestImpl::getParams()
00204 {
00205     if(!getQueryString().empty()){
00206         std::stringstream ss(getQueryString());
00207         parseQueryString(ss);
00208     }
00209     if(m_contentLength!=-1 && m_method=="POST"){
00210         std::string transfer_encoding=
00211             getHeader("content-type");
00212         size_t rs = ((size_t)m_contentLength>m_maxRequestSize)?m_maxRequestSize:m_contentLength;
00213         if(transfer_encoding.find("multipart/form-data")!=std::string::npos) {
00214             parseMultipartData(m_inputStream);
00215         } else {
00216             parseQueryString(m_inputStream);
00217         }
00218     }
00219 }
00220 
00224 void HttpServletRequestImpl::parseQueryString(std::istream& queryString)
00225 {
00226     std::istream_iterator<char> begin(queryString);
00227     boost::char_separator<char> amp("&","",boost::keep_empty_tokens);
00228     boost::char_separator<char> eq("=","",boost::keep_empty_tokens);
00229     boost::tokenizer<boost::char_separator<char>, std::istream_iterator<char> > t(begin, std::istream_iterator<char>(), amp);
00230     for(boost::tokenizer<boost::char_separator<char>, std::istream_iterator<char> >::iterator token=t.begin();
00231         token!=t.end(); token++)
00232     {
00233         boost::tokenizer<boost::char_separator<char> > nv(*token, eq);
00234         boost::tokenizer<boost::char_separator<char> >::const_iterator it=nv.begin();
00235         std::string name, value;
00236         if(it!=nv.end()) {
00237             name=*it;
00238             it++;
00239         }
00240         if(it!=nv.end())
00241             value=*it;
00242         servlet::util::urlInPlaceDecode(name);
00243         servlet::util::urlInPlaceDecode(value);
00244         m_parameters.insert(util::nvpair(name,value));
00245     }
00246 }
00247 
00248 
00249 void HttpServletRequestImpl::CookieSeparator::do_escape(std::string::const_iterator next,std::string::const_iterator end,std::string& tok)
00250 {
00251     if (++next == end)
00252         throw servlet::IllegalArgumentException("error while parsing cookie: cannot end with escape");
00253     tok+=*next;
00254 }
00255 
00256 bool HttpServletRequestImpl::CookieSeparator::operator()(std::string::const_iterator& next,std::string::const_iterator end,std::string& tok)
00257 {
00258     //bool bInQuote = false;
00259     tok.clear();
00260     if (next == end)
00261     {
00262         return false;
00263     }
00264     // We just came here, so we are
00265     // at the beginning of a token
00266     // (IOW, not in quote, not in escape, etc
00267     // Check if char is one of return delimiters
00268     if(is_sep(*next, m_sep_return))
00269     {
00270         tok+=*next;
00271         ++next;
00272         return true;
00273     }
00274     for (;next != end;++next)
00275     {
00276         if (is_escape(*next))
00277         {
00278             do_escape(next,end,tok);
00279         }
00280         else if(!m_cur_quote)
00281         {
00282             if(is_sep(*next,m_sep_drop))
00283             {
00284                 if(tok.empty())
00285                     continue;
00286                 ++next;
00287                 return true;
00288             }
00289             else if (is_sep(*next,m_sep_return))
00290             {
00291                 // We are at one of returned separators
00292                 // Stop, without advancing
00293                 if(tok.empty())
00294                     continue;
00295                 return true;
00296             }
00297             else if (is_quote(*next))
00298             {
00299                 m_cur_quote = *next;
00300             }
00301             else
00302                 tok += *next;
00303         }
00304         else
00305         {
00306             if(is_quote(*next))
00307                 m_cur_quote=0;
00308             else
00309                 tok += *next;
00310         }
00311     }
00312     return !tok.empty();
00313 }
00314 
00319 void HttpServletRequestImpl::parseCookieHeader(const std::string& data)
00320 {
00321     if(!data.empty())
00322     {
00323         CookieSeparator sep;
00324         typedef boost::tokenizer<CookieSeparator> tokenizer;
00325         tokenizer t(data, sep);
00326         enum {C_VERSION, C_CONTENT, C_ATTRS} state = C_VERSION;
00327         char version;
00328         std::string name;
00329         std::string value;
00330         servlet::Cookie *cookie;
00331         for(tokenizer::iterator token=t.begin(); token!=t.end(); token++)
00332         {
00333             std::string nm;
00334             std::string val;
00335             nm=*token;
00336             if(++token == t.end() || *token!="=") // Invalid cookie token. Ignore for now.
00337             {
00338                 std::cerr<<"Invalid cookie token: "<<*token<<" (full string: \""<<data<<"\")"<<std::endl;
00339                 break;
00340             }
00341             if(++token != t.end())
00342                 val=*token;
00343             if(nm[0]=='$')
00344                 std::transform(nm.begin(),nm.end(),nm.begin(),::tolower);
00345             switch(state)
00346             {
00347             case C_ATTRS:
00348                 if(nm[0]=='$' && nm!="$version")
00349                 {
00350                     if(nm=="$path")
00351                         cookie->setPath(val);
00352                     else if(nm=="$domain")
00353                         cookie->setDomain(val);
00354                     else
00355                         std::cerr<<"Unknown attribute \""<<nm
00356                             <<"\" for cookie \""<<name
00357                             <<"\" (full header value: \""
00358                             <<data<<"\")"<<std::endl;
00359                     break;
00360                 }
00361             case C_VERSION:
00362                 name.clear();
00363                 value.clear();
00364                 if(nm=="$version")
00365                 {
00366                     version=::atoi(val.c_str());
00367                     state = C_CONTENT;
00368                     break;
00369                 }
00370                 else if(nm[0]=='$') // Can't start with attribute unless it's version...
00371                 {
00372                     throw servlet::IllegalArgumentException("Invalid cookie header: "+data);
00373                 }
00374                 else
00375                 {
00376                     version=0;
00377                 }
00378             case C_CONTENT:
00379                 name=nm;
00380                 value=val;
00381                 cookie = new servlet::Cookie(name, value);
00382                 cookie->setVersion(version);
00383                 m_cookies[name]=cookie;
00384                 if(name==m_ctx->getSessionCookieName())
00385                 {
00386                     m_sessionId=value;
00387                 }
00388                 state=C_ATTRS;
00389                 break;
00390             }
00391         }
00392     }
00393 }
00394 
00395 
00406 servlet::HttpSession* HttpServletRequestImpl::getSession(bool create)
00407 //  throw (servlet::IllegalStateException)
00408 {
00409     if(m_session)
00410         return m_session;
00411     m_session=m_ctx->getSession(getRequestedSessionId(), create);
00412     if(m_session && m_session->isNew()){
00413         servlet::Cookie sc(m_ctx->getSessionCookieName(),m_session->getId());
00414         sc.setMaxAge(-1);
00415         sc.setPath(m_ctx->getUriBase()+m_ctx->getServletContextName());
00416         m_resp->addCookie(sc);
00417     }
00418     return m_session;
00419 }
00420 
00421 
00431 void HttpServletRequestImpl::setRespRef(HttpServletResponseImpl* resp)
00432 {
00433     this->m_resp=resp;
00434     // If client sent session cookie and session is valid, touch session
00435     if((!getRequestedSessionId().empty())&&isRequestedSessionIdValid()){
00436         getSession();
00437     }
00438 }
00439 
00440 
00444 bool HttpServletRequestImpl::isRequestedSessionIdValid()
00445 {
00446     return m_ctx->isSessionValid(this->getRequestedSessionId());
00447 }
00448 
00449 
00458 servlet::UploadedFile* HttpServletRequestImpl::getUploadedFile(const std::string& name)
00459 {
00460     filelist_t::const_iterator it=m_files.find(name);
00461     if(it==m_files.end())
00462         return 0;
00463     return it->second;
00464 }
00465 
00466 class CharSink
00467 {
00468 public:
00469     virtual void consume(char* data, int maxind) = 0;
00470     virtual ~CharSink(){}
00471 };
00472 
00473 static bool find_boundary(const std::string& boundary, std::istream& data, CharSink& sink)
00474 {
00475     char buf[boundary.length()];
00476     std::string::size_type ptr=0;
00477     while(!data.eof()) {
00478         data.read(buf+ptr,1);
00479         if(boundary[ptr]!=buf[ptr]) {
00480             sink.consume(buf, ptr);
00481             ptr = 0;
00482         } else {
00483             if(++ptr == boundary.length()) // Found a match
00484                 return true;
00485         }
00486     }
00487     return false; // Didn't find boundary match before EOF
00488 }
00489 
00490 class NullCharSink: public CharSink
00491 {
00492 public:
00493     virtual void consume(char* data, int maxind){}
00494     virtual ~NullCharSink(){}
00495 };
00496 
00497 class MimePartCharSink: public CharSink
00498 {
00499 private:
00500     enum state
00501     {
00502         HEADER_NAME,
00503         HEADER_VALUE_BEGIN,
00504         HEADER_VALUE,
00505         HEADER_VALUE_END,
00506         DATA
00507     } state;
00508     HttpServletRequestImpl& req;
00509     std::string headerName;
00510     std::string headerValue;
00511     std::string fileName;
00512     std::string filePath;
00513     std::string contentType;
00514     std::ostream *dataout;
00515     std::string partName;
00516     bool empty;
00517     bool killFile;
00518 public:
00519     virtual void consume(char* data, int maxind)
00520     {
00521         for(int i=0; i<=maxind; i++)
00522         {
00523             switch(state)
00524             {
00525             case HEADER_NAME:
00526                 switch(data[i])
00527                 {
00528                 case ' ':
00529                     break;
00530                 case ':':
00531                     state=HEADER_VALUE_BEGIN;
00532                     break;
00533                 case '\r':
00534                     state=HEADER_VALUE_END;
00535                     break;
00536                 default:
00537                     headerName.append(data+i,1);
00538                     break;
00539                 }
00540                 break;
00541             case HEADER_VALUE_BEGIN:
00542                 if(data[i]==' ') {
00543                     break;
00544                 } else if(data[i]=='\r') {
00545                     state=HEADER_VALUE_END;
00546                 } else {
00547                     state=HEADER_VALUE;
00548                     headerValue.assign(data+i,1);
00549                 }
00550                 break;
00551             case HEADER_VALUE:
00552                 if(data[i]=='\r') {
00553                     state=HEADER_VALUE_END;
00554                 } else {
00555                     headerValue.append(data+i,1);
00556                 }
00557                 break;
00558             case HEADER_VALUE_END:
00559                 if(data[i]!='\n')
00560                     throw servlet::ServletException("Invalid header in multi-part/form-data post");
00561                 processHeader();
00562                 break;
00563             case DATA:
00564                 dataout->write(data+i, maxind-i+1);
00565                 if(dataout->bad())
00566                 {
00567                     throw servlet::IOError("Unable to write all of data");
00568                 }
00569                 i=maxind+1;
00570                 empty=false;
00571                 break;
00572             }
00573         }
00574     }
00575     void partDone()
00576     {
00577         if(partName.empty())
00578             return;
00579         if(filePath.empty()) {
00580             req.addParam(partName,static_cast<std::stringstream*>(dataout)->str());
00581         } else {
00582             req.addUploadedFile(partName,new UploadedFileImpl(filePath,empty,contentType,fileName));
00583             killFile=false;
00584         }
00585     }
00586 private:
00587     void processHeader()
00588     {
00589         if(headerName.empty()) {
00590             if(headerValue.empty()) {
00591                 if(fileName.empty()) {
00592                     dataout = new std::stringstream;
00593                 } else {
00594                     char tmpPath[PATH_MAX];
00595                     strncpy(tmpPath,req.getFileSaveTemplate().c_str(),PATH_MAX);
00596                     int fd=::mkstemp(tmpPath); // Just how portable is this?
00597                     if(fd==-1)
00598                         throw servlet::IOError("creating temporary file");
00599                     ::close(fd); // Should we just use fd-based stream?
00600                     filePath=tmpPath;
00601                     dataout = new std::ofstream(tmpPath, std::ofstream::out|std::ofstream::trunc);
00602                 }
00603                 state = DATA;
00604                 return;
00605             }
00606         } else {
00607             std::transform(headerName.begin(),headerName.end(),headerName.begin(),::tolower);
00608             if(headerName=="content-type") {
00609                 contentType = headerValue;
00610             } else if(headerName=="content-disposition") {
00611                 std::string::size_type col=headerValue.find("name=");
00612                 if(col!=std::string::npos) {
00613                     col+=sizeof("name=")-1;
00614                     partName=getHeaderPart(headerValue,col);
00615                 }
00616                 col=headerValue.find("filename=");
00617                 if(col!=std::string::npos) {
00618                     col+=sizeof("filename=")-1;
00619                     fileName=getHeaderPart(headerValue,col);
00620                 }
00621             }
00622             state=HEADER_NAME;
00623             headerName.clear();
00624             headerValue.clear();
00625         }
00626     }
00632     std::string getHeaderPart(std::string header, std::string::size_type start)
00633     {
00634         start=header.find_first_not_of(" \t",start, 2);
00635         if(start==std::string::npos)
00636             return std::string();
00637         std::string::size_type end=0;
00638         if(header[start]=='"') {
00639             start++;
00640             end=header.find('"', start);
00641             if(end==std::string::npos)
00642                 throw servlet::ServletException("Invalid header value (unterminated quote)");
00643             header.erase(end);
00644         }
00645         end=header.find(';',end);
00646         if(end==std::string::npos)// last element
00647             end=header.length();
00648         end--;
00649         end=header.find_last_not_of(" \t", end, 2);
00650         if(header[end]=='"')end--;
00651         return header.substr(start, end-start+1);
00652     }
00653 public:
00654     MimePartCharSink(HttpServletRequestImpl& req)
00655         : state(HEADER_NAME)
00656         , req(req)
00657         , dataout(0)
00658         , empty(true)
00659         , killFile(true)
00660     {}
00661     ~MimePartCharSink()
00662     {
00663         if(dataout)
00664             delete dataout;
00665         if(!filePath.empty() && killFile)
00666             ::unlink(filePath.c_str());
00667     }
00668 };
00669 
00677 void HttpServletRequestImpl::parseMultipartData(std::istream& data)
00678 {
00679     std::string::size_type pos=getContentType().find("boundary=")+sizeof("boundary=")-1;
00680     std::string boundary("--");
00681     boundary.append(getContentType().substr(pos));
00682     NullCharSink nullSink;
00683     if(!find_boundary(boundary, data, nullSink))
00684         throw servlet::ServletException("Unable to parse multipart/form-data request: could not find boundary"); // Probably didn't get all of the request
00685     char c[2];
00686     data.read(c,2);
00687     if(c[0] != '\r' || c[1]!='\n') {
00688         throw servlet::ServletException("Unable to parse multipart/form-data request: could not find boundary"); // Probably didn't get all of the request
00689     }
00690     boundary.insert(0,"\r\n",2);
00691     while(true) {
00692         MimePartCharSink sink(*this);
00693         if(!find_boundary(boundary, data, sink))
00694             throw servlet::ServletException("Unable to parse multipart/form-data request: could not find boundary"); // Probably didn't get all of the request
00695         sink.partDone();
00696         data.read(c,2);
00697         if(c[0] == '\r' && c[1]=='\n') {
00698             continue;
00699         } else if (c[0] == '-' && c[1] == '-') {
00700             data.read(c,2);
00701             if(c[0]=='\r' && c[1]=='\n') {
00702                 break; // This was the last mime part
00703             }
00704         }
00705         // If we got here, we didn't get propper mime message termination
00706         throw servlet::ServletException("Unable to parse multipart/form-data request: message is not terminated properly");
00707     }
00708 }
00709 
00710 void HttpServletRequestImpl::addUploadedFile(const std::string& name, UploadedFileImpl* file)
00711 {
00712     filelist_t::iterator it=m_files.find(name);
00713     if(it!=m_files.end())
00714         delete it->second;
00715     m_files[name]=file;
00716 }
00717 
00718 void HttpServletRequestImpl::addParam(const std::string& name, const std::string& value)
00719 {
00720     m_parameters.insert(util::nvpair(name, value));
00721 }
00722 
00723 boost::shared_ptr<void> HttpServletRequestImpl::getAttribute(const std::string& name)
00724 {
00725     util::attr_t::iterator it = m_attributes.find(name);
00726     if(it == m_attributes.end())
00727         return boost::shared_ptr<void>();
00728     return it->second;
00729 }
00730 bool HttpServletRequestImpl::hasAttribute(const std::string& name) const
00731 {
00732     util::attr_t::const_iterator it = m_attributes.find(name);
00733     return (it != m_attributes.end());
00734 }
00735 std::auto_ptr< std::vector<std::string> > HttpServletRequestImpl::getAttributeNames() const
00736 {
00737     return util::getMapKeyNames(m_attributes);
00738 }
00739 void  HttpServletRequestImpl::setAttribute(const std::string& name, boost::shared_ptr<void> o)
00740 {
00741     m_attributes[name]=o;
00742 }
00743 void  HttpServletRequestImpl::removeAttribute(const std::string& name)
00744 {
00745     util::attr_t::iterator it = m_attributes.find(name);
00746     if(it != m_attributes.end())
00747         m_attributes.erase(it);
00748 }
00749 std::string  HttpServletRequestImpl::getCharacterEncoding() const
00750 {
00751     return m_characterEncoding;
00752 }
00753 void  HttpServletRequestImpl::setCharacterEncoding(const std::string& enc) 
00754 {
00755     m_characterEncoding = enc;
00756 }
00757 int  HttpServletRequestImpl::getContentLength() const
00758 {
00759     return m_contentLength;
00760 }
00761 std::string  HttpServletRequestImpl::getContentType() const
00762 {
00763     return m_contentType;
00764 }
00765 std::istream&  HttpServletRequestImpl::getInputStream()
00766 {
00767     if(m_inputStreamTaken)
00768         throw servlet::IllegalStateException();
00769     m_inputStreamTaken = true;
00770     return m_inputStream;
00771 }
00772 std::string  HttpServletRequestImpl::getParameter(const std::string& name) const
00773 {
00774     util::mparam_t::const_iterator it = m_parameters.find(name);
00775     if(it == m_parameters.end())
00776         return std::string();
00777     return it->second;
00778 }
00779 std::auto_ptr< std::vector<std::string> > HttpServletRequestImpl::getParameterNames() const
00780 {
00781     return util::getMapKeyNames(m_parameters);
00782 }
00783 std::auto_ptr< std::vector<std::string> > HttpServletRequestImpl::getParameterValues(const std::string& name) const
00784 {
00785     return util::getMapValues(m_parameters, name);
00786 }
00787 std::auto_ptr< std::multimap<std::string,std::string> > HttpServletRequestImpl::getParameterMap() const
00788 {
00789     return std::auto_ptr<util::mparam_t>(new util::mparam_t(m_parameters));
00790 }
00791 std::string  HttpServletRequestImpl::getProtocol() const
00792 {
00793     return m_protocol;
00794 }
00795 std::string  HttpServletRequestImpl::getScheme() const
00796 {
00797     return m_scheme;
00798 }
00799 std::string  HttpServletRequestImpl::getServerName() const
00800 {
00801     return m_serverName;
00802 }
00803 int  HttpServletRequestImpl::getServerPort() const
00804 {
00805     return m_serverPort;
00806 }
00807 std::string  HttpServletRequestImpl::getRemoteAddr() const
00808 {
00809     return m_remoteAddr;
00810 }
00811 std::string  HttpServletRequestImpl::getRemoteHost() const
00812 {
00813     if(m_remoteHost.empty())
00814         addr2host(m_remoteAddr, m_remoteHost);
00815     return m_remoteHost;
00816 }
00817 bool  HttpServletRequestImpl::isSecure() const
00818 {
00819     return m_isSecure;
00820 }
00821 servlet::RequestDispatcher* HttpServletRequestImpl::getRequestDispatcher(const std::string& path)
00822 {
00823     std::string lpath(path);
00824     if(path[0]!='/')
00825         lpath.insert(0,"/");
00826     return m_ctx->getRequestDispatcher(lpath);
00827 }
00828 int  HttpServletRequestImpl::getRemotePort() const
00829 {
00830     return m_remotePort;
00831 }
00832 std::string  HttpServletRequestImpl::getLocalName() const
00833 {
00834     if(m_localName.empty())
00835         addr2host(m_localAddr, m_localName);
00836     return m_localName;
00837 }
00838 std::string  HttpServletRequestImpl::getLocalAddr() const
00839 {
00840     return m_localAddr;
00841 }
00842 int  HttpServletRequestImpl::getLocalPort() const
00843 {
00844     return m_localPort;
00845 }
00846 std::string  HttpServletRequestImpl::getAuthType() const 
00847 {
00848     throw servlet::ServletException("Method unimplemented");
00849 }
00850 std::auto_ptr< servlet::HttpServletRequest::cookielist_t > HttpServletRequestImpl::getCookies() const
00851 {
00852     return std::auto_ptr<cookielist_t>(new cookielist_t(m_cookies));
00853 }
00854 long  HttpServletRequestImpl::getDateHeader(const std::string& name) const
00855 {
00856     std::string hval = getHeader(name);
00857     if(hval.empty())
00858         return -1;
00859     struct tm out;
00860     if(strptime(hval.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &out) ||
00861        strptime(hval.c_str(), "%A, %d-%m-%y %H:%M:%S GMT", &out) ||
00862        strptime(hval.c_str(), "%a %m %d %H:%M:%S %Y GMT", &out))
00863         return mktime(&out);
00864     throw servlet::ServletException("IllegalArgumentException");
00865 }
00866 std::string  HttpServletRequestImpl::getHeader(const std::string& name) const 
00867 {
00868     util::mparam_t::const_iterator it=m_headers.find(name);
00869     if(it == m_headers.end())
00870         return "";
00871     return it->second;
00872 }
00873 std::auto_ptr< std::vector<std::string> > HttpServletRequestImpl::getHeaders(const std::string& name) const 
00874 {
00875     return util::getMapValues(m_headers, name);
00876 }
00877 std::auto_ptr< std::vector<std::string> > HttpServletRequestImpl::getHeaderNames() const 
00878 {
00879     return util::getMapKeyNames(m_headers);
00880 }
00881 int  HttpServletRequestImpl::getIntHeader(const std::string& name) const 
00882 {
00883     std::string hval = getHeader(name);
00884     if(hval.empty())
00885         return -1;
00886     int ret, len;
00887     if(sscanf(hval.c_str(), "%d%n", &ret, &len)==EOF)
00888         throw servlet::NumberFormatException();
00889     if((unsigned)len != hval.length())
00890         throw servlet::NumberFormatException();
00891     return ret;
00892 }
00893 std::string  HttpServletRequestImpl::getMethod() const 
00894 {
00895     return m_method;
00896 }
00897 std::string  HttpServletRequestImpl::getPathInfo() const 
00898 {
00899     return m_pathInfo;
00900 }
00901 std::string  HttpServletRequestImpl::getPathTranslated() const 
00902 {
00903     return m_ctx->getRealPath(getPathInfo());
00904 }
00905 std::string  HttpServletRequestImpl::getContextPath() const 
00906 {
00907     //TODO: verify that my interpretation of HttpServletRequest::getContextPath() is correct
00908     // Right now I think it means '/' + context (app) name
00909     // for us, since we simply add app name right after URI base.
00910     // exception is root app (one with an empty name), where
00911     // return value must be an empty string
00912     std::string ret = m_ctx->getServletContextName();
00913     if(!ret.empty())
00914         ret.insert(0,"/");
00915     return ret;
00916 }
00917 std::string  HttpServletRequestImpl::getQueryString() const 
00918 {
00919     return m_queryString;
00920 }
00921 std::string  HttpServletRequestImpl::getRemoteUser() const 
00922 {
00923     return m_remoteUser;
00924 }
00925 bool HttpServletRequestImpl::isUserInRole(const std::string& role) const 
00926 {
00927     throw servlet::ServletException("Method unimplemented");
00928 }
00929 std::string  HttpServletRequestImpl::getRequestedSessionId() const 
00930 {
00931     return m_sessionId;
00932 }
00933 std::string  HttpServletRequestImpl::getRequestURI() const 
00934 {
00935     return m_uri;
00936 }
00937 std::string  HttpServletRequestImpl::getRequestURL() const 
00938 {
00939         std::stringstream url;
00940     url<<getScheme()<<"://"<<getServerName()<<':'<<getServerPort()<<getRequestURI();
00941     return url.str();
00942 }
00943 std::string  HttpServletRequestImpl::getServletPath() const 
00944 {
00945     return m_servletPath;
00946 }
00947 bool  HttpServletRequestImpl::isRequestedSessionIdValid() const 
00948 {
00949     HttpSessionImpl* session = m_ctx->getSession(m_sessionId, false);
00950     return session && session->validP();
00951 }
00952 bool  HttpServletRequestImpl::isRequestedSessionIdFromCookie() const 
00953 {
00954     return true;
00955 }
00956 bool  HttpServletRequestImpl::isRequestedSessionIdFromURL() const 
00957 {
00958     return false;
00959 }
00960 
00961 }

SourceForge.net Logo