1 |
|
|
/* |
2 |
|
|
* The ManaPlus Client |
3 |
|
|
* Copyright (C) 2004-2009 The Mana World Development Team |
4 |
|
|
* Copyright (C) 2009-2010 The Mana Developers |
5 |
|
|
* Copyright (C) 2011-2019 The ManaPlus Developers |
6 |
|
|
* Copyright (C) 2019-2021 Andrei Karas |
7 |
|
|
* |
8 |
|
|
* This file is part of The ManaPlus Client. |
9 |
|
|
* |
10 |
|
|
* This program is free software; you can redistribute it and/or modify |
11 |
|
|
* it under the terms of the GNU General Public License as published by |
12 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
13 |
|
|
* any later version. |
14 |
|
|
* |
15 |
|
|
* This program is distributed in the hope that it will be useful, |
16 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 |
|
|
* GNU General Public License for more details. |
19 |
|
|
* |
20 |
|
|
* You should have received a copy of the GNU General Public License |
21 |
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "dirs.h" |
25 |
|
|
|
26 |
|
|
#include "client.h" |
27 |
|
|
#include "configuration.h" |
28 |
|
|
#include "logger.h" |
29 |
|
|
#include "main.h" |
30 |
|
|
#include "settings.h" |
31 |
|
|
|
32 |
|
|
#include "fs/mkdir.h" |
33 |
|
|
#include "fs/paths.h" |
34 |
|
|
|
35 |
|
|
#include "fs/virtfs/fs.h" |
36 |
|
|
|
37 |
|
|
#include "utils/base64.h" |
38 |
|
|
#if defined(__native_client__) || (defined(ANDROID) && defined(USE_SDL2)) |
39 |
|
|
#include "fs/files.h" |
40 |
|
|
#endif // defined(__native_client__) || (defined(ANDROID) && |
41 |
|
|
// defined(USE_SDL2)) |
42 |
|
|
|
43 |
|
|
#include "utils/cast.h" |
44 |
|
|
#include "utils/gettext.h" |
45 |
|
|
|
46 |
|
|
#ifdef ANDROID |
47 |
|
|
#ifdef USE_SDL2 |
48 |
|
|
#include "main.h" |
49 |
|
|
|
50 |
|
|
#include "render/graphics.h" |
51 |
|
|
#endif // USE_SDL2 |
52 |
|
|
#endif // ANDROID |
53 |
|
|
|
54 |
|
|
#ifdef __APPLE__ |
55 |
|
|
#include <CoreFoundation/CFBundle.h> |
56 |
|
|
#endif // __APPLE__ |
57 |
|
|
|
58 |
|
|
#ifdef WIN32 |
59 |
|
|
PRAGMA48(GCC diagnostic push) |
60 |
|
|
PRAGMA48(GCC diagnostic ignored "-Wshadow") |
61 |
|
|
#include <SDL_syswm.h> |
62 |
|
|
PRAGMA48(GCC diagnostic pop) |
63 |
|
|
#include "fs/specialfolder.h" |
64 |
|
|
#undef ERROR |
65 |
|
|
#endif // WIN32 |
66 |
|
|
|
67 |
|
|
#include <sys/stat.h> |
68 |
|
|
|
69 |
|
|
#include <sstream> |
70 |
|
|
|
71 |
|
|
#include "debug.h" |
72 |
|
|
|
73 |
|
|
#if defined __native_client__ |
74 |
|
|
#define _nacl_dir std::string("/persistent/manaplus") |
75 |
|
|
#endif // defined __native_client__ |
76 |
|
|
|
77 |
|
|
#ifdef ANDROID |
78 |
|
|
#ifdef USE_SDL2 |
79 |
|
|
|
80 |
|
|
int loadingProgressCounter = 1; |
81 |
|
|
|
82 |
|
|
static void updateProgress(int cnt) |
83 |
|
|
{ |
84 |
|
|
const int progress = cnt + loadingProgressCounter; |
85 |
|
|
const int h = mainGraphics->mHeight; |
86 |
|
|
mainGraphics->setColor(Color(255, 255, 255, 255)); |
87 |
|
|
const int maxSize = mainGraphics->mWidth - 100; |
88 |
|
|
const int width = maxSize * progress / 50; |
89 |
|
|
mainGraphics->fillRectangle(Rect(50, h - 100, width, 50)); |
90 |
|
|
mainGraphics->updateScreen(); |
91 |
|
|
} |
92 |
|
|
|
93 |
|
|
void Dirs::setProgress() |
94 |
|
|
{ |
95 |
|
|
loadingProgressCounter++; |
96 |
|
|
updateProgress(loadingProgressCounter); |
97 |
|
|
} |
98 |
|
|
|
99 |
|
|
static void resetProgress() |
100 |
|
|
{ |
101 |
|
|
loadingProgressCounter = 0; |
102 |
|
|
updateProgress(loadingProgressCounter); |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
void extractAssets() |
106 |
|
|
{ |
107 |
|
|
if (!getenv("APPDIR")) |
108 |
|
|
{ |
109 |
|
|
logger->log("error: APPDIR is not set!"); |
110 |
|
|
return; |
111 |
|
|
} |
112 |
|
|
const std::string fileName = pathJoin(getenv("APPDIR"), |
113 |
|
|
"data.zip"); |
114 |
|
|
logger->log("Extracting asset into: " + fileName); |
115 |
|
|
uint8_t *buf = new uint8_t[1000000]; |
116 |
|
|
|
117 |
|
|
FILE *const file = fopen(fileName.c_str(), "w"); |
118 |
|
|
for (int f = 0; f < 100; f ++) |
119 |
|
|
{ |
120 |
|
|
std::string part = strprintf("manaplus-data.zip%u%u", |
121 |
|
|
CAST_U32(f / 10), |
122 |
|
|
CAST_U32(f % 10)); |
123 |
|
|
logger->log("testing asset: " + part); |
124 |
|
|
SDL_RWops *const rw = SDL_RWFromFile(part.c_str(), "r"); |
125 |
|
|
if (rw) |
126 |
|
|
{ |
127 |
|
|
const int size = SDL_RWsize(rw); |
128 |
|
|
int size2 = SDL_RWread(rw, buf, 1, size); |
129 |
|
|
logger->log("asset size: %d", size2); |
130 |
|
|
fwrite(buf, 1, size2, file); |
131 |
|
|
SDL_RWclose(rw); |
132 |
|
|
Dirs::setProgress(); |
133 |
|
|
} |
134 |
|
|
else |
135 |
|
|
{ |
136 |
|
|
break; |
137 |
|
|
} |
138 |
|
|
} |
139 |
|
|
fclose(file); |
140 |
|
|
|
141 |
|
|
const std::string fileName2 = pathJoin(getenv("APPDIR"), |
142 |
|
|
"locale.zip"); |
143 |
|
|
FILE *const file2 = fopen(fileName2.c_str(), "w"); |
144 |
|
|
SDL_RWops *const rw = SDL_RWFromFile("manaplus-locale.zip", "r"); |
145 |
|
|
if (rw) |
146 |
|
|
{ |
147 |
|
|
const int size = SDL_RWsize(rw); |
148 |
|
|
int size2 = SDL_RWread(rw, buf, 1, size); |
149 |
|
|
fwrite(buf, 1, size2, file2); |
150 |
|
|
SDL_RWclose(rw); |
151 |
|
|
Dirs::setProgress(); |
152 |
|
|
} |
153 |
|
|
fclose(file2); |
154 |
|
|
|
155 |
|
|
delete [] buf; |
156 |
|
|
} |
157 |
|
|
|
158 |
|
|
#endif // USE_SDL2 |
159 |
|
|
#endif // ANDROID |
160 |
|
|
|
161 |
|
|
void Dirs::updateDataPath() |
162 |
|
|
{ |
163 |
|
|
if (settings.options.dataPath.empty() |
164 |
|
|
&& !branding.getStringValue("dataPath").empty()) |
165 |
|
|
{ |
166 |
|
|
if (isRealPath(branding.getStringValue("dataPath"))) |
167 |
|
|
{ |
168 |
|
|
settings.options.dataPath = branding.getStringValue("dataPath"); |
169 |
|
|
} |
170 |
|
|
else |
171 |
|
|
{ |
172 |
|
|
settings.options.dataPath = pathJoin(branding.getDirectory(), |
173 |
|
|
branding.getStringValue("dataPath")); |
174 |
|
|
} |
175 |
|
|
settings.options.skipUpdate = true; |
176 |
|
|
} |
177 |
|
|
} |
178 |
|
|
|
179 |
|
|
void Dirs::extractDataDir() |
180 |
|
|
{ |
181 |
|
|
#if defined(ANDROID) && defined(USE_SDL2) |
182 |
|
|
Files::setCopyCallBack(&updateProgress); |
183 |
|
|
resetProgress(); |
184 |
|
|
extractAssets(); |
185 |
|
|
|
186 |
|
|
const std::string zipName = pathJoin(getenv("APPDIR"), "data.zip"); |
187 |
|
|
const std::string dirName = pathJoin(getenv("APPDIR"), "data"); |
188 |
|
|
VirtFs::mountZip2(zipName, |
189 |
|
|
"data", |
190 |
|
|
Append_false); |
191 |
|
|
VirtFs::mountZip2(zipName, |
192 |
|
|
"data/perserver/default", |
193 |
|
|
Append_false); |
194 |
|
|
Files::extractLocale(); |
195 |
|
|
#endif // defined(ANDROID) && defined(USE_SDL2) |
196 |
|
|
} |
197 |
|
|
|
198 |
|
|
void Dirs::mountDataDir() |
199 |
|
|
{ |
200 |
|
|
VirtFs::mountDirSilent(PKG_DATADIR "data/perserver/default", |
201 |
|
|
Append_false); |
202 |
|
|
VirtFs::mountDirSilent("data/perserver/default", |
203 |
|
|
Append_false); |
204 |
|
|
|
205 |
|
|
#if defined __APPLE__ |
206 |
|
|
CFBundleRef mainBundle = CFBundleGetMainBundle(); |
207 |
|
|
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); |
208 |
|
|
char path[PATH_MAX]; |
209 |
|
|
if (!CFURLGetFileSystemRepresentation(resourcesURL, |
210 |
|
|
TRUE, |
211 |
|
|
reinterpret_cast<uint8_t*>(path), |
212 |
|
|
PATH_MAX)) |
213 |
|
|
{ |
214 |
|
|
fprintf(stderr, "Can't find Resources directory\n"); |
215 |
|
|
} |
216 |
|
|
CFRelease(resourcesURL); |
217 |
|
|
std::string path2 = pathJoin(path, "data"); |
218 |
|
|
VirtFs::mountDir(pathJoin(path2, "perserver/default"), Append_false); |
219 |
|
|
VirtFs::mountDir(path2, Append_false); |
220 |
|
|
// possible this need for support run client from dmg images. |
221 |
|
|
// mPackageDir = path; |
222 |
|
|
#endif // defined __APPLE__ |
223 |
|
|
|
224 |
|
|
VirtFs::mountDirSilent(PKG_DATADIR "data", Append_false); |
225 |
|
|
setPackageDir(PKG_DATADIR "data"); |
226 |
|
|
VirtFs::mountDirSilent("data", Append_false); |
227 |
|
|
|
228 |
|
|
#ifdef ANDROID |
229 |
|
|
#ifdef USE_SDL2 |
230 |
|
|
if (getenv("APPDIR")) |
231 |
|
|
{ |
232 |
|
|
const std::string appDir = getenv("APPDIR"); |
233 |
|
|
VirtFs::mountDir(appDir + "/data", Append_false); |
234 |
|
|
VirtFs::mountDir(appDir + "/data/perserver/default", |
235 |
|
|
Append_false); |
236 |
|
|
} |
237 |
|
|
#endif // USE_SDL2 |
238 |
|
|
#endif // ANDROID |
239 |
|
|
|
240 |
|
|
#if defined __native_client__ |
241 |
|
|
VirtFs::mountZip("/http/data.zip", Append_false); |
242 |
|
|
VirtFs::mountZip2("/http/data.zip", |
243 |
|
|
"perserver/default", |
244 |
|
|
Append_false); |
245 |
|
|
#endif // defined __native_client__ |
246 |
|
|
|
247 |
|
|
#ifndef WIN32 |
248 |
|
|
// Add branding/data to VirtFS search path |
249 |
|
|
if (!settings.options.brandingPath.empty()) |
250 |
|
|
{ |
251 |
|
|
std::string path = settings.options.brandingPath; |
252 |
|
|
|
253 |
|
|
// Strip blah.manaplus from the path |
254 |
|
|
const int loc = CAST_S32(path.find_last_of('/')); |
255 |
|
|
|
256 |
|
|
if (loc > 0) |
257 |
|
|
{ |
258 |
|
|
VirtFs::mountDir(path.substr( |
259 |
|
|
0, loc + 1).append("data"), |
260 |
|
|
Append_false); |
261 |
|
|
} |
262 |
|
|
} |
263 |
|
|
#endif // WIN32 |
264 |
|
|
} |
265 |
|
|
|
266 |
|
302 |
void Dirs::initRootDir() |
267 |
|
|
{ |
268 |
|
604 |
settings.rootDir = VirtFs::getBaseDir(); |
269 |
|
604 |
const std::string portableName = settings.rootDir + "portable.xml"; |
270 |
|
|
struct stat statbuf; |
271 |
|
|
|
272 |
✗✓✗✗ ✗✓ |
604 |
if (stat(portableName.c_str(), &statbuf) == 0 && |
273 |
|
|
S_ISREG(statbuf.st_mode)) |
274 |
|
|
{ |
275 |
|
|
std::string dir; |
276 |
|
|
Configuration portable; |
277 |
|
|
portable.init(portableName, |
278 |
|
|
UseVirtFs_false, |
279 |
|
|
SkipError_false); |
280 |
|
|
|
281 |
|
|
if (settings.options.brandingPath.empty()) |
282 |
|
|
{ |
283 |
|
|
branding.init(portableName, |
284 |
|
|
UseVirtFs_false, |
285 |
|
|
SkipError_false); |
286 |
|
|
setBrandingDefaults(branding); |
287 |
|
|
} |
288 |
|
|
|
289 |
|
|
logger->log("Portable file: %s", portableName.c_str()); |
290 |
|
|
|
291 |
|
|
if (settings.options.localDataDir.empty()) |
292 |
|
|
{ |
293 |
|
|
dir = portable.getValue("dataDir", ""); |
294 |
|
|
if (!dir.empty()) |
295 |
|
|
{ |
296 |
|
|
settings.options.localDataDir = settings.rootDir + dir; |
297 |
|
|
logger->log("Portable data dir: %s", |
298 |
|
|
settings.options.localDataDir.c_str()); |
299 |
|
|
} |
300 |
|
|
} |
301 |
|
|
|
302 |
|
|
if (settings.options.configDir.empty()) |
303 |
|
|
{ |
304 |
|
|
dir = portable.getValue("configDir", ""); |
305 |
|
|
if (!dir.empty()) |
306 |
|
|
{ |
307 |
|
|
settings.options.configDir = settings.rootDir + dir; |
308 |
|
|
logger->log("Portable config dir: %s", |
309 |
|
|
settings.options.configDir.c_str()); |
310 |
|
|
} |
311 |
|
|
} |
312 |
|
|
|
313 |
|
|
if (settings.options.screenshotDir.empty()) |
314 |
|
|
{ |
315 |
|
|
dir = portable.getValue("screenshotDir", ""); |
316 |
|
|
if (!dir.empty()) |
317 |
|
|
{ |
318 |
|
|
settings.options.screenshotDir = settings.rootDir + dir; |
319 |
|
|
logger->log("Portable screenshot dir: %s", |
320 |
|
|
settings.options.screenshotDir.c_str()); |
321 |
|
|
} |
322 |
|
|
} |
323 |
|
|
} |
324 |
|
302 |
} |
325 |
|
|
|
326 |
|
|
/** |
327 |
|
|
* Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On |
328 |
|
|
* Windows and other systems we use the current working directory. |
329 |
|
|
*/ |
330 |
|
302 |
void Dirs::initHomeDir() |
331 |
|
|
{ |
332 |
|
302 |
initLocalDataDir(); |
333 |
|
302 |
initTempDir(); |
334 |
|
302 |
initConfigDir(); |
335 |
|
302 |
} |
336 |
|
|
|
337 |
|
302 |
void Dirs::initLocalDataDir() |
338 |
|
|
{ |
339 |
|
302 |
settings.localDataDir = settings.options.localDataDir; |
340 |
|
|
|
341 |
✓✗ |
302 |
if (settings.localDataDir.empty()) |
342 |
|
|
{ |
343 |
|
|
#ifdef __APPLE__ |
344 |
|
|
// Use Application Directory instead of .mana |
345 |
|
|
settings.localDataDir = pathJoin(VirtFs::getUserDir(), |
346 |
|
|
"Library/Application Support", |
347 |
|
|
branding.getValue("appName", "ManaPlus")); |
348 |
|
|
#elif defined __HAIKU__ |
349 |
|
|
settings.localDataDir = pathJoin(VirtFs::getUserDir(), |
350 |
|
|
"config/cache/Mana"); |
351 |
|
|
#elif defined WIN32 |
352 |
|
|
settings.localDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA); |
353 |
|
|
if (settings.localDataDir.empty()) |
354 |
|
|
settings.localDataDir = VirtFs::getUserDir(); |
355 |
|
|
settings.localDataDir = pathJoin(settings.localDataDir, |
356 |
|
|
"Mana"); |
357 |
|
|
#elif defined __ANDROID__ |
358 |
|
|
settings.localDataDir = pathJoin(getSdStoragePath(), |
359 |
|
|
branding.getValue("appShort", "ManaPlus"), |
360 |
|
|
"local"); |
361 |
|
|
#elif defined __native_client__ |
362 |
|
|
settings.localDataDir = pathJoin(_nacl_dir, "local"); |
363 |
|
|
#elif defined __SWITCH__ |
364 |
|
|
settings.localDataDir = pathJoin(VirtFs::getUserDir(), "local"); |
365 |
|
|
#else // __APPLE__ |
366 |
|
|
|
367 |
✓✗✓✗ ✓✗ |
2416 |
settings.localDataDir = pathJoin(VirtFs::getUserDir(), |
368 |
|
302 |
".local/share/mana"); |
369 |
|
|
#endif // __APPLE__ |
370 |
|
|
} |
371 |
|
|
|
372 |
✗✓ |
302 |
if (mkdir_r(settings.localDataDir.c_str()) != 0) |
373 |
|
|
{ |
374 |
|
|
// TRANSLATORS: directory creation error |
375 |
|
|
logger->error(strprintf(_("%s doesn't exist and can't be created! " |
376 |
|
|
"Exiting."), settings.localDataDir.c_str())); |
377 |
|
|
} |
378 |
|
|
#ifdef USE_PROFILER |
379 |
|
|
Perfomance::init(pathJoin(settings.localDataDir, "profiler.log")); |
380 |
|
|
#endif // USE_PROFILER |
381 |
|
302 |
} |
382 |
|
|
|
383 |
|
302 |
void Dirs::initTempDir() |
384 |
|
|
{ |
385 |
✓✗ |
2114 |
settings.tempDir = pathJoin(settings.localDataDir, "temp"); |
386 |
|
|
|
387 |
✗✓ |
302 |
if (mkdir_r(settings.tempDir.c_str()) != 0) |
388 |
|
|
{ |
389 |
|
|
// TRANSLATORS: directory creation error |
390 |
|
|
logger->error(strprintf(_("%s doesn't exist and can't be created! " |
391 |
|
|
"Exiting."), settings.tempDir.c_str())); |
392 |
|
|
} |
393 |
|
|
// ResourceManager::deleteFilesInDirectory(settings.tempDir); |
394 |
|
302 |
} |
395 |
|
|
|
396 |
|
302 |
void Dirs::initConfigDir() |
397 |
|
|
{ |
398 |
|
302 |
settings.configDir = settings.options.configDir; |
399 |
|
|
|
400 |
✓✗ |
302 |
if (settings.configDir.empty()) |
401 |
|
|
{ |
402 |
|
|
#ifdef __APPLE__ |
403 |
|
|
settings.configDir = pathJoin(settings.localDataDir, |
404 |
|
|
branding.getValue("appShort", "mana")); |
405 |
|
|
#elif defined __HAIKU__ |
406 |
|
|
settings.configDir = pathJoin(VirtFs::getUserDir(), |
407 |
|
|
"config/settings/Mana", |
408 |
|
|
branding.getValue("appName", "ManaPlus")); |
409 |
|
|
#elif defined WIN32 |
410 |
|
|
settings.configDir = getSpecialFolderLocation(CSIDL_APPDATA); |
411 |
|
|
if (settings.configDir.empty()) |
412 |
|
|
{ |
413 |
|
|
settings.configDir = settings.localDataDir; |
414 |
|
|
} |
415 |
|
|
else |
416 |
|
|
{ |
417 |
|
|
settings.configDir = pathJoin(settings.configDir, |
418 |
|
|
"mana", |
419 |
|
|
branding.getValue("appShort", "mana")); |
420 |
|
|
} |
421 |
|
|
#elif defined __ANDROID__ |
422 |
|
|
settings.configDir = pathJoin(getSdStoragePath(), |
423 |
|
|
branding.getValue("appShort", "ManaPlus"), |
424 |
|
|
"config"); |
425 |
|
|
#elif defined __native_client__ |
426 |
|
|
settings.configDir = pathJoin(_nacl_dir, "config"); |
427 |
|
|
#elif defined __SWITCH__ |
428 |
|
|
settings.configDir = pathJoin(VirtFs::getUserDir(), "config"); |
429 |
|
|
#else // __APPLE__ |
430 |
|
|
|
431 |
✓✗✓✗ ✓✗✓✗
|
2416 |
settings.configDir = pathJoin(VirtFs::getUserDir(), |
432 |
|
|
".config/mana", |
433 |
✓✗✓✗
|
2718 |
branding.getValue("appShort", "mana")); |
434 |
|
|
#endif // __APPLE__ |
435 |
|
|
|
436 |
✓✗ |
604 |
logger->log("Generating config dir: " + settings.configDir); |
437 |
|
|
} |
438 |
|
|
|
439 |
✗✓ |
302 |
if (mkdir_r(settings.configDir.c_str()) != 0) |
440 |
|
|
{ |
441 |
|
|
// TRANSLATORS: directory creation error |
442 |
|
|
logger->error(strprintf(_("%s doesn't exist and can't be created! " |
443 |
|
|
"Exiting."), settings.configDir.c_str())); |
444 |
|
|
} |
445 |
|
302 |
} |
446 |
|
|
|
447 |
|
|
/** |
448 |
|
|
* Parse the update host and determine the updates directory |
449 |
|
|
* Then verify that the directory exists (creating if needed). |
450 |
|
|
*/ |
451 |
|
|
void Dirs::initUpdatesDir() |
452 |
|
|
{ |
453 |
|
|
std::stringstream updates; |
454 |
|
|
|
455 |
|
|
// If updatesHost is currently empty, fill it from config file |
456 |
|
|
if (settings.updateHost.empty()) |
457 |
|
|
settings.updateHost = config.getStringValue("updatehost"); |
458 |
|
|
if (!checkPath(settings.updateHost)) |
459 |
|
|
return; |
460 |
|
|
|
461 |
|
|
// Don't go out of range int he next check |
462 |
|
|
if (settings.updateHost.length() < 2) |
463 |
|
|
{ |
464 |
|
|
if (settings.updatesDir.empty()) |
465 |
|
|
settings.updatesDir = pathJoin("updates", settings.serverName); |
466 |
|
|
return; |
467 |
|
|
} |
468 |
|
|
|
469 |
|
|
const size_t sz = settings.updateHost.size(); |
470 |
|
|
// Remove any trailing slash at the end of the update host |
471 |
|
|
if (settings.updateHost.at(sz - 1) == '/') |
472 |
|
|
settings.updateHost.resize(sz - 1); |
473 |
|
|
|
474 |
|
|
// Parse out any "http://" or "https://", and set the updates directory |
475 |
|
|
const size_t pos = settings.updateHost.find("://"); |
476 |
|
|
if (pos != std::string::npos) |
477 |
|
|
{ |
478 |
|
|
if (pos + 3 < settings.updateHost.length() |
479 |
|
|
&& !settings.updateHost.empty()) |
480 |
|
|
{ |
481 |
|
|
updates << "updates/" << settings.updateHost.substr(pos + 3); |
482 |
|
|
settings.updatesDir = updates.str(); |
483 |
|
|
} |
484 |
|
|
else |
485 |
|
|
{ |
486 |
|
|
logger->log("Error: Invalid update host: %s", |
487 |
|
|
settings.updateHost.c_str()); |
488 |
|
|
// TRANSLATORS: update server initialisation error |
489 |
|
|
errorMessage = strprintf(_("Invalid update host: %s."), |
490 |
|
|
settings.updateHost.c_str()); |
491 |
|
|
client->setState(State::ERROR); |
492 |
|
|
} |
493 |
|
|
} |
494 |
|
|
else |
495 |
|
|
{ |
496 |
|
|
logger->log1("Warning: no protocol was specified for the update host"); |
497 |
|
|
updates << "updates/" << settings.updateHost; |
498 |
|
|
settings.updatesDir = updates.str(); |
499 |
|
|
} |
500 |
|
|
|
501 |
|
|
#ifdef WIN32 |
502 |
|
|
if (settings.updatesDir.find(":") != std::string::npos) |
503 |
|
|
replaceAll(settings.updatesDir, ":", "_"); |
504 |
|
|
#endif // WIN32 |
505 |
|
|
|
506 |
|
|
const std::string updateDir("/" + settings.updatesDir); |
507 |
|
|
|
508 |
|
|
// Verify that the updates directory exists. Create if necessary. |
509 |
|
|
if (!VirtFs::isDirectory(updateDir)) |
510 |
|
|
{ |
511 |
|
|
if (!VirtFs::mkdir(updateDir)) |
512 |
|
|
{ |
513 |
|
|
#if defined WIN32 |
514 |
|
|
std::string newDir = pathJoin(settings.localDataDir, |
515 |
|
|
settings.updatesDir); |
516 |
|
|
if (!CreateDirectory(newDir.c_str(), nullptr) && |
517 |
|
|
GetLastError() != ERROR_ALREADY_EXISTS) |
518 |
|
|
{ |
519 |
|
|
logger->log("Error: %s can't be made, but doesn't exist!", |
520 |
|
|
newDir.c_str()); |
521 |
|
|
// TRANSLATORS: update server initialisation error |
522 |
|
|
errorMessage = _("Error creating updates directory!"); |
523 |
|
|
client->setState(State::ERROR); |
524 |
|
|
} |
525 |
|
|
#else // defined WIN32 |
526 |
|
|
|
527 |
|
|
logger->log("Error: %s/%s can't be made, but doesn't exist!", |
528 |
|
|
settings.localDataDir.c_str(), |
529 |
|
|
settings.updatesDir.c_str()); |
530 |
|
|
// TRANSLATORS: update server initialisation error |
531 |
|
|
errorMessage = _("Error creating updates directory!"); |
532 |
|
|
client->setState(State::ERROR); |
533 |
|
|
#endif // defined WIN32 |
534 |
|
|
} |
535 |
|
|
} |
536 |
|
|
const std::string updateLocal = pathJoin(updateDir, "local"); |
537 |
|
|
const std::string updateFix = pathJoin(updateDir, "fix"); |
538 |
|
|
if (!VirtFs::isDirectory(updateLocal)) |
539 |
|
|
VirtFs::mkdir(updateLocal); |
540 |
|
|
if (!VirtFs::isDirectory(updateFix)) |
541 |
|
|
VirtFs::mkdir(updateFix); |
542 |
|
|
} |
543 |
|
|
|
544 |
|
|
void Dirs::initScreenshotDir() |
545 |
|
|
{ |
546 |
|
|
if (!settings.options.screenshotDir.empty()) |
547 |
|
|
{ |
548 |
|
|
settings.screenshotDir = settings.options.screenshotDir; |
549 |
|
|
if (mkdir_r(settings.screenshotDir.c_str()) != 0) |
550 |
|
|
{ |
551 |
|
|
logger->log(strprintf( |
552 |
|
|
// TRANSLATORS: directory creation error |
553 |
|
|
_("Error: %s doesn't exist and can't be created! " |
554 |
|
|
"Exiting."), settings.screenshotDir.c_str())); |
555 |
|
|
} |
556 |
|
|
} |
557 |
|
|
else if (settings.screenshotDir.empty()) |
558 |
|
|
{ |
559 |
|
|
#ifdef __native_client__ |
560 |
|
|
settings.screenshotDir = pathJoin(_nacl_dir, "screenshots/"); |
561 |
|
|
#else // __native_client__ |
562 |
|
|
settings.screenshotDir = decodeBase64String( |
563 |
|
|
config.getStringValue("screenshotDirectory3")); |
564 |
|
|
if (settings.screenshotDir.empty()) |
565 |
|
|
{ |
566 |
|
|
#ifdef __ANDROID__ |
567 |
|
|
settings.screenshotDir = getSdStoragePath() |
568 |
|
|
+ std::string("/images"); |
569 |
|
|
|
570 |
|
|
if (mkdir_r(settings.screenshotDir.c_str())) |
571 |
|
|
{ |
572 |
|
|
logger->log(strprintf( |
573 |
|
|
// TRANSLATORS: directory creation error |
574 |
|
|
_("Error: %s doesn't exist and can't be created! " |
575 |
|
|
"Exiting."), settings.screenshotDir.c_str())); |
576 |
|
|
} |
577 |
|
|
#else // ANDROID |
578 |
|
|
settings.screenshotDir = getPicturesDir(); |
579 |
|
|
#endif // ANDROID |
580 |
|
|
if (config.getBoolValue("useScreenshotDirectorySuffix")) |
581 |
|
|
{ |
582 |
|
|
const std::string configScreenshotSuffix = |
583 |
|
|
branding.getValue("screenshots", "ManaPlus"); |
584 |
|
|
|
585 |
|
|
if (!configScreenshotSuffix.empty()) |
586 |
|
|
{ |
587 |
|
|
settings.screenshotDir = pathJoin(settings.screenshotDir, |
588 |
|
|
configScreenshotSuffix); |
589 |
|
|
} |
590 |
|
|
} |
591 |
|
|
config.setValue("screenshotDirectory3", |
592 |
|
|
encodeBase64String(settings.screenshotDir)); |
593 |
|
|
} |
594 |
|
|
#endif // __native_client__ |
595 |
|
|
} |
596 |
|
|
logger->log("screenshotDirectory: " + settings.screenshotDir); |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
void Dirs::initUsersDir() |
600 |
|
|
{ |
601 |
|
|
settings.usersDir = settings.serverConfigDir + "/users/"; |
602 |
|
|
if (mkdir_r(settings.usersDir.c_str()) != 0) |
603 |
|
|
{ |
604 |
|
|
// TRANSLATORS: directory creation error |
605 |
|
|
logger->error(strprintf(_("%s doesn't exist and can't be created!"), |
606 |
|
|
settings.usersDir.c_str())); |
607 |
|
|
} |
608 |
|
|
|
609 |
|
|
settings.npcsDir = settings.serverConfigDir + "/npcs/"; |
610 |
|
|
if (mkdir_r(settings.npcsDir.c_str()) != 0) |
611 |
|
|
{ |
612 |
|
|
// TRANSLATORS: directory creation error |
613 |
|
|
logger->error(strprintf(_("%s doesn't exist and can't be created!"), |
614 |
|
|
settings.npcsDir.c_str())); |
615 |
|
|
} |
616 |
|
|
|
617 |
|
|
settings.usersIdDir = settings.serverConfigDir + "/usersid/"; |
618 |
|
|
if (mkdir_r(settings.usersIdDir.c_str()) != 0) |
619 |
|
|
{ |
620 |
|
|
// TRANSLATORS: directory creation error |
621 |
|
|
logger->error(strprintf(_("%s doesn't exist and can't be created!"), |
622 |
|
|
settings.usersIdDir.c_str())); |
623 |
|
|
} |
624 |
|
|
} |