warsvrprotocolhttp.cpp
来自「ftpserver very good sample」· C++ 代码 · 共 890 行 · 第 1/2 页
CPP
890 行
{ WarLog db_log(WARLOG_DEBUG, "WarSvrProtocolHttp::ProcessInput()", this); if (db_log) { db_log << "HTTP request type " << mRequestHeader.GetMethodName() << " not supported (uninplemented)" << war_endl; } // Send reply GetReply() << HSM_NOT_IMPLEMENTED << HTTPR_NOT_IMPLEMENTED; } break; case WAR_ERR_ACCESS_DENIED: GetReply() << HSM_ACCESS_DENIED << HTTPR_FORBIDDEN; break; default: { WarLog warn_log(WARLOG_WARNINGS, "WarSvrProtocolHttp::ProcessInput()", this); warn_log << "Caught an unexcpected exception while " "processing a HTTP request. " << ex.Explain() << ex << war_endl; GetReply() << HSM_GENERIC_FAIL << ex.Explain() << HTTPR_INTERNAL_SERVER_ERROR; } } } // Prepare for the next request OnTransferDone(WarError(WAR_ERR_OK)); // may throw if (!mInputBuffer.IsEmpty()) goto again; }}void WarSvrProtocolHttp::OnGetRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ // If the path is to a directory, we must look for default // page handlers. We also need to take care of virtual mappings // and security. if (!DeduceRealUrl()) { // Nothing we can do here... OnPageNotFound(); return; } // Check security // The URL should be OK. Now, decide mime-type DeduceMimeType(); // Se if we have an agent for this page if (ProcessWithAgent(contentData, contentLength)) return; // Page processed. // Just send the page StartPageTransfer();}void WarSvrProtocolHttp::OnOptionsRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnHeadRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnPostRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnPutRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnDeleteRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnTraceRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnInvalidRequest(war_ccstr_t contentData, const contentlen_t contentLength) throw(WarException){ WarThrow(WarError(WAR_ERR_NOT_IMPLEMENTED), NULL);}void WarSvrProtocolHttp::OnPageNotFound()throw(WarException){ GetReply() << HSM_NOT_FOUND << HTTPR_NOT_FOUND;}bool WarSvrProtocolHttp::DeduceRealUrl()throw(WarException){ // Map the logical URL to the physical location // The result is stored in mCurrentFile ResolvPath(mRequestHeader.GetUrl().GetUrlPath().c_str()); war_stat_t st; switch(WarFsysExamine(mCurrentFile.GetUrl(), st)) { case WarFileEnums::FT_NORMAL: // The file exist. Just return OK return true; case WarFileEnums::FT_DIR: { // If this is a directory, we must look for default // processors. WarSvrDefinition::filename_list_t name_list; GetSvrDefinition().GetDefaultPage(name_list); war_svrpath_t base_path = mCurrentFile.GetAlias(); for(WarSvrDefinition::filename_list_t::const_iterator P = name_list.begin() ; P != name_list.end() ; ++P) { war_svrpath_t my_path; my_path << base_path.GetPath() << WAR_SLASH << P->c_str(); try { ResolvPath(my_path, mCurrentFile); } catch(WarException) { continue; } if (WarFsysExamine(mCurrentFile.GetUrl(), st) == WarFileEnums::FT_NORMAL) { WarLog debug_log(WARLOG_DEBUG, "WarSvrProtocolHttp::OnReceived()", this); if (debug_log) { debug_log << "Mapped \"" << mRequestHeader.GetUrl().GetUrlPath() << "\" --> \"" << mCurrentFile << "\"." << war_endl; } return true; // Found! } } } break; default: ; } return false;}void WarSvrProtocolHttp::DeduceMimeType()throw(WarException){ mMimeType = ""; war_syspath_t file_extension = mCurrentFile.GetUrl().GetFilePath().GetExtension(); if (file_extension.IsEmpty()) return; GetSvrDefinition().ResolvMimeType(file_extension.GetValue(), mMimeType);}void WarSvrProtocolHttp::StartPageTransfer()throw(WarException){ AUTO_LOCK; int flags = WarFileEnums::F_READ | WarFileEnums::F_MUSTEXIST | WarFileEnums::F_SEQUENTIAL; mFilePtr = OpenFile(mCurrentFile, flags); // Set headers WarCollector<char> content_len; content_len << mFilePtr->GetLength(); GetReply().mHeader.Set(string("Content-Type"), mMimeType); GetReply().mHeader.Set(string("Content-Length"), content_len.GetValue()); SetTransferMode(TM_FAST); // Optimized for file transfers GetReply() << HTTPR_OK; SendFile(mFilePtr); mRelayInput = true; WarThrow(WarError(WAR_BYPASS_DEFAULT_PRC), NULL);}void WarSvrProtocolHttp::VerfiyHttpAuth() throw(WarException){ WarCollector<char> auth_token(WarCollector<char>::SM_ERASE), auth_passwd(WarCollector<char>::SM_ERASE); std::string auth_name; try { auth_token = mRequestHeader.GetHeaderValue("Authorization"); } catch(...) { // No auth-token. Check for anonymous access. VerfiyAnonymousAccess(); return; } // Ok, let's see what we have... if (strnicmp(auth_token.GetValue().c_str(), "Basic ", 6) == 0) { // Basic authentication. We know how to play that game. const char *token = auth_token.GetValue().c_str() + 6; int buf_len = ap_base64decode_len(token); if ((0 > buf_len) && (1024 < buf_len)) { WarThrow(WarError(WAR_ERR_BUFFER_OVERFLOW), "base-64 decode error in authentication header"); } std::vector<char> auth_buf(buf_len + 2, 0); if (ap_base64decode((char *)&auth_buf[0], token) >= buf_len) { // Fail WarThrow(WarError(WAR_ERR_BUFFER_OVERFLOW), "base-64 decode overflow in authentication header"); } char *p = (char *)&auth_buf[0]; // Scan for password while(*p && (':' != *p)) ++p; if (':' != *p) { WarThrow(WarError(WAR_ERR_PARSER_ERROR), "Missing column in authentication header."); } *p++ = 0; // Terminate user-name auth_name = (const char *)&auth_buf[0]; auth_passwd = p; // Erase the temporary clear-text password memset(&auth_buf[0], 0, auth_buf.size()); // Try to log on WarLoginResultE login_result = Login(NULL, auth_name.c_str(), auth_passwd.GetValue().c_str()); if (LF_OK == login_result) return; // Authenticated ok. } // Give up AskForAuthentication();}void WarSvrProtocolHttp::VerfiyAnonymousAccess() throw(WarException){ // Try login as anonymous war_ccstr_t virtual_host = mRequestHeader.GetUrl().GetHostName().c_str(); if (!*virtual_host) virtual_host = NULL; WarLoginResultE login_result = Login(virtual_host, NULL, "httpuser@"); WarLog http_log(WARLOG_DEBUG_HTTP, "WarSvrProtocolHttp::VerfiyAnonymousAccess()", this); if ((LF_OK != login_result ) && http_log) { http_log << "Login failed for user with reason " << login_result << war_endl; } switch(login_result) { case LF_OK: return; // OK case LF_CALLER_NOT_AUTHENTICATED: case LF_BAD_PASSWORD: case LF_NEED_PASSWORD: case LF_USER_NOT_FOUND: case LF_ACCESS_DENIED: AskForAuthentication(); break; case LF_USER_NOT_PERMITTED_TO_SERVICE: GetReply() << HSM_USER_NOT_PERMITTED_TO_SERVICE << HTTPR_FORBIDDEN; break; case LF_TOO_LONG_USERNAME: { WarLog security_log(WARLOG_SECURITY, "WarSvrProtocolHttp::VerfiyAnonymousAccess()", this); security_log << "Too long username from client." << war_endl; } GetReply() << HSM_TOO_LONG_USERNAME << HTTPR_FORBIDDEN; break; case LF_TOO_LONG_PASSWORD: { WarLog security_log(WARLOG_SECURITY, "WarSvrProtocolHttp::VerfiyAnonymousAccess()", this); security_log << "Too long password from client." << war_endl; } GetReply() << HSM_TOO_LONG_PASSWORD << HTTPR_FORBIDDEN; break; case LF_TOO_LONG_HOSTNAME: { WarLog security_log(WARLOG_SECURITY, "WarSvrProtocolHttp::VerfiyAnonymousAccess()", this); security_log << "Too long hostname from client." << war_endl; } GetReply() << HSM_TOO_LONG_HOSTNAME << HTTPR_FORBIDDEN; break; case LF_TOO_MANY_CONNECTIONS: GetReply() << HSM_TOO_MANY_CONNECTIONS << HTTPR_FORBIDDEN; break; case LF_TOO_MANY_CONNECTIONS_FROM_IP: GetReply() << HSM_TOO_MANY_CONNECTIONS_FROM_IP << HTTPR_FORBIDDEN; break; case LF_TOO_MANY_CONNECTIONS_TOTAL: GetReply() << HSM_TOO_MANY_CONNECTIONS_TOTAL << HTTPR_FORBIDDEN; break; case LF_INTERNAL_ERROR: GetReply() << HSM_INTERNAL_ERROR << HTTPR_INTERNAL_SERVER_ERROR; break; case LF_TOO_MANY_FAILED_LOGINS: GetReply() << HSM_TOO_MANY_FAILED_LOGINS << HTTPR_FORBIDDEN; break; case LF_TIME_OF_DAY_DENIAL: GetReply() << HSM_TIME_OF_DAY_DENIAL << HTTPR_FORBIDDEN; break; case LF_IP_SHITLISTED: GetReply() << HSM_IP_SHITLISTED << HTTPR_FORBIDDEN; break; case LF_IP_MARKED_AS_HACKER: GetReply() << HSM_IP_MARKED_AS_HACKER << HTTPR_FORBIDDEN; break; case LF_SYSTEM_SHUTDOWN: GetReply() << HSM_SYSTEM_SHUTDOWN << HTTPR_FORBIDDEN; break; case LF_NO_ANONYMOUS_USERS: GetReply() << HSM_NO_ANONYMOUS_USERS << HTTPR_FORBIDDEN; break; case LF_CONFIGURATION_ERROR: GetReply() << HSM_USER_NOT_PERMITTED_TO_SERVICE << HTTPR_INTERNAL_SERVER_ERROR; break; default: GetReply() << HSM_GENERIC_FAIL << HTTPR_FORBIDDEN; break; }}void WarSvrProtocolHttp::AskForAuthentication() throw(WarException){ WarCollector<char> realm; string header_name = "WWW-Authenticate"; realm << "Basic realm=\"" << GetNativeSiteName() << "\""; GetReply().GetHeader().Set(header_name, realm.GetValue()); GetReply() << HSM_ACCESS_DENIED << HTTPR_UNAUTHORIZED; WarThrow(WarError(WAR_ERR_ACCESS_DENIED), NULL);}void WarSvrProtocolHttp::OnTransferDone(const WarError& status){ WarTransferSocket::OnTransferDone(status); if (mReply.GetHeader().GetHttpVersion() == HTTP_1_0) { Logout(); CloseConnection(WarError()); // Throws // HTTP 1.0 can only do one request/connection. } Reset();}/////////////////////////////// PRIVATE ///////////////////////////////////#endif // #if WAR_RFC2068
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?