GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/configmanager.cpp Lines: 58 210 27.6 %
Date: 2018-07-14 Branches: 54 542 10.0 %

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-2018  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
154
static void setDefaultOption(const char *const name,
44
                             const bool def)
45
{
46
616
    const int val = serverConfig.getValue(name, -1);
47
154
    if (val == -1)
48
770
        serverConfig.setValue(name, def);
49
154
}
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
77
void ConfigManager::initServerConfig(const std::string &serverName)
56
{
57
231
    settings.serverConfigDir = pathJoin(settings.configDir, serverName);
58
59
77
    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
154
    const std::string configPath = settings.serverConfigDir + "/config.xml";
66
77
    FILE *configFile = fopen(configPath.c_str(), "r");
67
77
    if (configFile == nullptr)
68
    {
69
77
        configFile = fopen(configPath.c_str(), "wb");
70

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

154
        logger->log("serverConfigPath: " + configPath);
86
    }
87
    else
88
    {
89
        reportAlways("Error creating server config: %s",
90
            configPath.c_str());
91
    }
92
93
154
    const bool val = Client::isTmw();
94
77
    setDefaultOption("enableManaMarketBot", val);
95
77
    setDefaultOption("enableRemoteCommands", !val);
96
77
}
97
98
290
void ConfigManager::initConfiguration()
99
{
100
#ifdef DEBUG_CONFIG
101
    config.setIsMain(true);
102
#endif  // DEBUG_CONFIG
103
104
    // Fill configuration with defaults
105
1450
    config.setValue("hwaccel", false);
106
#ifdef USE_OPENGL
107
#if (defined __APPLE__)
108
    config.setValue("opengl", CAST_S32(RENDER_NORMAL_OPENGL));
109
#elif (defined ANDROID)
110
    config.setValue("opengl", CAST_S32(RENDER_GLES_OPENGL));
111
#elif (defined WIN32)
112
    config.setValue("opengl", CAST_S32(RENDER_SAFE_OPENGL));
113
#else  // (defined __APPLE__)
114
115
1160
    config.setValue("opengl", CAST_S32(RENDER_SOFTWARE));
116
#endif  // (defined __APPLE__)
117
#else  // USE_OPENGL
118
119
    config.setValue("opengl", CAST_S32(RENDER_SOFTWARE));
120
#endif  // USE_OPENGL
121
122
1450
    config.setValue("screen", false);
123
1450
    config.setValue("sound", true);
124
1160
    config.setValue("guialpha", 0.8F);
125
//    config.setValue("remember", true);
126
1160
    config.setValue("sfxVolume", 100);
127
1160
    config.setValue("musicVolume", 60);
128
1160
    config.setValue("fpslimit", 60);
129

2320
    std::string defaultUpdateHost = branding.getValue("defaultUpdateHost", "");
130

290
    if (!checkPath(defaultUpdateHost))
131
        defaultUpdateHost.clear();
132

1160
    config.setValue("updatehost", defaultUpdateHost);
133
1450
    config.setValue("useScreenshotDirectorySuffix", true);
134

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

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