void WEnvironment::init(const WebRequest& request) { Configuration& conf = session_->controller()->configuration(); queryString_ = request.queryString(); parameters_ = request.getParameterMap(); urlScheme_ = request.urlScheme(); referer_ = request.headerValue("Referer"); accept_ = request.headerValue("Accept"); serverSignature_ = request.envValue("SERVER_SIGNATURE"); serverSoftware_ = request.envValue("SERVER_SOFTWARE"); serverAdmin_ = request.envValue("SERVER_ADMIN"); pathInfo_ = request.pathInfo(); #ifndef WT_TARGET_JAVA sslInfo_ = request.sslInfo(); #endif setUserAgent(request.headerValue("User-Agent")); LOG_INFO("UserAgent: " << userAgent_); /* * Determine server host name */ if (conf.behindReverseProxy()) { /* * Take the last entry in X-Forwarded-Host, assuming that we are only * behind 1 proxy */ std::string forwardedHost = request.headerValue("X-Forwarded-Host"); if (!forwardedHost.empty()) { std::string::size_type i = forwardedHost.rfind(','); if (i == std::string::npos) host_ = forwardedHost; else host_ = forwardedHost.substr(i+1); } else host_ = request.headerValue("Host"); } else host_ = request.headerValue("Host"); if (host_.empty()) { /* * HTTP 1.0 doesn't require it: guess from config */ host_ = request.serverName(); if (!request.serverPort().empty()) host_ += ":" + request.serverPort(); } clientAddress_ = getClientAddress(request, conf); std::string cookie = request.headerValue("Cookie"); doesCookies_ = !cookie.empty(); if (doesCookies_) parseCookies(cookie, cookies_); locale_ = request.parseLocale(); }
void CgiParser::parse(WebRequest& request, ReadOption readOption) { /* * TODO: optimize this ... */ request_ = &request; ::int64_t len = request.contentLength(); std::string type = request.contentType(); std::string meth = request.requestMethod(); request.postDataExceeded_ = (len > maxPostData_ ? len : 0); std::string queryString = request.queryString(); // XDomainRequest cannot set a contentType header, we therefore pass it // as a request parameter if (readOption != ReadHeadersOnly && meth == "POST" && (type.find("application/x-www-form-urlencoded") == 0 || queryString.find("&contentType=x-www-form-urlencoded") != std::string::npos)) { /* * TODO: parse this stream-based to avoid the malloc here. For now * we protect the maximum that can be POST'ed as form data. */ if (len > 5*1024*1024) throw WException("Oversized application/x-www-form-urlencoded (" + boost::lexical_cast<std::string>(len) + ")"); char *buf = new char[len + 1]; request.in().read(buf, len); if (request.in().gcount() != (int)len) { delete[] buf; throw WException("Unexpected short read."); } buf[len] = 0; // This is a special Wt feature, I do not think it standard. // For POST, parameters in url-encoded URL are still parsed. if (!queryString.empty()) queryString += '&'; queryString += buf; delete[] buf; } LOG_DEBUG("queryString (len=" << len << "): " << queryString); if (!queryString.empty()) Http::Request::parseFormUrlEncoded(queryString, request_->parameters_); if (readOption != ReadHeadersOnly && type.find("multipart/form-data") == 0) { if (meth != "POST") { throw WException("Invalid method for multipart/form-data: " + meth); } if (!request.postDataExceeded_) readMultipartData(request, type, len); else if (readOption == ReadBodyAnyway) { for (;len > 0;) { ::int64_t toRead = std::min(::int64_t(BUFSIZE), len); request.in().read(buf_, toRead); if (request.in().gcount() != (::int64_t)toRead) throw WException("CgiParser: short read"); len -= toRead; } } } }
void WEnvironment::updateUrlScheme(const WebRequest& request) { urlScheme_ = str(request.urlScheme()); Configuration& conf = session_->controller()->configuration(); #ifndef WT_TARGET_JAVA if (conf.behindReverseProxy() || server()->dedicatedSessionProcess()) { #else if (conf.behindReverseProxy()){ #endif std::string forwardedProto = str(request.headerValue("X-Forwarded-Proto")); if (!forwardedProto.empty()) { std::string::size_type i = forwardedProto.rfind(','); if (i == std::string::npos) urlScheme_ = forwardedProto; else urlScheme_ = forwardedProto.substr(i+1); } } } void WEnvironment::init(const WebRequest& request) { Configuration& conf = session_->controller()->configuration(); queryString_ = request.queryString(); parameters_ = request.getParameterMap(); host_ = str(request.headerValue("Host")); referer_ = str(request.headerValue("Referer")); accept_ = str(request.headerValue("Accept")); serverSignature_ = str(request.envValue("SERVER_SIGNATURE")); serverSoftware_ = str(request.envValue("SERVER_SOFTWARE")); serverAdmin_ = str(request.envValue("SERVER_ADMIN")); pathInfo_ = request.pathInfo(); #ifndef WT_TARGET_JAVA if(!str(request.headerValue("Redirect-Secret")).empty()) session_->controller()->redirectSecret_ = str(request.headerValue("Redirect-Secret")); sslInfo_ = request.sslInfo(); if(!sslInfo_ && !str(request.headerValue("SSL-Client-Certificates")).empty()) { parseSSLInfo(str(request.headerValue("SSL-Client-Certificates"))); } #endif setUserAgent(str(request.headerValue("User-Agent"))); updateUrlScheme(request); LOG_INFO("UserAgent: " << userAgent_); /* * If behind a reverse proxy, use external host, schema as communicated using 'X-Forwarded' * headers. */ #ifndef WT_TARGET_JAVA if (conf.behindReverseProxy() || server()->dedicatedSessionProcess()) { #else if (conf.behindReverseProxy()){ #endif std::string forwardedHost = str(request.headerValue("X-Forwarded-Host")); if (!forwardedHost.empty()) { std::string::size_type i = forwardedHost.rfind(','); if (i == std::string::npos) host_ = forwardedHost; else host_ = forwardedHost.substr(i+1); } } if (host_.empty()) { /* * HTTP 1.0 doesn't require it: guess from config */ host_ = request.serverName(); if (!request.serverPort().empty()) host_ += ":" + request.serverPort(); } clientAddress_ = getClientAddress(request, conf); const char *cookie = request.headerValue("Cookie"); doesCookies_ = cookie; if (cookie) parseCookies(cookie, cookies_); locale_ = request.parseLocale(); } #ifndef WT_TARGET_JAVA void WEnvironment::parseSSLInfo(const std::string& json) { #ifdef WT_WITH_SSL Wt::Json::Object obj; Wt::Json::ParseError error; if(!Wt::Json::parse(Wt::Utils::base64Decode(json), obj, error)) { LOG_ERROR("error while parsing client certificates"); return; } std::string clientCertificatePem = obj["client-certificate"]; X509* cert = Wt::Ssl::readFromPem(clientCertificatePem); if(cert) { Wt::WSslCertificate clientCert = Wt::Ssl::x509ToWSslCertificate(cert); X509_free(cert); Wt::Json::Array arr = obj["client-pem-certification-chain"]; std::vector<Wt::WSslCertificate> clientCertChain; for(unsigned int i = 0; i < arr.size(); ++i ) { clientCertChain.push_back(Wt::Ssl::x509ToWSslCertificate(Wt::Ssl::readFromPem(arr[i]))); } Wt::WValidator::State state = static_cast<Wt::WValidator::State>((int)obj["client-verification-result-state"]); Wt::WString message = obj["client-verification-result-message"]; sslInfo_ = new Wt::WSslInfo(clientCert, clientCertChain, Wt::WValidator::Result(state, message)); } #endif // WT_WITH_SSL }