diff --git a/src/kits/network/libnetapi/FileRequest.cpp b/src/kits/network/libnetapi/FileRequest.cpp index 21f087f400..cad1502728 100644 --- a/src/kits/network/libnetapi/FileRequest.cpp +++ b/src/kits/network/libnetapi/FileRequest.cpp @@ -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 #include +#include #include #include #include +#include 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; }