📄 httpsrvr.cxx
字号:
{ if (!request.outMIME.Contains(PHTTP::ContentTypeTag) && !contentType) request.outMIME.SetAt(PHTTP::ContentTypeTag, contentType); PCharArray data; if (LoadData(request, data)) { server.StartResponse(request.code, request.outMIME, request.contentSize); do { server.Write(data, data.GetSize()); data.SetSize(0); } while (LoadData(request, data)); } else server.StartResponse(request.code, request.outMIME, data.GetSize()); server.Write(data, data.GetSize()); return request.outMIME.Contains(PHTTP::ContentLengthTag);}BOOL PHTTPResource::OnPOST(PHTTPServer & server, const PURL & url, const PMIMEInfo & info, const PStringToString & data, const PHTTPConnectionInfo & connectInfo){ PHTTPRequest * request = CreateRequest(url, info, server); BOOL persist = TRUE; if (CheckAuthority(server, *request, connectInfo)) { PHTML msg; persist = Post(*request, data, msg); if (msg.IsEmpty()) persist = server.OnError(request->code, "", connectInfo) && persist; else { if (msg.Is(PHTML::InBody)) msg << PHTML::Body(); request->outMIME.SetAt(PHTTP::ContentTypeTag, "text/html"); PINDEX len = msg.GetLength(); server.StartResponse(request->code, request->outMIME, len); persist = server.Write((const char *)msg, len) && persist; } } delete request; return persist;}BOOL PHTTPResource::CheckAuthority(PHTTPServer & server, const PHTTPRequest & request, const PHTTPConnectionInfo & connectInfo){ if (authority == NULL) return TRUE; return CheckAuthority(*authority, server, request, connectInfo);} BOOL PHTTPResource::CheckAuthority(PHTTPAuthority & authority, PHTTPServer & server, const PHTTPRequest & request, const PHTTPConnectionInfo & connectInfo){ if (!authority.IsActive()) return TRUE; // if this is an authorisation request... if (request.inMIME.Contains(PHTTP::AuthorizationTag) && authority.Validate(request, request.inMIME[PHTTP::AuthorizationTag])) return TRUE; // it must be a request for authorisation PMIMEInfo headers; server.SetDefaultMIMEInfo(headers, connectInfo); headers.SetAt(PHTTP::WWWAuthenticateTag, "Basic realm=\"" + authority.GetRealm(request) + "\""); headers.SetAt(PHTTP::ContentTypeTag, "text/html"); const httpStatusCodeStruct * statusInfo = GetStatusCodeStruct(PHTTP::UnAuthorised); PHTML reply; reply << PHTML::Title() << statusInfo->code << ' ' << statusInfo->text << PHTML::Body() << PHTML::Heading(1) << statusInfo->code << ' ' << statusInfo->text << PHTML::Heading(1) << "Your request cannot be authorised because it requires authentication." << PHTML::Paragraph() << "This may be because you entered an incorrect username or password, " << "or because your browser is not performing Basic authentication." << PHTML::Body(); server.StartResponse(PHTTP::UnAuthorised, headers, reply.GetLength()); server.WriteString(reply); return FALSE;}void PHTTPResource::SetAuthority(const PHTTPAuthority & auth){ delete authority; authority = (PHTTPAuthority *)auth.Clone();}void PHTTPResource::ClearAuthority(){ delete authority; authority = NULL;}BOOL PHTTPResource::IsModifiedSince(const PTime &){ return TRUE;}BOOL PHTTPResource::GetExpirationDate(PTime &){ return FALSE;}PHTTPRequest * PHTTPResource::CreateRequest(const PURL & url, const PMIMEInfo & inMIME, PHTTPServer & socket){ return new PHTTPRequest(url, inMIME, socket);}BOOL PHTTPResource::LoadData(PHTTPRequest & request, PCharArray & data){ PString text = LoadText(request); OnLoadedText(request, text); text.SetSize(text.GetLength()); // Lose the trailing '\0' data = text; return FALSE;}PString PHTTPResource::LoadText(PHTTPRequest &){ PAssertAlways(PUnimplementedFunction); return PString();}void PHTTPResource::OnLoadedText(PHTTPRequest &, PString &){ // Do nothing}BOOL PHTTPResource::Post(PHTTPRequest & request, const PStringToString &, PHTML & msg){ request.code = PHTTP::MethodNotAllowed; msg = "Error in POST"; msg << "Post to this resource is not allowed" << PHTML::Body(); return TRUE;}//////////////////////////////////////////////////////////////////////////////// PHTTPStringPHTTPString::PHTTPString(const PURL & url) : PHTTPResource(url, "text/html"){}PHTTPString::PHTTPString(const PURL & url, const PHTTPAuthority & auth) : PHTTPResource(url, "text/html", auth){}PHTTPString::PHTTPString(const PURL & url, const PString & str) : PHTTPResource(url, "text/html"), string(str){}PHTTPString::PHTTPString(const PURL & url, const PString & str, const PString & type) : PHTTPResource(url, type), string(str){}PHTTPString::PHTTPString(const PURL & url, const PString & str, const PHTTPAuthority & auth) : PHTTPResource(url, "text/html", auth), string(str){}PHTTPString::PHTTPString(const PURL & url, const PString & str, const PString & type, const PHTTPAuthority & auth) : PHTTPResource(url, type, auth), string(str){}BOOL PHTTPString::LoadHeaders(PHTTPRequest & request){ request.contentSize = string.GetLength(); return TRUE;}PString PHTTPString::LoadText(PHTTPRequest &){ return string;}//////////////////////////////////////////////////////////////////////////////// PHTTPFilePHTTPFile::PHTTPFile(const PURL & url, int) : PHTTPResource(url){}PHTTPFile::PHTTPFile(const PString & filename) : PHTTPResource(filename), filePath(filename){ SetContentType(PMIMEInfo::GetContentType(filePath.GetType()));}PHTTPFile::PHTTPFile(const PString & filename, const PHTTPAuthority & auth) : PHTTPResource(filename, auth), filePath(filename){}PHTTPFile::PHTTPFile(const PURL & url, const PFilePath & path) : PHTTPResource(url), filePath(path){ SetContentType(PMIMEInfo::GetContentType(path.GetType()));}PHTTPFile::PHTTPFile(const PURL & url, const PFilePath & path, const PString & type) : PHTTPResource(url, type), filePath(path){}PHTTPFile::PHTTPFile(const PURL & url, const PFilePath & path, const PHTTPAuthority & auth) : PHTTPResource(url, PString(), auth), filePath(path){ SetContentType(PMIMEInfo::GetContentType(filePath.GetType()));}PHTTPFile::PHTTPFile(const PURL & url, const PFilePath & path, const PString & type, const PHTTPAuthority & auth) : PHTTPResource(url, type, auth), filePath(path){}PHTTPFileRequest::PHTTPFileRequest(const PURL & url, const PMIMEInfo & inMIME, PHTTPServer & server) : PHTTPRequest(url, inMIME, server){}PHTTPRequest * PHTTPFile::CreateRequest(const PURL & url, const PMIMEInfo & inMIME, PHTTPServer & server){ return new PHTTPFileRequest(url, inMIME, server);}BOOL PHTTPFile::LoadHeaders(PHTTPRequest & request){ PFile & file = ((PHTTPFileRequest&)request).file; if (!file.Open(filePath, PFile::ReadOnly)) { request.code = PHTTP::NotFound; return FALSE; } request.contentSize = file.GetLength(); return TRUE;}BOOL PHTTPFile::LoadData(PHTTPRequest & request, PCharArray & data){ if (contentType(0, 4) == "text/") return PHTTPResource::LoadData(request, data); PFile & file = ((PHTTPFileRequest&)request).file; PAssert(file.IsOpen(), PLogicError); PINDEX count = file.GetLength() - file.GetPosition(); if (count > 10000) count = 10000; if (count > 0) PAssert(file.Read(data.GetPointer(count), count), PLogicError); if (!file.IsEndOfFile()) return TRUE; file.Close(); return FALSE;}PString PHTTPFile::LoadText(PHTTPRequest & request){ PFile & file = ((PHTTPFileRequest&)request).file; PAssert(file.IsOpen(), PLogicError); PINDEX count = file.GetLength(); PString text; if (count > 0) PAssert(file.Read(text.GetPointer(count+1), count), PLogicError); PAssert(file.Close(), PLogicError); return text;}//////////////////////////////////////////////////////////////////////////////// PHTTPDirectoryPHTTPDirectory::PHTTPDirectory(const PURL & url, const PDirectory & dir) : PHTTPFile(url, 0), basePath(dir), allowDirectoryListing(TRUE){}PHTTPDirectory::PHTTPDirectory(const PURL & url, const PDirectory & dir, const PHTTPAuthority & auth) : PHTTPFile(url, PString(), auth), basePath(dir), allowDirectoryListing(TRUE){}PHTTPDirRequest::PHTTPDirRequest(const PURL & url, const PMIMEInfo & inMIME, PHTTPServer & server) : PHTTPFileRequest(url, inMIME, server){}PHTTPRequest * PHTTPDirectory::CreateRequest(const PURL & url, const PMIMEInfo & inMIME, PHTTPServer & socket){ return new PHTTPDirRequest(url, inMIME, socket);}void PHTTPDirectory::EnableAuthorisation(const PString & realm){ authorisationRealm = realm;}BOOL PHTTPDirectory::FindAuthorisations(const PDirectory & dir, PString & realm, PStringToString & authorisations){ PFilePath fn = dir + accessFilename; PTextFile file; BOOL first = TRUE; if (file.Open(fn, PFile::ReadOnly)) { PString line; while (file.ReadLine(line)) { if (first) { realm = line.Trim(); first = FALSE; } else { PStringArray tokens = line.Tokenise(':'); if (tokens.GetSize() > 1) authorisations.SetAt(tokens[0].Trim(), tokens[1].Trim()); } } return TRUE; } if (dir.IsRoot() || (dir == basePath)) return FALSE; return FindAuthorisations(dir.GetParent(), realm, authorisations);}BOOL PHTTPDirectory::CheckAuthority(PHTTPServer & server, const PHTTPRequest & request, const PHTTPConnectionInfo & conInfo){ PFilePath & realPath = ((PHTTPDirRequest&)request).realPath; // construct the real path name const PStringArray & path = request.url.GetPath(); realPath = basePath; PINDEX i; for (i = baseURL.GetPath().GetSize(); i < path.GetSize()-1; i++) realPath += path[i] + PDIR_SEPARATOR; // append the last path element if (i < path.GetSize()) realPath += path[i]; // if access control is enabled, then search parent directories for password files PStringToString authorisations; PString newRealm; if (authorisationRealm.IsEmpty() || !FindAuthorisations(realPath.GetDirectory(), newRealm, authorisations) || authorisations.GetSize() == 0) return TRUE; PHTTPMultiSimpAuth authority(newRealm, authorisations); return PHTTPResource::CheckAuthority(authority, server, request, conInfo);}BOOL PHTTPDirectory::LoadHeaders(PHTTPRequest & request){ PFilePath & realPath = ((PHTTPDirRequest&)request).realPath; // if not able to obtain resource information, then consider the resource "not found" PFileInfo info; if (!PFile::GetInfo(realPath, info)) { request.code = PHTTP::NotFound; return FALSE; } // if the resource is a file, and the file can't be opened, then return "not found" PFile & file = ((PHTTPDirRequest&)request).file; if (info.type != PFileInfo::SubDirectory) { if (!file.Open(realPath, PFile::ReadOnly) || (!authorisationRealm.IsEmpty() && realPath.GetFileName() == accessFilename)) { request.code = PHTTP::NotFound; return FALSE; } } // resource is a directory - if index files disabled, then return "not found" else if (!allowDirectoryListing) { request.code = PHTTP::NotFound; return FALSE; } // else look for index files else { PINDEX i; for (i = 0; i < PARRAYSIZE(HTMLIndexFiles); i++) if (file.Open(realPath + PDIR_SEPARATOR + HTMLIndexFiles[i], PFile::ReadOnly)) break; } // open the file and return information PString & fakeIndex = ((PHTTPDirRequest&)request).fakeIndex; if (file.IsOpen()) { contentType = PMIMEInfo::GetContentType(file.GetFilePath().GetType()); request.contentSize = file.GetLength(); fakeIndex = PString(); return TRUE; } // construct a directory listing contentType = "text/html"; PHTML reply("Directory of " + request.url.AsString()); PDirectory dir = realPath; if (dir.Open()) { do { const char * imgName; if (dir.IsSubDir()) imgName = "internal-gopher-menu"; else if (PMIMEInfo::GetContentType( PFilePath(dir.GetEntryName()).GetType())(0,4) == "text/") imgName = "internal-gopher-text"; else imgName = "internal-gopher-unknown"; reply << PHTML::Image(imgName) << ' ' << PHTML::HotLink(realPath.GetFileName()+'/'+dir.GetEntryName()) << dir.GetEntryName() << PHTML::HotLink() << PHTML::BreakLine(); } while (dir.Next()); } reply << PHTML::Body(); fakeIndex = reply; return TRUE;}PString PHTTPDirectory::LoadText(PHTTPRequest & request){ PString & fakeIndex = ((PHTTPDirRequest&)request).fakeIndex; if (fakeIndex.IsEmpty()) return PHTTPFile::LoadText(request); return fakeIndex;}// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -