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 + -
显示快捷键?