FileRequest: implement directory listings.
Use the EPFL (Easily Parsed File Listing) format. This is one of the formats that WebKit allows for directory listings, and it's easily parsed and generated.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2013 Haiku Inc. All rights reserved.
|
* Copyright 2013-2014 Haiku Inc. All rights reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -7,11 +7,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
#include <File.h>
|
#include <File.h>
|
||||||
#include <FileRequest.h>
|
#include <FileRequest.h>
|
||||||
#include <NodeInfo.h>
|
#include <NodeInfo.h>
|
||||||
|
#include <Path.h>
|
||||||
|
|
||||||
|
|
||||||
BFileRequest::BFileRequest(const BUrl& url, BUrlProtocolListener* listener,
|
BFileRequest::BFileRequest(const BUrl& url, BUrlProtocolListener* listener,
|
||||||
@@ -38,30 +41,80 @@ BFileRequest::Result() const
|
|||||||
status_t
|
status_t
|
||||||
BFileRequest::_ProtocolLoop()
|
BFileRequest::_ProtocolLoop()
|
||||||
{
|
{
|
||||||
// FIXME error handling (file does not exists, etc.)
|
BNode node(fUrl.Path().String());
|
||||||
BFile file(fUrl.Path().String(), B_READ_ONLY);
|
node_ref ref;
|
||||||
|
if (node.GetNodeRef(&ref) != B_OK)
|
||||||
if (file.InitCheck() != B_OK || !file.IsFile())
|
|
||||||
return B_PROT_CONNECTION_FAILED;
|
return B_PROT_CONNECTION_FAILED;
|
||||||
|
|
||||||
// Send all notifications to listener, if any
|
if (node.IsFile()) {
|
||||||
if (fListener != NULL) {
|
BFile file(fUrl.Path().String(), B_READ_ONLY);
|
||||||
fListener->ConnectionOpened(this);
|
if (file.InitCheck() != B_OK)
|
||||||
off_t size = 0;
|
return B_PROT_CONNECTION_FAILED;
|
||||||
file.GetSize(&size);
|
|
||||||
|
// Send all notifications to listener, if any
|
||||||
|
if (fListener != NULL) {
|
||||||
|
fListener->ConnectionOpened(this);
|
||||||
|
off_t size = 0;
|
||||||
|
file.GetSize(&size);
|
||||||
|
fListener->DownloadProgress(this, size, size);
|
||||||
|
fResult.SetLength(size);
|
||||||
|
|
||||||
|
ssize_t chunkSize;
|
||||||
|
char chunk[4096];
|
||||||
|
while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0)
|
||||||
|
fListener->DataReceived(this, chunk, chunkSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
BNodeInfo info(&file);
|
||||||
|
char mimeType[B_MIME_TYPE_LENGTH + 1];
|
||||||
|
if (info.GetType(mimeType) == B_OK)
|
||||||
|
fResult.SetContentType(mimeType);
|
||||||
|
|
||||||
|
return B_PROT_SUCCESS;
|
||||||
|
} else if (node.IsDirectory()) {
|
||||||
|
BDirectory directory(&ref);
|
||||||
|
|
||||||
|
fResult.SetContentType("application/x-ftp-directory");
|
||||||
|
// This tells WebKit to use its FTP directory rendering code.
|
||||||
|
|
||||||
|
// Send all notifications to listener, if any
|
||||||
|
if (fListener != NULL)
|
||||||
|
fListener->ConnectionOpened(this);
|
||||||
|
|
||||||
|
int size = 0;
|
||||||
|
char name[B_FILE_NAME_LENGTH];
|
||||||
|
BEntry entry;
|
||||||
|
while(directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND)
|
||||||
|
{
|
||||||
|
// We read directories using the EPFL (Easily Parsed List Format)
|
||||||
|
// This happens to be one of the formats that WebKit can understand,
|
||||||
|
// and it is not too hard to parse or generate.
|
||||||
|
// http://tools.ietf.org/html/draft-bernstein-eplf-02
|
||||||
|
BString epfl("+");
|
||||||
|
if(entry.IsFile() || entry.IsSymLink()) {
|
||||||
|
epfl += "r,";
|
||||||
|
off_t fileSize;
|
||||||
|
if (entry.GetSize(&fileSize) == B_OK)
|
||||||
|
epfl << "s" << fileSize << ",";
|
||||||
|
|
||||||
|
} else if(entry.IsDirectory())
|
||||||
|
epfl += "/,";
|
||||||
|
|
||||||
|
time_t modification;
|
||||||
|
if (entry.GetModificationTime(&modification) == B_OK)
|
||||||
|
epfl << "m" << modification << ",";
|
||||||
|
|
||||||
|
entry.GetName(name);
|
||||||
|
epfl << "\t" << name << "\r\n";
|
||||||
|
fListener->DataReceived(this, epfl.String(), epfl.Length());
|
||||||
|
size += epfl.Length();
|
||||||
|
}
|
||||||
|
|
||||||
fListener->DownloadProgress(this, size, size);
|
fListener->DownloadProgress(this, size, size);
|
||||||
fResult.SetLength(size);
|
fResult.SetLength(size);
|
||||||
|
|
||||||
ssize_t chunkSize;
|
return B_PROT_SUCCESS;
|
||||||
char chunk[4096];
|
|
||||||
while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0)
|
|
||||||
fListener->DataReceived(this, chunk, chunkSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BNodeInfo info(&file);
|
return B_PROT_CONNECTION_FAILED;
|
||||||
char mimeType[B_MIME_TYPE_LENGTH + 1];
|
|
||||||
if (info.GetType(mimeType) == B_OK)
|
|
||||||
fResult.SetContentType(mimeType);
|
|
||||||
|
|
||||||
return B_PROT_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user