summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/client.cpp463
-rw-r--r--src/client.h22
-rw-r--r--src/dirs.cpp491
-rw-r--r--src/dirs.h56
6 files changed, 565 insertions, 471 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index dd24d7ae2..819b5372a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -743,6 +743,8 @@ SET(SRCS
debug.h
defaults.cpp
defaults.h
+ dirs.cpp
+ dirs.h
dragdrop.h
effectmanager.cpp
effectmanager.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 072bc6949..f81145e6a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -858,6 +858,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \
debug.h \
defaults.cpp \
defaults.h \
+ dirs.cpp \
+ dirs.h \
dragdrop.h \
dropshortcut.cpp \
dropshortcut.h \
diff --git a/src/client.cpp b/src/client.cpp
index 454573ac6..c0733c50b 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -27,6 +27,7 @@
#include "auctionmanager.h"
#include "chatlogger.h"
#include "configuration.h"
+#include "dirs.h"
#include "dropshortcut.h"
#include "emoteshortcut.h"
#include "eventsmanager.h"
@@ -255,9 +256,9 @@ void Client::testsInit()
else
{
logger = new Logger;
- initLocalDataDir();
- initTempDir();
- initConfigDir();
+ Dirs::initLocalDataDir();
+ Dirs::initTempDir();
+ Dirs::initConfigDir();
}
}
@@ -270,8 +271,8 @@ void Client::gameInit()
branding.init(settings.options.brandingPath);
branding.setDefaultValues(getBrandingDefaults());
- initRootDir();
- initHomeDir();
+ Dirs::initRootDir();
+ Dirs::initHomeDir();
// Configure logger
if (!settings.options.logFileName.empty())
@@ -322,7 +323,7 @@ void Client::gameInit()
logger->log1(FULL_VERSION);
logger->log("Start configPath: " + config.getConfigPath());
- initScreenshotDir();
+ Dirs::initScreenshotDir();
// Initialize SDL
logger->log1("Initializing SDL...");
@@ -347,8 +348,8 @@ void Client::gameInit()
SDL_EventState(SDL_USEREVENT, SDL_IGNORE);
#ifdef WIN32
- extractDataDir();
- mountDataDir();
+ Dirs::extractDataDir();
+ Dirs::mountDataDir();
#endif
setIcon();
@@ -368,11 +369,11 @@ void Client::gameInit()
initGraphics();
#ifndef WIN32
- extractDataDir();
- mountDataDir();
+ Dirs::extractDataDir();
+ Dirs::mountDataDir();
#endif
- updateDataPath();
+ Dirs::updateDataPath();
// Add the main data directories to our PhysicsFS search path
if (!settings.options.dataPath.empty())
@@ -536,24 +537,6 @@ void Client::updateEnv()
setEnv("SDL_VIDEO_ALLOW_SCREENSAVER", "0");
}
-void Client::updateDataPath()
-{
- if (settings.options.dataPath.empty()
- && !branding.getStringValue("dataPath").empty())
- {
- if (isRealPath(branding.getStringValue("dataPath")))
- {
- settings.options.dataPath = branding.getStringValue("dataPath");
- }
- else
- {
- settings.options.dataPath = branding.getDirectory().append(dirSeparator)
- + branding.getStringValue("dataPath");
- }
- settings.options.skipUpdate = true;
- }
-}
-
void Client::initGraphics()
{
graphicsManager.initGraphics(settings.options.noOpenGL);
@@ -611,91 +594,6 @@ static void setProgress(const int val)
#endif
#endif
-void Client::extractDataDir()
-{
-#ifdef ANDROID
-#ifdef USE_SDL2
- Files::setCopyCallBack(&updateProgress);
- setProgress(0);
- extractAssets();
-
- const std::string zipName = std::string(getenv(
- "APPDIR")).append("/data.zip");
- const std::string dirName = std::string(getenv(
- "APPDIR")).append("/data");
- Files::extractZip(zipName, "data", dirName);
- Files::extractLocale();
-#endif
-#endif
-
-#if defined __native_client__
- const std::string dirName = _nacl_dir.append("/data");
- Files::extractZip("/http/data.zip", "data", dirName);
-#endif
-}
-
-void Client::mountDataDir()
-{
- const ResourceManager *const resman = ResourceManager::getInstance();
- resman->addToSearchPath(PKG_DATADIR "data/perserver/default", false);
- resman->addToSearchPath("data/perserver/default", false);
-
-#if defined __APPLE__
- CFBundleRef mainBundle = CFBundleGetMainBundle();
- CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
- char path[PATH_MAX];
- if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (uint8_t*)path,
- PATH_MAX))
- {
- fprintf(stderr, "Can't find Resources directory\n");
- }
- CFRelease(resourcesURL);
- // possible crash
- strncat(path, "/data", PATH_MAX - 1);
- resman->addToSearchPath(path, false);
-// possible this need for support run client from dmg images.
-// mPackageDir = path;
-#endif
- resman->addToSearchPath(PKG_DATADIR "data", false);
- setPackageDir(PKG_DATADIR "data");
- resman->addToSearchPath("data", false);
-
-#ifdef ANDROID
-#ifdef USE_SDL2
- if (getenv("APPDIR"))
- {
- const std::string appDir = getenv("APPDIR");
- resman->addToSearchPath(appDir + "/data", false);
- resman->addToSearchPath(appDir + "/data/perserver/default", false);
- }
-#endif
-#endif
-
-#if defined __native_client__
- resman->addToSearchPath(_nacl_dir.append("/data"), false);
-#endif
-
- // Add branding/data to PhysFS search path
- if (!settings.options.brandingPath.empty())
- {
- std::string path = settings.options.brandingPath;
-
- // Strip blah.manaplus from the path
-#ifdef WIN32
- const int loc1 = path.find_last_of('/');
- const int loc2 = path.find_last_of('\\');
- const int loc = static_cast<int>(std::max(loc1, loc2));
-#else
- const int loc = static_cast<int>(path.find_last_of('/'));
-#endif
- if (loc > 0)
- {
- resman->addToSearchPath(path.substr(
- 0, loc + 1).append("data"), false);
- }
- }
-}
-
void Client::initLang()
{
#ifdef ENABLE_NLS
@@ -1349,7 +1247,7 @@ int Client::gameExec()
settings.updateHost = settings.options.updateHost;
else
settings.updateHost = loginData.updateHost;
- initUpdatesDir();
+ Dirs::initUpdatesDir();
if (!settings.oldUpdates.empty())
UpdaterWindow::unloadUpdates(settings.oldUpdates);
@@ -1874,170 +1772,6 @@ void Client::action(const ActionEvent &event)
}
}
-void Client::initRootDir()
-{
- settings.rootDir = PhysFs::getBaseDir();
- const std::string portableName = settings.rootDir + "portable.xml";
- struct stat statbuf;
-
- if (!stat(portableName.c_str(), &statbuf) && S_ISREG(statbuf.st_mode))
- {
- std::string dir;
- Configuration portable;
- portable.init(portableName);
-
- if (settings.options.brandingPath.empty())
- {
- branding.init(portableName);
- branding.setDefaultValues(getBrandingDefaults());
- }
-
- logger->log("Portable file: %s", portableName.c_str());
-
- if (settings.options.localDataDir.empty())
- {
- dir = portable.getValue("dataDir", "");
- if (!dir.empty())
- {
- settings.options.localDataDir = settings.rootDir + dir;
- logger->log("Portable data dir: %s",
- settings.options.localDataDir.c_str());
- }
- }
-
- if (settings.options.configDir.empty())
- {
- dir = portable.getValue("configDir", "");
- if (!dir.empty())
- {
- settings.options.configDir = settings.rootDir + dir;
- logger->log("Portable config dir: %s",
- settings.options.configDir.c_str());
- }
- }
-
- if (settings.options.screenshotDir.empty())
- {
- dir = portable.getValue("screenshotDir", "");
- if (!dir.empty())
- {
- settings.options.screenshotDir = settings.rootDir + dir;
- logger->log("Portable screenshot dir: %s",
- settings.options.screenshotDir.c_str());
- }
- }
- }
-}
-
-/**
- * Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On
- * Windows and other systems we use the current working directory.
- */
-void Client::initHomeDir()
-{
- initLocalDataDir();
- initTempDir();
- initConfigDir();
-}
-
-void Client::initLocalDataDir()
-{
- settings.localDataDir = settings.options.localDataDir;
-
- if (settings.localDataDir.empty())
- {
-#ifdef __APPLE__
- // Use Application Directory instead of .mana
- settings.localDataDir = std::string(PhysFs::getUserDir()) +
- "/Library/Application Support/" +
- branding.getValue("appName", "ManaPlus");
-#elif defined __HAIKU__
- settings.localDataDir = std::string(PhysFs::getUserDir()) +
- "/config/data/Mana";
-#elif defined WIN32
- settings.localDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA);
- if (settings.localDataDir.empty())
- settings.localDataDir = std::string(PhysFs::getUserDir());
- settings.localDataDir.append("/Mana");
-#elif defined __ANDROID__
- settings.localDataDir = getSdStoragePath() + branding.getValue(
- "appShort", "ManaPlus") + "/local";
-#elif defined __native_client__
- settings.localDataDir = _nacl_dir.append("/local");
-#else
- settings.localDataDir = std::string(PhysFs::getUserDir()) +
- ".local/share/mana";
-#endif
- }
-
- if (mkdir_r(settings.localDataDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->error(strprintf(_("%s doesn't exist and can't be created! "
- "Exiting."), settings.localDataDir.c_str()));
- }
-#ifdef USE_PROFILER
- Perfomance::init(settings.localDataDir + "/profiler.log");
-#endif
-}
-
-void Client::initTempDir()
-{
- settings.tempDir = settings.localDataDir + dirSeparator + "temp";
-
- if (mkdir_r(settings.tempDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->error(strprintf(_("%s doesn't exist and can't be created! "
- "Exiting."), settings.tempDir.c_str()));
- }
-// ResourceManager::deleteFilesInDirectory(settings.tempDir);
-}
-
-void Client::initConfigDir()
-{
- settings.configDir = settings.options.configDir;
-
- if (settings.configDir.empty())
- {
-#ifdef __APPLE__
- settings.configDir = settings.localDataDir + dirSeparator
- + branding.getValue("appShort", "mana");
-#elif defined __HAIKU__
- settings.configDir = std::string(PhysFs::getUserDir()) +
- "/config/settings/Mana" +
- branding.getValue("appName", "ManaPlus");
-#elif defined WIN32
- settings.configDir = getSpecialFolderLocation(CSIDL_APPDATA);
- if (settings.configDir.empty())
- {
- settings.configDir = settings.localDataDir;
- }
- else
- {
- settings.configDir.append("/mana/").append(branding.getValue(
- "appShort", "mana"));
- }
-#elif defined __ANDROID__
- settings.configDir = getSdStoragePath() + branding.getValue(
- "appShort", "ManaPlus").append("/config");
-#elif defined __native_client__
- settings.configDir = _nacl_dir.append("/config");
-#else
- settings.configDir = std::string(PhysFs::getUserDir()).append(
- "/.config/mana/").append(branding.getValue("appShort", "mana"));
-#endif
- logger->log("Generating config dir: " + settings.configDir);
- }
-
- if (mkdir_r(settings.configDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->error(strprintf(_("%s doesn't exist and can't be created! "
- "Exiting."), settings.configDir.c_str()));
- }
-}
-
/**
* Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On
* Windows and other systems we use the current working directory.
@@ -2068,7 +1802,7 @@ void Client::initServerConfig(const std::string &serverName)
}
initPacketLimiter();
initTradeFilter();
- initUsersDir();
+ Dirs::initUsersDir();
player_relations.init();
// Initialize the item and emote shortcuts.
@@ -2169,156 +1903,6 @@ void Client::backupConfig() const
Files::copyFile(fileName3, fileName4);
}
-/**
- * Parse the update host and determine the updates directory
- * Then verify that the directory exists (creating if needed).
- */
-void Client::initUpdatesDir()
-{
- std::stringstream updates;
-
- // If updatesHost is currently empty, fill it from config file
- if (settings.updateHost.empty())
- settings.updateHost = config.getStringValue("updatehost");
- if (!checkPath(settings.updateHost))
- return;
-
- // Don't go out of range int he next check
- if (settings.updateHost.length() < 2)
- return;
-
- const size_t sz = settings.updateHost.size();
- // Remove any trailing slash at the end of the update host
- if (settings.updateHost.at(sz - 1) == '/')
- settings.updateHost.resize(sz - 1);
-
- // Parse out any "http://" or "https://", and set the updates directory
- const size_t pos = settings.updateHost.find("://");
- if (pos != settings.updateHost.npos)
- {
- if (pos + 3 < settings.updateHost.length()
- && !settings.updateHost.empty())
- {
- updates << "updates/" << settings.updateHost.substr(pos + 3);
- settings.updatesDir = updates.str();
- }
- else
- {
- logger->log("Error: Invalid update host: %s",
- settings.updateHost.c_str());
- // TRANSLATORS: update server initialisation error
- errorMessage = strprintf(_("Invalid update host: %s."),
- settings.updateHost.c_str());
- mState = STATE_ERROR;
- }
- }
- else
- {
- logger->log1("Warning: no protocol was specified for the update host");
- updates << "updates/" << settings.updateHost;
- settings.updatesDir = updates.str();
- }
-
-#ifdef WIN32
- if (settings.updatesDir.find(":") != std::string::npos)
- replaceAll(settings.updatesDir, ":", "_");
-#endif
-
- const std::string updateDir("/" + settings.updatesDir);
-
- // Verify that the updates directory exists. Create if necessary.
- if (!PhysFs::isDirectory(updateDir.c_str()))
- {
- if (!PhysFs::mkdir(updateDir.c_str()))
- {
-#if defined WIN32
- std::string newDir = settings.localDataDir
- + "\\" + settings.updatesDir;
- size_t loc = newDir.find("/", 0);
-
- while (loc != std::string::npos)
- {
- newDir.replace(loc, 1, "\\");
- loc = newDir.find("/", loc);
- }
-
- if (!CreateDirectory(newDir.c_str(), nullptr) &&
- GetLastError() != ERROR_ALREADY_EXISTS)
- {
- logger->log("Error: %s can't be made, but doesn't exist!",
- newDir.c_str());
- // TRANSLATORS: update server initialisation error
- errorMessage = _("Error creating updates directory!");
- mState = STATE_ERROR;
- }
-#else
- logger->log("Error: %s/%s can't be made, but doesn't exist!",
- settings.localDataDir.c_str(), settings.updatesDir.c_str());
- // TRANSLATORS: update server initialisation error
- errorMessage = _("Error creating updates directory!");
- mState = STATE_ERROR;
-#endif
- }
- }
- const std::string updateLocal = updateDir + "/local";
- const std::string updateFix = updateDir + "/fix";
- if (!PhysFs::isDirectory(updateLocal.c_str()))
- PhysFs::mkdir(updateLocal.c_str());
- if (!PhysFs::isDirectory(updateFix.c_str()))
- PhysFs::mkdir(updateFix.c_str());
-}
-
-void Client::initScreenshotDir()
-{
- if (!settings.options.screenshotDir.empty())
- {
- settings.screenshotDir = settings.options.screenshotDir;
- if (mkdir_r(settings.screenshotDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->log(strprintf(
- _("Error: %s doesn't exist and can't be created! "
- "Exiting."), settings.screenshotDir.c_str()));
- }
- }
- else if (settings.screenshotDir.empty())
- {
- settings.screenshotDir = decodeBase64String(
- config.getStringValue("screenshotDirectory3"));
- if (settings.screenshotDir.empty())
- {
-#ifdef __ANDROID__
- settings.screenshotDir = getSdStoragePath()
- + std::string("/images");
-
- if (mkdir_r(settings.screenshotDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->log(strprintf(
- _("Error: %s doesn't exist and can't be created! "
- "Exiting."), settings.screenshotDir.c_str()));
- }
-#else
- settings.screenshotDir = getPicturesDir();
-#endif
- if (config.getBoolValue("useScreenshotDirectorySuffix"))
- {
- const std::string configScreenshotSuffix =
- branding.getValue("screenshots", "ManaPlus");
-
- if (!configScreenshotSuffix.empty())
- {
- settings.screenshotDir.append(dirSeparator).append(
- configScreenshotSuffix);
- }
- }
- config.setValue("screenshotDirectory3",
- encodeBase64String(settings.screenshotDir));
- }
- }
- logger->log("screenshotDirectory: " + settings.screenshotDir);
-}
-
#ifndef ANDROID
void Client::storeSafeParameters() const
{
@@ -2473,25 +2057,6 @@ void Client::initTradeFilter() const
}
}
-void Client::initUsersDir()
-{
- settings.usersDir = settings.serverConfigDir + "/users/";
- if (mkdir_r(settings.usersDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->error(strprintf(_("%s doesn't exist and can't be created! "
- "Exiting."), settings.usersDir.c_str()));
- }
-
- settings.npcsDir = settings.serverConfigDir + "/npcs/";
- if (mkdir_r(settings.npcsDir.c_str()))
- {
- // TRANSLATORS: directory creation error
- logger->error(strprintf(_("%s doesn't exist and can't be created! "
- "Exiting."), settings.npcsDir.c_str()));
- }
-}
-
void Client::initPacketLimiter()
{
// here i setting packet limits. but current server is broken,
diff --git a/src/client.h b/src/client.h
index 7fb34b98e..d7066145a 100644
--- a/src/client.h
+++ b/src/client.h
@@ -162,8 +162,6 @@ public:
void initTradeFilter() const;
- void initUsersDir();
-
void initPacketLimiter();
void writePacketLimits(const std::string &packetLimitsName) const;
@@ -202,28 +200,8 @@ private:
void initTitle();
- void updateDataPath();
-
- static void extractDataDir();
-
- void mountDataDir();
-
- void initRootDir();
-
- void initHomeDir();
-
void initConfiguration() const;
- void initLocalDataDir();
-
- void initTempDir();
-
- void initConfigDir();
-
- void initUpdatesDir();
-
- void initScreenshotDir();
-
void initServerConfig(const std::string &serverName);
static void initFeatures();
diff --git a/src/dirs.cpp b/src/dirs.cpp
new file mode 100644
index 000000000..da3aacd8e
--- /dev/null
+++ b/src/dirs.cpp
@@ -0,0 +1,491 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dirs.h"
+
+#include "client.h"
+#include "configuration.h"
+#include "logger.h"
+#include "settings.h"
+
+#include "utils/base64.h"
+#include "utils/gettext.h"
+#include "utils/mkdir.h"
+#include "utils/paths.h"
+#include "utils/physfstools.h"
+
+#include "resources/resourcemanager.h"
+
+#ifdef __APPLE__
+#include <CoreFoundation/CFBundle.h>
+#endif
+
+#include <SDL_image.h>
+
+#ifdef WIN32
+#include <SDL_syswm.h>
+#include "utils/specialfolder.h"
+#endif
+
+#include <sys/stat.h>
+
+#include "debug.h"
+
+#if defined __native_client__
+#define _nacl_dir std::string("/persistent/manaplus")
+#endif
+
+void Dirs::updateDataPath()
+{
+ if (settings.options.dataPath.empty()
+ && !branding.getStringValue("dataPath").empty())
+ {
+ if (isRealPath(branding.getStringValue("dataPath")))
+ {
+ settings.options.dataPath = branding.getStringValue("dataPath");
+ }
+ else
+ {
+ settings.options.dataPath = branding.getDirectory().append(dirSeparator)
+ + branding.getStringValue("dataPath");
+ }
+ settings.options.skipUpdate = true;
+ }
+}
+
+void Dirs::extractDataDir()
+{
+#ifdef ANDROID
+#ifdef USE_SDL2
+ Files::setCopyCallBack(&updateProgress);
+ setProgress(0);
+ extractAssets();
+
+ const std::string zipName = std::string(getenv(
+ "APPDIR")).append("/data.zip");
+ const std::string dirName = std::string(getenv(
+ "APPDIR")).append("/data");
+ Files::extractZip(zipName, "data", dirName);
+ Files::extractLocale();
+#endif
+#endif
+
+#if defined __native_client__
+ const std::string dirName = _nacl_dir.append("/data");
+ Files::extractZip("/http/data.zip", "data", dirName);
+#endif
+}
+
+void Dirs::mountDataDir()
+{
+ const ResourceManager *const resman = ResourceManager::getInstance();
+ resman->addToSearchPath(PKG_DATADIR "data/perserver/default", false);
+ resman->addToSearchPath("data/perserver/default", false);
+
+#if defined __APPLE__
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
+ char path[PATH_MAX];
+ if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (uint8_t*)path,
+ PATH_MAX))
+ {
+ fprintf(stderr, "Can't find Resources directory\n");
+ }
+ CFRelease(resourcesURL);
+ // possible crash
+ strncat(path, "/data", PATH_MAX - 1);
+ resman->addToSearchPath(path, false);
+// possible this need for support run client from dmg images.
+// mPackageDir = path;
+#endif
+ resman->addToSearchPath(PKG_DATADIR "data", false);
+ setPackageDir(PKG_DATADIR "data");
+ resman->addToSearchPath("data", false);
+
+#ifdef ANDROID
+#ifdef USE_SDL2
+ if (getenv("APPDIR"))
+ {
+ const std::string appDir = getenv("APPDIR");
+ resman->addToSearchPath(appDir + "/data", false);
+ resman->addToSearchPath(appDir + "/data/perserver/default", false);
+ }
+#endif
+#endif
+
+#if defined __native_client__
+ resman->addToSearchPath(_nacl_dir.append("/data"), false);
+#endif
+
+ // Add branding/data to PhysFS search path
+ if (!settings.options.brandingPath.empty())
+ {
+ std::string path = settings.options.brandingPath;
+
+ // Strip blah.manaplus from the path
+#ifdef WIN32
+ const int loc1 = path.find_last_of('/');
+ const int loc2 = path.find_last_of('\\');
+ const int loc = static_cast<int>(std::max(loc1, loc2));
+#else
+ const int loc = static_cast<int>(path.find_last_of('/'));
+#endif
+ if (loc > 0)
+ {
+ resman->addToSearchPath(path.substr(
+ 0, loc + 1).append("data"), false);
+ }
+ }
+}
+
+void Dirs::initRootDir()
+{
+ settings.rootDir = PhysFs::getBaseDir();
+ const std::string portableName = settings.rootDir + "portable.xml";
+ struct stat statbuf;
+
+ if (!stat(portableName.c_str(), &statbuf) && S_ISREG(statbuf.st_mode))
+ {
+ std::string dir;
+ Configuration portable;
+ portable.init(portableName);
+
+ if (settings.options.brandingPath.empty())
+ {
+ branding.init(portableName);
+ branding.setDefaultValues(getBrandingDefaults());
+ }
+
+ logger->log("Portable file: %s", portableName.c_str());
+
+ if (settings.options.localDataDir.empty())
+ {
+ dir = portable.getValue("dataDir", "");
+ if (!dir.empty())
+ {
+ settings.options.localDataDir = settings.rootDir + dir;
+ logger->log("Portable data dir: %s",
+ settings.options.localDataDir.c_str());
+ }
+ }
+
+ if (settings.options.configDir.empty())
+ {
+ dir = portable.getValue("configDir", "");
+ if (!dir.empty())
+ {
+ settings.options.configDir = settings.rootDir + dir;
+ logger->log("Portable config dir: %s",
+ settings.options.configDir.c_str());
+ }
+ }
+
+ if (settings.options.screenshotDir.empty())
+ {
+ dir = portable.getValue("screenshotDir", "");
+ if (!dir.empty())
+ {
+ settings.options.screenshotDir = settings.rootDir + dir;
+ logger->log("Portable screenshot dir: %s",
+ settings.options.screenshotDir.c_str());
+ }
+ }
+ }
+}
+
+/**
+ * Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On
+ * Windows and other systems we use the current working directory.
+ */
+void Dirs::initHomeDir()
+{
+ initLocalDataDir();
+ initTempDir();
+ initConfigDir();
+}
+
+void Dirs::initLocalDataDir()
+{
+ settings.localDataDir = settings.options.localDataDir;
+
+ if (settings.localDataDir.empty())
+ {
+#ifdef __APPLE__
+ // Use Application Directory instead of .mana
+ settings.localDataDir = std::string(PhysFs::getUserDir()) +
+ "/Library/Application Support/" +
+ branding.getValue("appName", "ManaPlus");
+#elif defined __HAIKU__
+ settings.localDataDir = std::string(PhysFs::getUserDir()) +
+ "/config/data/Mana";
+#elif defined WIN32
+ settings.localDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA);
+ if (settings.localDataDir.empty())
+ settings.localDataDir = std::string(PhysFs::getUserDir());
+ settings.localDataDir.append("/Mana");
+#elif defined __ANDROID__
+ settings.localDataDir = getSdStoragePath() + branding.getValue(
+ "appShort", "ManaPlus") + "/local";
+#elif defined __native_client__
+ settings.localDataDir = _nacl_dir.append("/local");
+#else
+ settings.localDataDir = std::string(PhysFs::getUserDir()) +
+ ".local/share/mana";
+#endif
+ }
+
+ if (mkdir_r(settings.localDataDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->error(strprintf(_("%s doesn't exist and can't be created! "
+ "Exiting."), settings.localDataDir.c_str()));
+ }
+#ifdef USE_PROFILER
+ Perfomance::init(settings.localDataDir + "/profiler.log");
+#endif
+}
+
+void Dirs::initTempDir()
+{
+ settings.tempDir = settings.localDataDir + dirSeparator + "temp";
+
+ if (mkdir_r(settings.tempDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->error(strprintf(_("%s doesn't exist and can't be created! "
+ "Exiting."), settings.tempDir.c_str()));
+ }
+// ResourceManager::deleteFilesInDirectory(settings.tempDir);
+}
+
+void Dirs::initConfigDir()
+{
+ settings.configDir = settings.options.configDir;
+
+ if (settings.configDir.empty())
+ {
+#ifdef __APPLE__
+ settings.configDir = settings.localDataDir + dirSeparator
+ + branding.getValue("appShort", "mana");
+#elif defined __HAIKU__
+ settings.configDir = std::string(PhysFs::getUserDir()) +
+ "/config/settings/Mana" +
+ branding.getValue("appName", "ManaPlus");
+#elif defined WIN32
+ settings.configDir = getSpecialFolderLocation(CSIDL_APPDATA);
+ if (settings.configDir.empty())
+ {
+ settings.configDir = settings.localDataDir;
+ }
+ else
+ {
+ settings.configDir.append("/mana/").append(branding.getValue(
+ "appShort", "mana"));
+ }
+#elif defined __ANDROID__
+ settings.configDir = getSdStoragePath() + branding.getValue(
+ "appShort", "ManaPlus").append("/config");
+#elif defined __native_client__
+ settings.configDir = _nacl_dir.append("/config");
+#else
+ settings.configDir = std::string(PhysFs::getUserDir()).append(
+ "/.config/mana/").append(branding.getValue("appShort", "mana"));
+#endif
+ logger->log("Generating config dir: " + settings.configDir);
+ }
+
+ if (mkdir_r(settings.configDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->error(strprintf(_("%s doesn't exist and can't be created! "
+ "Exiting."), settings.configDir.c_str()));
+ }
+}
+
+/**
+ * Parse the update host and determine the updates directory
+ * Then verify that the directory exists (creating if needed).
+ */
+void Dirs::initUpdatesDir()
+{
+ std::stringstream updates;
+
+ // If updatesHost is currently empty, fill it from config file
+ if (settings.updateHost.empty())
+ settings.updateHost = config.getStringValue("updatehost");
+ if (!checkPath(settings.updateHost))
+ return;
+
+ // Don't go out of range int he next check
+ if (settings.updateHost.length() < 2)
+ return;
+
+ const size_t sz = settings.updateHost.size();
+ // Remove any trailing slash at the end of the update host
+ if (settings.updateHost.at(sz - 1) == '/')
+ settings.updateHost.resize(sz - 1);
+
+ // Parse out any "http://" or "https://", and set the updates directory
+ const size_t pos = settings.updateHost.find("://");
+ if (pos != settings.updateHost.npos)
+ {
+ if (pos + 3 < settings.updateHost.length()
+ && !settings.updateHost.empty())
+ {
+ updates << "updates/" << settings.updateHost.substr(pos + 3);
+ settings.updatesDir = updates.str();
+ }
+ else
+ {
+ logger->log("Error: Invalid update host: %s",
+ settings.updateHost.c_str());
+ // TRANSLATORS: update server initialisation error
+ errorMessage = strprintf(_("Invalid update host: %s."),
+ settings.updateHost.c_str());
+ client->setState(STATE_ERROR);
+ }
+ }
+ else
+ {
+ logger->log1("Warning: no protocol was specified for the update host");
+ updates << "updates/" << settings.updateHost;
+ settings.updatesDir = updates.str();
+ }
+
+#ifdef WIN32
+ if (settings.updatesDir.find(":") != std::string::npos)
+ replaceAll(settings.updatesDir, ":", "_");
+#endif
+
+ const std::string updateDir("/" + settings.updatesDir);
+
+ // Verify that the updates directory exists. Create if necessary.
+ if (!PhysFs::isDirectory(updateDir.c_str()))
+ {
+ if (!PhysFs::mkdir(updateDir.c_str()))
+ {
+#if defined WIN32
+ std::string newDir = settings.localDataDir
+ + "\\" + settings.updatesDir;
+ size_t loc = newDir.find("/", 0);
+
+ while (loc != std::string::npos)
+ {
+ newDir.replace(loc, 1, "\\");
+ loc = newDir.find("/", loc);
+ }
+
+ if (!CreateDirectory(newDir.c_str(), nullptr) &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ logger->log("Error: %s can't be made, but doesn't exist!",
+ newDir.c_str());
+ // TRANSLATORS: update server initialisation error
+ errorMessage = _("Error creating updates directory!");
+ client->setState(STATE_ERROR);
+ }
+#else
+ logger->log("Error: %s/%s can't be made, but doesn't exist!",
+ settings.localDataDir.c_str(), settings.updatesDir.c_str());
+ // TRANSLATORS: update server initialisation error
+ errorMessage = _("Error creating updates directory!");
+ client->setState(STATE_ERROR);
+#endif
+ }
+ }
+ const std::string updateLocal = updateDir + "/local";
+ const std::string updateFix = updateDir + "/fix";
+ if (!PhysFs::isDirectory(updateLocal.c_str()))
+ PhysFs::mkdir(updateLocal.c_str());
+ if (!PhysFs::isDirectory(updateFix.c_str()))
+ PhysFs::mkdir(updateFix.c_str());
+}
+
+void Dirs::initScreenshotDir()
+{
+ if (!settings.options.screenshotDir.empty())
+ {
+ settings.screenshotDir = settings.options.screenshotDir;
+ if (mkdir_r(settings.screenshotDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->log(strprintf(
+ _("Error: %s doesn't exist and can't be created! "
+ "Exiting."), settings.screenshotDir.c_str()));
+ }
+ }
+ else if (settings.screenshotDir.empty())
+ {
+ settings.screenshotDir = decodeBase64String(
+ config.getStringValue("screenshotDirectory3"));
+ if (settings.screenshotDir.empty())
+ {
+#ifdef __ANDROID__
+ settings.screenshotDir = getSdStoragePath()
+ + std::string("/images");
+
+ if (mkdir_r(settings.screenshotDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->log(strprintf(
+ _("Error: %s doesn't exist and can't be created! "
+ "Exiting."), settings.screenshotDir.c_str()));
+ }
+#else
+ settings.screenshotDir = getPicturesDir();
+#endif
+ if (config.getBoolValue("useScreenshotDirectorySuffix"))
+ {
+ const std::string configScreenshotSuffix =
+ branding.getValue("screenshots", "ManaPlus");
+
+ if (!configScreenshotSuffix.empty())
+ {
+ settings.screenshotDir.append(dirSeparator).append(
+ configScreenshotSuffix);
+ }
+ }
+ config.setValue("screenshotDirectory3",
+ encodeBase64String(settings.screenshotDir));
+ }
+ }
+ logger->log("screenshotDirectory: " + settings.screenshotDir);
+}
+
+void Dirs::initUsersDir()
+{
+ settings.usersDir = settings.serverConfigDir + "/users/";
+ if (mkdir_r(settings.usersDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->error(strprintf(_("%s doesn't exist and can't be created! "
+ "Exiting."), settings.usersDir.c_str()));
+ }
+
+ settings.npcsDir = settings.serverConfigDir + "/npcs/";
+ if (mkdir_r(settings.npcsDir.c_str()))
+ {
+ // TRANSLATORS: directory creation error
+ logger->error(strprintf(_("%s doesn't exist and can't be created! "
+ "Exiting."), settings.npcsDir.c_str()));
+ }
+}
diff --git a/src/dirs.h b/src/dirs.h
new file mode 100644
index 000000000..ed01a822a
--- /dev/null
+++ b/src/dirs.h
@@ -0,0 +1,56 @@
+/*
+ * The ManaPlus Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ * Copyright (C) 2011-2014 The ManaPlus Developers
+ *
+ * This file is part of The ManaPlus Client.
+ *
+ * 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
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DIRS_H
+#define DIRS_H
+
+#include <string>
+
+#include "localconsts.h"
+
+class Dirs final
+{
+ public:
+ static void initUsersDir();
+
+ static void updateDataPath();
+
+ static void extractDataDir();
+
+ static void mountDataDir();
+
+ static void initRootDir();
+
+ static void initHomeDir();
+
+ static void initLocalDataDir();
+
+ static void initTempDir();
+
+ static void initConfigDir();
+
+ static void initUpdatesDir();
+
+ static void initScreenshotDir();
+};
+
+#endif // DIRS_H