📄 sharemanager.cpp
字号:
/*
* Copyright (C) 2001-2003 Jacek Sieka, j_s@telia.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "stdinc.h"
#include "DCPlusPlus.h"
#include "ShareManager.h"
#include "CryptoManager.h"
#include "SimpleXML.h"
#include "StringTokenizer.h"
#include "UploadManager.h"
#include "ClientManager.h"
#include "File.h"
ShareManager* Singleton<ShareManager>::instance = NULL;
ShareManager::ShareManager() : hits(0), listLen(0), dirty(false), refreshDirs(false),
update(false), listN(0), lFile(NULL), bFile(NULL), lastUpdate(GET_TICK()) {
SettingsManager::getInstance()->addListener(this);
TimerManager::getInstance()->addListener(this);
/* Common search words used to make search more efficient, should be more dynamic */
words.push_back("avi");
words.push_back("mp3");
words.push_back("bin");
words.push_back("zip");
words.push_back("jpg");
words.push_back("mpeg");
words.push_back("mpg");
words.push_back("rar");
words.push_back("ace");
words.push_back("bin");
words.push_back("iso");
words.push_back("dev");
words.push_back("flt");
words.push_back("ccd");
words.push_back("txt");
words.push_back("sub");
words.push_back("nfo");
words.push_back("wav");
words.push_back("exe");
words.push_back("ccd");
};
ShareManager::~ShareManager() {
SettingsManager::getInstance()->removeListener(this);
TimerManager::getInstance()->removeListener(this);
join();
delete lFile;
delete bFile;
for(int i = 0; i <= listN; ++i) {
File::deleteFile(Util::getAppPath() + "MyList" + Util::toString(i) + ".DcLst");
File::deleteFile(Util::getAppPath() + "MyList" + Util::toString(i) + ".bz2");
}
for(Directory::MapIter j = directories.begin(); j != directories.end(); ++j) {
delete j->second;
}
}
string ShareManager::translateFileName(const string& aFile) throw(ShareException) {
RLock l(cs);
if(aFile == "MyList.DcLst") {
return getListFile();
} else if(aFile == "MyList.bz2") {
return getBZListFile();
} else {
string::size_type i = aFile.find('\\');
if(i == string::npos)
throw ShareException("File Not Available");
string aDir = aFile.substr(0, i);
RLock l(cs);
StringMapIter j = dirs.find(aDir);
if(j == dirs.end()) {
throw ShareException("File Not Available");
}
if(!checkFile(j->second, aFile.substr(i + 1))) {
throw ShareException("File Not Available");
}
return j->second + aFile.substr(i);
}
}
bool ShareManager::checkFile(const string& dir, const string& aFile) {
Directory::MapIter mi = directories.find(dir);
if(mi == directories.end())
return false;
Directory* d = mi->second;
string::size_type i;
string::size_type j = 0;
while( (i = aFile.find('\\', j)) != string::npos) {
mi = d->directories.find(aFile.substr(j, i-j));
j = i + 1;
if(mi == d->directories.end())
return false;
d = mi->second;
}
if(find_if(d->files.begin(), d->files.end(), CompareFirst<string, int64_t>(aFile.substr(j))) == d->files.end())
return false;
return true;
}
void ShareManager::load(SimpleXML* aXml) {
WLock l(cs);
if(aXml->findChild("Share")) {
aXml->stepIn();
while(aXml->findChild("Directory")) {
try {
addDirectory(aXml->getChildData());
} catch(const ShareException&) {
// ...
}
}
aXml->stepOut();
}
dirty = true;
}
void ShareManager::save(SimpleXML* aXml) {
RLock l(cs);
aXml->addTag("Share");
aXml->stepIn();
for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
aXml->addTag("Directory", i->first);
}
aXml->stepOut();
}
void ShareManager::addDirectory(const string& aDirectory) throw(ShareException) {
if(aDirectory.size() == 0) {
throw ShareException(STRING(NO_DIRECTORY_SPECIFIED));
}
{
WLock l(cs);
string d;
if(aDirectory[aDirectory.size() - 1] == '\\') {
d = aDirectory.substr(0, aDirectory.size()-1);
} else {
d = aDirectory;
}
for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
if(d.find(i->first + '\\') != string::npos) {
throw ShareException(STRING(DIRECTORY_ALREADY_SHARED));
} else if(i->first.find(d + '\\') != string::npos) {
throw ShareException(STRING(REMOVE_ALL_SUBDIRECTORIES));
}
}
string dir = Util::toLower(d.substr(d.rfind('\\') + 1));
if(dirs.find(dir) != dirs.end()) {
// We have a duplicate, rename it internally...
char c = 'a';
while(dirs.find(dir + c) != dirs.end()) {
c++;
}
dir += c;
}
Directory* dp = buildTree(d, NULL);
dp->setName(dir);
directories[d] = dp;
dirs[dir] = d;
dirty = true;
}
}
void ShareManager::removeDirectory(const string& aDirectory) {
WLock l(cs);
Directory::MapIter i = directories.find(aDirectory);
if(i != directories.end()) {
delete i->second;
directories.erase(i);
}
for(StringMapIter j = dirs.begin(); j != dirs.end(); ++j) {
if(Util::stricmp(j->second.c_str(), aDirectory.c_str()) == 0) {
dirs.erase(j);
break;
}
}
dirty = true;
}
ShareManager::Directory* ShareManager::buildTree(const string& aName, Directory* aParent) {
Directory* dir = new Directory(aName.substr(aName.rfind('\\') + 1), aParent);
dir->addSearchType(getMask(dir->getName()));
#ifdef WIN32
WIN32_FIND_DATA data;
HANDLE hFind;
hFind = FindFirstFile((aName + "\\*").c_str(), &data);
if(hFind != INVALID_HANDLE_VALUE) {
do {
string name = data.cFileName;
if(name == "." || name == "..")
continue;
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if( !((!BOOLSETTING(SHARE_HIDDEN)) && (data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) ) {
dir->addType(SearchManager::TYPE_DIRECTORY);
dir->directories[name] = buildTree(aName + '\\' + name, dir);
dir->addSearchType(dir->directories[name]->getSearchTypes());
}
} else {
if( !((!BOOLSETTING(SHARE_HIDDEN)) && (data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)) ) {
// Not a directory, assume it's a file...make sure we're not sharing the settings file...
if( (Util::stricmp(name.c_str(), "DCPlusPlus.xml") != 0) &&
(Util::stricmp(name.c_str(), "Favorites.xml") != 0) &&
(name.find('$') == string::npos) ) {
dir->addSearchType(getMask(name));
dir->addType(getType(name));
dir->files.push_back(make_pair(name, (int64_t)data.nFileSizeLow | ((int64_t)data.nFileSizeHigh)<<32));
dir->size+=(int64_t)data.nFileSizeLow | ((int64_t)data.nFileSizeHigh)<<32;
}
}
}
} while(FindNextFile(hFind, &data));
}
FindClose(hFind);
#endif
return dir;
}
StringList ShareManager::getDirectories() {
RLock l(cs);
StringList tmp;
tmp.reserve(directories.size());
for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
tmp.push_back(i->first);
}
return tmp;
}
void ShareManager::refresh(bool dirs /* = false */, bool aUpdate /* = true */, bool block /* = false */) throw(ShareException) {
update = aUpdate;
refreshDirs = dirs;
if(dirty) {
join();
start();
if(block) {
join();
} else {
setThreadPriority(Thread::LOW);
}
}
}
int ShareManager::run() {
string tmp, tmp2;
{
WLock l(cs);
if(refreshDirs) {
StringList dirs = getDirectories();
for(StringIter k = dirs.begin(); k != dirs.end(); ++k) {
removeDirectory(*k);
}
for(StringIter l = dirs.begin(); l != dirs.end(); ++l) {
addDirectory(*l);
}
refreshDirs = false;
}
Directory::DupeMap dupes;
for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
i->second->toString(tmp, dupes);
}
CryptoManager::getInstance()->encodeHuffman(tmp, tmp2);
listN++;
try {
if(lFile != NULL) {
delete lFile;
lFile = NULL;
// Try to delete it...
File::deleteFile(getListFile());
}
setListFile(Util::getAppPath() + "MyList" + Util::toString(listN) + ".DcLst");
lFile = new File(getListFile(), File::WRITE, File::CREATE | File::TRUNCATE);
lFile->write(tmp2);
delete lFile;
// Null in case of exception...
lFile = NULL;
lFile = new File(getListFile(), File::READ, File::OPEN);
} catch(const FileException&) {
}
listLen = tmp2.length();
tmp2.clear();
CryptoManager::getInstance()->encodeBZ2(tmp, tmp2);
try {
if(bFile != NULL) {
delete bFile;
bFile = NULL;
File::deleteFile(getBZListFile());
}
setBZListFile(Util::getAppPath() + "MyList" + Util::toString(listN) + ".bz2");
bFile = new File(getBZListFile(), File::WRITE, File::CREATE | File::TRUNCATE);
bFile->write(tmp2);
delete bFile;
bFile = NULL;
bFile = new File(getBZListFile(), File::READ, File::OPEN);
} catch(const FileException&) {
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -