Port directory lister to posix.
Fix of issue 11437. Review URL: http://codereview.chromium.org/11293 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5730 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#elif defined(OS_POSIX)
|
#elif defined(OS_POSIX)
|
||||||
#include <fts.h>
|
#include <fts.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -323,6 +324,15 @@ bool SetCurrentDirectory(const std::wstring& current_directory);
|
|||||||
// program where latency does not matter. This class is blocking.
|
// program where latency does not matter. This class is blocking.
|
||||||
class FileEnumerator {
|
class FileEnumerator {
|
||||||
public:
|
public:
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
typedef WIN32_FIND_DATA FindInfo;
|
||||||
|
#elif defined(OS_POSIX)
|
||||||
|
typedef struct {
|
||||||
|
struct stat stat;
|
||||||
|
std::string filename;
|
||||||
|
} FindInfo;
|
||||||
|
#endif
|
||||||
|
|
||||||
enum FILE_TYPE {
|
enum FILE_TYPE {
|
||||||
FILES = 0x1,
|
FILES = 0x1,
|
||||||
DIRECTORIES = 0x2,
|
DIRECTORIES = 0x2,
|
||||||
@@ -361,6 +371,9 @@ class FileEnumerator {
|
|||||||
// Returns an empty string if there are no more results.
|
// Returns an empty string if there are no more results.
|
||||||
std::wstring Next();
|
std::wstring Next();
|
||||||
|
|
||||||
|
// Write the file info into |info|.
|
||||||
|
void GetFindInfo(FindInfo* info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::wstring root_path_;
|
std::wstring root_path_;
|
||||||
bool recursive_;
|
bool recursive_;
|
||||||
@@ -380,6 +393,7 @@ class FileEnumerator {
|
|||||||
HANDLE find_handle_;
|
HANDLE find_handle_;
|
||||||
#elif defined(OS_POSIX)
|
#elif defined(OS_POSIX)
|
||||||
FTS* fts_;
|
FTS* fts_;
|
||||||
|
FTSENT* fts_ent_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator);
|
DISALLOW_EVIL_CONSTRUCTORS(FileEnumerator);
|
||||||
|
@@ -409,6 +409,16 @@ FileEnumerator::~FileEnumerator() {
|
|||||||
fts_close(fts_);
|
fts_close(fts_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileEnumerator::GetFindInfo(FindInfo* info) {
|
||||||
|
DCHECK(info);
|
||||||
|
|
||||||
|
if (!is_in_find_op_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(&(info->stat), fts_ent_->fts_statp, sizeof(info->stat));
|
||||||
|
info->filename.assign(fts_ent_->fts_name);
|
||||||
|
}
|
||||||
|
|
||||||
// As it stands, this method calls itself recursively when the next item of
|
// As it stands, this method calls itself recursively when the next item of
|
||||||
// the fts enumeration doesn't match (type, pattern, etc.). In the case of
|
// the fts enumeration doesn't match (type, pattern, etc.). In the case of
|
||||||
// large directories with many files this can be quite deep.
|
// large directories with many files this can be quite deep.
|
||||||
@@ -417,12 +427,12 @@ std::wstring FileEnumerator::Next() {
|
|||||||
if (!is_in_find_op_) {
|
if (!is_in_find_op_) {
|
||||||
if (pending_paths_.empty())
|
if (pending_paths_.empty())
|
||||||
return std::wstring();
|
return std::wstring();
|
||||||
|
|
||||||
// The last find FindFirstFile operation is done, prepare a new one.
|
// The last find FindFirstFile operation is done, prepare a new one.
|
||||||
root_path_ = pending_paths_.top();
|
root_path_ = pending_paths_.top();
|
||||||
TrimTrailingSeparator(&root_path_);
|
TrimTrailingSeparator(&root_path_);
|
||||||
pending_paths_.pop();
|
pending_paths_.pop();
|
||||||
|
|
||||||
// Start a new find operation.
|
// Start a new find operation.
|
||||||
int ftsflags = FTS_LOGICAL;
|
int ftsflags = FTS_LOGICAL;
|
||||||
char top_dir[PATH_MAX];
|
char top_dir[PATH_MAX];
|
||||||
@@ -433,41 +443,41 @@ std::wstring FileEnumerator::Next() {
|
|||||||
return Next();
|
return Next();
|
||||||
is_in_find_op_ = true;
|
is_in_find_op_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FTSENT* fts_ent = fts_read(fts_);
|
fts_ent_ = fts_read(fts_);
|
||||||
if (fts_ent == NULL) {
|
if (fts_ent_ == NULL) {
|
||||||
fts_close(fts_);
|
fts_close(fts_);
|
||||||
fts_ = NULL;
|
fts_ = NULL;
|
||||||
is_in_find_op_ = false;
|
is_in_find_op_ = false;
|
||||||
return Next();
|
return Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Level 0 is the top, which is always skipped.
|
// Level 0 is the top, which is always skipped.
|
||||||
if (fts_ent->fts_level == 0)
|
if (fts_ent_->fts_level == 0)
|
||||||
return Next();
|
return Next();
|
||||||
|
|
||||||
// Patterns are only matched on the items in the top-most directory.
|
// Patterns are only matched on the items in the top-most directory.
|
||||||
// (see Windows implementation)
|
// (see Windows implementation)
|
||||||
if (fts_ent->fts_level == 1 && pattern_.length() > 0) {
|
if (fts_ent_->fts_level == 1 && pattern_.length() > 0) {
|
||||||
if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent->fts_path, 0) != 0) {
|
if (fnmatch(WideToUTF8(pattern_).c_str(), fts_ent_->fts_path, 0) != 0) {
|
||||||
if (fts_ent->fts_info == FTS_D)
|
if (fts_ent_->fts_info == FTS_D)
|
||||||
fts_set(fts_, fts_ent, FTS_SKIP);
|
fts_set(fts_, fts_ent_, FTS_SKIP);
|
||||||
return Next();
|
return Next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstring cur_file(UTF8ToWide(fts_ent->fts_path));
|
std::wstring cur_file(UTF8ToWide(fts_ent_->fts_path));
|
||||||
if (fts_ent->fts_info == FTS_D) {
|
if (fts_ent_->fts_info == FTS_D) {
|
||||||
// If not recursive, then prune children.
|
// If not recursive, then prune children.
|
||||||
if (!recursive_)
|
if (!recursive_)
|
||||||
fts_set(fts_, fts_ent, FTS_SKIP);
|
fts_set(fts_, fts_ent_, FTS_SKIP);
|
||||||
return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next();
|
return (file_type_ & FileEnumerator::DIRECTORIES) ? cur_file : Next();
|
||||||
} else if (fts_ent->fts_info == FTS_F) {
|
} else if (fts_ent_->fts_info == FTS_F) {
|
||||||
return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
|
return (file_type_ & FileEnumerator::FILES) ? cur_file : Next();
|
||||||
}
|
}
|
||||||
// TODO(erikkay) - verify that the other fts_info types aren't interesting
|
// TODO(erikkay) - verify that the other fts_info types aren't interesting
|
||||||
return Next();
|
return Next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace file_util
|
} // namespace file_util
|
||||||
|
@@ -625,6 +625,15 @@ FileEnumerator::~FileEnumerator() {
|
|||||||
FindClose(find_handle_);
|
FindClose(find_handle_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileEnumerator::GetFindInfo(FindInfo* info) {
|
||||||
|
DCHECK(info);
|
||||||
|
|
||||||
|
if (!is_in_find_op_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(info, &find_data_, sizeof(*info));
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring FileEnumerator::Next() {
|
std::wstring FileEnumerator::Next() {
|
||||||
if (!is_in_find_op_) {
|
if (!is_in_find_op_) {
|
||||||
if (pending_paths_.empty())
|
if (pending_paths_.empty())
|
||||||
|
@@ -2,11 +2,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
#include "net/base/directory_lister.h"
|
#include "net/base/directory_lister.h"
|
||||||
|
|
||||||
|
#include "base/file_util.h"
|
||||||
#include "base/message_loop.h"
|
#include "base/message_loop.h"
|
||||||
|
#include "base/platform_thread.h"
|
||||||
|
#include "net/base/net_errors.h"
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
@@ -27,65 +28,24 @@ class DirectoryDataEvent : public Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scoped_refptr<DirectoryLister> lister;
|
scoped_refptr<DirectoryLister> lister;
|
||||||
WIN32_FIND_DATA data[kFilesPerEvent];
|
file_util::FileEnumerator::FindInfo data[kFilesPerEvent];
|
||||||
int count;
|
int count, error;
|
||||||
DWORD error;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*static*/
|
DirectoryLister::DirectoryLister(const std::wstring& dir,
|
||||||
unsigned __stdcall DirectoryLister::ThreadFunc(void* param) {
|
DirectoryListerDelegate* delegate)
|
||||||
DirectoryLister* self = reinterpret_cast<DirectoryLister*>(param);
|
|
||||||
|
|
||||||
std::wstring pattern = self->directory();
|
|
||||||
if (pattern[pattern.size()-1] != '\\') {
|
|
||||||
pattern.append(L"\\*");
|
|
||||||
} else {
|
|
||||||
pattern.append(L"*");
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryDataEvent* e = new DirectoryDataEvent(self);
|
|
||||||
|
|
||||||
HANDLE handle = FindFirstFile(pattern.c_str(), &e->data[e->count]);
|
|
||||||
if (handle == INVALID_HANDLE_VALUE) {
|
|
||||||
e->error = GetLastError();
|
|
||||||
self->message_loop_->PostTask(FROM_HERE, e);
|
|
||||||
e = NULL;
|
|
||||||
} else {
|
|
||||||
do {
|
|
||||||
if (++e->count == kFilesPerEvent) {
|
|
||||||
self->message_loop_->PostTask(FROM_HERE, e);
|
|
||||||
e = new DirectoryDataEvent(self);
|
|
||||||
}
|
|
||||||
} while (!self->was_canceled() && FindNextFile(handle, &e->data[e->count]));
|
|
||||||
|
|
||||||
FindClose(handle);
|
|
||||||
|
|
||||||
if (e->count > 0) {
|
|
||||||
self->message_loop_->PostTask(FROM_HERE, e);
|
|
||||||
e = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify done
|
|
||||||
e = new DirectoryDataEvent(self);
|
|
||||||
self->message_loop_->PostTask(FROM_HERE, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->Release();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
DirectoryLister::DirectoryLister(const std::wstring& dir, Delegate* delegate)
|
|
||||||
: dir_(dir),
|
: dir_(dir),
|
||||||
message_loop_(NULL),
|
|
||||||
delegate_(delegate),
|
delegate_(delegate),
|
||||||
|
message_loop_(NULL),
|
||||||
thread_(NULL),
|
thread_(NULL),
|
||||||
canceled_(false) {
|
canceled_(false) {
|
||||||
DCHECK(!dir.empty());
|
DCHECK(!dir.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectoryLister::~DirectoryLister() {
|
DirectoryLister::~DirectoryLister() {
|
||||||
if (thread_)
|
if (thread_) {
|
||||||
CloseHandle(thread_);
|
PlatformThread::Join(thread_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DirectoryLister::Start() {
|
bool DirectoryLister::Start() {
|
||||||
@@ -97,12 +57,7 @@ bool DirectoryLister::Start() {
|
|||||||
|
|
||||||
AddRef(); // the thread will release us when it is done
|
AddRef(); // the thread will release us when it is done
|
||||||
|
|
||||||
unsigned thread_id;
|
if (!PlatformThread::Create(0, this, &thread_)) {
|
||||||
thread_ = reinterpret_cast<HANDLE>(
|
|
||||||
_beginthreadex(NULL, 0, DirectoryLister::ThreadFunc, this, 0,
|
|
||||||
&thread_id));
|
|
||||||
|
|
||||||
if (!thread_) {
|
|
||||||
Release();
|
Release();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -114,13 +69,48 @@ void DirectoryLister::Cancel() {
|
|||||||
canceled_ = true;
|
canceled_ = true;
|
||||||
|
|
||||||
if (thread_) {
|
if (thread_) {
|
||||||
WaitForSingleObject(thread_, INFINITE);
|
PlatformThread::Join(thread_);
|
||||||
CloseHandle(thread_);
|
|
||||||
thread_ = NULL;
|
thread_ = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectoryLister::OnReceivedData(const WIN32_FIND_DATA* data, int count) {
|
void DirectoryLister::ThreadMain() {
|
||||||
|
DirectoryDataEvent* e = new DirectoryDataEvent(this);
|
||||||
|
|
||||||
|
if (!file_util::DirectoryExists(directory())) {
|
||||||
|
e->error = net::ERR_FILE_NOT_FOUND;
|
||||||
|
message_loop_->PostTask(FROM_HERE, e);
|
||||||
|
Release();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_util::FileEnumerator file_enum(directory(), false,
|
||||||
|
file_util::FileEnumerator::FILES_AND_DIRECTORIES);
|
||||||
|
|
||||||
|
std::wstring filename;
|
||||||
|
while (!was_canceled() && !(filename = file_enum.Next()).empty()) {
|
||||||
|
file_enum.GetFindInfo(&e->data[e->count]);
|
||||||
|
|
||||||
|
if (++e->count == kFilesPerEvent) {
|
||||||
|
message_loop_->PostTask(FROM_HERE, e);
|
||||||
|
e = new DirectoryDataEvent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->count > 0) {
|
||||||
|
message_loop_->PostTask(FROM_HERE, e);
|
||||||
|
e = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify done
|
||||||
|
e = new DirectoryDataEvent(this);
|
||||||
|
message_loop_->PostTask(FROM_HERE, e);
|
||||||
|
|
||||||
|
Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirectoryLister::OnReceivedData(
|
||||||
|
const file_util::FileEnumerator::FindInfo* data, int count) {
|
||||||
// Since the delegate can clear itself during the OnListFile callback, we
|
// Since the delegate can clear itself during the OnListFile callback, we
|
||||||
// need to null check it during each iteration of the loop. Similarly, it is
|
// need to null check it during each iteration of the loop. Similarly, it is
|
||||||
// necessary to check the canceled_ flag to avoid sending data to a delegate
|
// necessary to check the canceled_ flag to avoid sending data to a delegate
|
||||||
@@ -133,7 +123,7 @@ void DirectoryLister::OnDone(int error) {
|
|||||||
// If canceled, we need to report some kind of error, but don't overwrite the
|
// If canceled, we need to report some kind of error, but don't overwrite the
|
||||||
// error condition if it is already set.
|
// error condition if it is already set.
|
||||||
if (!error && canceled_)
|
if (!error && canceled_)
|
||||||
error = ERROR_OPERATION_ABORTED;
|
error = net::ERR_ABORTED;
|
||||||
|
|
||||||
if (delegate_)
|
if (delegate_)
|
||||||
delegate_->OnListDone(error);
|
delegate_->OnListDone(error);
|
||||||
|
@@ -5,9 +5,10 @@
|
|||||||
#ifndef NET_BASE_DIRECTORY_LISTER_H__
|
#ifndef NET_BASE_DIRECTORY_LISTER_H__
|
||||||
#define NET_BASE_DIRECTORY_LISTER_H__
|
#define NET_BASE_DIRECTORY_LISTER_H__
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/file_util.h"
|
||||||
|
#include "base/platform_thread.h"
|
||||||
#include "base/ref_counted.h"
|
#include "base/ref_counted.h"
|
||||||
|
|
||||||
class MessageLoop;
|
class MessageLoop;
|
||||||
@@ -21,16 +22,18 @@ namespace net {
|
|||||||
// structs over to the main application thread. The consumer of this class
|
// structs over to the main application thread. The consumer of this class
|
||||||
// is insulated from any of the multi-threading details.
|
// is insulated from any of the multi-threading details.
|
||||||
//
|
//
|
||||||
class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> {
|
class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister>,
|
||||||
|
public PlatformThread::Delegate {
|
||||||
public:
|
public:
|
||||||
// Implement this class to receive directory entries.
|
// Implement this class to receive directory entries.
|
||||||
class Delegate {
|
class DirectoryListerDelegate {
|
||||||
public:
|
public:
|
||||||
virtual void OnListFile(const WIN32_FIND_DATA& data) = 0;
|
virtual void OnListFile(
|
||||||
|
const file_util::FileEnumerator::FindInfo& data) = 0;
|
||||||
virtual void OnListDone(int error) = 0;
|
virtual void OnListDone(int error) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
DirectoryLister(const std::wstring& dir, Delegate* delegate);
|
DirectoryLister(const std::wstring& dir, DirectoryListerDelegate* delegate);
|
||||||
~DirectoryLister();
|
~DirectoryLister();
|
||||||
|
|
||||||
// Call this method to start the directory enumeration thread.
|
// Call this method to start the directory enumeration thread.
|
||||||
@@ -42,8 +45,8 @@ class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> {
|
|||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
||||||
// The delegate pointer may be modified at any time.
|
// The delegate pointer may be modified at any time.
|
||||||
Delegate* delegate() const { return delegate_; }
|
DirectoryListerDelegate* delegate() const { return delegate_; }
|
||||||
void set_delegate(Delegate* d) { delegate_ = d; }
|
void set_delegate(DirectoryListerDelegate* d) { delegate_ = d; }
|
||||||
|
|
||||||
// Returns the directory being enumerated.
|
// Returns the directory being enumerated.
|
||||||
const std::wstring& directory() const { return dir_; }
|
const std::wstring& directory() const { return dir_; }
|
||||||
@@ -51,18 +54,21 @@ class DirectoryLister : public base::RefCountedThreadSafe<DirectoryLister> {
|
|||||||
// Returns true if the directory enumeration was canceled.
|
// Returns true if the directory enumeration was canceled.
|
||||||
bool was_canceled() const { return canceled_; }
|
bool was_canceled() const { return canceled_; }
|
||||||
|
|
||||||
|
// PlatformThread::Delegate implementation
|
||||||
|
void ThreadMain();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class DirectoryDataEvent;
|
friend class DirectoryDataEvent;
|
||||||
|
friend class ThreadDelegate;
|
||||||
|
|
||||||
void OnReceivedData(const WIN32_FIND_DATA* data, int count);
|
void OnReceivedData(const file_util::FileEnumerator::FindInfo* data,
|
||||||
|
int count);
|
||||||
void OnDone(int error);
|
void OnDone(int error);
|
||||||
|
|
||||||
static unsigned __stdcall ThreadFunc(void* param);
|
|
||||||
|
|
||||||
std::wstring dir_;
|
std::wstring dir_;
|
||||||
Delegate* delegate_;
|
DirectoryListerDelegate* delegate_;
|
||||||
MessageLoop* message_loop_;
|
MessageLoop* message_loop_;
|
||||||
HANDLE thread_;
|
PlatformThreadHandle thread_;
|
||||||
bool canceled_;
|
bool canceled_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "net/base/net_util.h"
|
#include "net/base/net_util.h"
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
|
#include "base/file_path.h"
|
||||||
#include "base/file_util.h"
|
#include "base/file_util.h"
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
@@ -798,12 +799,22 @@ std::string CanonicalizeHost(const std::wstring& host, bool* is_ip_address) {
|
|||||||
return CanonicalizeHost(converted_host, is_ip_address);
|
return CanonicalizeHost(converted_host, is_ip_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OS_WIN
|
|
||||||
std::string GetDirectoryListingHeader(const std::string& title) {
|
std::string GetDirectoryListingHeader(const std::string& title) {
|
||||||
|
#if defined(OS_WIN)
|
||||||
std::string result = NetModule::GetResource(IDR_DIR_HEADER_HTML);
|
std::string result = NetModule::GetResource(IDR_DIR_HEADER_HTML);
|
||||||
if (result.empty()) {
|
if (result.empty()) {
|
||||||
NOTREACHED() << "expected resource not found";
|
NOTREACHED() << "expected resource not found";
|
||||||
}
|
}
|
||||||
|
#elif defined(OS_POSIX)
|
||||||
|
// TODO(estade): Temporary hack. Remove these platform #ifdefs when we
|
||||||
|
// have implemented resources for non-Windows platforms.
|
||||||
|
LOG(INFO) << "FIXME: hacked resource loading";
|
||||||
|
FilePath path;
|
||||||
|
PathService::Get(base::DIR_EXE, &path);
|
||||||
|
path = path.Append("../../net/base/dir_header.html");
|
||||||
|
std::string result;
|
||||||
|
file_util::ReadFileToString(path.ToWStringHack(), &result);
|
||||||
|
#endif
|
||||||
|
|
||||||
result.append("<script>start(");
|
result.append("<script>start(");
|
||||||
string_escape::JavascriptDoubleQuote(title, true, &result);
|
string_escape::JavascriptDoubleQuote(title, true, &result);
|
||||||
@@ -813,16 +824,16 @@ std::string GetDirectoryListingHeader(const std::string& title) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDirectoryListingEntry(const std::string& name,
|
std::string GetDirectoryListingEntry(const std::string& name,
|
||||||
DWORD attrib,
|
bool is_dir,
|
||||||
int64 size,
|
int64 size,
|
||||||
const FILETIME* modified) {
|
const Time& modified) {
|
||||||
std::string result;
|
std::string result;
|
||||||
result.append("<script>addRow(");
|
result.append("<script>addRow(");
|
||||||
string_escape::JavascriptDoubleQuote(name, true, &result);
|
string_escape::JavascriptDoubleQuote(name, true, &result);
|
||||||
result.append(",");
|
result.append(",");
|
||||||
string_escape::JavascriptDoubleQuote(
|
string_escape::JavascriptDoubleQuote(
|
||||||
EscapePath(name), true, &result);
|
EscapePath(name), true, &result);
|
||||||
if (attrib & FILE_ATTRIBUTE_DIRECTORY) {
|
if (is_dir) {
|
||||||
result.append(",1,");
|
result.append(",1,");
|
||||||
} else {
|
} else {
|
||||||
result.append(",0,");
|
result.append(",0,");
|
||||||
@@ -835,9 +846,8 @@ std::string GetDirectoryListingEntry(const std::string& name,
|
|||||||
|
|
||||||
std::wstring modified_str;
|
std::wstring modified_str;
|
||||||
// |modified| can be NULL in FTP listings.
|
// |modified| can be NULL in FTP listings.
|
||||||
if (modified) {
|
if (!modified.is_null()) {
|
||||||
Time time(Time::FromFileTime(*modified));
|
modified_str = base::TimeFormatShortDateAndTime(modified);
|
||||||
modified_str = base::TimeFormatShortDateAndTime(time);
|
|
||||||
}
|
}
|
||||||
string_escape::JavascriptDoubleQuote(modified_str, true, &result);
|
string_escape::JavascriptDoubleQuote(modified_str, true, &result);
|
||||||
|
|
||||||
@@ -845,7 +855,6 @@ std::string GetDirectoryListingEntry(const std::string& name,
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
std::wstring StripWWW(const std::wstring& text) {
|
std::wstring StripWWW(const std::wstring& text) {
|
||||||
const std::wstring www(L"www.");
|
const std::wstring www(L"www.");
|
||||||
|
@@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
class GURL;
|
class GURL;
|
||||||
|
|
||||||
|
namespace base {
|
||||||
|
class Time;
|
||||||
|
}
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
// Given the full path to a file name, creates a file: URL. The returned URL
|
// Given the full path to a file name, creates a file: URL. The returned URL
|
||||||
@@ -95,15 +99,12 @@ void IDNToUnicode(const char* host,
|
|||||||
std::string CanonicalizeHost(const std::string& host, bool* is_ip_address);
|
std::string CanonicalizeHost(const std::string& host, bool* is_ip_address);
|
||||||
std::string CanonicalizeHost(const std::wstring& host, bool* is_ip_address);
|
std::string CanonicalizeHost(const std::wstring& host, bool* is_ip_address);
|
||||||
|
|
||||||
#ifdef OS_WIN
|
|
||||||
// TODO: Port GetDirectoryListingEntry for OSX and linux.
|
|
||||||
// Call these functions to get the html for a directory listing.
|
// Call these functions to get the html for a directory listing.
|
||||||
// They will pass non-7bit-ascii characters unescaped, allowing
|
// They will pass non-7bit-ascii characters unescaped, allowing
|
||||||
// the browser to interpret the encoding (utf8, etc).
|
// the browser to interpret the encoding (utf8, etc).
|
||||||
std::string GetDirectoryListingHeader(const std::string& title);
|
std::string GetDirectoryListingHeader(const std::string& title);
|
||||||
std::string GetDirectoryListingEntry(const std::string& name, DWORD attrib,
|
std::string GetDirectoryListingEntry(const std::string& name, bool is_dir,
|
||||||
int64 size, const FILETIME* modified);
|
int64 size, const base::Time& modified);
|
||||||
#endif
|
|
||||||
|
|
||||||
// If text starts with "www." it is removed, otherwise text is returned
|
// If text starts with "www." it is removed, otherwise text is returned
|
||||||
// unmodified.
|
// unmodified.
|
||||||
|
@@ -110,11 +110,9 @@ if env['PLATFORM'] in ('posix', 'darwin'):
|
|||||||
# Remove files that still need to be ported from the input_files list.
|
# Remove files that still need to be ported from the input_files list.
|
||||||
# TODO(port): delete files from this list as they get ported.
|
# TODO(port): delete files from this list as they get ported.
|
||||||
to_be_ported_files = [
|
to_be_ported_files = [
|
||||||
'base/directory_lister.cc',
|
|
||||||
'base/ssl_config_service.cc',
|
'base/ssl_config_service.cc',
|
||||||
'http/http_transaction_winhttp.cc',
|
'http/http_transaction_winhttp.cc',
|
||||||
'http/winhttp_request_throttle.cc',
|
'http/winhttp_request_throttle.cc',
|
||||||
'url_request/url_request_file_dir_job.cc',
|
|
||||||
'url_request/url_request_ftp_job.cc',
|
'url_request/url_request_ftp_job.cc',
|
||||||
]
|
]
|
||||||
for remove in to_be_ported_files:
|
for remove in to_be_ported_files:
|
||||||
|
@@ -7,16 +7,18 @@
|
|||||||
#include "base/file_util.h"
|
#include "base/file_util.h"
|
||||||
#include "base/message_loop.h"
|
#include "base/message_loop.h"
|
||||||
#include "base/string_util.h"
|
#include "base/string_util.h"
|
||||||
|
#include "base/time.h"
|
||||||
#include "googleurl/src/gurl.h"
|
#include "googleurl/src/gurl.h"
|
||||||
#include "net/base/net_util.h"
|
#include "net/base/net_util.h"
|
||||||
#include "net/base/wininet_util.h"
|
|
||||||
#include "net/url_request/url_request.h"
|
#include "net/url_request/url_request.h"
|
||||||
|
|
||||||
|
#if defined(OS_POSIX)
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::wstring;
|
using std::wstring;
|
||||||
|
|
||||||
using net::WinInetUtil;
|
|
||||||
|
|
||||||
URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request,
|
URLRequestFileDirJob::URLRequestFileDirJob(URLRequest* request,
|
||||||
const wstring& dir_path)
|
const wstring& dir_path)
|
||||||
: URLRequestJob(request),
|
: URLRequestJob(request),
|
||||||
@@ -97,12 +99,8 @@ bool URLRequestFileDirJob::GetCharset(string* charset) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void URLRequestFileDirJob::OnListFile(const WIN32_FIND_DATA& data) {
|
void URLRequestFileDirJob::OnListFile(
|
||||||
FILETIME local_time;
|
const file_util::FileEnumerator::FindInfo& data) {
|
||||||
FileTimeToLocalFileTime(&data.ftLastWriteTime, &local_time);
|
|
||||||
int64 size = (static_cast<unsigned __int64>(data.nFileSizeHigh) << 32) |
|
|
||||||
data.nFileSizeLow;
|
|
||||||
|
|
||||||
// We wait to write out the header until we get the first file, so that we
|
// We wait to write out the header until we get the first file, so that we
|
||||||
// can catch errors from DirectoryLister and show an error page.
|
// can catch errors from DirectoryLister and show an error page.
|
||||||
if (!wrote_header_) {
|
if (!wrote_header_) {
|
||||||
@@ -110,11 +108,27 @@ void URLRequestFileDirJob::OnListFile(const WIN32_FIND_DATA& data) {
|
|||||||
wrote_header_ = true;
|
wrote_header_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
FILETIME local_time;
|
||||||
|
::FileTimeToLocalFileTime(&data.ftLastWriteTime, &local_time);
|
||||||
|
int64 size = (static_cast<unsigned __int64>(data.nFileSizeHigh) << 32) |
|
||||||
|
data.nFileSizeLow;
|
||||||
|
|
||||||
data_.append(net::GetDirectoryListingEntry(
|
data_.append(net::GetDirectoryListingEntry(
|
||||||
WideToUTF8(data.cFileName), data.dwFileAttributes, size, &local_time));
|
WideToUTF8(data.cFileName),
|
||||||
|
(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false,
|
||||||
|
size,
|
||||||
|
base::Time::FromFileTime(local_time)));
|
||||||
|
|
||||||
|
#elif defined(OS_POSIX)
|
||||||
|
data_.append(net::GetDirectoryListingEntry(
|
||||||
|
data.filename.c_str(),
|
||||||
|
S_ISDIR(data.stat.st_mode),
|
||||||
|
data.stat.st_size,
|
||||||
|
base::Time::FromTimeT(data.stat.st_mtime)));
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO(darin): coalesce more?
|
// TODO(darin): coalesce more?
|
||||||
|
|
||||||
CompleteRead();
|
CompleteRead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,8 +137,7 @@ void URLRequestFileDirJob::OnListDone(int error) {
|
|||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
read_pending_ = false;
|
read_pending_ = false;
|
||||||
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED,
|
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, error));
|
||||||
WinInetUtil::OSErrorToNetError(error)));
|
|
||||||
} else if (canceled_) {
|
} else if (canceled_) {
|
||||||
read_pending_ = false;
|
read_pending_ = false;
|
||||||
NotifyCanceled();
|
NotifyCanceled();
|
||||||
@@ -176,7 +189,8 @@ void URLRequestFileDirJob::CompleteRead() {
|
|||||||
NotifyReadComplete(bytes_read);
|
NotifyReadComplete(bytes_read);
|
||||||
} else {
|
} else {
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0)); // TODO: Better error code.
|
// TODO: Better error code.
|
||||||
|
NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,13 @@
|
|||||||
#ifndef NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__
|
#ifndef NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__
|
||||||
#define NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__
|
#define NET_URL_REQUEST_URL_REQUEST_FILE_DIR_JOB_H__
|
||||||
|
|
||||||
|
#include "base/file_util.h"
|
||||||
#include "net/base/directory_lister.h"
|
#include "net/base/directory_lister.h"
|
||||||
#include "net/url_request/url_request_job.h"
|
#include "net/url_request/url_request_job.h"
|
||||||
|
|
||||||
class URLRequestFileDirJob : public URLRequestJob,
|
class URLRequestFileDirJob
|
||||||
public net::DirectoryLister::Delegate {
|
: public URLRequestJob,
|
||||||
|
public net::DirectoryLister::DirectoryListerDelegate {
|
||||||
public:
|
public:
|
||||||
URLRequestFileDirJob(URLRequest* request, const std::wstring& dir_path);
|
URLRequestFileDirJob(URLRequest* request, const std::wstring& dir_path);
|
||||||
virtual ~URLRequestFileDirJob();
|
virtual ~URLRequestFileDirJob();
|
||||||
@@ -22,8 +24,8 @@ class URLRequestFileDirJob : public URLRequestJob,
|
|||||||
virtual bool GetMimeType(std::string* mime_type);
|
virtual bool GetMimeType(std::string* mime_type);
|
||||||
virtual bool GetCharset(std::string* charset);
|
virtual bool GetCharset(std::string* charset);
|
||||||
|
|
||||||
// DirectoryLister::Delegate methods:
|
// DirectoryLister::DirectoryListerDelegate methods:
|
||||||
virtual void OnListFile(const WIN32_FIND_DATA& data);
|
virtual void OnListFile(const file_util::FileEnumerator::FindInfo& data);
|
||||||
virtual void OnListDone(int error);
|
virtual void OnListDone(int error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@@ -28,9 +28,7 @@
|
|||||||
#include "net/base/net_errors.h"
|
#include "net/base/net_errors.h"
|
||||||
#include "net/base/net_util.h"
|
#include "net/base/net_util.h"
|
||||||
#include "net/url_request/url_request.h"
|
#include "net/url_request/url_request.h"
|
||||||
#if defined(OS_WIN)
|
|
||||||
#include "net/url_request/url_request_file_dir_job.h"
|
#include "net/url_request/url_request_file_dir_job.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
class URLRequestFileJob::AsyncResolver :
|
class URLRequestFileJob::AsyncResolver :
|
||||||
@@ -76,10 +74,8 @@ URLRequestJob* URLRequestFileJob::Factory(
|
|||||||
std::wstring file_path;
|
std::wstring file_path;
|
||||||
if (net::FileURLToFilePath(request->url(), &file_path)) {
|
if (net::FileURLToFilePath(request->url(), &file_path)) {
|
||||||
if (file_path[file_path.size() - 1] == file_util::kPathSeparator) {
|
if (file_path[file_path.size() - 1] == file_util::kPathSeparator) {
|
||||||
#if defined(OS_WIN)
|
|
||||||
// Only directories have trailing slashes.
|
// Only directories have trailing slashes.
|
||||||
return new URLRequestFileDirJob(request, file_path);
|
return new URLRequestFileDirJob(request, file_path);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "base/message_loop.h"
|
#include "base/message_loop.h"
|
||||||
#include "base/string_util.h"
|
#include "base/string_util.h"
|
||||||
|
#include "base/time.h"
|
||||||
#include "net/base/auth.h"
|
#include "net/base/auth.h"
|
||||||
#include "net/base/load_flags.h"
|
#include "net/base/load_flags.h"
|
||||||
#include "net/base/net_util.h"
|
#include "net/base/net_util.h"
|
||||||
@@ -378,8 +379,8 @@ void URLRequestFtpJob::OnFindFile(DWORD last_error) {
|
|||||||
// We don't know the encoding, and can't assume utf8, so pass the 8bit
|
// We don't know the encoding, and can't assume utf8, so pass the 8bit
|
||||||
// directly to the browser for it to decide.
|
// directly to the browser for it to decide.
|
||||||
string file_entry = net::GetDirectoryListingEntry(
|
string file_entry = net::GetDirectoryListingEntry(
|
||||||
find_data_.cFileName, find_data_.dwFileAttributes, size,
|
find_data_.cFileName, false, size,
|
||||||
&find_data_.ftLastWriteTime);
|
base::Time::FromFileTime(find_data_.ftLastWriteTime));
|
||||||
WriteData(&file_entry, true);
|
WriteData(&file_entry, true);
|
||||||
|
|
||||||
FindNextFile();
|
FindNextFile();
|
||||||
@@ -401,7 +402,7 @@ void URLRequestFtpJob::OnStartDirectoryTraversal() {
|
|||||||
// If this isn't top level directory (i.e. the path isn't "/",) add a link to
|
// If this isn't top level directory (i.e. the path isn't "/",) add a link to
|
||||||
// the parent directory.
|
// the parent directory.
|
||||||
if (request_->url().path().length() > 1)
|
if (request_->url().path().length() > 1)
|
||||||
html.append(net::GetDirectoryListingEntry("..", 0, 0, NULL));
|
html.append(net::GetDirectoryListingEntry("..", false, 0, base::Time()));
|
||||||
|
|
||||||
WriteData(&html, true);
|
WriteData(&html, true);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user