| 
      
      
      From: <arn...@us...> - 2008-04-14 20:10:55
      
     | 
| Revision: 1143
          http://dcplusplus.svn.sourceforge.net/dcplusplus/?rev=1143&view=rev
Author:   arnetheduck
Date:     2008-04-14 13:10:48 -0700 (Mon, 14 Apr 2008)
Log Message:
-----------
multiple shares with same name
Modified Paths:
--------------
    dcplusplus/trunk/changelog.txt
    dcplusplus/trunk/dcpp/ShareManager.cpp
    dcplusplus/trunk/dcpp/ShareManager.h
    dcplusplus/trunk/win32/UploadPage.cpp
Property Changed:
----------------
    dcplusplus/trunk/
Property changes on: dcplusplus/trunk
___________________________________________________________________
Name: bzr:revision-info
   - timestamp: 2008-04-06 18:48:35.145999908 +0200
committer: poy <po...@12...>
properties: 
	branch-nick: bzr
   + timestamp: 2008-04-06 23:02:37.905999899 +0200
committer: Jacek Sieka <arn...@gm...>
properties: 
	branch-nick: dcplusplus
Name: bzr:revision-id:v3-trunk1
   - 1027 arn...@gm...-20080323183926-schknwnkgeo7ivdn
1028 zouzou123gen-20080323220411-r8usuc3qxwuh7zsn
1029 zouzou123gen-20080323221249-0su72zaj13e706mk
1030 arn...@gm...-20080324140623-muba1dl46m000o8c
1031 zouzou123gen-20080324141933-qbgr93ugpe0297m6
1032 arn...@gm...-20080324153706-siidja05n84i00b1
1033 arn...@gm...-20080324153823-lhn3awurnu77riln
1034 arn...@gm...-20080324165650-zapppziji67yf5a2
1035 zouzou123gen-20080324175936-4mqc2kh0lo5wtdu2
1036 zouzou123gen-20080325004602-6wdsoym95mjuhwd3
1037 arn...@gm...-20080325100659-8fqy6q65itmghlep
1038 zouzou123gen-20080325175216-s297sdiucukfvijh
1039 arn...@gm...-20080325210137-3dfqyoi8ykosy087
1040 arn...@gm...-20080325211747-nwwy1eb33r071sca
1041 arn...@gm...-20080326084110-qbselrjckku275xi
1042 zouzou123gen-20080326123631-35642mgbk2i4ty32
1043 zouzou123gen-20080326124345-f4xwn2d3ty8ubd6r
1044 arn...@gm...-20080326162031-il0nyms30w0mky43
1045 arn...@gm...-20080326164801-8dru8mjc06xgzjpv
1046 arn...@gm...-20080326170438-uzl2rx8fqnohak7g
1047 zouzou123gen-20080326172821-d6uqcbmfb0c6rwlv
1048 arn...@gm...-20080326213257-qlgdh7m2712p2l0q
1049 arn...@gm...-20080326214313-ktnoekgk3s0wmatz
1050 arn...@gm...-20080326215256-0j1iqrf286b9g7zf
1051 arn...@gm...-20080327082121-hoi22wh1gwjdfbyd
1052 arn...@gm...-20080327120639-um3tukdt374rwvgm
1053 zouzou123gen-20080327130703-6vtek6uxy3vua543
1054 arn...@gm...-20080327215831-dmg5mkufskabwkro
1055 arn...@gm...-20080327231459-cdztcv25alsuyqmf
1056 arn...@gm...-20080328085925-gceybsr53oml1p24
1057 arn...@gm...-20080328200512-1sjuu6bcnl2dyd2a
1058 arn...@gm...-20080328210347-bussqjrm5mfswh7o
1059 arn...@gm...-20080329055630-braiir1dskv7a4qm
1060 arn...@gm...-20080329061558-rck8dz60wpj3c5ja
1061 arn...@gm...-20080329081253-if6o5jn329mbzfpl
1062 arn...@gm...-20080329081619-cb4x930j8sp55cs0
1063 arn...@gm...-20080329103216-hgjzo7ra2zixbztd
1064 arn...@gm...-20080329124042-q3aw4iodmo5kafyp
1065 arn...@gm...-20080329124926-2je1z18p0272zpua
1066 arn...@gm...-20080329150901-ehj9t32en7eps2dp
1067 zouzou123gen-20080329153653-36xlvpik2ns9r84r
1068 zouzou123gen-20080329162703-51xr8hg073pg7wq5
1069 zouzou123gen-20080329234706-8ddipdqu0xeudkql
1070 arn...@gm...-20080330081232-ubqr1171ewalrd4q
1071 zouzou123gen-20080330131607-yppbs3mgyjef1cux
1072 zouzou123gen-20080330134835-yv1nogy77ib1uehd
1073 zouzou123gen-20080331124549-alyw7vugdn30piqy
1074 zouzou123gen-20080331135108-q8frtqsin5bosfzm
1075 zouzou123gen-20080331140757-u94q52yccl5lsifk
1076 zouzou123gen-20080331152513-ue1x5qhigcw51348
1077 arn...@gm...-20080331184436-a8g6chibmg8nswls
1078 arn...@gm...-20080331220648-81485k28qmwruwz6
1079 zouzou123gen-20080401081001-2yjn07cf8s5sxr3a
1080 zouzou123gen-20080401081247-f3p4hdjojnd460jw
1081 zouzou123gen-20080401084117-24a454g8o0x656kg
1082 zouzou123gen-20080401133146-jabb5i8870fg6f66
1083 zouzou123gen-20080401154610-mxdqoo5bksru93e6
1084 arn...@gm...-20080401185530-lqj4tflt5ldmx46f
1085 arn...@gm...-20080401212616-ffl7m0xm8gt15knk
1086 arn...@gm...-20080402084515-ofmnwihzv159jton
1087 arn...@gm...-20080402133105-y70soi38owzl76i9
1088 arn...@gm...-20080402142417-rn2dbkx19wfz3vae
1089 arn...@gm...-20080402144459-u3z3hqvl8aqjc4a0
1090 zouzou123gen-20080402145051-zi8tmvy8u3r2mzu8
1091 arn...@gm...-20080402152137-f397uz1yp9qjvfwh
1092 zouzou123gen-20080402170355-29wda40wk3cy7lu5
1093 arn...@gm...-20080402180628-ipos9li0c4bsmq1h
1094 arn...@gm...-20080402181235-s2a6f4ww4lzayl46
1095 arn...@gm...-20080402193851-6mu64vgep6tijith
1096 arn...@gm...-20080402203810-86zpxsx69q83zf3r
1097 arn...@gm...-20080402204331-so2e8n892o23pejr
1098 poy-20080402224153-225qylr2cfwhqrg7
1099 mrmikejj-20080403125112-o8polh8rkn62umyh
1100 arn...@gm...-20080403125139-8xub76j1xazhfxna
1101 po...@12...-20080403140544-13kockkjho883nb4
1102 po...@12...-20080403143012-bxghtoodiolugpbs
1103 arn...@gm...-20080403190809-bbi4bz5rfcvjnt20
1104 arn...@gm...-20080403205410-czxru1vcg1s4wcws
1105 arn...@gm...-20080403213124-54spdrwszgyimd90
1106 po...@12...-20080404002406-aj74x5tngi6mmmj1
1107 arn...@gm...-20080404122415-mjy07qzbaxyhagra
1108 po...@12...-20080404145445-84lyk5tyy3b3br14
1109 po...@12...-20080404231417-v4v8x7u3f0hm0ejc
1110 po...@12...-20080405001107-14d1ojjof8xhvcj8
1111 arn...@gm...-20080405071929-jmnrul21sxx04kky
1112 arn...@gm...-20080405080105-9qbda7be0pi7y1ai
1113 po...@12...-20080405154555-yuj2n5kyndfjlpsf
1114 po...@12...-20080405220250-8y09d0samsj8ja94
1115 po...@12...-20080406134101-4860ytb61sbu3yhg
1116 po...@12...-20080406155849-2wzxzuzs5m8zpk0g
1117 po...@12...-20080406164835-bv5dydhm3qqydsty
   + 1027 arn...@gm...-20080323183926-schknwnkgeo7ivdn
1028 zouzou123gen-20080323220411-r8usuc3qxwuh7zsn
1029 zouzou123gen-20080323221249-0su72zaj13e706mk
1030 arn...@gm...-20080324140623-muba1dl46m000o8c
1031 zouzou123gen-20080324141933-qbgr93ugpe0297m6
1032 arn...@gm...-20080324153706-siidja05n84i00b1
1033 arn...@gm...-20080324153823-lhn3awurnu77riln
1034 arn...@gm...-20080324165650-zapppziji67yf5a2
1035 zouzou123gen-20080324175936-4mqc2kh0lo5wtdu2
1036 zouzou123gen-20080325004602-6wdsoym95mjuhwd3
1037 arn...@gm...-20080325100659-8fqy6q65itmghlep
1038 zouzou123gen-20080325175216-s297sdiucukfvijh
1039 arn...@gm...-20080325210137-3dfqyoi8ykosy087
1040 arn...@gm...-20080325211747-nwwy1eb33r071sca
1041 arn...@gm...-20080326084110-qbselrjckku275xi
1042 zouzou123gen-20080326123631-35642mgbk2i4ty32
1043 zouzou123gen-20080326124345-f4xwn2d3ty8ubd6r
1044 arn...@gm...-20080326162031-il0nyms30w0mky43
1045 arn...@gm...-20080326164801-8dru8mjc06xgzjpv
1046 arn...@gm...-20080326170438-uzl2rx8fqnohak7g
1047 zouzou123gen-20080326172821-d6uqcbmfb0c6rwlv
1048 arn...@gm...-20080326213257-qlgdh7m2712p2l0q
1049 arn...@gm...-20080326214313-ktnoekgk3s0wmatz
1050 arn...@gm...-20080326215256-0j1iqrf286b9g7zf
1051 arn...@gm...-20080327082121-hoi22wh1gwjdfbyd
1052 arn...@gm...-20080327120639-um3tukdt374rwvgm
1053 zouzou123gen-20080327130703-6vtek6uxy3vua543
1054 arn...@gm...-20080327215831-dmg5mkufskabwkro
1055 arn...@gm...-20080327231459-cdztcv25alsuyqmf
1056 arn...@gm...-20080328085925-gceybsr53oml1p24
1057 arn...@gm...-20080328200512-1sjuu6bcnl2dyd2a
1058 arn...@gm...-20080328210347-bussqjrm5mfswh7o
1059 arn...@gm...-20080329055630-braiir1dskv7a4qm
1060 arn...@gm...-20080329061558-rck8dz60wpj3c5ja
1061 arn...@gm...-20080329081253-if6o5jn329mbzfpl
1062 arn...@gm...-20080329081619-cb4x930j8sp55cs0
1063 arn...@gm...-20080329103216-hgjzo7ra2zixbztd
1064 arn...@gm...-20080329124042-q3aw4iodmo5kafyp
1065 arn...@gm...-20080329124926-2je1z18p0272zpua
1066 arn...@gm...-20080329150901-ehj9t32en7eps2dp
1067 zouzou123gen-20080329153653-36xlvpik2ns9r84r
1068 zouzou123gen-20080329162703-51xr8hg073pg7wq5
1069 zouzou123gen-20080329234706-8ddipdqu0xeudkql
1070 arn...@gm...-20080330081232-ubqr1171ewalrd4q
1071 zouzou123gen-20080330131607-yppbs3mgyjef1cux
1072 zouzou123gen-20080330134835-yv1nogy77ib1uehd
1073 zouzou123gen-20080331124549-alyw7vugdn30piqy
1074 zouzou123gen-20080331135108-q8frtqsin5bosfzm
1075 zouzou123gen-20080331140757-u94q52yccl5lsifk
1076 zouzou123gen-20080331152513-ue1x5qhigcw51348
1077 arn...@gm...-20080331184436-a8g6chibmg8nswls
1078 arn...@gm...-20080331220648-81485k28qmwruwz6
1079 zouzou123gen-20080401081001-2yjn07cf8s5sxr3a
1080 zouzou123gen-20080401081247-f3p4hdjojnd460jw
1081 zouzou123gen-20080401084117-24a454g8o0x656kg
1082 zouzou123gen-20080401133146-jabb5i8870fg6f66
1083 zouzou123gen-20080401154610-mxdqoo5bksru93e6
1084 arn...@gm...-20080401185530-lqj4tflt5ldmx46f
1085 arn...@gm...-20080401212616-ffl7m0xm8gt15knk
1086 arn...@gm...-20080402084515-ofmnwihzv159jton
1087 arn...@gm...-20080402133105-y70soi38owzl76i9
1088 arn...@gm...-20080402142417-rn2dbkx19wfz3vae
1089 arn...@gm...-20080402144459-u3z3hqvl8aqjc4a0
1090 zouzou123gen-20080402145051-zi8tmvy8u3r2mzu8
1091 arn...@gm...-20080402152137-f397uz1yp9qjvfwh
1092 zouzou123gen-20080402170355-29wda40wk3cy7lu5
1093 arn...@gm...-20080402180628-ipos9li0c4bsmq1h
1094 arn...@gm...-20080402181235-s2a6f4ww4lzayl46
1095 arn...@gm...-20080402193851-6mu64vgep6tijith
1096 arn...@gm...-20080402203810-86zpxsx69q83zf3r
1097 arn...@gm...-20080402204331-so2e8n892o23pejr
1098 poy-20080402224153-225qylr2cfwhqrg7
1099 mrmikejj-20080403125112-o8polh8rkn62umyh
1100 arn...@gm...-20080403125139-8xub76j1xazhfxna
1101 po...@12...-20080403140544-13kockkjho883nb4
1102 po...@12...-20080403143012-bxghtoodiolugpbs
1103 arn...@gm...-20080403190809-bbi4bz5rfcvjnt20
1104 arn...@gm...-20080403205410-czxru1vcg1s4wcws
1105 arn...@gm...-20080403213124-54spdrwszgyimd90
1106 po...@12...-20080404002406-aj74x5tngi6mmmj1
1107 arn...@gm...-20080404122415-mjy07qzbaxyhagra
1108 po...@12...-20080404145445-84lyk5tyy3b3br14
1109 po...@12...-20080404231417-v4v8x7u3f0hm0ejc
1110 po...@12...-20080405001107-14d1ojjof8xhvcj8
1111 arn...@gm...-20080405071929-jmnrul21sxx04kky
1112 arn...@gm...-20080405080105-9qbda7be0pi7y1ai
1113 po...@12...-20080405154555-yuj2n5kyndfjlpsf
1114 po...@12...-20080405220250-8y09d0samsj8ja94
1115 po...@12...-20080406134101-4860ytb61sbu3yhg
1116 po...@12...-20080406155849-2wzxzuzs5m8zpk0g
1117 po...@12...-20080406164835-bv5dydhm3qqydsty
1118 arn...@gm...-20080406210237-c7tyfgiz2sjgv044
Modified: dcplusplus/trunk/changelog.txt
===================================================================
--- dcplusplus/trunk/changelog.txt	2008-04-14 20:10:03 UTC (rev 1142)
+++ dcplusplus/trunk/changelog.txt	2008-04-14 20:10:48 UTC (rev 1143)
@@ -26,6 +26,8 @@
 * Added the title of the currently selected page in settings (poy)
 * [L#206785] Fixed a crash when a menu is owner-drawn while the desktop isn't visible (poy)
 * [L#211313] Fixed bad virtual name being loaded (thanks kulmegil)
+* [L#202801] Allow virtual folders to have the same name
+* Allow more characters in virtual names
 * Fixed downloading multiple file lists with the enter key (poy)
 
 -- 0.705 2008-03-14 --
Modified: dcplusplus/trunk/dcpp/ShareManager.cpp
===================================================================
--- dcplusplus/trunk/dcpp/ShareManager.cpp	2008-04-14 20:10:03 UTC (rev 1142)
+++ dcplusplus/trunk/dcpp/ShareManager.cpp	2008-04-14 20:10:48 UTC (rev 1143)
@@ -70,9 +70,7 @@
 	StringList lists = File::findFiles(Util::getConfigPath(), "files?*.xml.bz2");
 	for_each(lists.begin(), lists.end(), File::deleteFile);
 
-	for(Directory::MapIter j = directories.begin(); j != directories.end(); ++j) {
-		delete j->second;
-	}
+	for_each(directories.begin(), directories.end(), DeleteFunction());
 }
 
 ShareManager::Directory::Directory(const string& aName, Directory* aParent) :
@@ -107,15 +105,27 @@
 	}
 }
 
-string ShareManager::Directory::getRealPath() const throw() {
+string ShareManager::Directory::getRealPath(const std::string& path) const throw(ShareException) {
 	if(getParent()) {
-		return getParent()->getRealPath() + getName() + PATH_SEPARATOR_STR;
+		return getParent()->getRealPath(getName() + PATH_SEPARATOR_STR + path);
 	} else {
-		dcassert(ShareManager::getInstance()->getByVirtual(getName()) != ShareManager::getInstance()->directories.end());
-		return ShareManager::getInstance()->getByVirtual(getName())->first;
+		return ShareManager::getInstance()->findRealRoot(getName(), path);
 	}
 }
 
+string ShareManager::findRealRoot(const string& virtualRoot, const string& virtualPath) const throw(ShareException) {
+	for(StringMap::const_iterator i = shares.begin(); i != shares.end(); ++i) {
+		if(Util::stricmp(i->second, virtualRoot)) {
+			std::string name = i->first + PATH_SEPARATOR_STR + virtualPath;
+			if(File::getSize(name) != -1) {
+				return name;
+			}
+		}
+	}
+	
+	throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
+}
+
 int64_t ShareManager::Directory::getSize() const throw() {
 	int64_t tmp = size;
 	for(Map::const_iterator i = directories.begin(); i != directories.end(); ++i)
@@ -123,21 +133,14 @@
 	return tmp;
 }
 
-size_t ShareManager::Directory::countFiles() const throw() {
-	size_t tmp = files.size();
-	for(Map::const_iterator i = directories.begin(); i != directories.end(); ++i)
-		tmp+=i->second->countFiles();
-	return tmp;
-}
-
 string ShareManager::toVirtual(const TTHValue& tth) const throw(ShareException) {
-	Lock l(cs);
 	if(tth == bzXmlRoot) {
 		return Transfer::USER_LIST_NAME_BZ;
 	} else if(tth == xmlRoot) {
 		return Transfer::USER_LIST_NAME;
 	}
 
+	Lock l(cs);
 	HashFileMap::const_iterator i = tthIndex.find(tth);
 	if(i != tthIndex.end()) {
 		return i->second->getADCPath();
@@ -147,17 +150,15 @@
 }
 
 string ShareManager::toReal(const string& virtualFile) throw(ShareException) {
+	Lock l(cs);
 	if(virtualFile == "MyList.DcLst") {
 		throw ShareException("NMDC-style lists no longer supported, please upgrade your client");
 	} else if(virtualFile == Transfer::USER_LIST_NAME_BZ || virtualFile == Transfer::USER_LIST_NAME) {
 		generateXmlList();
 		return getBZXmlFile();
-	} else {
-		string realFile;
-		Lock l(cs);
+	} 
 
-		return findFile(virtualFile)->getRealPath();
-	}
+	return findFile(virtualFile)->getRealPath();
 }
 
 TTHValue ShareManager::getTTH(const string& virtualFile) const throw(ShareException) {
@@ -210,8 +211,8 @@
 	if(aFile.compare(0, 4, "TTH/") != 0)
 		throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
 
+	TTHValue val(aFile.substr(4));
 	Lock l(cs);
-	TTHValue val(aFile.substr(4));
 	HashFileIter i = tthIndex.find(val);
 	if(i == tthIndex.end()) {
 		throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
@@ -242,24 +243,22 @@
 	}
 
 	string virtualName = virtualFile.substr(1, i-1);
-	Directory::Map::const_iterator dmi = getByVirtual(virtualName);
+	DirList::const_iterator dmi = getByVirtual(virtualName);
 	if(dmi == directories.end()) {
 		throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
 	}
-	Directory* d = dmi->second;
+	Directory* d = *dmi;
 
-	string file = virtualFile.substr(i + 1);
-	
-	string::size_type j = 0;
-	while( (i = file.find('/', j)) != string::npos) {
-		Directory::MapIter mi = d->directories.find(file.substr(j, i-j));
+	string::size_type j = i + 1;
+	while( (i = virtualName.find('/', j)) != string::npos) {
+		Directory::MapIter mi = d->directories.find(virtualName.substr(j, i-j));
 		j = i + 1;
 		if(mi == d->directories.end())
 			throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
 		d = mi->second;
 	}
 
-	Directory::File::Set::const_iterator it = find_if(d->files.begin(), d->files.end(), Directory::File::StringComp(file.substr(j)));
+	Directory::File::Set::const_iterator it = find_if(d->files.begin(), d->files.end(), Directory::File::StringComp(virtualName.substr(j)));
 	if(it == d->files.end())
 		throw ShareException(UserConnection::FILE_NOT_AVAILABLE);
 	return it;
@@ -269,13 +268,14 @@
 	string tmp = aVirt;
 	string::size_type idx = 0;
 
-	while( (idx = tmp.find_first_of("$|:\\/"), idx) != string::npos) {
+	while( (idx = tmp.find_first_of("\\/"), idx) != string::npos) {
 		tmp[idx] = '_';
 	}
 	return tmp;
 }
 
 bool ShareManager::hasVirtual(const string& virtualName) const throw() {
+	Lock l(cs);
 	return getByVirtual(virtualName) != directories.end();
 }
 
@@ -292,11 +292,7 @@
 
 			const string& virtualName = aXml.getChildAttrib("Virtual");
 			string vName = validateVirtual(virtualName.empty() ? Util::getLastDir(realPath) : virtualName);
-
-			// add only unique directories
-			if(!hasVirtual(vName)) {
-				directories[realPath] = new Directory(vName, 0);
-			}
+			shares.insert(std::make_pair(realPath, virtualName));
 		}
 		aXml.stepOut();
 	}
@@ -309,15 +305,15 @@
 static const string STTH = "TTH";
 
 struct ShareLoader : public SimpleXMLReader::CallBack {
-	ShareLoader(ShareManager::Directory::Map& aDirs) : dirs(aDirs), cur(0), depth(0) { }
+	ShareLoader(ShareManager::DirList& aDirs) : dirs(aDirs), cur(0), depth(0) { }
 	virtual void startTag(const string& name, StringPairList& attribs, bool simple) {
 		if(name == SDIRECTORY) {
 			const string& name = getAttrib(attribs, SNAME, 0);
 			if(!name.empty()) {
 				if(depth == 0) {
-					for(ShareManager::Directory::MapIter i = dirs.begin(); i != dirs.end(); ++i) {
-						if(Util::stricmp(i->second->getName(), name) == 0) {
-							cur = i->second;
+					for(ShareManager::DirList::iterator i = dirs.begin(); i != dirs.end(); ++i) {
+						if(Util::stricmp((*i)->getName(), name) == 0) {
+							cur = *i;
 							break;
 						}
 					}
@@ -355,7 +351,7 @@
 	}
 
 private:
-	ShareManager::Directory::Map& dirs;
+	ShareManager::DirList& dirs;
 
 	ShareManager::Directory* cur;
 	size_t depth;
@@ -380,8 +376,8 @@
 
 		SimpleXMLReader(&loader).fromXML(txt);
 
-		for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
-			addTree(*i->second);
+		for(DirList::const_iterator i = directories.begin(); i != directories.end(); ++i) {
+			updateIndices(**i);
 		}
 
 		return true;
@@ -396,9 +392,9 @@
 
 	aXml.addTag("Share");
 	aXml.stepIn();
-	for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
+	for(StringMapIter i = shares.begin(); i != shares.end(); ++i) {
 		aXml.addTag("Directory", i->first);
-		aXml.addChildAttrib("Virtual", i->second->getName());
+		aXml.addChildAttrib("Virtual", i->second);
 	}
 	aXml.stepOut();
 }
@@ -412,12 +408,10 @@
 		throw ShareException(_("The temporary download directory cannot be shared"));
 	}
 
-	string vName = validateVirtual(virtualName);
-
 	{
 		Lock l(cs);
 
-		for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
+		for(StringMapIter i = shares.begin(); i != shares.end(); ++i) {
 			if(Util::strnicmp(realPath, i->first, i->first.length()) == 0) {
 				// Trying to share an already shared directory
 				throw ShareException(_("Directory already shared"));
@@ -426,63 +420,110 @@
 				throw ShareException(_("Remove all subdirectories before adding this one"));
 			}
 		}
-
-		if(hasVirtual(vName)) {
-			throw ShareException(_("Virtual directory name already exists"));
-		}
 	}
 
 	Directory* dp = buildTree(realPath, 0);
+
+	string vName = validateVirtual(virtualName);
 	dp->setName(vName);
 
 	{
 		Lock l(cs);
-		addTree(*dp);
 
-		directories[realPath] = dp;
+		shares.insert(std::make_pair(realPath, vName));
+		updateIndices(*merge(dp));
+		
 		setDirty();
 	}
 }
 
+ShareManager::Directory* ShareManager::merge(Directory* directory) {
+	for(DirList::iterator i = directories.begin(); i != directories.end(); ++i) {
+		if(Util::stricmp((*i)->getName(), directory->getName()) == 0) {
+			dcdebug("Merging directory %s\n", directory->getName().c_str());
+			(*i)->merge(directory);
+			return *i;
+		}
+	}
+	
+	dcdebug("Adding new directory %s\n", directory->getName().c_str());
+	
+	directories.push_back(directory);
+	return directory;
+}
+
+void ShareManager::Directory::merge(Directory* source) {
+	for(MapIter i = source->directories.begin(); i != source->directories.end(); ++i) {
+		Directory* subSource = i->second;
+		
+		MapIter ti = directories.find(subSource->getName());
+		if(ti == directories.end()) {
+			if(findFile(subSource->getName()) != files.end()) {
+				dcdebug("File named the same as directory");
+				delete subSource;
+			} else {
+				directories.insert(std::make_pair(subSource->getName(), subSource));
+			}
+		} else {
+			Directory* subTarget = ti->second;
+			subTarget->merge(subSource);
+			delete subSource;
+		}
+	}
+
+	// All subdirs either deleted or moved to target...
+	source->directories.clear();
+	
+	for(File::Set::iterator i = source->files.begin(); i != source->files.end(); ++i) {
+		File::Set::iterator j = findFile(i->getName());
+		
+		if(j == files.end()) {
+			if(directories.find(i->getName()) != directories.end()) {
+				dcdebug("Directory named the same as file");
+			} else {
+				files.insert(*i);
+			}
+		}
+	}
+}
+
 void ShareManager::removeDirectory(const string& realPath) {
 	if(realPath.empty())
 		return;
 
-	{
-		Lock l(cs);
+	HashManager::getInstance()->stopHashing(realPath);
 
-		Directory::MapIter i = directories.find(realPath);
-		if(i != directories.end()) {
-			delete i->second;
-			directories.erase(i);
+	Lock l(cs);
+	
+	StringMapIter i = shares.find(realPath);
+	if(i == shares.end()) {
+		return;
+	}
+	
+	const std::string& vName = i->second;
+	for(DirList::iterator j = directories.begin(); j != directories.end(); ) {
+		if(Util::stricmp((*j)->getName(), vName) == 0) {
+			delete *j;
+			directories.erase(j++);
+		} else {
+			++j;
 		}
-
-		rebuildIndices();
-		setDirty();
 	}
+	
+	shares.erase(i);
 
-	HashManager::getInstance()->stopHashing(realPath);
+	rebuildIndices();
+	setDirty();
 }
 
 void ShareManager::renameDirectory(const string& realPath, const string& virtualName) throw(ShareException) {
-	string vName = validateVirtual(virtualName);
-
-	Lock l(cs);
-	//Find the virtual name
-	if (hasVirtual(vName)) {
-		throw ShareException(_("Virtual directory name already exists"));
-	}
-
-	Directory::MapIter j = directories.find(realPath);
-	if(j == directories.end())
-		return;
-
-	j->second->setName(vName);
+	removeDirectory(realPath);
+	addDirectory(realPath, virtualName);
 }
 
-ShareManager::Directory::Map::const_iterator ShareManager::getByVirtual(const string& virtualName) const throw() {
-	for(Directory::Map::const_iterator i = directories.begin(); i != directories.end(); ++i) {
-		if(Util::stricmp(i->second->getName(), virtualName) == 0) {
+ShareManager::DirList::const_iterator ShareManager::getByVirtual(const string& virtualName) const throw() {
+	for(DirList::const_iterator i = directories.begin(); i != directories.end(); ++i) {
+		if(Util::stricmp((*i)->getName(), virtualName) == 0) {
 			return i;
 		}
 	}
@@ -491,20 +532,21 @@
 
 int64_t ShareManager::getShareSize(const string& realPath) const throw() {
 	Lock l(cs);
-	dcassert(realPath.size()>0);
+#ifdef PORT_ME
+ 	dcassert(realPath.size()>0);
 	Directory::Map::const_iterator i = directories.find(realPath);
 
 	if(i != directories.end()) {
 		return i->second->getSize();
 	}
-
+#endif
 	return -1;
 }
 
 int64_t ShareManager::getShareSize() const throw() {
 	Lock l(cs);
 	int64_t tmp = 0;
-	for(Directory::Map::const_iterator i = directories.begin(); i != directories.end(); ++i) {
+	for(HashFileMap::const_iterator i = tthIndex.begin(); i != tthIndex.end(); ++i) {
 		tmp += i->second->getSize();
 	}
 	return tmp;
@@ -711,17 +753,17 @@
 	return dir;
 }
 
-void ShareManager::addTree(Directory& dir) {
+void ShareManager::updateIndices(Directory& dir) {
 	bloom.add(Text::toLower(dir.getName()));
 
 	for(Directory::MapIter i = dir.directories.begin(); i != dir.directories.end(); ++i) {
-		addTree(*i->second);
+		updateIndices(*i->second);
 	}
 
 	dir.size = 0;
 
 	for(Directory::File::Set::iterator i = dir.files.begin(); i != dir.files.end(); ) {
-		addFile(dir, i++);
+		updateIndices(dir, i++);
 	}
 }
 
@@ -729,12 +771,12 @@
 	tthIndex.clear();
 	bloom.clear();
 
-	for(Directory::Map::const_iterator i = directories.begin(); i != directories.end(); ++i) {
-		addTree(*i->second);
+	for(DirList::const_iterator i = directories.begin(); i != directories.end(); ++i) {
+		updateIndices(**i);
 	}
 }
 
-void ShareManager::addFile(Directory& dir, const Directory::File::Set::iterator& i) {
+void ShareManager::updateIndices(Directory& dir, const Directory::File::Set::iterator& i) {
 	const Directory::File& f = *i;
 
 	HashFileIter j = tthIndex.find(f.getTTH());
@@ -784,8 +826,8 @@
 StringPairList ShareManager::getDirectories() const throw() {
 	Lock l(cs);
 	StringPairList ret;
-	for(Directory::Map::const_iterator i = directories.begin(); i != directories.end(); ++i) {
-		ret.push_back(make_pair(i->second->getName(), i->first));
+	for(StringMap::const_iterator i = shares.begin(); i != shares.end(); ++i) {
+		ret.push_back(make_pair(i->second, i->first));
 	}
 	return ret;
 }
@@ -794,35 +836,35 @@
 	
 	StringPairList dirs = getDirectories();
 	// Don't need to refresh if no directories are shared
-	if(dirs.begin() == dirs.end())		
+	if(dirs.empty())		
 		refreshDirs = false;
 
-	{
-		if(refreshDirs) {
-			LogManager::getInstance()->message(_("File list refresh initiated"));
+	if(refreshDirs) {
+		LogManager::getInstance()->message(_("File list refresh initiated"));
+		
+		lastFullUpdate = GET_TICK();
+
+		DirList newDirs;
+		for(StringPairIter i = dirs.begin(); i != dirs.end(); ++i) {
+			Directory* dp = buildTree(i->second, 0);
+			dp->setName(i->first);
+			newDirs.push_back(dp);
+		}
+
+		{
+			Lock l(cs);
+			for_each(directories.begin(), directories.end(), DeleteFunction());
+			directories.clear();
 			
-			lastFullUpdate = GET_TICK();
-
-			Directory::Map newDirs;
-			for(StringPairIter i = dirs.begin(); i != dirs.end(); ++i) {
-				Directory* dp = buildTree(i->second, 0);
-				dp->setName(i->first);
-				newDirs.insert(make_pair(i->second, dp));
+			for(DirList::iterator i = newDirs.begin(); i != newDirs.end(); ++i) {
+				merge(*i);
 			}
 
-			{
-				Lock l(cs);
-				for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
-					delete i->second;
-				}
-				directories = newDirs;
-
-				rebuildIndices();
-			}
-			refreshDirs = false;
-			
-			LogManager::getInstance()->message(_("File list refresh finished"));
+			rebuildIndices();
 		}
+		refreshDirs = false;
+		
+		LogManager::getInstance()->message(_("File list refresh finished"));
 	}
 	
 	if(update) {
@@ -864,8 +906,8 @@
 
 				newXmlFile.write(SimpleXML::utf8Header);
 				newXmlFile.write("<FileListing Version=\"1\" CID=\"" + ClientManager::getInstance()->getMe()->getCID().toBase32() + "\" Base=\"/\" Generator=\"" APPNAME " " VERSIONSTRING "\">\r\n");
-				for(Directory::MapIter i = directories.begin(); i != directories.end(); ++i) {
-					i->second->toXml(newXmlFile, indent, tmp2, true);
+				for(DirList::const_iterator i = directories.begin(); i != directories.end(); ++i) {
+					(*i)->toXml(newXmlFile, indent, tmp2, true);
 				}
 				newXmlFile.write("</FileListing>");
 				newXmlFile.flush();
@@ -914,13 +956,15 @@
 
 	Lock l(cs);
 	if(dir == "/") {
-		for(Directory::Map::const_iterator i = directories.begin(); i != directories.end(); ++i) {
+		for(DirList::const_iterator i = directories.begin(); i != directories.end(); ++i) {
 			tmp.clear();
-			i->second->toXml(sos, indent, tmp, recurse);
+			(*i)->toXml(sos, indent, tmp, recurse);
 		}
 	} else {
 		string::size_type i = 1, j = 1;
-		Directory::Map::const_iterator it = directories.end();
+		
+		Directory* root = NULL;
+		
 		bool first = true;
 		while( (i = dir.find('/', j)) != string::npos) {
 			if(i == j) {
@@ -930,23 +974,25 @@
 
 			if(first) {
 				first = false;
-				it = getByVirtual(dir.substr(j, i-j));
+				DirList::const_iterator it = getByVirtual(dir.substr(j, i-j));
 
 				if(it == directories.end())
 					return 0;
+				root = *it;
+				
 			} else {
-				Directory::Map::const_iterator it2 = it->second->directories.find(dir.substr(j, i-j));
-				if(it2 == it->second->directories.end()) {
+				Directory::Map::const_iterator it2 = root->directories.find(dir.substr(j, i-j));
+				if(it2 == root->directories.end()) {
 					return 0;
 				}
-				it = it2;
+				root = it2->second;
 			}
 			j = i + 1;
 		}
-		for(Directory::Map::const_iterator it2 = it->second->directories.begin(); it2 != it->second->directories.end(); ++it2) {
+		for(Directory::Map::const_iterator it2 = root->directories.begin(); it2 != root->directories.end(); ++it2) {
 			it2->second->toXml(sos, indent, tmp, recurse);
 		}
-		it->second->filesToXml(sos, indent, tmp);
+		root->filesToXml(sos, indent, tmp);
 	}
 
 	xml += "</FileListing>";
@@ -1207,8 +1253,8 @@
 	if(ssl.empty())
 		return;
 
-	for(Directory::Map::const_iterator j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
-		j->second->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults);
+	for(DirList::const_iterator j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
+		(*j)->search(results, ssl, aSearchType, aSize, aFileType, aClient, maxResults);
 	}
 }
 
@@ -1336,24 +1382,33 @@
 			return;
 	}
 
-	for(Directory::Map::const_iterator j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
-		j->second->search(results, srch, maxResults);
+	for(DirList::const_iterator j = directories.begin(); (j != directories.end()) && (results.size() < maxResults); ++j) {
+		(*j)->search(results, srch, maxResults);
 	}
 }
 
 ShareManager::Directory* ShareManager::getDirectory(const string& fname) {
-	for(Directory::MapIter mi = directories.begin(); mi != directories.end(); ++mi) {
+	for(StringMapIter mi = shares.begin(); mi != shares.end(); ++mi) {
 		if(Util::strnicmp(fname, mi->first, mi->first.length()) == 0) {
-			Directory* d = mi->second;
-
+			Directory* d = NULL;
+			for(DirList::iterator i = directories.begin(); i != directories.end(); ++i) {
+				if(Util::stricmp((*i)->getName(), mi->second) == 0) {
+					d = *i;
+				}
+			}
+			
+			if(!d) {
+				return NULL;
+			}
+			
 			string::size_type i;
 			string::size_type j = mi->first.length();
 			while( (i = fname.find(PATH_SEPARATOR, j)) != string::npos) {
-				mi = d->directories.find(fname.substr(j, i-j));
+				Directory::MapIter dmi = d->directories.find(fname.substr(j, i-j));
 				j = i + 1;
-				if(mi == d->directories.end())
+				if(dmi == d->directories.end())
 					return NULL;
-				d = mi->second;
+				d = dmi->second;
 			}
 			return d;
 		}
@@ -1366,7 +1421,7 @@
 		// Check if finished download is supposed to be shared
 		Lock l(cs);
 		const string& n = d->getPath();
-		for(Directory::MapIter i = directories.begin(); i != directories.end(); i++) {
+		for(StringMapIter i = shares.begin(); i != shares.end(); i++) {
 			if(Util::strnicmp(i->first, n, i->first.size()) == 0 && n[i->first.size()] == PATH_SEPARATOR) {
 				string s = n.substr(i->first.size()+1);
 				try {
@@ -1397,7 +1452,7 @@
 			string name = Util::getFileName(fname);
 			int64_t size = File::getSize(fname);
 			Directory::File::Set::iterator it = d->files.insert(Directory::File(name, size, d, root)).first;
-			addFile(*d, it);
+			updateIndices(*d, it);
 		}
 		setDirty();
 	}
Modified: dcplusplus/trunk/dcpp/ShareManager.h
===================================================================
--- dcplusplus/trunk/dcpp/ShareManager.h	2008-04-14 20:10:03 UTC (rev 1142)
+++ dcplusplus/trunk/dcpp/ShareManager.h	2008-04-14 20:10:48 UTC (rev 1143)
@@ -86,6 +86,7 @@
 	SearchManager::TypeModes getType(const string& fileName) const throw();
 
 	string validateVirtual(const string& /*aVirt*/) const throw();
+	bool hasVirtual(const string& name) const throw();
 
 	void addHits(uint32_t aHits) {
 		hits += aHits;
@@ -139,7 +140,7 @@
 
 			string getADCPath() const { return parent->getADCPath() + name; }
 			string getFullName() const { return parent->getFullName() + name; }
-			string getRealPath() const { return parent->getRealPath() + name; }
+			string getRealPath() const { return parent->getRealPath(name); }
 
 			GETSET(string, name, Name);
 			GETSET(TTHValue, tth, TTH);
@@ -166,10 +167,9 @@
 
 		string getADCPath() const throw();
 		string getFullName() const throw();
-		string getRealPath() const throw();
+		string getRealPath(const std::string& path) const throw(ShareException);
 
 		int64_t getSize() const throw();
-		size_t countFiles() const throw();
 
 		void search(SearchResult::List& aResults, StringSearch::List& aStrings, int aSearchType, int64_t aSize, int aFileType, Client* aClient, StringList::size_type maxResults) const throw();
 		void search(SearchResult::List& aResults, AdcSearch& aStrings, StringList::size_type maxResults) const throw();
@@ -179,6 +179,8 @@
 
 		File::Set::const_iterator findFile(const string& aFile) const { return find_if(files.begin(), files.end(), Directory::File::StringComp(aFile)); }
 
+		void merge(Directory* source);
+		
 		GETSET(string, name, Name);
 		GETSET(Directory*, parent, Parent);
 	private:
@@ -253,9 +255,13 @@
 
 	mutable CriticalSection cs;
 
-	// Map real name to directory structure
-	Directory::Map directories;
+	// List of root directory items
+	typedef std::list<Directory*> DirList;
+	DirList directories;
 
+	/** Map real name to virtual name - multiple real names may be mapped to a single virtual one */
+	StringMap shares;
+	
 	typedef unordered_map<TTHValue, Directory::File::Set::const_iterator> HashFileMap;
 	typedef HashFileMap::iterator HashFileIter;
 
@@ -269,12 +275,16 @@
 
 	void rebuildIndices();
 
-	void addTree(Directory& aDirectory);
-	void addFile(Directory& dir, const Directory::File::Set::iterator& i);
+	void updateIndices(Directory& aDirectory);
+	void updateIndices(Directory& dir, const Directory::File::Set::iterator& i);
+	
+	Directory* merge(Directory* directory);
+	
 	void generateXmlList();
 	bool loadCache() throw();
-	bool hasVirtual(const string& name) const throw();
-	Directory::Map::const_iterator getByVirtual(const string& virtualName) const throw();
+	DirList::const_iterator getByVirtual(const string& virtualName) const throw();
+	
+	string findRealRoot(const string& virtualRoot, const string& virtualLeaf) const throw(ShareException);
 
 	Directory* getDirectory(const string& fname);
 
Modified: dcplusplus/trunk/win32/UploadPage.cpp
===================================================================
--- dcplusplus/trunk/win32/UploadPage.cpp	2008-04-14 20:10:03 UTC (rev 1142)
+++ dcplusplus/trunk/win32/UploadPage.cpp	2008-04-14 20:10:48 UTC (rev 1143)
@@ -256,17 +256,27 @@
 	if( path[ path.length() -1 ] != _T('\\') )
 		path += _T('\\');
 
+	ShareManager* sm = ShareManager::getInstance();
 	try {
-		LineDlg dlg(this, T_("Virtual name"), T_("Name under which the others see the directory"), Text::toT(ShareManager::getInstance()->validateVirtual(Util::getLastDir(Text::fromT(path)))));
-		if(dlg.run() == IDOK) {
-			tstring line = dlg.getLine();
-			ShareManager::getInstance()->addDirectory(Text::fromT(path), Text::fromT(line));
-			TStringList row;
-			row.push_back(line);
-			row.push_back(path);
-			row.push_back(Text::toT(Util::formatBytes(ShareManager::getInstance()->getShareSize(Text::fromT(path)))));
-			directories->insert(row);
-			total->setText(Text::toT(Util::formatBytes(ShareManager::getInstance()->getShareSize())));
+		while(true) {
+			LineDlg dlg(this, T_("Virtual name"), T_("Name under which the others see the directory"), Text::toT(sm->validateVirtual(Util::getLastDir(Text::fromT(path)))));
+			if(dlg.run() == IDOK) {
+				tstring line = dlg.getLine();
+				if(sm->hasVirtual(sm->validateVirtual(Text::fromT(line)))) {
+					if(createMessageBox().show(str(TF_("A virtual directory named %1% already exists, do you wish to merge the contents?") % line),
+						_T(APPNAME) _T(" ") _T(VERSIONSTRING), MessageBox::BOX_YESNO, MessageBox::BOX_ICONQUESTION) == IDNO) {
+						continue;
+					}
+				}
+				ShareManager::getInstance()->addDirectory(Text::fromT(path), Text::fromT(line));
+				TStringList row;
+				row.push_back(line);
+				row.push_back(path);
+				row.push_back(Text::toT(Util::formatBytes(ShareManager::getInstance()->getShareSize(Text::fromT(path)))));
+				directories->insert(row);
+				total->setText(Text::toT(Util::formatBytes(ShareManager::getInstance()->getShareSize())));
+			}
+			break;
 		}
 	} catch(const ShareException& e) {
 		createMessageBox().show(Text::toT(e.getError()), _T(APPNAME) _T(" ") _T(VERSIONSTRING), MessageBox::BOX_OK, MessageBox::BOX_ICONSTOP);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |