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(!inProcessor()) 00117 { 00118 if(sizeof(multipart)-1 == m_environment.contentType.size() && equal(multipart, multipart+sizeof(multipart)-1, m_environment.contentType.begin())) 00119 m_environment.parsePostsMultipart(); 00120 00121 else if(sizeof(urlEncoded)-1 == m_environment.contentType.size() && equal(urlEncoded, urlEncoded+sizeof(urlEncoded)-1, m_environment.contentType.begin())) 00122 m_environment.parsePostsUrlEncoded(); 00123 00124 else 00125 throw Exceptions::UnknownContentType(); 00126 } 00127 } 00128 00129 m_environment.clearPostBuffer(); 00130 state=OUT; 00131 if(response()) 00132 { 00133 complete(); 00134 return true; 00135 } 00136 break; 00137 } 00138 00139 if(!m_environment.fillPostBuffer(body, header.getContentLength())) 00140 { 00141 bigPostErrorHandler(); 00142 complete(); 00143 return true; 00144 } 00145 00146 inHandler(header.getContentLength()); 00147 break; 00148 } 00149 00150 case ABORT_REQUEST: 00151 { 00152 return true; 00153 } 00154 } 00155 } 00156 else if(response()) 00157 { 00158 complete(); 00159 return true; 00160 } 00161 } 00162 catch(const std::exception& e) 00163 { 00164 errorHandler(e); 00165 complete(); 00166 return true; 00167 } 00168 return false; 00169 } 00170 00171 template void Fastcgipp::Request<char>::errorHandler(const std::exception& error); 00172 template void Fastcgipp::Request<wchar_t>::errorHandler(const std::exception& error); 00173 template<class charT> void Fastcgipp::Request<charT>::errorHandler(const std::exception& error) 00174 { 00175 out << \ 00176 "Status: 500 Internal Server Error\n"\ 00177 "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"\ 00178 "<!DOCTYPE html>"\ 00179 "<html lang='en'>"\ 00180 "<head>"\ 00181 "<title>500 Internal Server Error</title>"\ 00182 "</head>"\ 00183 "<body>"\ 00184 "<h1>500 Internal Server Error</h1>"\ 00185 "</body>"\ 00186 "</html>"; 00187 00188 err << '"' << error.what() << '"' << " from \"http://" << environment().host << environment().requestUri << "\" with a " << environment().requestMethod << " request method."; 00189 } 00190 00191 template void Fastcgipp::Request<char>::bigPostErrorHandler(); 00192 template void Fastcgipp::Request<wchar_t>::bigPostErrorHandler(); 00193 template<class charT> void Fastcgipp::Request<charT>::bigPostErrorHandler() 00194 { 00195 out << \ 00196 "Status: 413 Request Entity Too Large\n"\ 00197 "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n"\ 00198 "<!DOCTYPE html>"\ 00199 "<html lang='en'>"\ 00200 "<head>"\ 00201 "<title>413 Request Entity Too Large</title>"\ 00202 "</head>"\ 00203 "<body>"\ 00204 "<h1>413 Request Entity Too Large</h1>"\ 00205 "</body>"\ 00206 "</html>"; 00207 }