fastcgi++
|
00001 00002 /*************************************************************************** 00003 * Copyright (C) 2007 Eddie Carle [eddie@erctech.org] * 00004 * * 00005 * This file is part of fastcgi++. * 00006 * * 00007 * fastcgi++ is free software: you can redistribute it and/or modify it * 00008 * under the terms of the GNU Lesser General Public License as published * 00009 * by the Free Software Foundation, either version 3 of the License, or (at * 00010 * your option) any later version. * 00011 * * 00012 * fastcgi++ is distributed in the hope that it will be useful, but WITHOUT * 00013 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * 00014 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * 00015 * License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Lesser General Public License * 00018 * along with fastcgi++. If not, see <http://www.gnu.org/licenses/>. * 00019 ****************************************************************************/ 00020 00021 #include <fastcgi++/request.hpp> 00022 00023 template void Fastcgipp::Request<char>::complete(); 00024 template void Fastcgipp::Request<wchar_t>::complete(); 00025 template<class charT> void Fastcgipp::Request<charT>::complete() 00026 { 00027 using namespace Protocol; 00028 out.flush(); 00029 err.flush(); 00030 00031 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest))); 00032 00033 Header& header=*(Header*)buffer.data; 00034 header.setVersion(Protocol::version); 00035 header.setType(END_REQUEST); 00036 header.setRequestId(id.fcgiId); 00037 header.setContentLength(sizeof(EndRequest)); 00038 header.setPaddingLength(0); 00039 00040 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header)); 00041 body.setAppStatus(0); 00042 body.setProtocolStatus(REQUEST_COMPLETE); 00043 00044 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon); 00045 } 00046 00047 template bool Fastcgipp::Request<char>::handler(); 00048 template bool Fastcgipp::Request<wchar_t>::handler(); 00049 template<class charT> bool Fastcgipp::Request<charT>::handler() 00050 { 00051 using namespace Protocol; 00052 using namespace std; 00053 00054 try 00055 { 00056 if(!(role()==RESPONDER || role()==AUTHORIZER)) 00057 { 00058 Block buffer(transceiver->requestWrite(sizeof(Header)+sizeof(EndRequest))); 00059 00060 Header& header=*(Header*)buffer.data; 00061 header.setVersion(Protocol::version); 00062 header.setType(END_REQUEST); 00063 header.setRequestId(id.fcgiId); 00064 header.setContentLength(sizeof(EndRequest)); 00065 header.setPaddingLength(0); 00066 00067 EndRequest& body=*(EndRequest*)(buffer.data+sizeof(Header)); 00068 body.setAppStatus(0); 00069 body.setProtocolStatus(UNKNOWN_ROLE); 00070 00071 transceiver->secureWrite(sizeof(Header)+sizeof(EndRequest), id, killCon); 00072 return true; 00073 } 00074 00075 { 00076 boost::lock_guard<boost::mutex> lock(messages); 00077 m_message=messages.front(); 00078 messages.pop(); 00079 } 00080 00081 if(message().type==0) 00082 { 00083 const Header& header=*(Header*)message().data.get(); 00084 const char* body=message().data.get()+sizeof(Header); 00085 switch(header.getType()) 00086 { 00087 case PARAMS: 00088 { 00089 if(state!=PARAMS) throw Exceptions::RecordsOutOfOrder(); 00090 if(header.getContentLength()==0) 00091 { 00092 if(m_maxPostSize && environment().contentLength > m_maxPostSize) 00093 { 00094 bigPostErrorHandler(); 00095 complete(); 00096 return true; 00097 } 00098 state=IN; 00099 break; 00100 } 00101 m_environment.fill(body, header.getContentLength()); 00102 break; 00103 } 00104 00105 case IN: 00106 { 00107 if(state!=IN) throw Exceptions::RecordsOutOfOrder(); 00108 if(header.getContentLength()==0) 00109 { 00110 // Process POST data based on what our incoming content type is 00111 if(m_environment.requestMethod == Http::HTTP_METHOD_POST) 00112 { 00113 const char multipart[] = "multipart/form-data"; 00114 const char urlEncoded[] = "application/x-www-form-urlencoded"; 00115 00116 if(equal(multipart, multipart+sizeof(multipart), m_environment.contentType.begin())) 00117 m_environment.parsePostsMultipart(); 00118 00119 else if(equal(urlEncoded, urlEncoded+sizeof(urlEncoded), m_environment.contentType.begin())) 00120 m_environment.parsePostsUrlEncoded(); 00121 00122 else 00123 throw Exceptions::UnknownContentType(); 00124 } 00125 00126 m_environment.clearPostBuffer(); 00127 state=OUT; 00128 if(response()) 00129 { 00130 complete(); 00131 return true; 00132 } 00133 break; 00134 } 00135 00136 if(!m_environment.fillPostBuffer(body, header.getContentLength())) 00137 { 00138 bigPostErrorHandler(); 00139 complete(); 00140 return true; 00141 } 00142 00143 inHandler(header.getContentLength()); 00144 break; 00145 } 00146 00147 case ABORT_REQUEST: 00148 { 00149 return true; 00150 } 00151 } 00152 } 00153 else if(response()) 00154 { 00155 complete(); 00156 return true; 00157 } 00158 } 00159 catch(const std::exception& e) 00160 { 00161 errorHandler(e); 00162 complete(); 00163 return true; 00164 } 00165 return false; 00166 } 00167 00168 template void Fastcgipp::Request<char>::errorHandler(const std::exception& error); 00169 template void Fastcgipp::Request<wchar_t>::errorHandler(const std::exception& error); 00170 template<class charT> void Fastcgipp::Request<charT>::errorHandler(const std::exception& error) 00171 { 00172 out << \ 00173 "Status: 500 Internal Server Error\n"\ 00174 "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"\ 00175 "<!DOCTYPE html>"\ 00176 "<html lang='en'>"\ 00177 "<head>"\ 00178 "<title>500 Internal Server Error</title>"\ 00179 "</head>"\ 00180 "<body>"\ 00181 "<h1>500 Internal Server Error</h1>"\ 00182 "</body>"\ 00183 "</html>"; 00184 00185 err << '"' << error.what() << '"' << " from \"http://" << environment().host << environment().requestUri << "\" with a " << environment().requestMethod << " request method."; 00186 } 00187 00188 template void Fastcgipp::Request<char>::bigPostErrorHandler(); 00189 template void Fastcgipp::Request<wchar_t>::bigPostErrorHandler(); 00190 template<class charT> void Fastcgipp::Request<charT>::bigPostErrorHandler() 00191 { 00192 out << \ 00193 "Status: 413 Request Entity Too Large\n"\ 00194 "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"\ 00195 "<!DOCTYPE html>"\ 00196 "<html lang='en'>"\ 00197 "<head>"\ 00198 "<title>413 Request Entity Too Large</title>"\ 00199 "</head>"\ 00200 "<body>"\ 00201 "<h1>413 Request Entity Too Large</h1>"\ 00202 "</body>"\ 00203 "</html>"; 00204 }