📄 httpsrvr.cxx
字号:
if (request.server.StartResponse(request.code, request.outMIME, request.contentSize)) {
// Chunked transfer encoding
request.outMIME.RemoveAll();
do {
WriteChunkedDataToServer(request.server, data);
} while (LoadData(request, data));
WriteChunkedDataToServer(request.server, data);
request.server << "0\r\n" << request.outMIME;
}
else {
do {
request.server.Write(data, data.GetSize());
data.SetSize(0);
} while (LoadData(request, data));
request.server.Write(data, data.GetSize());
}
}
else {
request.server.StartResponse(request.code, request.outMIME, data.GetSize());
request.server.Write(data, data.GetSize());
}
}
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;
}
//////////////////////////////////////////////////////////////////////////////
// PHTTPString
PHTTPString::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;
}
//////////////////////////////////////////////////////////////////////////////
// PHTTPFile
PHTTPFile::PHTTPFile(const PURL & url, int)
: PHTTPResource(url)
{
}
PHTTPFile::PHTTPFile(const PString & filename)
: PHTTPResource(filename, PMIMEInfo::GetContentType(PFilePath(filename).GetType())),
filePath(filename)
{
}
PHTTPFile::PHTTPFile(const PString & filename, const PHTTPAuthority & auth)
: PHTTPResource(filename, auth), filePath(filename)
{
}
PHTTPFile::PHTTPFile(const PURL & url, const PFilePath & path)
: PHTTPResource(url, PMIMEInfo::GetContentType(path.GetType())),
filePath(path)
{
}
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, PMIMEInfo::GetContentType(path.GetType()), auth),
filePath(path)
{
}
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,
const PMultipartFormInfoArray & multipartFormInfo,
PHTTPServer & server)
: PHTTPRequest(url, inMIME, multipartFormInfo, server)
{
}
PHTTPRequest * PHTTPFile::CreateRequest(const PURL & url,
const PMIMEInfo & inMIME,
const PMultipartFormInfoArray & multipartFormInfo,
PHTTPServer & server)
{
return new PHTTPFileRequest(url, inMIME, multipartFormInfo, 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)
{
PFile & file = ((PHTTPFileRequest&)request).file;
PString contentType = GetContentType();
if (contentType.IsEmpty())
contentType = PMIMEInfo::GetContentType(file.GetFilePath().GetType());
if (contentType(0, 4) *= "text/")
return PHTTPResource::LoadData(request, data);
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;
}
//////////////////////////////////////////////////////////////////////////////
// PHTTPTailFile
PHTTPTailFile::PHTTPTailFile(const PString & filename)
: PHTTPFile(filename)
{
}
PHTTPTailFile::PHTTPTailFile(const PString & filename,
const PHTTPAuthority & auth)
: PHTTPFile(filename, auth)
{
}
PHTTPTailFile::PHTTPTailFile(const PURL & url,
const PFilePath & file)
: PHTTPFile(url, file)
{
}
PHTTPTailFile::PHTTPTailFile(const PURL & url,
const PFilePath & file,
const PString & contentType)
: PHTTPFile(url, file, contentType)
{
}
PHTTPTailFile::PHTTPTailFile(const PURL & url,
const PFilePath & file,
const PHTTPAuthority & auth)
: PHTTPFile(url, file, auth)
{
}
PHTTPTailFile::PHTTPTailFile(const PURL & url,
const PFilePath & file,
const PString & contentType,
const PHTTPAuthority & auth)
: PHTTPFile(url, file, contentType, auth)
{
}
BOOL PHTTPTailFile::LoadHeaders(PHTTPRequest & request)
{
if (!PHTTPFile::LoadHeaders(request))
return FALSE;
request.contentSize = P_MAX_INDEX;
return TRUE;
}
BOOL PHTTPTailFile::LoadData(PHTTPRequest & request, PCharArray & data)
{
PFile & file = ((PHTTPFileRequest&)request).file;
if (file.GetPosition() == 0)
file.SetPosition(file.GetLength()-request.url.GetQueryVars()("offset", "10000").AsUnsigned());
while (file.GetPosition() >= file.GetLength()) {
if (!request.server.Write(NULL, 0))
return FALSE;
PThread::Sleep(200);
}
PINDEX count = file.GetLength() - file.GetPosition();
return file.Read(data.GetPointer(count), count);
}
//////////////////////////////////////////////////////////////////////////////
// PHTTPDirectory
PHTTPDirectory::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,
const PMultipartFormInfoArray & multipartFormInfo,
PHTTPServer & server)
: PHTTPFileRequest(url, inMIME, multipartFormInfo, server)
{
}
PHTTPRequest * PHTTPDirectory::CreateRequest(const PURL & url,
const PMIMEInfo & inMIME,
const PMultipartFormInfoArray & multipartFormInfo,
PHTTPServer & socket)
{
PHTTPDirRequest * request = new PHTTPDirRequest(url, inMIME, multipartFormInfo, socket);
const PStringArray & path = url.GetPath();
request->realPath = basePath;
PINDEX i;
for (i = GetURL().GetPath().GetSize(); i < path.GetSize()-1; i++)
request->realPath += path[i] + PDIR_SEPARATOR;
// append the last path element
if (i < path.GetSize())
request->realPath += path[i];
if (request->realPath.Find(basePath) != 0)
request->realPath = basePath;
return request;
}
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)
{
// if access control is enabled, then search parent directories for password files
PStringToString authorisations;
PString newRealm;
if (authorisationRealm.IsEmpty() ||
!FindAuthorisations(((PHTTPDirRequest&)request).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()) {
request.outMIME.SetAt(PHTTP::ContentTypeTag,
PMIMEInfo::GetContentType(file.GetFilePath().GetType()));
request.contentSize = file.GetLength();
fakeIndex = PString();
return TRUE;
}
// construct a directory listing
request.outMIME.SetAt(PHTTP::ContentTypeTag, "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;
}
#endif // P_HTTP
// End Of File ///////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -