[sword-svn] r2077 - in trunk: . include src/mgr utilities

scribe at www.crosswire.org scribe at www.crosswire.org
Thu Sep 13 18:34:38 MST 2007


Author: scribe
Date: 2007-09-13 18:34:37 -0700 (Thu, 13 Sep 2007)
New Revision: 2077

Modified:
   trunk/ChangeLog
   trunk/include/installmgr.h
   trunk/include/swmgr.h
   trunk/src/mgr/ftptrans.cpp
   trunk/src/mgr/installmgr.cpp
   trunk/utilities/installmgr.cpp
Log:
Normalized all paths in installmgr to be safe
Added new getModuleStatus to installmgr to help
  frontends know which modules are new/updated
Added a const SWModule *getModule method to SWMgr


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-09-09 01:20:11 UTC (rev 2076)
+++ trunk/ChangeLog	2007-09-14 01:34:37 UTC (rev 2077)
@@ -1,6 +1,10 @@
-API ChangeLog	(see the ChangeLog in each 'apps' directory for
-		app specific changes)
+API ChangeLog 
 
+13-Sep-2007	Troy A. Griffitts <scribe at crosswire.org>
+	Added InstallMgr::getModuleStatus to return a list
+		of differences between the modules of two SWMgr
+		objects
+
 03-Mar-2007 	Joachim Ansorg <jansorg at crosswire.org>
 	Added osis morph segments filter include file to the dist
 	Fixed wrong stricmp in SWObject
@@ -25,7 +29,7 @@
 	Added recognition of additional greek accent ~
 		in UTF8GreekAccents filter
 	Fixed bug in RawGenBook::setText where default size
-		is < 0, not false.
+		is < 0, not false
 	Changed lucene indexing to actually index the key field.  This
 		allows searching within key field (e.g. key:word)
 	Fixed divineName logic

Modified: trunk/include/installmgr.h
===================================================================
--- trunk/include/installmgr.h	2007-09-09 01:20:11 UTC (rev 2076)
+++ trunk/include/installmgr.h	2007-09-14 01:34:37 UTC (rev 2077)
@@ -9,6 +9,7 @@
 SWORD_NAMESPACE_START
 
 class SWMgr;
+class SWModule;
 class SWConfig;
 class FTPTransport;
 class StatusReporter;
@@ -53,6 +54,14 @@
 	FTPTransport *transport;	
 	
 public:
+
+	const static int MODSTAT_OLDER;
+	const static int MODSTAT_SAMEVERSION;
+	const static int MODSTAT_UPDATED;
+	const static int MODSTAT_NEW;
+	const static int MODSTAT_CIPHERED;
+	const static int MODSTAT_CIPHERKEYPRESENT;
+
 	SWConfig *installConf;
 	InstallSourceMap sources;
 	bool term;
@@ -70,6 +79,12 @@
 	void terminate();
 
 	/************************************************************************
+	 * getModuleStatus - compare the modules of two SWMgrs and return a 
+	 * 	vector describing the status of each.  See MODSTAT_*
+	 */
+	static std::map<SWModule *, int> getModuleStatus(const SWMgr &base, const SWMgr &other);
+
+	/************************************************************************
 	 * isDefaultModule - allows an installation to provide a set of modules
 	 *   in installMgr.conf like:
 	 *     [General]

Modified: trunk/include/swmgr.h
===================================================================
--- trunk/include/swmgr.h	2007-09-09 01:20:11 UTC (rev 2076)
+++ trunk/include/swmgr.h	2007-09-14 01:34:37 UTC (rev 2077)
@@ -209,6 +209,7 @@
 	 * @return the module, if found, otherwise 0
 	 */
 	SWModule *getModule(const char *modName) { ModMap::iterator it = Modules.find(modName); return ((it != Modules.end()) ? it->second : 0); }
+	const SWModule *getModule(const char *modName) const { ModMap::const_iterator it = Modules.find(modName); return ((it != Modules.end()) ? it->second : 0); }
 
 
 	/** Constructs an instance of SWMgr

Modified: trunk/src/mgr/ftptrans.cpp
===================================================================
--- trunk/src/mgr/ftptrans.cpp	2007-09-09 01:20:11 UTC (rev 2076)
+++ trunk/src/mgr/ftptrans.cpp	2007-09-14 01:34:37 UTC (rev 2077)
@@ -18,6 +18,18 @@
 SWORD_NAMESPACE_START
 
 
+namespace {
+
+void removeTrailingSlash(SWBuf &buf) {
+	int len = buf.size();
+	if ((buf[len-1] == '/')
+	 || (buf[len-1] == '\\'))
+		buf.size(len-1);
+}
+
+};
+
+
 void StatusReporter::preStatus(long totalBytes, long completedBytes, const char *message) {
 }
 
@@ -90,9 +102,8 @@
 	int retVal = 0;
 	
 	SWBuf url = SWBuf(urlPrefix) + SWBuf(dir);
-	if (url[url.length()-1] != '/') {
-		url.append('/'); //don't forget the final slash if it's not yet at the end
-	}
+	removeTrailingSlash(url);
+	url += '/';
 	
 	SWLog::getSystemLog()->logWarning("FTPCopy: getting dir %s\n", url.c_str());
 	vector<struct ftpparse> dirList = getDirList(url.c_str());
@@ -108,7 +119,9 @@
 	long completedBytes = 0;
 	for (i = 0; i < dirList.size(); i++) {
 		struct ftpparse &dirEntry = dirList[i];
-		SWBuf buffer = (SWBuf)dest + "/" + (dirEntry.name);
+		SWBuf buffer = (SWBuf)dest;
+		removeTrailingSlash(buffer);
+		buffer += (SWBuf)"/" + (dirEntry.name);
 		if (!strcmp(&buffer.c_str()[buffer.length()-strlen(suffix)], suffix)) {
 			SWBuf buffer2 = "Downloading (";
 			buffer2.appendFormatted("%d", i+1);
@@ -120,7 +133,9 @@
 				statusReporter->preStatus(totalBytes, completedBytes, buffer2.c_str());
 			FileMgr::createParent(buffer.c_str());	// make sure parent directory exists
 			SWTRY {
-				SWBuf url = (SWBuf)urlPrefix + (SWBuf)dir + "/" + dirEntry.name; //dont forget the final slash
+				SWBuf url = (SWBuf)urlPrefix + (SWBuf)dir;
+				removeTrailingSlash(url);
+				url += (SWBuf)"/" + dirEntry.name; //dont forget the final slash
 				if (dirEntry.flagtrycwd != 1) {
 					if (getURL(buffer.c_str(), url.c_str())) {
 						SWLog::getSystemLog()->logWarning("FTPCopy: failed to get file %s\n", url.c_str());
@@ -129,7 +144,9 @@
 					completedBytes += dirEntry.size;
 				}
 				else {
-					SWBuf subdir = (SWBuf)dir + "/" + dirEntry.name;
+					SWBuf subdir = (SWBuf)dir;
+					removeTrailingSlash(subdir);
+					subdir += (SWBuf)"/" + dirEntry.name;
 					if (copyDirectory(urlPrefix, subdir, buffer.c_str(), suffix)) {
 						SWLog::getSystemLog()->logWarning("FTPCopy: failed to get file %s\n", subdir.c_str());
 						return -2;

Modified: trunk/src/mgr/installmgr.cpp
===================================================================
--- trunk/src/mgr/installmgr.cpp	2007-09-09 01:20:11 UTC (rev 2076)
+++ trunk/src/mgr/installmgr.cpp	2007-09-14 01:34:37 UTC (rev 2077)
@@ -18,9 +18,12 @@
 #include <fcntl.h>
 
 #include <swmgr.h>
+#include <swmodule.h>
+#include <swversion.h>
 #include <dirent.h>
 
 #include <stdio.h>
+#include <map>
 
 #ifdef CURLAVAILABLE
 #include <curlftpt.h>
@@ -28,10 +31,29 @@
 #include <ftplibftpt.h>
 #endif
 
-
 SWORD_NAMESPACE_START
 
+namespace {
 
+void removeTrailingSlash(SWBuf &buf) {
+	int len = buf.size();
+	if ((buf[len-1] == '/')
+	 || (buf[len-1] == '\\'))
+		buf.size(len-1);
+}
+
+};
+
+
+using std::map;
+
+const int InstallMgr::MODSTAT_OLDER            = 0x001;
+const int InstallMgr::MODSTAT_SAMEVERSION      = 0x002;
+const int InstallMgr::MODSTAT_UPDATED          = 0x004;
+const int InstallMgr::MODSTAT_NEW              = 0x008;
+const int InstallMgr::MODSTAT_CIPHERED         = 0x010;
+const int InstallMgr::MODSTAT_CIPHERKEYPRESENT = 0x020;
+
 // override this method and provide your own custom FTPTransport subclass
 // here we try a couple defaults if sword was compiled with support for them.
 // see these classes for examples of how to make your own
@@ -51,6 +73,12 @@
 	this->privatePath = 0;
 	this->transport = 0;
 	stdstr(&(this->privatePath), privatePath);
+	if (this->privatePath) {
+		int len = strlen(this->privatePath);
+		if ((this->privatePath[len-1] == '/')
+		 || (this->privatePath[len-1] == '\\'))
+			this->privatePath[len-1] = 0;
+	}
 	SWBuf confPath = (SWBuf)privatePath + "/InstallMgr.conf";
 	FileMgr::createParent(confPath.c_str());
 	
@@ -127,6 +155,7 @@
 		SWBuf modDir;
 		entry = module->second.find("AbsoluteDataPath");
 		modDir = entry->second.c_str();
+		removeTrailingSlash(modDir);
 		if (fileBegin != fileEnd) {	// remove each file
 			while (fileBegin != fileEnd) {
 				modFile = modDir;
@@ -150,6 +179,7 @@
 				while ((ent = readdir(dir))) {
 					if ((strcmp(ent->d_name, ".")) && (strcmp(ent->d_name, ".."))) {
 						modFile = manager->configPath;
+						removeTrailingSlash(modFile);
 						modFile += "/";
 						modFile += ent->d_name;
 						SWConfig *config = new SWConfig(modFile.c_str());
@@ -169,45 +199,6 @@
 }
 
 
-
-InstallSource::InstallSource(const char *type, const char *confEnt) {
-	this->type = type;
-	mgr = 0;
-	userData = 0;
-	if (confEnt) {
-		char *buf = 0;
-		stdstr(&buf, confEnt);
-
-		caption = strtok(buf, "|");
-		source = strtok(0, "|");
-		directory = strtok(0, "|");
-		delete [] buf;
-	}
-}
-
-
-InstallSource::~InstallSource() {
-	if (mgr)
-		delete mgr;
-}
-
-
-void InstallSource::flush() {
-	if (mgr) {
-		delete mgr;
-		mgr = 0;
-	}
-}
-
-
-SWMgr *InstallSource::getMgr() {
-	if (!mgr)
-		// ..., false = don't augment ~home directory.
-		mgr = new SWMgr(localShadow.c_str(), true, 0, false, false);
-	return mgr;
-}
-
-
 int InstallMgr::ftpCopy(InstallSource *is, const char *src, const char *dest, bool dirTransfer, const char *suffix) {
 	int retVal = 0;
 	FTPTransport *trans = createFTPTransport(is->source, statusReporter);
@@ -225,7 +216,9 @@
 
 	   
 	if (dirTransfer) {
-		SWBuf dir = (SWBuf)is->directory.c_str() + "/" + src; //dont forget the final slash
+		SWBuf dir = (SWBuf)is->directory.c_str();
+		removeTrailingSlash(dir);
+		dir += (SWBuf)"/" + src; //dont forget the final slash
 
 		retVal = trans->copyDirectory(urlPrefix, dir, dest, suffix);
 
@@ -233,7 +226,9 @@
 	}
 	else {
 		SWTRY {
-			SWBuf url = urlPrefix + is->directory.c_str() + "/" + src; //dont forget the final slash
+			SWBuf url = urlPrefix + is->directory.c_str();
+			removeTrailingSlash(url);
+			url += (SWBuf)"/" + src; //dont forget the final slash
 			if (trans->getURL(dest, url.c_str())) {
 				fprintf(stderr, "FTPCopy: failed to get file %s", url.c_str());
 				retVal = -1;
@@ -273,8 +268,8 @@
 		sourceDir = (SWBuf)privatePath + "/" + is->source;
 	else	sourceDir = fromLocation;
 
-	if (sourceDir[sourceDir.length()-1] != '/')
-		sourceDir += '/';
+	removeTrailingSlash(sourceDir);
+	sourceDir += '/';
 
 	SWMgr mgr(sourceDir.c_str());
 	
@@ -296,7 +291,7 @@
 		if (fileBegin != fileEnd) {	// copy each file
 			if (is) {
 				while (fileBegin != fileEnd) {	// ftp each file first
-					buffer = sourceDir + "/" + fileBegin->second.c_str();
+					buffer = sourceDir + fileBegin->second.c_str();
 					if (ftpCopy(is, fileBegin->second.c_str(), buffer.c_str())) {
 						aborted = true;
 						break;	// user aborted
@@ -312,8 +307,8 @@
 					SWBuf sourcePath = sourceDir;
 					sourcePath += fileBegin->second.c_str();
 					SWBuf dest = destMgr->prefixPath;
-					if ((destMgr->prefixPath[strlen(destMgr->prefixPath)-1] != '\\') && (destMgr->prefixPath[strlen(destMgr->prefixPath)-1] != '/'))
-						dest += "/";
+					removeTrailingSlash(dest);
+					dest += '/';
 					dest += fileBegin->second.c_str();
 					FileMgr::copyFile(sourcePath.c_str(), dest.c_str());
 
@@ -325,7 +320,7 @@
 			if (is) {
 				fileBegin = module->second.lower_bound("File");
 				while (fileBegin != fileEnd) {	// delete each tmp ftp file
-					buffer = sourceDir + "/" + fileBegin->second.c_str();
+					buffer = sourceDir + fileBegin->second.c_str();
 					FileMgr::removeFile(buffer.c_str());
 					fileBegin++;
 				}
@@ -362,7 +357,7 @@
 			}
 		}
 		if (!aborted) {
-			SWBuf confDir = sourceDir + "/mods.d/";
+			SWBuf confDir = sourceDir + "mods.d/";
 			if ((dir = opendir(confDir.c_str()))) {	// find and copy .conf file
 				rewinddir(dir);
 				while ((ent = readdir(dir))) {
@@ -372,6 +367,7 @@
 						SWConfig *config = new SWConfig(modFile.c_str());
 						if (config->Sections.find(modName) != config->Sections.end()) {
 							SWBuf targetFile = destMgr->configPath; //"./mods.d/";
+							removeTrailingSlash(targetFile);
 							targetFile += "/";
 							targetFile += ent->d_name;
 							FileMgr::copyFile(modFile.c_str(), targetFile.c_str());
@@ -441,6 +437,7 @@
 
 int InstallMgr::refreshRemoteSource(InstallSource *is) {
 	SWBuf root = (SWBuf)privatePath + (SWBuf)"/" + is->source.c_str();
+	removeTrailingSlash(root);
 	SWBuf target = root + "/mods.d";
 	int errorCode = -1; //0 means successful
 	
@@ -471,6 +468,97 @@
 	return defaultMods.count(modName);
 }
 
+/************************************************************************
+ * getModuleStatus - compare the modules of two SWMgrs and return a 
+ * 	vector describing the status of each.  See MODSTAT_*
+ */
+map<SWModule *, int> InstallMgr::getModuleStatus(const SWMgr &base, const SWMgr &other) {
+	map<SWModule *, int> retVal;
+	SWBuf targetVersion;
+	SWBuf sourceVersion;
+	SWBuf softwareVersion;
+	bool cipher;
+	bool keyPresent;
+	int modStat;
+	
+	for (ModMap::const_iterator mod = other.Modules.begin(); mod != other.Modules.end(); mod++) {
+	
+		modStat = 0;
 
+		cipher = false;
+		keyPresent = false;
+		
+		const char *v = mod->second->getConfigEntry("CipherKey");
+		if (v) {
+			cipher = true;
+			keyPresent = *v;
+		}
+		
+		targetVersion = "0.0";
+		sourceVersion = "1.0";
+		softwareVersion = (const char *)SWVersion::currentVersion;
+		
+		v = mod->second->getConfigEntry("Version");
+		if (v) sourceVersion = v;
+
+		v = mod->second->getConfigEntry("MinimumVersion");
+		if (v) softwareVersion = v;
+
+		const SWModule *baseMod = base.getModule(mod->first);
+		if (baseMod) {
+			targetVersion = "1.0";
+			v = baseMod->getConfigEntry("Version");
+			if (v) targetVersion = v;
+			modStat |= (SWVersion(sourceVersion.c_str()) > SWVersion(targetVersion.c_str())) ? MODSTAT_UPDATED : (SWVersion(sourceVersion.c_str()) < SWVersion(targetVersion.c_str())) ? MODSTAT_OLDER : MODSTAT_SAMEVERSION;
+		}
+		else modStat |= MODSTAT_NEW;
+
+		if (cipher) modStat |= MODSTAT_CIPHERED;
+		if (keyPresent) modStat |= MODSTAT_CIPHERKEYPRESENT;
+		retVal[mod->second] = modStat;
+	}
+	return retVal;
+}
+
+
+InstallSource::InstallSource(const char *type, const char *confEnt) {
+	this->type = type;
+	mgr = 0;
+	userData = 0;
+	if (confEnt) {
+		char *buf = 0;
+		stdstr(&buf, confEnt);
+
+		caption = strtok(buf, "|");
+		source = strtok(0, "|");
+		directory = strtok(0, "|");
+		removeTrailingSlash(directory);
+		delete [] buf;
+	}
+}
+
+
+InstallSource::~InstallSource() {
+	if (mgr)
+		delete mgr;
+}
+
+
+void InstallSource::flush() {
+	if (mgr) {
+		delete mgr;
+		mgr = 0;
+	}
+}
+
+
+SWMgr *InstallSource::getMgr() {
+	if (!mgr)
+		// ..., false = don't augment ~home directory.
+		mgr = new SWMgr(localShadow.c_str(), true, 0, false, false);
+	return mgr;
+}
+
+
 SWORD_NAMESPACE_END
 

Modified: trunk/utilities/installmgr.cpp
===================================================================
--- trunk/utilities/installmgr.cpp	2007-09-09 01:20:11 UTC (rev 2076)
+++ trunk/utilities/installmgr.cpp	2007-09-14 01:34:37 UTC (rev 2077)
@@ -2,14 +2,14 @@
 #include <installmgr.h>
 #include <filemgr.h>
 #include <iostream>
-#include <string>
+#include <map>
 #include <swmodule.h>
 #include <stdio.h>
 
 using namespace sword;
 using std::cout;
 using std::cin;
-using std::string;
+using std::map;
 
 
 SWMgr *mgr;
@@ -33,6 +33,7 @@
 		"\t-s\t\t\t\tlist remote sources\n"
 		"\t-r  <remoteSrcName>\t\trefresh remote source\n"
 		"\t-rl <remoteSrcName>\t\tlist available modules from remote source\n"
+		"\t-rd <remoteSrcName>\t\tlist new/updated modules from remote source\n"
 		"\t-ri <remoteSrcName> <modName>\tinstall module from remote source\n"
 		"\t-ll <path>\t\t\tlist available modules at local path\n"
 		"\t-li <path> <modName>\t\tinstall module from local path\n"
@@ -123,6 +124,28 @@
 }
 
 
+void remoteNewModules(const SWMgr *base, const char *sourceName) {
+	cout << "Updated and New Modules:\n(be sure to refresh remote source (-r) first for most current list)\n\n";
+	InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
+	if (source == installMgr->sources.end()) {
+		fprintf(stderr, "Couldn't find remote source [%s]\n", sourceName);
+		finish(-3);
+	}
+	map<SWModule *, int> modStats = installMgr->getModuleStatus(*base, *source->second->getMgr());
+	SWModule *module;
+	int status;
+	bool updated;
+	for (map<SWModule *, int>::iterator it = modStats.begin(); it != modStats.end(); it++) {
+		module = it->first;
+		status = it->second;
+		updated = (status & InstallMgr::MODSTAT_UPDATED);
+		if ((status & InstallMgr::MODSTAT_NEW) || (updated)) {
+			cout << ((updated)?"U":"N") << " [" << module->Name() << "]  \t- " << module->Description() << "\n";
+		}
+	}
+}
+
+
 void remoteListModules(const char *sourceName) {
 	cout << "Available Modules:\n(be sure to refresh remote source (-r) first for most current list)\n\n";
 	InstallSourceMap::iterator source = installMgr->sources.find(sourceName);
@@ -156,8 +179,10 @@
 		finish(-4);
 	}
 	module = it->second;
-	installMgr->installModule(mgr, 0, module->Name(), is);
-	cout << "Installed module: [" << module->Name() << "]\n";
+	int error = installMgr->installModule(mgr, 0, module->Name(), is);
+	if (error) {
+		cout << "Error installing module: [" << module->Name() << "] (write permissions?)\n";
+	} else cout << "Installed module: [" << module->Name() << "]\n";
 }
 
 
@@ -170,8 +195,10 @@
 		finish(-4);
 	}
 	module = it->second;
-	installMgr->installModule(mgr, dir, module->Name());
-	cout << "Installed module: [" << module->Name() << "]\n";
+	int error = installMgr->installModule(mgr, dir, module->Name());
+	if (error) {
+		cout << "Error installing module: [" << module->Name() << "] (write permissions?)\n";
+	} else cout << "Installed module: [" << module->Name() << "]\n";
 }
 
 
@@ -233,6 +260,11 @@
 				usage(*argv);
 			remoteListModules(argv[2]);
 			break;
+		case 'd':		// -rl remote list
+			if (argc < 3)
+				usage(*argv);
+			remoteNewModules(mgr, argv[2]);
+			break;
 		case 'i':		// -ri remote install
 			if (argc < 4)
 				usage(*argv);




More information about the sword-cvs mailing list