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:
Adrien Destugues 2014-01-10 15:27:49 +01:00
parent 5143323fb6
commit 090ba6d06b
1 changed files with 73 additions and 20 deletions

View File

@ -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.
*
* Authors:
@ -7,11 +7,14 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <Directory.h>
#include <File.h>
#include <FileRequest.h>
#include <NodeInfo.h>
#include <Path.h>
BFileRequest::BFileRequest(const BUrl& url, BUrlProtocolListener* listener,
@ -38,30 +41,80 @@ BFileRequest::Result() const
status_t
BFileRequest::_ProtocolLoop()
{
// FIXME error handling (file does not exists, etc.)
BFile file(fUrl.Path().String(), B_READ_ONLY);
if (file.InitCheck() != B_OK || !file.IsFile())
BNode node(fUrl.Path().String());
node_ref ref;
if (node.GetNodeRef(&ref) != B_OK)
return B_PROT_CONNECTION_FAILED;
// Send all notifications to listener, if any
if (fListener != NULL) {
fListener->ConnectionOpened(this);
off_t size = 0;
file.GetSize(&size);
if (node.IsFile()) {
BFile file(fUrl.Path().String(), B_READ_ONLY);
if (file.InitCheck() != B_OK)
return B_PROT_CONNECTION_FAILED;
// 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);
fResult.SetLength(size);
ssize_t chunkSize;
char chunk[4096];
while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0)
fListener->DataReceived(this, chunk, chunkSize);
return B_PROT_SUCCESS;
}
BNodeInfo info(&file);
char mimeType[B_MIME_TYPE_LENGTH + 1];
if (info.GetType(mimeType) == B_OK)
fResult.SetContentType(mimeType);
return B_PROT_SUCCESS;
return B_PROT_CONNECTION_FAILED;
}