2 * Copyright 2013-2014 Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Adrien Destugues, pulkomandy@pulkomandy.tk
13 #include <Directory.h>
15 #include <FileRequest.h>
20 BFileRequest::BFileRequest(const BUrl
& url
, BUrlProtocolListener
* listener
,
23 BUrlRequest(url
, listener
, context
, "BUrlProtocol.File", "file"),
30 BFileRequest::~BFileRequest()
32 status_t status
= Stop();
34 wait_for_thread(fThreadId
, &status
);
39 BFileRequest::Result() const
46 BFileRequest::_ProtocolLoop()
48 BNode
node(fUrl
.Path().String());
50 if (node
.IsSymLink()) {
51 // Traverse the symlink and start over
52 BEntry
entry(fUrl
.Path().String(), true);
56 ssize_t transferredSize
= 0;
58 BFile
file(fUrl
.Path().String(), B_READ_ONLY
);
59 status_t error
= file
.InitCheck();
63 BNodeInfo
info(&file
);
64 char mimeType
[B_MIME_TYPE_LENGTH
+ 1];
65 if (info
.GetType(mimeType
) != B_OK
)
66 update_mime_info(fUrl
.Path().String(), false, true, false);
67 if (info
.GetType(mimeType
) == B_OK
)
68 fResult
.SetContentType(mimeType
);
70 // Send all notifications to listener, if any
71 if (fListener
!= NULL
) {
72 fListener
->ConnectionOpened(this);
75 error
= file
.GetSize(&size
);
78 fResult
.SetLength(size
);
80 fListener
->HeadersReceived(this);
84 while ((chunkSize
= file
.Read(chunk
, sizeof(chunk
))) > 0) {
85 fListener
->DataReceived(this, chunk
, transferredSize
, chunkSize
);
86 transferredSize
+= chunkSize
;
88 // Return error if we didn't transfer everything
89 if (transferredSize
!= size
) {
91 return (status_t
)chunkSize
;
95 fListener
->DownloadProgress(this, size
, size
);
102 status_t error
= node
.GetNodeRef(&ref
);
104 // Stop here, and don't hit the assert below, if the file doesn't exist.
108 assert(node
.IsDirectory());
109 BDirectory
directory(&ref
);
111 fResult
.SetContentType("application/x-ftp-directory; charset=utf-8");
112 // This tells WebKit to use its FTP directory rendering code.
114 if (fListener
!= NULL
) {
115 fListener
->ConnectionOpened(this);
116 fListener
->HeadersReceived(this);
118 // Add a parent directory entry.
119 fListener
->DataReceived(this, "+/,\t..\r\n", transferredSize
, 8);
120 transferredSize
+= 8;
123 char name
[B_FILE_NAME_LENGTH
];
125 while (directory
.GetNextEntry(&entry
) != B_ENTRY_NOT_FOUND
) {
126 // We read directories using the EPLF (Easily Parsed List Format)
127 // This happens to be one of the formats that WebKit can understand,
128 // and it is not too hard to parse or generate.
129 // http://tools.ietf.org/html/draft-bernstein-eplf-02
131 if (entry
.IsFile() || entry
.IsSymLink()) {
134 if (entry
.GetSize(&fileSize
) == B_OK
)
135 eplf
<< "s" << fileSize
<< ",";
137 } else if (entry
.IsDirectory())
141 if (entry
.GetModificationTime(&modification
) == B_OK
)
142 eplf
<< "m" << modification
<< ",";
145 if (entry
.GetPermissions(&permissions
) == B_OK
)
146 eplf
<< "up" << BString().SetToFormat("%03o", permissions
) << ",";
149 if (entry
.GetNodeRef(&ref
) == B_OK
)
150 eplf
<< "i" << ref
.device
<< "." << ref
.node
<< ",";
153 eplf
<< "\t" << name
<< "\r\n";
154 if (fListener
!= NULL
) {
155 fListener
->DataReceived(this, eplf
.String(), transferredSize
,
158 transferredSize
+= eplf
.Length();
161 if (fListener
!= NULL
)
162 fListener
->DownloadProgress(this, transferredSize
, transferredSize
);
163 fResult
.SetLength(transferredSize
);