GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/configmanager.cpp Lines: 58 206 28.2 %
Date: 2017-11-29 Branches: 65 598 10.9 %

Line Branch Exec Source
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-2017  The ManaPlus Developers
6
 *
7
 *  This file is part of The ManaPlus Client.
8
 *
9
 *  This program is free software; you can redistribute it and/or modify
10
 *  it under the terms of the GNU General Public License as published by
11
 *  the Free Software Foundation; either version 2 of the License, or
12
 *  any later version.
13
 *
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU General Public License for more details.
18
 *
19
 *  You should have received a copy of the GNU General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 */
22
23
#include "configmanager.h"
24
25
#include "client.h"
26
#include "configuration.h"
27
#include "settings.h"
28
29
#include "being/beingspeech.h"
30
31
#include "fs/files.h"
32
#include "fs/mkdir.h"
33
#include "fs/paths.h"
34
35
#include "utils/cast.h"
36
#include "utils/checkutils.h"
37
#include "utils/gettext.h"
38
39
#include "render/renderers.h"
40
41
#include "debug.h"
42
43
304
static void setDefaultOption(const char *const name,
44
                             const bool def)
45
{
46

1216
    const int val = serverConfig.getValue(name, -1);
47
304
    if (val == -1)
48
1520
        serverConfig.setValue(name, def);
49
304
}
50
51
/**
52
 * Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On
53
 * Windows and other systems we use the current working directory.
54
 */
55
152
void ConfigManager::initServerConfig(const std::string &serverName)
56
{
57
456
    settings.serverConfigDir = pathJoin(settings.configDir, serverName);
58
59
152
    if (mkdir_r(settings.serverConfigDir.c_str()) != 0)
60
    {
61
        // TRANSLATORS: directory creation error
62
        logger->error(strprintf(_("%s doesn't exist and can't be created! "
63
            "Exiting."), settings.serverConfigDir.c_str()));
64
    }
65
304
    const std::string configPath = settings.serverConfigDir + "/config.xml";
66
152
    FILE *configFile = fopen(configPath.c_str(), "r");
67
152
    if (configFile == nullptr)
68
    {
69
152
        configFile = fopen(configPath.c_str(), "wb");
70

304
        logger->log("Creating new server config: " + configPath);
71
152
        if (configFile != nullptr)
72
        {
73
152
            fputs("<?xml version=\"1.0\"?>\n", configFile);
74
152
            fputs("<configuration>\n", configFile);
75
152
            fputs("</configuration>\n", configFile);
76
        }
77
    }
78
152
    if (configFile != nullptr)
79
    {
80
152
        fclose(configFile);
81
152
        serverConfig.init(configPath);
82
152
        setConfigDefaults(serverConfig);
83

304
        logger->log("serverConfigPath: " + configPath);
84
    }
85
    else
86
    {
87
        reportAlways("Error creating server config: %s",
88
            configPath.c_str());
89
    }
90
91
304
    const bool val = Client::isTmw();
92
152
    setDefaultOption("enableManaMarketBot", val);
93
152
    setDefaultOption("enableRemoteCommands", !val);
94
152
}
95
96
558
void ConfigManager::initConfiguration()
97
{
98
#ifdef DEBUG_CONFIG
99
    config.setIsMain(true);
100
#endif  // DEBUG_CONFIG
101
102
    // Fill configuration with defaults
103
2790
    config.setValue("hwaccel", false);
104
#ifdef USE_OPENGL
105
#if (defined __APPLE__)
106
    config.setValue("opengl", CAST_S32(RENDER_NORMAL_OPENGL));
107
#elif (defined ANDROID)
108
    config.setValue("opengl", CAST_S32(RENDER_GLES_OPENGL));
109
#elif (defined WIN32)
110
    config.setValue("opengl", CAST_S32(RENDER_SAFE_OPENGL));
111
#else  // (defined __APPLE__)
112
113

2232
    config.setValue("opengl", CAST_S32(RENDER_SOFTWARE));
114
#endif  // (defined __APPLE__)
115
#else  // USE_OPENGL
116
117
    config.setValue("opengl", CAST_S32(RENDER_SOFTWARE));
118
#endif  // USE_OPENGL
119
120
2790
    config.setValue("screen", false);
121
2790
    config.setValue("sound", true);
122

2232
    config.setValue("guialpha", 0.8F);
123
//    config.setValue("remember", true);
124

2232
    config.setValue("sfxVolume", 100);
125

2232
    config.setValue("musicVolume", 60);
126

2232
    config.setValue("fpslimit", 60);
127

4464
    std::string defaultUpdateHost = branding.getValue("defaultUpdateHost", "");
128

558
    if (!checkPath(defaultUpdateHost))
129
        defaultUpdateHost.clear();
130

2232
    config.setValue("updatehost", defaultUpdateHost);
131
2232
    config.setValue("useScreenshotDirectorySuffix", true);
132

2232
    config.setValue("ChatLogLength", 128);
133
134
1116
    std::string configPath;
135
136
#ifndef UNITTESTS
137
    if (settings.options.test.empty())
138
        configPath = settings.configDir + "/config.xml";
139
    else
140
        configPath = settings.configDir + "/test.xml";
141
#else  // UNITTESTS
142
143
1116
    configPath = settings.configDir + "/unittestconfig.xml";
144
#endif  // UNITTESTS
145
146
558
    FILE *configFile = fopen(configPath.c_str(), "r");
147
558
    if (configFile == nullptr)
148
    {
149
1
        configFile = fopen(configPath.c_str(), "wb");
150
1
        logger->log1("Creating new config");
151
1
        if (configFile != nullptr)
152
        {
153
1
            fputs("<?xml version=\"1.0\"?>\n", configFile);
154
1
            fputs("<configuration>\n", configFile);
155
1
            fputs("</configuration>\n", configFile);
156
        }
157
    }
158
558
    if (configFile == nullptr)
159
    {
160
        reportAlways("Can't create %s. Using defaults.",
161
            configPath.c_str());
162
    }
163
    else
164
    {
165
558
        fclose(configFile);
166
558
        config.init(configPath);
167
558
        logger->log1("init 3");
168
558
        setConfigDefaults(config);
169
558
        setConfigDefaults(serverConfig);
170

1116
        logger->log("configuration file: " + configPath);
171
    }
172
558
}
173
174
void ConfigManager::backupConfig(const std::string &name)
175
{
176
    const std::string fileName3 = pathJoin(settings.configDir, name);
177
    StringVect arr;
178
    if (Files::existsLocal(fileName3) == false)
179
    {
180
        logger->log("Config %s not exists, backup skipped.",
181
            name.c_str());
182
        return;
183
    }
184
    if (Files::loadTextFileLocal(fileName3, arr) == true)
185
    {
186
        if (arr.empty())
187
            return;
188
189
        arr.clear();
190
        const std::string tmpName = pathJoin(settings.configDir,
191
            name).append(".tmp");
192
        Files::copyFile(fileName3, tmpName);
193
        if (Files::loadTextFileLocal(tmpName, arr) == false ||
194
            arr.empty())
195
        {
196
            logger->safeError("Error backuping configs. "
197
                "Probably no free space on disk.");
198
        }
199
        arr.clear();
200
    }
201
202
    const std::string confName = pathJoin(settings.configDir,
203
        name).append(".bak");
204
    const int maxFileIndex = 5;
205
    ::remove((confName + toString(maxFileIndex)).c_str());
206
    for (int f = maxFileIndex; f > 1; f --)
207
    {
208
        const std::string fileName1 = confName + toString(f - 1);
209
        const std::string fileName2 = confName + toString(f);
210
        Files::renameFile(fileName1, fileName2);
211
    }
212
    const std::string fileName4 = confName + toString(1);
213
    Files::copyFile(fileName3, fileName4);
214
}
215
216
#ifdef __native_client__
217
void ConfigManager::storeSafeParameters()
218
{
219
    RenderType tmpOpengl;
220
221
    isSafeMode = config.getBoolValue("safemode");
222
    if (isSafeMode)
223
        logger->log1("Run in safe mode");
224
225
    tmpOpengl = intToRenderType(config.getIntValue("opengl"));
226
227
    config.setValue("opengl", CAST_S32(RENDER_SOFTWARE));
228
229
    config.write();
230
231
    if (settings.options.safeMode)
232
    {
233
        isSafeMode = true;
234
        return;
235
    }
236
237
    config.setValue("safemode", false);
238
    config.setValue("opengl", CAST_S32(tmpOpengl));
239
}
240
#elif !defined(ANDROID)
241
void ConfigManager::storeSafeParameters()
242
{
243
    bool tmpHwaccel;
244
    RenderType tmpOpengl;
245
    int tmpFpslimit;
246
    int tmpAltFpslimit;
247
    bool tmpSound;
248
    int width;
249
    int height;
250
    std::string font;
251
    std::string bFont;
252
    std::string particleFont;
253
    std::string helpFont;
254
    std::string secureFont;
255
    std::string npcFont;
256
    std::string japanFont;
257
    std::string chinaFont;
258
    bool showBackground;
259
    bool enableMumble;
260
    bool enableMapReduce;
261
262
    isSafeMode = config.getBoolValue("safemode");
263
    if (isSafeMode)
264
        logger->log1("Run in safe mode");
265
266
    tmpOpengl = intToRenderType(config.getIntValue("opengl"));
267
268
    width = config.getIntValue("screenwidth");
269
    height = config.getIntValue("screenheight");
270
    tmpHwaccel = config.getBoolValue("hwaccel");
271
272
    tmpFpslimit = config.getIntValue("fpslimit");
273
    tmpAltFpslimit = config.getIntValue("altfpslimit");
274
    tmpSound = config.getBoolValue("sound");
275
276
    font = config.getStringValue("font");
277
    bFont = config.getStringValue("boldFont");
278
    particleFont = config.getStringValue("particleFont");
279
    helpFont = config.getStringValue("helpFont");
280
    secureFont = config.getStringValue("secureFont");
281
    npcFont = config.getStringValue("npcFont");
282
    japanFont = config.getStringValue("japanFont");
283
    chinaFont = config.getStringValue("chinaFont");
284
285
    showBackground = config.getBoolValue("showBackground");
286
    enableMumble = config.getBoolValue("enableMumble");
287
    enableMapReduce = config.getBoolValue("enableMapReduce");
288
289
    if (!settings.options.safeMode && tmpOpengl == RENDER_SOFTWARE)
290
    {
291
        // if video mode configured reset most settings to safe
292
        config.setValue("hwaccel", false);
293
        config.setValue("altfpslimit", 3);
294
        config.setValue("sound", false);
295
        config.setValue("safemode", true);
296
        config.setValue("screenwidth", 640);
297
        config.setValue("screenheight", 480);
298
        config.setValue("font", "fonts/dejavusans.ttf");
299
        config.setValue("boldFont", "fonts/dejavusans-bold.ttf");
300
        config.setValue("particleFont", "fonts/dejavusans.ttf");
301
        config.setValue("helpFont", "fonts/dejavusansmono.ttf");
302
        config.setValue("secureFont", "fonts/dejavusansmono.ttf");
303
        config.setValue("npcFont", "fonts/dejavusans.ttf");
304
        config.setValue("japanFont", "fonts/mplus-1p-regular.ttf");
305
        config.setValue("chinaFont", "fonts/wqy-microhei.ttf");
306
        config.setValue("showBackground", false);
307
        config.setValue("enableMumble", false);
308
        config.setValue("enableMapReduce", false);
309
    }
310
    else
311
    {
312
        // if video mode not configured reset only video mode to safe
313
        config.setValue("screenwidth", 640);
314
        config.setValue("screenheight", 480);
315
    }
316
#if defined(__APPLE__)
317
    config.setValue("opengl", CAST_S32(RENDER_NORMAL_OPENGL));
318
#else  // defined(__APPLE__)
319
320
    config.setValue("opengl", CAST_S32(RENDER_SOFTWARE));
321
#endif  // defined(__APPLE__)
322
323
    config.write();
324
325
    if (settings.options.safeMode)
326
    {
327
        isSafeMode = true;
328
        return;
329
    }
330
331
    config.setValue("safemode", false);
332
    if (tmpOpengl == RENDER_SOFTWARE)
333
    {
334
        config.setValue("hwaccel", tmpHwaccel);
335
        config.setValue("opengl", CAST_S32(tmpOpengl));
336
        config.setValue("fpslimit", tmpFpslimit);
337
        config.setValue("altfpslimit", tmpAltFpslimit);
338
        config.setValue("sound", tmpSound);
339
        config.setValue("screenwidth", width);
340
        config.setValue("screenheight", height);
341
        config.setValue("font", font);
342
        config.setValue("boldFont", bFont);
343
        config.setValue("particleFont", particleFont);
344
        config.setValue("helpFont", helpFont);
345
        config.setValue("secureFont", secureFont);
346
        config.setValue("npcFont", npcFont);
347
        config.setValue("japanFont", japanFont);
348
        config.setValue("chinaFont", chinaFont);
349
        config.setValue("showBackground", showBackground);
350
        config.setValue("enableMumble", enableMumble);
351
        config.setValue("enableMapReduce", enableMapReduce);
352
    }
353
    else
354
    {
355
        config.setValue("opengl", CAST_S32(tmpOpengl));
356
        config.setValue("screenwidth", width);
357
        config.setValue("screenheight", height);
358
    }
359
}
360
#endif  // __native_client__
361
362
#define unassignKey(key, value) \
363
    if (config.getStringValue(prefix + key) == value) \
364
        config.setValue(key, "-1");
365
366
void ConfigManager::checkConfigVersion()
367
{
368
    const int version = config.getIntValue("cfgver");
369
    if (version < 1)
370
    {
371
        if (config.getIntValue("fontSize") == 11)
372
            config.deleteKey("fontSize");
373
        if (config.getIntValue("npcfontSize") == 13)
374
            config.deleteKey("npcfontSize");
375
    }
376
    if (version < 2)
377
    {
378
        if (config.getIntValue("screenButtonsSize") == 1)
379
            config.deleteKey("screenButtonsSize");
380
        if (config.getIntValue("screenJoystickSize") == 1)
381
            config.deleteKey("screenJoystickSize");
382
    }
383
    if (version < 3)
384
    {
385
        config.setValue("audioFrequency", 44100);
386
#ifdef ANDROID
387
        config.setValue("customcursor", false);
388
#endif  // ANDROID
389
    }
390
#ifdef ANDROID
391
    if (version < 4)
392
    {
393
        config.setValue("showDidYouKnow", false);
394
    }
395
#endif  // ANDROID
396
397
    if (version < 5)
398
    {
399
        if (config.getIntValue("speech") == BeingSpeech::TEXT_OVERHEAD)
400
        {
401
            config.setValue("speech", CAST_S32(
402
                BeingSpeech::NO_NAME_IN_BUBBLE));
403
        }
404
    }
405
    if (version < 6)
406
        config.setValue("blur", false);
407
408
    if (version < 7)
409
        config.setValue("download-music", true);
410
411
    if (version < 9)
412
    {
413
        config.deleteKey("videodetected");
414
        config.setValue("moveToTargetType", 10);
415
    }
416
    if (version < 10)
417
        config.setValue("enableLazyScrolling", false);
418
419
    if (version < 11)
420
    {
421
#ifdef USE_SDL2
422
        const std::string prefix = std::string("sdl2");
423
#else  // USE_SDL2
424
425
        const std::string prefix = std::string();
426
#endif  // USE_SDL2
427
428
        unassignKey("keyDirectUp", "k108");
429
        unassignKey("keyDirectDown", "k59");
430
        unassignKey("keyDirectLeft", "k107");
431
        unassignKey("keyDirectRight", "k39");
432
    }
433
    if (version < 12)
434
    {
435
#ifdef USE_SDL2
436
        const std::string prefix = std::string("sdl2");
437
#else  // USE_SDL2
438
439
        const std::string prefix = std::string();
440
#endif  // USE_SDL2
441
442
        unassignKey("keyAttack", "k120");
443
    }
444
445
    if (version < 13)
446
        config.setValue("keyWindowBotChecker", -1);
447
448
    if (version < 14 && config.getIntValue("syncPlayerMoveDistance") == 2)
449
        config.setValue("syncPlayerMoveDistance", 5);
450
    config.setValue("cfgver", 14);
451
}
452
453
#undef unassignKey