📄 sharemanager.cpp
字号:
dirty = false;
lastUpdate = GET_TICK();
}
if(update) {
ClientManager::getInstance()->infoUpdated();
}
return 0;
}
#define STRINGLEN(n) n, sizeof(n)-1
void ShareManager::Directory::toString(string& tmp, DupeMap& dupes, int ident /* = 0 */) {
tmp.append(ident, '\t');
tmp.append(name);
tmp.append(STRINGLEN("\r\n"));
for(MapIter i = directories.begin(); i != directories.end(); ++i) {
i->second->toString(tmp, dupes, ident + 1);
}
Directory::FileIter j = files.begin();
while(j != files.end()) {
pair<DupeIter, DupeIter> p = dupes.equal_range(j->second);
DupeIter k = p.first;
for(; k != p.second; ++k) {
if(k->second == j->first) {
dcdebug("SM::D::toString Dupe found: %s (%I64d bytes)\n", k->second.c_str(), j->second);
break;
}
}
if(k != p.second) {
size-=j->second;
if(BOOLSETTING(REMOVE_DUPES)) {
j = files.erase(j);
} else {
tmp.append(ident+1, '\t');
tmp.append(j->first);
tmp.append(STRINGLEN("|"));
tmp.append(Util::toString(j->second));
tmp.append(STRINGLEN("\r\n"));
++j;
}
} else {
dupes.insert(make_pair(j->second, j->first));
tmp.append(ident+1, '\t');
tmp.append(j->first);
tmp.append(STRINGLEN("|"));
tmp.append(Util::toString(j->second));
tmp.append(STRINGLEN("\r\n"));
++j;
}
}
}
// These ones we can look up as ints (4 bytes...)...
static const char* typeAudio[] = { ".mp3", ".mp2", ".mid", ".wav", ".ogg", ".wma" };
static const char* typeCompressed[] = { ".zip", ".ace", ".rar" };
static const char* typeDocument[] = { ".htm", ".doc", ".txt", ".nfo" };
static const char* typeExecutable[] = { ".exe" };
static const char* typePicture[] = { ".jpg", ".gif", ".png", ".eps", ".img", ".pct", ".psp", ".pic", ".tif", ".rle", ".bmp", ".pcx" };
static const char* typeVideo[] = { ".mpg", ".mov", ".asf", ".avi", ".pxp" };
static const string type2Audio[] = { ".au", ".aiff" };
static const string type2Picture[] = { ".ai", ".ps", ".pict" };
static const string type2Video[] = { ".rm", ".divx", ".mpeg" };
#define IS_TYPE(x) ( type == (*((u_int32_t*)x)) )
#define IS_TYPE2(x) (Util::stricmp(aString.c_str() + aString.length() - x.length(), x.c_str()) == 0)
static bool checkType(const string& aString, int aType) {
if(aType == SearchManager::TYPE_ANY)
return true;
if(aString.length() < 5)
return false;
const char* c = aString.c_str() + aString.length() - 3;
u_int32_t type = '.' | (Util::toLower(c[0]) << 8) | (Util::toLower(c[1]) << 16) | (((u_int32_t)Util::toLower(c[2])) << 24);
switch(aType) {
case SearchManager::TYPE_AUDIO:
{
for(int i = 0; i < (sizeof(typeAudio) / sizeof(typeAudio[0])); i++) {
if(IS_TYPE(typeAudio[i])) {
return true;
}
}
if( IS_TYPE2(type2Audio[0]) || IS_TYPE2(type2Audio[1]) ) {
return true;
}
}
break;
case SearchManager::TYPE_COMPRESSED:
if( IS_TYPE(typeCompressed[0]) || IS_TYPE(typeCompressed[1]) || IS_TYPE(typeCompressed[2]) ) {
return true;
}
break;
case SearchManager::TYPE_DOCUMENT:
if( IS_TYPE(typeDocument[0]) || IS_TYPE(typeDocument[1]) ||
IS_TYPE(typeDocument[2]) || IS_TYPE(typeDocument[3]) ) {
return true;
}
break;
case SearchManager::TYPE_EXECUTABLE:
if(IS_TYPE(typeExecutable[0]) ) {
return true;
}
break;
case SearchManager::TYPE_PICTURE:
{
for(int i = 0; i < (sizeof(typePicture) / sizeof(typePicture[0])); i++) {
if(IS_TYPE(typePicture[i])) {
return true;
}
}
if( IS_TYPE2(type2Picture[0]) || IS_TYPE2(type2Picture[1]) || IS_TYPE2(type2Picture[2]) ) {
return true;
}
}
break;
case SearchManager::TYPE_VIDEO:
{
for(int i = 0; i < (sizeof(typeVideo) / sizeof(typeVideo[0])); i++) {
if(IS_TYPE(typeVideo[i])) {
return true;
}
}
if( IS_TYPE2(type2Video[0]) || IS_TYPE2(type2Video[1]) || IS_TYPE2(type2Video[2]) ) {
return true;
}
}
break;
default:
dcasserta(0);
break;
}
return false;
}
SearchManager::TypeModes ShareManager::getType(const string& aFileName) {
if(aFileName[aFileName.length() - 1] == '\\') {
return SearchManager::TYPE_DIRECTORY;
}
if(checkType(aFileName, SearchManager::TYPE_VIDEO))
return SearchManager::TYPE_VIDEO;
else if(checkType(aFileName, SearchManager::TYPE_AUDIO))
return SearchManager::TYPE_AUDIO;
else if(checkType(aFileName, SearchManager::TYPE_COMPRESSED))
return SearchManager::TYPE_COMPRESSED;
else if(checkType(aFileName, SearchManager::TYPE_DOCUMENT))
return SearchManager::TYPE_DOCUMENT;
else if(checkType(aFileName, SearchManager::TYPE_EXECUTABLE))
return SearchManager::TYPE_EXECUTABLE;
else if(checkType(aFileName, SearchManager::TYPE_PICTURE))
return SearchManager::TYPE_PICTURE;
return SearchManager::TYPE_ANY;
}
/**
* The mask is a set of bits that say which words a file matches. Each bit means
* that a fileName matches the word at position n-1 in the words list where n is
* the bit number. bit 0 is only set when no words match.
*/
u_int32_t ShareManager::getMask(const string& fileName) {
u_int32_t mask = 0;
int n = 1;
for(StringIter i = words.begin(); i != words.end(); ++i, n++) {
if(Util::findSubString(fileName, *i) != string::npos) {
mask |= (1 << n);
}
}
return (mask == 0) ? 1 : mask;
}
u_int32_t ShareManager::getMask(StringList& l) {
u_int32_t mask = 0;
int n = 1;
for(StringIter i = words.begin(); i != words.end(); ++i, n++) {
for(StringIter j = l.begin(); j != l.end(); ++j) {
if(Util::findSubString(*j, *i) != string::npos) {
mask |= (1 << n);
}
}
}
return (mask == 0) ? 1 : mask;
}
u_int32_t ShareManager::getMask(StringSearch::List& l) {
u_int32_t mask = 0;
int n = 1;
for(StringIter i = words.begin(); i != words.end(); ++i, n++) {
for(StringSearch::Iter j = l.begin(); j != l.end(); ++j) {
if(Util::findSubString(j->getPattern(), *i) != string::npos) {
mask |= (1 << n);
}
}
}
return (mask == 0) ? 1 : mask;
}
/**
* Alright, the main point here is that when searching, a search string is most often found in
* the filename, not directory name, so we want to make that case faster. Also, we want to
* avoid changing StringLists unless we absolutely have to --> this should only be done if a string
* has been matched in the directory name. This new stringlist should also be used in all descendants,
* but not the parents...
*/
void ShareManager::Directory::search(SearchResult::List& aResults, StringSearch::List& aStrings, int aSearchType, int64_t aSize, int aFileType, Client* aClient, StringList::size_type maxResults, u_int32_t mask) {
// Skip everything if there's nothing to find here (doh! =)
if(!hasType(aFileType))
return;
if(!hasSearchType(mask))
return;
StringSearch::List* cur = &aStrings;
auto_ptr<StringSearch::List> newStr;
// Find any matches in the directory name
for(StringSearch::Iter k = aStrings.begin(); k != aStrings.end(); ++k) {
if(k->match(name)) {
if(!newStr.get()) {
newStr = auto_ptr<StringSearch::List>(new StringSearch::List(aStrings));
}
dcassert(find(newStr->begin(), newStr->end(), *k) != newStr->end());
newStr->erase(find(newStr->begin(), newStr->end(), *k));
u_int32_t xmask = ShareManager::getInstance()->getMask(k->getPattern());
if(xmask != 1) {
mask &= ~xmask;
}
}
}
if(newStr.get() != 0) {
cur = newStr.get();
}
bool sizeOk = (aSearchType != SearchManager::SIZE_ATLEAST) || (aSize == 0);
if( (cur->empty()) &&
(((aFileType == SearchManager::TYPE_ANY) && sizeOk) || (aFileType == SearchManager::TYPE_DIRECTORY)) ) {
// We satisfied all the search words! Add the directory...
SearchResult* sr = new SearchResult();
sr->setType(SearchResult::TYPE_DIRECTORY);
sr->setFile(getFullName());
sr->setFreeSlots(UploadManager::getInstance()->getFreeSlots());
sr->setSlots(SETTING(SLOTS));
sr->setUser(ClientManager::getInstance()->getUser(aClient->getNick(), aClient, false));
sr->setHubAddress(aClient->getIp());
sr->setHubName(aClient->getName());
aResults.push_back(sr);
ShareManager::getInstance()->setHits(ShareManager::getInstance()->getHits()+1);
}
if(aFileType != SearchManager::TYPE_DIRECTORY) {
for(FileIter i = files.begin(); i != files.end(); ++i) {
if(aSearchType == SearchManager::SIZE_ATLEAST && aSize > i->second) {
continue;
} else if(aSearchType == SearchManager::SIZE_ATMOST && aSize < i->second) {
continue;
}
StringSearch::Iter j = cur->begin();
for(; j != cur->end() && j->match(i->first); ++j)
; // Empty
if(j != cur->end())
continue;
// Check file type...
if(checkType(i->first, aFileType)) {
SearchResult* sr = new SearchResult();
sr->setType(SearchResult::TYPE_FILE);
sr->setFile(getFullName() + i->first);
sr->setSize(i->second);
sr->setFreeSlots(UploadManager::getInstance()->getFreeSlots());
sr->setSlots(SETTING(SLOTS));
sr->setUser(ClientManager::getInstance()->getUser(aClient->getNick(), aClient, false));
sr->setHubAddress(aClient->getIp());
sr->setHubName(aClient->getName());
aResults.push_back(sr);
ShareManager::getInstance()->setHits(ShareManager::getInstance()->getHits()+1);
if(aResults.size() >= maxResults) {
break;
}
}
}
}
for(Directory::MapIter l = directories.begin(); (l != directories.end()) && (aResults.size() < maxResults); ++l) {
l->second->search(aResults, *cur, aSearchType, aSize, aFileType, aClient, maxResults, mask);
}
}
SearchResult::List ShareManager::search(const string& aString, int aSearchType, int64_t aSize, int aFileType, Client* aClient, StringList::size_type maxResults) {
RLock l(cs);
StringTokenizer t(aString, '$');
StringList& sl = t.getTokens();
StringSearch::List ssl;
for(StringList::iterator i = sl.begin(); i != sl.end(); ++i) {
if(!i->empty()) {
ssl.push_back(StringSearch(*i));
}
}
u_int32_t mask = getMask(sl);
SearchResult::List results;
for(Directory::MapIter j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
j->second->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults, mask);
}
return results;
}
// SettingsManagerListener
void ShareManager::onAction(SettingsManagerListener::Types type, SimpleXML* xml) throw() {
switch(type) {
case SettingsManagerListener::LOAD: load(xml); break;
case SettingsManagerListener::SAVE: save(xml); break;
}
}
void ShareManager::onAction(TimerManagerListener::Types type, u_int32_t tick) throw() {
if(type == TimerManagerListener::MINUTE && BOOLSETTING(AUTO_UPDATE_LIST)) {
if(lastUpdate + 60 * 60 * 1000 < tick) {
try {
dirty = true;
refresh(true, true);
lastUpdate = tick;
} catch(const ShareException&) {
}
}
}
}
/**
* @file
* $Id: ShareManager.cpp,v 1.54 2003/07/15 14:53:11 arnetheduck Exp $
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -