diff --git a/src/addons/addons_manager.cpp b/src/addons/addons_manager.cpp index cce14cc34..19bab1445 100644 --- a/src/addons/addons_manager.cpp +++ b/src/addons/addons_manager.cpp @@ -30,6 +30,7 @@ #include "addons/network_http.hpp" #include "addons/zip.hpp" +#include "graphics/irr_driver.hpp" #include "io/file_manager.hpp" #include "io/xml_node.hpp" #include "karts/kart_properties_manager.hpp" @@ -65,8 +66,6 @@ void AddonsManager::initOnline() int download_state = 0; m_download_state = download_state; - // FIXME: It is _very_ dirty to save the list as a locale file - // since we have a function to load it directly in a string. if(UserConfigParams::m_verbosity>=3) printf("[addons] Addons manager downloading list\n"); if(!network_http->downloadFileSynchron("list")) @@ -171,7 +170,7 @@ int AddonsManager::getAddonIndex(const std::string &id) const void AddonsManager::install(const Addon &addon) { bool success=true; - std::string id = StringUtils::toLowerCase(addon.getName()); + const std::string &id = addon.getId(); file_manager->checkAndCreateDirForAddons(id, addon.getType()+ "s/"); //extract the zip in the addons folder called like the addons name @@ -197,6 +196,17 @@ void AddonsManager::install(const Addon &addon) m_addons_list[index].setInstalled(true); m_str_state = "Reloading kart list..."; + if(addon.getType()=="kart") + { + // We have to remove the mesh of the kart since otherwise it remains + // cashed, and will therefore be found again when reloading the karts. + // This is important on one hand since we reload all karts (this + // function is easily available) and existing karts will not reload + // their meshes. + const KartProperties *prop = kart_properties_manager->getKart(addon.getId()); + const KartModel &model = prop->getMasterKartModel(); + irr_driver->removeMesh(model.getModel()); + } saveInstalled(); } // install @@ -238,11 +248,11 @@ void AddonsManager::uninstall(const Addon &addon) m_addons_list[index].setInstalled(false); //write the xml file with the informations about installed karts - std::string dest_file = file_manager->getAddonsDir() + "/" - + addon.getType()+ "s/" + addon.getName()+ "/"; + std::string name=addon.getType()+"s/"+addon.getId(); + std::string dest_file = file_manager->getAddonsFile(name); //remove the addons directory - file_manager->removeDirectory(dest_file.c_str()); + file_manager->removeDirectory(dest_file); saveInstalled(); } // uninstall diff --git a/src/io/file_manager.cpp b/src/io/file_manager.cpp index 3096ea79d..2ad2b6be5 100644 --- a/src/io/file_manager.cpp +++ b/src/io/file_manager.cpp @@ -46,7 +46,7 @@ # include # ifndef __CYGWIN__ # define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) - // Some portabilty defines +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) # endif #else # include @@ -56,6 +56,7 @@ #include "irrlicht.h" #include "btBulletDynamicsCommon.h" +#include "config/user_config.hpp" #include "graphics/irr_driver.hpp" #include "graphics/material_manager.hpp" #include "karts/kart_properties_manager.hpp" @@ -495,6 +496,7 @@ void FileManager::checkAndCreateConfigDir() return; } // checkAndCreateConfigDir +// ---------------------------------------------------------------------------- #ifdef ADDONS_MANAGER void FileManager::checkAndCreateAddonsDir() { @@ -543,16 +545,17 @@ void FileManager::checkAndCreateAddonsDir() m_addons_dir.c_str()); m_config_dir = "."; } - else + + if (!checkAndCreateDirectory(m_addons_dir + "/icons/")) { - //we hope that there will be no problem since we created the other dir - if (!checkAndCreateDirectory(m_addons_dir + "/data/")) - { - fprintf(stderr, "Failed to create add-ons data dir at '%s'\n", - (m_addons_dir + "/data/").c_str()); - } + fprintf(stderr, "Failed to create add-ons icon dir at '%s'\n", + (m_addons_dir + "/icons/").c_str()); + } + if (!checkAndCreateDirectory(m_addons_dir + "/tmp/")) + { + fprintf(stderr, "Failed to create add-ons tmp dir at '%s'\n", + (m_addons_dir + "/tmp/").c_str()); } - return; } // checkAndCreateAddonsDir //----------------------------------------------------------------------------- @@ -620,6 +623,18 @@ std::string FileManager::getChallengeFile(const std::string &fname) const return getConfigDir()+"/"+fname; } // getChallengeFile +//----------------------------------------------------------------------------- +/** Returns true if the given name is a directory. + * \param path File name to test. + */ +bool FileManager::isDirectory(const std::string &path) const +{ + struct stat mystat; + + if(stat(path.c_str(), &mystat) < 0) return false; + return S_ISDIR(mystat.st_mode); +} // isDirectory + //----------------------------------------------------------------------------- void FileManager::listFiles(std::set& result, const std::string& dir, bool is_full_path, @@ -634,10 +649,7 @@ void FileManager::listFiles(std::set& result, #endif //printf("******* Path : %s \n", path.c_str()); - struct stat mystat; - - if(stat(path.c_str(), &mystat) < 0) return; - if(! S_ISDIR(mystat.st_mode)) return; + if(!isDirectory(path)) return; io::path previous_cwd = m_file_system->getWorkingDirectory(); @@ -675,72 +687,41 @@ void FileManager::checkAndCreateDirForAddons(std::string addons_name, } // checkAndCreateDirForAddons // ---------------------------------------------------------------------------- -bool FileManager::removeDirectory(char const *name) +/** Removes a directory (including all files contained). The function could + * easily recursively delete further subdirectories, but this is commented + * out atm (to limit the amount of damage in case of a bug). + * \param name Directory name to remove. + */ +bool FileManager::removeDirectory(const std::string &name) { -#ifndef WIN32 - // DIR etc. do not exist like this in windows, - // file system specific calls should be moved into - // the file manager!! - - DIR *directory; - struct dirent *entry; - struct stat file_stat; - - char buffer[1024] = {0}; - - directory = opendir(name); - if ( directory == NULL ) + std::set files; + listFiles(files, name, /*is full path*/ true); + for(std::set::iterator i=files.begin(); i!=files.end(); i++) { - fprintf(stderr, "cannot open directory %s\n", name); - return false; - } - - while ((entry = readdir(directory)) != NULL) - { - - /*this condition handles if it is the current directory (.) or the - parent directory (..), these names work only on unix-based I think*/ - if (strcmp(entry->d_name, ".") == 0 || - strcmp(entry->d_name, "..") == 0) + if((*i)=="." || (*i)=="..") continue; + if(UserConfigParams::m_verbosity>=3) + printf("Deleting directory '%s'.\n", (*i).c_str()); + std::string full_path=name+"/"+*i; + if(isDirectory(full_path)) { - continue; + // This should not be necessary (since this function is only + // used to remove addons), and it limits the damage in case + // of any bugs - i.e. if name should be "/" or so. + // removeDirectory(full_path); } - - snprintf(buffer, 1024, "%s/%s", name, entry->d_name); - - stat(buffer, &file_stat); - - if (S_ISREG(file_stat.st_mode)) + else { - remove(buffer); - } - else if (S_ISDIR(file_stat.st_mode)) - { - this->removeDirectory(buffer); + struct stat mystat; + if(stat(full_path.c_str(), &mystat) < 0) return false; + if( S_ISREG(mystat.st_mode)) + remove(full_path.c_str()); } } - closedir(directory); - - remove(name); - return true; - +#ifdef WIN32 + return ::RemoveDirectory(name.c_str())==TRUE; #else - ::RemoveDirectory(name); - return true; -#if 0 - SHFILEOPSTRUCT sh; - sh.hwnd = NULL; - sh.wFunc = FO_DELETE; - sh.pFrom = repertoire; - sh.pTo = NULL; - sh.fFlags = FOF_NOCONFIRMATION|FOF_SILENT; - sh.fAnyOperationsAborted = FALSE; - sh.lpszProgressTitle = NULL; - sh.hNameMappings = NULL; - - return (SHFileOperation(&sh)==0); + return remove(name.c_str()); #endif -#endif -} +} // remove directory #endif diff --git a/src/io/file_manager.hpp b/src/io/file_manager.hpp index 1d67bffaa..2ca634e75 100644 --- a/src/io/file_manager.hpp +++ b/src/io/file_manager.hpp @@ -70,6 +70,7 @@ private: void checkAndCreateConfigDir(); #ifdef ADDONS_MANAGER void checkAndCreateAddonsDir(); + bool isDirectory(const std::string &path) const; #endif public: FileManager(char *argv[]); @@ -86,7 +87,7 @@ public: std::string getAddonsFile(const std::string &name); void checkAndCreateDirForAddons(std::string addons_name, std::string addons_type); - bool removeDirectory(char const *name); + bool removeDirectory(const std::string &name); #endif std::string getDataDir () const; std::string getTranslationDir() const; diff --git a/src/states_screens/dialogs/addons_loading.cpp b/src/states_screens/dialogs/addons_loading.cpp index c4010594b..012735654 100644 --- a/src/states_screens/dialogs/addons_loading.cpp +++ b/src/states_screens/dialogs/addons_loading.cpp @@ -167,7 +167,6 @@ void AddonsLoading::onUpdate(float delta) { printf("Download finished.\n"); endInstall(); - dismiss(); return; } } @@ -223,5 +222,6 @@ void AddonsLoading::endInstall() // The list of the addon screen needs to be updated to correctly // display the newly (un)installed addon. AddonsScreen::getInstance()->loadList(); + dismiss(); } // endInstall #endif