Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 andreas 1
/*
21 andreas 2
 * Copyright (C) 2020, 2021 by Andreas Theofilu <andreas@theosys.at>
2 andreas 3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software Foundation,
16
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
17
 */
21 andreas 18
 
2 andreas 19
#include <fstream>
20
#include <vector>
21
#include <iterator>
22
#include <unistd.h>
21 andreas 23
#include <sys/stat.h>
24
#include <sys/types.h>
22 andreas 25
#ifdef __ANDROID__
134 andreas 26
#include <QUuid>
22 andreas 27
#include <android/log.h>
28
#include "tvalidatefile.h"
43 andreas 29
#include "tvalidatefile.h"
134 andreas 30
#else
31
#include <uuid/uuid.h>
22 andreas 32
#endif
118 andreas 33
#include "ttpinit.h"
22 andreas 34
#include "tconfig.h"
2 andreas 35
#include "terror.h"
73 andreas 36
#include "tresources.h"
2 andreas 37
 
38
using std::string;
39
using std::ifstream;
21 andreas 40
using std::ofstream;
2 andreas 41
using std::fstream;
42
using std::vector;
21 andreas 43
using std::cout;
44
using std::cerr;
45
using std::endl;
2 andreas 46
 
116 andreas 47
bool TConfig::mInitialized{false};
134 andreas 48
int TConfig::mChannel{0};
141 andreas 49
bool TConfig::mMute{false};
116 andreas 50
 
21 andreas 51
/**
52
 * @struct SETTINGS
53
 * @brief The SETTINGS struct bundles the configuration options.
54
 *
55
 * This structure contains variables for all possible configuration options.
56
 * It is used by the class TConfig. Through this class it's possible to
57
 * access all configuration options.
58
 */
2 andreas 59
struct SETTINGS
60
{
21 andreas 61
    string pname{"tpanel"};     //!< Name of the program (default "tpanel")
62
    string path;                //!< The path where the configuration file is located
63
    string name;                //!< The name of the configuration file
64
    string project;             //!< The path where the original project files are located
65
    string server;              //!< The name or IP address of the server to connect
66
    int system{0};              //!< The number of the AMX system
67
    int port{0};                //!< The port number
68
    int ID{0};                  //!< the panel ID (a number starting by 10000)
69
    string ptype;               //!< The type of the panel (android, ipad, iphone, ...)
70
    string version;             //!< The "firmware" version
71
    string logFile;             //!< Optional path and name of a logfile
72
    string logLevel;            //!< The log level(s).
71 andreas 73
    uint logLevelBits;          //!< The numeric bit field of the loglevel
21 andreas 74
    bool longformat{false};     //!< TRUE = long format
75
    bool noBanner{false};       //!< Startup without showing a banner on the command line.
76
    bool certCheck{false};      //!< TRUE = Check certificate for SSL connection
24 andreas 77
    bool scale{false};          //!< TRUE = Images are scaled to fit the whole screen
151 andreas 78
    bool tbsuppress{false};     //!< TRUE = Don't show toolbar even if enough space
79
    bool tbforce{true};         //!< Only if "tbsuppress" = FALSE: TRUE = The toolbar is forced to display, FALSE = The toolbar is only visible if there is enough space left
35 andreas 80
    bool profiling{false};      //!< TRUE = The declaration traces meassure the time and write it to the log
51 andreas 81
    string password1;           //!< First panel password
82
    string password2;           //!< Second panel password
83
    string password3;           //!< Third panel password
84
    string password4;           //!< Fourth panel password
134 andreas 85
    bool systemRotationFix{false};  //!< TRUE = Rotation is blocked and orientation sensor is ignored.
86
    string uuid;                //!< An UUID set automatically after first start.
112 andreas 87
    // FTP credentials
88
    string ftpUser;             //!< The username for FTP of the controller (default: administrator)
89
    string ftpPassword;         //!< The password for FTP of the controller (default: password)
115 andreas 90
    string ftpSurface;          //!< The name of the file containing the TPDesign4 file to load
116 andreas 91
    bool ftpPassive{true};      //!< If false the data port 20 is used for file transfer
115 andreas 92
    time_t ftpLastDownload{0};  //!< The timestamp of the last download
104 andreas 93
    // SIP settings
94
    string sip_proxy;           //!< The address of the SIP proxy
95
    int sip_port{5060};         //!< Initializes the port of the SIP proxy to 5060
127 andreas 96
    int sip_portTLS{0};         //!< Initializes the TLS port of the SIP proxy to 0 (not used by default)
104 andreas 97
    string sip_stun;            //!< STUN address
98
    string sip_domain;          //!< Local domain
99
    string sip_user;            //!< The SIP user to connect.
100
    string sip_password;        //!< The SIP password to connect. Note: This password is saved in plain text!
127 andreas 101
    bool sip_ipv4{true};        //!< Default: TRUE, Enables or disables IPv4.
102
    bool sip_ipv6{true};        //!< Default: TRUE, Enables or disables IPv6. Has precedence over IPv4.
139 andreas 103
    bool sip_iphone{false};     //!< Default: FALSE, if enabled and SIP is enabled then the internal phone dialog is used.
127 andreas 104
    TConfig::SIP_FIREWALL_t sip_firewall{TConfig::SIP_NO_FIREWALL}; //!< Defines how to deal with a firewall.
104 andreas 105
    bool sip_enabled{false};    //!< By default SIP is disabled
141 andreas 106
    // Sound settings
107
    string systemSound;         //!< name of the set system sound played on every touch.
108
    bool systemSoundState{false};   //!< TRUE = play systemsound on every touch
109
    string systemSingleBeep;    //!< name of the system sound file to play a single beep.
110
    string systemDoubleBeep;    //!< name of the system sound file to play a double beep.
111
    int systemVolume{100};      //!< The set volume to use [0 ... 100]
112
    int systemGain{100};        //!< The set microphone level to use [0 ... 100]
2 andreas 113
};
114
 
115
typedef struct SETTINGS settings_t;
21 andreas 116
static settings_t localSettings;    //!< Global defines settings used in class TConfig.
2 andreas 117
 
21 andreas 118
/**
119
 * @brief TConfig::TConfig constructor
120
 *
121
 * @param path  A path and name of a configuration file.
122
 */
2 andreas 123
TConfig::TConfig(const std::string& path)
116 andreas 124
    : mPath(path)
2 andreas 125
{
90 andreas 126
    // Initialize the possible configuration paths
127
    mCfgPaths.push_back("/etc");
128
    mCfgPaths.push_back("/etc/tpanel");
129
    mCfgPaths.push_back("/usr/etc");
130
    mCfgPaths.push_back("/usr/etc/tpanel");
131
#ifdef __APPLE__
132
    mCfgPath.push_back("/opt/local/etc");
133
    mCfgPath.push_back("/opt/local/etc/tpanel");
134
    mCfgPath.push_back("/opt/local/usr/etc");
135
    mCfgPath.push_back("/opt/local/usr/etc/tpanel");
136
#endif
137
    if (findConfig())
138
        readConfig();
2 andreas 139
}
140
 
118 andreas 141
/**
142
 * Simple method to read the configuration again. This is usefull if, for
143
 * example the configuration options changed but should not be saved. Instead
144
 * they were canceled and therefor the options are read again from file.
145
 *
146
 * @return On success it returns TRUE.
147
 */
23 andreas 148
bool TConfig::reReadConfig()
149
{
150
    return readConfig();
151
}
152
 
21 andreas 153
/**
154
 * @brief TConfig::setProgName Sets the name of the application.
155
 * @param pname The name of the application.
156
 */
2 andreas 157
void TConfig::setProgName(const std::string& pname)
158
{
116 andreas 159
    localSettings.pname = pname;
2 andreas 160
}
161
 
21 andreas 162
/**
163
 * @brief TConfig::getProgName Retrieves the prevously stored application name.
164
 * @return The name of this application.
165
 */
2 andreas 166
std::string & TConfig::getProgName()
167
{
116 andreas 168
    return localSettings.pname;
2 andreas 169
}
170
 
21 andreas 171
/**
172
 * @brief TConfig::getChannel returns the AMX channel to use.
173
 *
174
 * The AMX channels an AMX panel can use start at 10000. This method returns
175
 * the channel number found in the configuration file. If there was no
176
 * channel defination found, it returns the default channel 10001.
177
 *
178
 * @return The AMX channel number to use.
179
 */
2 andreas 180
int TConfig::getChannel()
181
{
116 andreas 182
    DECL_TRACER("TConfig::getChannel()");
183
 
134 andreas 184
    if (mChannel > 0 && mChannel != localSettings.ID)
185
        return mChannel;
186
 
116 andreas 187
    return localSettings.ID;
2 andreas 188
}
189
 
21 andreas 190
/**
191
 * @brief TConfig::getConfigFileName returns the name of the configuration file.
192
 *
193
 * @return The name of the configuration file.
194
 */
2 andreas 195
std::string& TConfig::getConfigFileName()
196
{
116 andreas 197
    return localSettings.name;
2 andreas 198
}
199
 
21 andreas 200
/**
201
 * @brief TConfig::getConfigPath returns the path configuration file.
202
 *
203
 * The path was defined on the command line or found by searching the standard
204
 * directories.
205
 *
206
 * @return The path of the configuration file.
207
 */
2 andreas 208
std::string& TConfig::getConfigPath()
209
{
116 andreas 210
    return localSettings.path;
2 andreas 211
}
212
 
21 andreas 213
/**
214
 * @brief TConfig::getController returns the network name or IP address of the AMX controller.
215
 *
216
 * The network name or the IP address was read from the configuration file.
217
 *
218
 * @return The network name of the AMX controller.
219
 */
2 andreas 220
std::string& TConfig::getController()
221
{
116 andreas 222
    DECL_TRACER("TConfig::getController()");
223
 
224
    return localSettings.server;
2 andreas 225
}
226
 
21 andreas 227
/**
228
 * @brief TConfig::getSystem return the AMX system number.
229
 *
230
 * This number was read from the configuration file. If there was no system
231
 * number defined in the configuration file, then the default number 0 is
232
 * returned.
233
 *
234
 * @return The AMX system number.
235
 */
11 andreas 236
int TConfig::getSystem()
237
{
116 andreas 238
    DECL_TRACER("TConfig::getSystem()");
239
 
11 andreas 240
    return localSettings.system;
241
}
242
 
21 andreas 243
/**
244
 * @brief TConfig::getFirmVersion returns the version of the firmware.
245
 *
246
 * This option was read from the configuration file. There can be any version
247
 * number defined. But you must keep in mind, that the AMX controller may not
248
 * accept any number. If there was no version number defined, the standard
249
 * version number 1.0 is returned.
250
 *
251
 * @return The firmware version of this panel.
252
 */
2 andreas 253
std::string& TConfig::getFirmVersion()
254
{
116 andreas 255
    DECL_TRACER("TConfig::getFirmVersion()");
256
 
257
    return localSettings.version;
2 andreas 258
}
259
 
21 andreas 260
/**
261
 * @brief TConfig::getLogFile the path and name of a logfile.
262
 *
263
 * If there is a logfile name defined in the configuration file, it is used
264
 * to write messages there. It depends on the _log level_ what is logged.
265
 *
266
 * @return The path and name of a logfile.
267
 */
2 andreas 268
std::string& TConfig::getLogFile()
269
{
116 andreas 270
    return localSettings.logFile;
2 andreas 271
}
272
 
21 andreas 273
/**
274
 * @brief TConfig::getLogLevel returns the defined log level.
275
 *
51 andreas 276
 * The loglevel can consist of the following values:
21 andreas 277
 *
278
 *     NONE         Logs nothing (default for Android)
279
 *     INFO         Logs only informations
280
 *     WARNING      Logs only warnings
51 andreas 281
 *     ERROR        Logs only errors
21 andreas 282
 *     TRACE        Logs only trace messages
283
 *     DEBUG        Logs only debug messages
284
 *     PROTOCOL     Logs only INFO and ERROR (default if NOT Android)
285
 *     ALL          Logs everything
286
 *
287
 * All log levels can be combined by concatenating them with the | symbol.
288
 *
289
 * @return The log level(s) as a string.
290
 */
2 andreas 291
string& TConfig::getLogLevel()
292
{
116 andreas 293
    return localSettings.logLevel;
2 andreas 294
}
295
 
21 andreas 296
/**
59 andreas 297
 * @brief TConfig::getLogLevelBits
298
 *
299
 * Returns the raw bit field defining the loglevels selected.
300
 *
301
 * @return The bit field of representing the selected log levels.
302
 */
303
uint TConfig::getLogLevelBits()
304
{
116 andreas 305
    DECL_TRACER("TConfig::getLogLevelBits()");
306
 
59 andreas 307
    return localSettings.logLevelBits;
308
}
309
/**
21 andreas 310
 * @brief TConfig::getPanelType the AMX type name of the panel.
311
 *
312
 * The type name of the panel is defined in the configuration file. If this
313
 * option was not defined, the default panel _android_ is returned.
314
 *
315
 * @return The type name of the panel.
316
 */
2 andreas 317
std::string& TConfig::getPanelType()
318
{
116 andreas 319
    DECL_TRACER("TConfig::getPanelType()");
320
 
321
    return localSettings.ptype;
2 andreas 322
}
323
 
21 andreas 324
/**
325
 * @brief TConfig::getPort returnes the AMX port number to connect to.
326
 *
327
 * The port number can be defined in the configuration file. If there is no
328
 * configuration the default number 1319 is returned.
329
 *
330
 * @return The AMX network port number.
331
 */
2 andreas 332
int TConfig::getPort()
333
{
116 andreas 334
    DECL_TRACER("TConfig::getPort()");
335
 
336
    return localSettings.port;
2 andreas 337
}
338
 
21 andreas 339
/**
340
 * @brief TConfig::getProjectPath returns the path to the AMX configuration files.
341
 *
342
 * The path was read from the configuration file. This path contains all the
343
 * files needed to display the elements of the surface.
344
 *
345
 * @return The path to the AMX configuration files.
346
 */
71 andreas 347
string& TConfig::getProjectPath()
2 andreas 348
{
116 andreas 349
    return localSettings.project;
2 andreas 350
}
351
 
112 andreas 352
 
71 andreas 353
string TConfig::getSystemPath(SYSTEMRESOURCE_t sres)
354
{
116 andreas 355
    DECL_TRACER("TConfig::getSystemPath(SYSTEMRESOURCE_t sres)");
356
 
71 andreas 357
    string p;
358
 
359
    switch(sres)
360
    {
361
        case BORDERS:   p = "/borders"; break;
362
        case FONTS:     p = "/fonts"; break;
363
        case IMAGES:    p = "/images"; break;
364
        case SLIDERS:   p = "/sliders"; break;
365
        case SOUNDS:    p = "/sounds"; break;
366
        default:
367
            p.clear();
368
    }
369
 
370
    return localSettings.project + "/__system/graphics" + p;
371
}
372
 
23 andreas 373
bool TConfig::saveLogFile(const string &file)
374
{
375
    DECL_TRACER("TConfig::saveLogFile(const string &file)");
376
 
377
    if (file.empty() || localSettings.logFile.compare(file) == 0)
378
        return false;
379
 
380
    localSettings.logFile = file;
381
    return true;
382
}
383
 
384
bool TConfig::saveLogLevel(const string &level)
385
{
386
    DECL_TRACER("TConfig::saveLogLevel(const string &level)");
387
 
59 andreas 388
    if (level.find(SLOG_NONE) == string::npos && level.find(SLOG_INFO) == string::npos && level.find(SLOG_WARNING) == string::npos &&
389
            level.find(SLOG_ERROR) == string::npos && level.find(SLOG_TRACE) == string::npos && level.find(SLOG_DEBUG) == string::npos &&
390
            level.find(SLOG_PROTOCOL) == string::npos && level.find(SLOG_ALL) == string::npos)
23 andreas 391
        return false;
392
 
393
    localSettings.logLevel = level;
59 andreas 394
    localSettings.logLevelBits = logLevelStrToBits(level);
395
    MSG_INFO("New log level: " << level);
23 andreas 396
    return true;
397
}
398
 
59 andreas 399
bool TConfig::saveLogLevel(uint level)
400
{
401
    DECL_TRACER("TConfig::saveLogLevel(uint level)");
402
 
403
    if (level != 0 && !(level&HLOG_INFO) && !(level&HLOG_WARNING) &&
404
            !(level&HLOG_ERROR) && !(level&HLOG_TRACE) && !(level&HLOG_DEBUG))
405
        return false;
406
 
407
    localSettings.logLevelBits = level;
408
    localSettings.logLevel = logLevelBitsToString(level);
409
    MSG_INFO("New log level from bits: " << localSettings.logLevel);
410
    return true;
411
}
412
 
23 andreas 413
bool TConfig::saveChannel(int channel)
414
{
415
    DECL_TRACER("TConfig::saveChannel(int channel)");
416
 
417
    if (channel < 10000 || channel > 12000)
418
        return false;
419
 
420
    localSettings.ID = channel;
421
    return true;
422
}
423
 
424
bool TConfig::saveController(const string &cnt)
425
{
426
    DECL_TRACER("TConfig::saveController(const string &cnt)");
427
 
428
    localSettings.server = cnt;
429
    return true;
430
}
431
 
432
bool TConfig::savePanelType(const string &pt)
433
{
434
    DECL_TRACER("TConfig::savePanelType(const string &pt)");
435
 
436
    localSettings.ptype = pt;
437
    return true;
438
}
439
 
440
bool TConfig::savePort(int port)
441
{
442
    DECL_TRACER("TConfig::savePort(int port)");
443
 
444
    if (port < 1024 || port > 32767)
445
        return false;
446
 
447
    localSettings.port = port;
448
    return true;
449
}
450
 
451
bool TConfig::saveProjectPath(const string &path)
452
{
453
    DECL_TRACER("TConfig::saveProjectPath(const string &path)");
454
 
455
    if (path.empty())
456
        return false;
457
 
458
    localSettings.project = path;
459
    return true;
460
}
461
 
462
void TConfig::saveFormat(bool format)
463
{
464
    DECL_TRACER("TConfig::saveFormat(bool format)");
465
 
466
    localSettings.longformat = format;
467
}
468
 
24 andreas 469
void TConfig::saveScale(bool scale)
470
{
471
    DECL_TRACER("TConfig::saveScale(bool scale)");
472
 
473
    localSettings.scale = scale;
474
}
475
 
118 andreas 476
void TConfig::saveBanner(bool banner)
477
{
478
    DECL_TRACER("TConfig::saveBanner(bool banner)");
479
 
480
    localSettings.noBanner = banner;
481
}
482
 
120 andreas 483
void TConfig::saveToolbarForce(bool tb)
484
{
485
    DECL_TRACER("TConfig::saveToolbarForce(bool tb)");
486
 
487
    localSettings.tbforce = tb;
488
}
489
 
151 andreas 490
void TConfig::saveToolbarSuppress(bool tb)
491
{
492
    DECL_TRACER("TConfig::saveToolbarSuppress(bool tb)");
493
 
494
    localSettings.tbsuppress = tb;
495
}
496
 
35 andreas 497
void TConfig::saveProfiling(bool prof)
498
{
116 andreas 499
    DECL_TRACER("TConfig::saveProfiling(bool prof)");
500
 
35 andreas 501
    localSettings.profiling = prof;
502
}
503
 
51 andreas 504
void TConfig::savePassword1(const std::string& pw)
505
{
116 andreas 506
    DECL_TRACER("TConfig::savePassword1(const std::string& pw)");
507
 
51 andreas 508
    localSettings.password1 = pw;
509
}
510
 
511
void TConfig::savePassword2(const std::string& pw)
512
{
116 andreas 513
    DECL_TRACER("TConfig::savePassword2(const std::string& pw)");
514
 
51 andreas 515
    localSettings.password2 = pw;
516
}
517
 
518
void TConfig::savePassword3(const std::string& pw)
519
{
116 andreas 520
    DECL_TRACER("TConfig::savePassword3(const std::string& pw)");
521
 
51 andreas 522
    localSettings.password3 = pw;
523
}
524
 
525
void TConfig::savePassword4(const std::string& pw)
526
{
116 andreas 527
    DECL_TRACER("TConfig::savePassword4(const std::string& pw)");
528
 
51 andreas 529
    localSettings.password4 = pw;
530
}
531
 
71 andreas 532
void TConfig::saveSystemSoundFile(const std::string& snd)
533
{
116 andreas 534
    DECL_TRACER("TConfig::saveSystemSoundFile(const std::string& snd)");
535
 
71 andreas 536
    localSettings.systemSound = snd;
537
}
538
 
539
void TConfig::saveSystemSoundState(bool state)
540
{
116 andreas 541
    DECL_TRACER("TConfig::saveSystemSoundState(bool state)");
542
 
71 andreas 543
    localSettings.systemSoundState = state;
544
}
545
 
141 andreas 546
void TConfig::saveSingleBeepFile(const std::string& snd)
547
{
548
    DECL_TRACER("TConfig::saveSingleBeepFile(const std::string& snd)");
549
 
550
    localSettings.systemSingleBeep = snd;
551
}
552
 
553
void TConfig::saveDoubleBeepFile(const std::string& snd)
554
{
555
    DECL_TRACER("TConfig::saveDoubleBeepFile(const std::string& snd)");
556
 
557
    localSettings.systemDoubleBeep = snd;
558
}
559
 
560
void TConfig::saveSystemVolume(int volume)
561
{
562
    DECL_TRACER("TConfig::saveSystemVolume(int volume)");
563
 
564
    if (volume < 0 || volume > 100)
565
        return;
566
 
567
    localSettings.systemVolume = volume;
568
}
569
 
570
void TConfig::saveSystemGain(int gain)
571
{
572
    DECL_TRACER("TConfig::saveSystemGain(int gain)");
573
 
574
    if (gain < 0 || gain > 100)
575
        return;
576
 
577
    localSettings.systemGain = gain;
578
}
579
 
112 andreas 580
void TConfig::saveFtpUser(const string& user)
581
{
116 andreas 582
    DECL_TRACER("TConfig::saveFtpUser(const string& user)");
583
 
112 andreas 584
    localSettings.ftpUser = user;
585
}
586
 
587
void TConfig::saveFtpPassword(const string& pw)
588
{
116 andreas 589
    DECL_TRACER("TConfig::saveFtpPassword(const string& pw)");
590
 
112 andreas 591
    localSettings.ftpPassword = pw;
592
}
593
 
115 andreas 594
void TConfig::saveFtpSurface(const string& fname)
595
{
116 andreas 596
    DECL_TRACER("TConfig::saveFtpSurface(const string& fname)");
597
 
115 andreas 598
    localSettings.ftpSurface = fname;
599
}
600
 
116 andreas 601
void TConfig::saveFtpPassive(bool mode)
602
{
603
    DECL_TRACER("TConfig::saveFtpPassive(bool mode)");
604
 
605
    localSettings.ftpPassive = mode;
606
}
607
 
115 andreas 608
void TConfig::saveFtpDownloadTime(time_t t)
609
{
116 andreas 610
    DECL_TRACER("TConfig::saveFtpDownloadTime(time_t t)");
611
 
115 andreas 612
    localSettings.ftpLastDownload = t;
613
}
614
 
104 andreas 615
std::string& TConfig::getSIPproxy()
616
{
116 andreas 617
    DECL_TRACER("TConfig::getSIPproxy()");
618
 
104 andreas 619
    return localSettings.sip_proxy;
620
}
621
 
622
void TConfig::setSIPproxy(const std::string& address)
623
{
116 andreas 624
    DECL_TRACER("TConfig::setSIPproxy(const std::string& address)");
625
 
104 andreas 626
    localSettings.sip_proxy = address;
627
}
628
 
629
int TConfig::getSIPport()
630
{
116 andreas 631
    DECL_TRACER("TConfig::getSIPport()");
632
 
104 andreas 633
    return localSettings.sip_port;
634
}
635
 
636
void TConfig::setSIPport(int port)
637
{
116 andreas 638
    DECL_TRACER("TConfig::setSIPport(int port)");
639
 
104 andreas 640
    localSettings.sip_port = port;
641
}
642
 
127 andreas 643
int TConfig::getSIPportTLS()
644
{
645
    DECL_TRACER("TConfig::getSIPportTLS()");
646
 
647
    return localSettings.sip_portTLS;
648
}
649
 
650
void TConfig::setSIPportTLS(int port)
651
{
652
    DECL_TRACER("TConfig::setSIPportTLS(int port)");
653
 
654
    localSettings.sip_portTLS = port;
655
}
656
 
104 andreas 657
std::string& TConfig::getSIPstun()
658
{
116 andreas 659
    DECL_TRACER("TConfig::getSIPstun()");
660
 
104 andreas 661
    return localSettings.sip_stun;
662
}
663
 
664
void TConfig::setSIPstun(const std::string& address)
665
{
116 andreas 666
    DECL_TRACER("TConfig::setSIPstun(const std::string& address)");
667
 
104 andreas 668
    localSettings.sip_stun = address;
669
}
670
 
671
std::string& TConfig::getSIPdomain()
672
{
116 andreas 673
    DECL_TRACER("TConfig::getSIPdomain()");
674
 
104 andreas 675
    return localSettings.sip_domain;
676
}
677
 
678
void TConfig::setSIPdomain(const std::string& domain)
679
{
116 andreas 680
    DECL_TRACER("TConfig::setSIPdomain(const std::string& domain)");
681
 
104 andreas 682
    localSettings.sip_domain = domain;
683
}
684
 
685
std::string& TConfig::getSIPuser()
686
{
116 andreas 687
    DECL_TRACER("TConfig::getSIPuser()");
688
 
104 andreas 689
    return localSettings.sip_user;
690
}
691
 
692
void TConfig::setSIPuser(const std::string& user)
693
{
116 andreas 694
    DECL_TRACER("TConfig::setSIPuser(const std::string& user)");
695
 
104 andreas 696
    localSettings.sip_user = user;
697
}
698
 
699
std::string& TConfig::getSIPpassword()
700
{
116 andreas 701
    DECL_TRACER("TConfig::getSIPpassword()");
702
 
104 andreas 703
    return localSettings.sip_password;
704
}
705
 
706
void TConfig::setSIPpassword(const std::string& pw)
707
{
116 andreas 708
    DECL_TRACER("TConfig::setSIPpassword(const std::string& pw)");
709
 
104 andreas 710
    localSettings.sip_password = pw;
711
}
712
 
713
bool TConfig::getSIPstatus()
714
{
116 andreas 715
    DECL_TRACER("TConfig::getSIPstatus()");
716
 
104 andreas 717
    return localSettings.sip_enabled;
718
}
719
 
127 andreas 720
bool TConfig::getSIPnetworkIPv4()
721
{
722
    DECL_TRACER("TConfig::getSIPnetworkIPv4()");
723
 
724
    return localSettings.sip_ipv4;
725
}
726
 
727
void TConfig::setSIPnetworkIPv4(bool state)
728
{
729
    DECL_TRACER("TConfig::setSIPnetworkIPv4(bool state)");
730
 
731
    localSettings.sip_ipv4 = state;
732
}
733
 
734
bool TConfig::getSIPnetworkIPv6()
735
{
736
    DECL_TRACER("TConfig::getSIPnetworkIPv6()");
737
 
738
    return localSettings.sip_ipv6;
739
}
740
 
741
void TConfig::setSIPnetworkIPv6(bool state)
742
{
743
    DECL_TRACER("TConfig::setSIPnetworkIPv6(bool state)");
744
 
745
    localSettings.sip_ipv6 = state;
746
}
747
 
139 andreas 748
void TConfig::setSIPiphone(bool state)
749
{
750
    DECL_TRACER("TConfig::setSIPiphone(bool state)");
751
 
752
    localSettings.sip_iphone = state;
753
}
754
 
755
bool TConfig::getSIPiphone()
756
{
757
    DECL_TRACER("TConfig::getSIPiphone()");
758
 
759
    return localSettings.sip_iphone;
760
}
761
 
127 andreas 762
TConfig::SIP_FIREWALL_t TConfig::getSIPfirewall()
763
{
764
    DECL_TRACER("TConfig::getSIPfirewall()");
765
 
766
    return localSettings.sip_firewall;
767
}
768
 
769
string TConfig::getSIPfirewallStr()
770
{
771
    DECL_TRACER("TConfig::getSIPfirewallStr()");
772
 
773
    return sipFirewallToString(localSettings.sip_firewall);
774
}
775
 
776
void TConfig::setSIPfirewall(TConfig::SIP_FIREWALL_t fw)
777
{
778
    DECL_TRACER("TConfig::setSIPfirewall(TConfig::SIP_FIREWALL_t fw)")
779
 
780
    localSettings.sip_firewall = fw;
781
}
782
 
104 andreas 783
void TConfig::setSIPstatus(bool state)
784
{
116 andreas 785
    DECL_TRACER("TConfig::setSIPstatus(bool state)");
786
 
104 andreas 787
    localSettings.sip_enabled = state;
788
}
789
 
23 andreas 790
bool TConfig::saveSettings()
791
{
792
    DECL_TRACER("TConfig::saveSettings()");
793
 
794
    try
795
    {
796
        string fname = localSettings.path + "/" + localSettings.name;
797
        ofstream file(fname);
798
        string lines = "LogFile=" + localSettings.logFile + "\n";
799
        lines += "LogLevel=" + localSettings.logLevel + "\n";
800
        lines += "ProjectPath=" + localSettings.project + "\n";
801
        lines += string("NoBanner=") + (localSettings.noBanner ? "true" : "false") + "\n";
151 andreas 802
        lines += string("ToolbarSuppress=") + (localSettings.tbsuppress ? "true" : "false") + "\n";
120 andreas 803
        lines += string("ToolbarForce=") + (localSettings.tbforce ? "true" : "false") + "\n";
23 andreas 804
        lines += string("LongFormat=") + (localSettings.longformat ? "true" : "false") + "\n";
805
        lines += "Address=" + localSettings.server + "\n";
806
        lines += "Port=" + std::to_string(localSettings.port) + "\n";
807
        lines += "Channel=" + std::to_string(localSettings.ID) + "\n";
808
        lines += "System=" + std::to_string(localSettings.system) + "\n";
809
        lines += "PanelType=" + localSettings.ptype + "\n";
810
        lines += "Firmware=" + localSettings.version + "\n";
811
        lines += string("CertCheck=") + (localSettings.certCheck ? "true" : "false") + "\n";
24 andreas 812
        lines += string("Scale=") + (localSettings.scale ? "true" : "false") + "\n";
35 andreas 813
        lines += string("Profiling=") + (localSettings.profiling ? "true" : "false") + "\n";
51 andreas 814
        lines += string("Password1=") + localSettings.password1 + "\n";
815
        lines += string("Password2=") + localSettings.password2 + "\n";
816
        lines += string("Password3=") + localSettings.password3 + "\n";
817
        lines += string("Password4=") + localSettings.password4 + "\n";
71 andreas 818
        lines += string("SystemSoundFile=") + localSettings.systemSound + "\n";
819
        lines += string("SystemSoundState=") + (localSettings.systemSoundState ? "ON" : "OFF") + "\n";
820
        lines += string("SystemSingleBeep=") + localSettings.systemSingleBeep + "\n";
821
        lines += string("SystemDoubleBeep=") + localSettings.systemDoubleBeep + "\n";
141 andreas 822
        lines += "SystemVolume=" + std::to_string(localSettings.systemVolume) + "\n";
823
        lines += "SystemGain=" + std::to_string(localSettings.systemGain) + "\n";
134 andreas 824
        lines += string("SystemRotationFix=") + (localSettings.systemRotationFix ? "ON" : "OFF") + "\n";
825
        lines += string("UUID=") + localSettings.uuid + "\n";
112 andreas 826
        // FTP credentials
827
        lines += string("FTPuser=") + localSettings.ftpUser + "\n";
828
        lines += string("FTPpassword=") + localSettings.ftpPassword + "\n";
115 andreas 829
        lines += string("FTPsurface=") + localSettings.ftpSurface + "\n";
116 andreas 830
        lines += string("FTPpassive=") + (localSettings.ftpPassive ? "true" : "false") + "\n";
115 andreas 831
        lines += string("FTPdownloadTime=") + std::to_string(localSettings.ftpLastDownload) + "\n";
104 andreas 832
        // SIP settings
116 andreas 833
        lines += string("SIP_DOMAIN=") + localSettings.sip_domain + "\n";
127 andreas 834
        lines += string("SIP_PROXY=") + localSettings.sip_proxy + "\n";
116 andreas 835
        lines += string("SIP_PORT=") + std::to_string(localSettings.sip_port) + "\n";
127 andreas 836
        lines += string("SIP_PORTTLS=") + std::to_string(localSettings.sip_portTLS) + "\n";
116 andreas 837
        lines += string("SIP_STUN=") + localSettings.sip_stun + "\n";
838
        lines += string("SIP_USER=") + localSettings.sip_user + "\n";
839
        lines += string("SIP_PASSWORD=") + localSettings.sip_password + "\n";
127 andreas 840
        lines += string("SIP_IPV4=") + (localSettings.sip_ipv4 ? "true" : "false") + "\n";
841
        lines += string("SIP_IPV6=") + (localSettings.sip_ipv6 ? "true" : "false") + "\n";
139 andreas 842
        lines += string("SIP_IPHONE=") + (localSettings.sip_iphone ? "true" : "false") + "\n";
127 andreas 843
        lines += "SIP_FIREWALL=" + sipFirewallToString(localSettings.sip_firewall) + "\n";
116 andreas 844
        lines += string("SIP_ENABLED=") + (localSettings.sip_enabled ? "true" : "false") + "\n";
23 andreas 845
        file.write(lines.c_str(), lines.size());
846
        file.close();
59 andreas 847
        MSG_INFO("Actual log level: " << localSettings.logLevel);
23 andreas 848
    }
849
    catch (std::exception& e)
850
    {
851
        MSG_ERROR("Couldn't write configs: " << e.what());
852
        return false;
853
    }
854
 
116 andreas 855
    TError::Current()->setLogLevel(localSettings.logLevel);
23 andreas 856
    TError::Current()->setLogFile(localSettings.logFile);
857
    return true;
858
}
859
 
21 andreas 860
/**
861
 * @brief TConfig::isLongFormat defines the format in the logfile.
862
 *
863
 * If this returns `true` the format in the logfile is a long format. This
864
 * means, that in front of each message is an additional timestamp.
865
 *
866
 * @return `true` = long format, `false` = short format (default).
867
 */
2 andreas 868
bool TConfig::isLongFormat()
869
{
116 andreas 870
    return localSettings.longformat;
2 andreas 871
}
872
 
21 andreas 873
/**
874
 * @brief TConfig::showBanner defines whether the banner should be showed or not.
875
 *
876
 * If this method returns `false` the banner on startup is not displayed.
877
 *
878
 * @return `true` = display the banner (default), `false` = show no banner.
879
 */
2 andreas 880
bool TConfig::showBanner()
881
{
116 andreas 882
    DECL_TRACER("TConfig::showBanner()");
883
 
884
    return !localSettings.noBanner;
2 andreas 885
}
886
 
21 andreas 887
/**
24 andreas 888
 * @brief TConfig::getScale returns the scale setting
889
 *
890
 * If this is set to TRUE, all images are scaled to fit the screen.
891
 *
892
 * @return scale state
893
 */
894
bool TConfig::getScale()
895
{
116 andreas 896
    DECL_TRACER("TConfig::getScale()");
897
 
24 andreas 898
    return localSettings.scale;
899
}
900
 
120 andreas 901
bool TConfig::getToolbarForce()
902
{
903
    DECL_TRACER("TConfig::getToolbarForce()");
904
 
905
    return localSettings.tbforce;
906
}
907
 
151 andreas 908
bool TConfig::getToolbarSuppress()
909
{
910
    DECL_TRACER("TConfig::getToolbarSuppress()");
911
 
912
    return localSettings.tbsuppress;
913
}
914
 
35 andreas 915
bool TConfig::getProfiling()
916
{
917
    return localSettings.profiling;
918
}
919
 
51 andreas 920
string & TConfig::getPassword1()
921
{
116 andreas 922
    DECL_TRACER("TConfig::getPassword1()");
923
 
51 andreas 924
    return localSettings.password1;
925
}
926
 
927
string & TConfig::getPassword2()
928
{
116 andreas 929
    DECL_TRACER("TConfig::getPassword2()");
930
 
51 andreas 931
    return localSettings.password2;
932
}
933
 
934
string & TConfig::getPassword3()
935
{
116 andreas 936
    DECL_TRACER("TConfig::getPassword3()");
937
 
51 andreas 938
    return localSettings.password3;
939
}
940
 
941
string & TConfig::getPassword4()
942
{
116 andreas 943
    DECL_TRACER("TConfig::getPassword4()");
944
 
51 andreas 945
    return localSettings.password4;
946
}
947
 
71 andreas 948
string & TConfig::getSystemSound()
949
{
116 andreas 950
    DECL_TRACER("TConfig::getSystemSound()");
951
 
71 andreas 952
    return localSettings.systemSound;
953
}
954
 
955
bool TConfig::getSystemSoundState()
956
{
116 andreas 957
    DECL_TRACER("TConfig::getSystemSoundState()");
958
 
71 andreas 959
    return localSettings.systemSoundState;
960
}
961
 
141 andreas 962
int TConfig::getSystemVolume()
963
{
964
    DECL_TRACER("TConfig::getSystemVolume()");
965
 
966
    return localSettings.systemVolume;
967
}
968
 
969
int TConfig::getSystemGain()
970
{
971
    DECL_TRACER("TConfig::getSystemGain()");
972
 
973
    return localSettings.systemGain;
974
}
975
 
134 andreas 976
bool TConfig::getRotationFixed()
977
{
978
    DECL_TRACER("TConfig::getRotationFixed()");
979
 
980
    return localSettings.systemRotationFix;
981
}
982
 
983
void TConfig::setRotationFixed(bool fix)
984
{
985
    DECL_TRACER("TConfig::setRotationFixed(bool fix)");
986
 
987
    localSettings.systemRotationFix = fix;
988
}
989
 
990
void TConfig::setSystemChannel(int ch)
991
{
992
    DECL_TRACER("TConfig::setSystemChannel(int ch)");
993
 
994
    if (ch >= 10000 && ch < 30000)
995
        mChannel = ch;
996
}
997
 
71 andreas 998
string& TConfig::getSingleBeepSound()
999
{
116 andreas 1000
    DECL_TRACER("TConfig::getSingleBeepSound()");
1001
 
71 andreas 1002
    return localSettings.systemSingleBeep;
1003
}
1004
 
1005
string& TConfig::getDoubleBeepSound()
1006
{
116 andreas 1007
    DECL_TRACER("TConfig::getDoubleBeepSound()");
1008
 
71 andreas 1009
    return localSettings.systemDoubleBeep;
1010
}
1011
 
134 andreas 1012
string& TConfig::getUUID()
1013
{
1014
    DECL_TRACER("TConfig::getUUID()");
1015
 
1016
    return localSettings.uuid;
1017
}
1018
 
112 andreas 1019
string& TConfig::getFtpUser()
1020
{
116 andreas 1021
    DECL_TRACER("TConfig::getFtpUser()");
1022
 
112 andreas 1023
    return localSettings.ftpUser;
1024
}
1025
 
1026
string& TConfig::getFtpPassword()
1027
{
116 andreas 1028
    DECL_TRACER("TConfig::getFtpPassword()");
1029
 
112 andreas 1030
    return localSettings.ftpPassword;
1031
}
1032
 
115 andreas 1033
string& TConfig::getFtpSurface()
1034
{
116 andreas 1035
    DECL_TRACER("TConfig::getFtpSurface()");
1036
 
115 andreas 1037
    return localSettings.ftpSurface;
1038
}
1039
 
116 andreas 1040
bool TConfig::getFtpPassive()
1041
{
1042
    DECL_TRACER("TConfig::getFtpPassive()");
1043
 
1044
    return localSettings.ftpPassive;
1045
}
1046
 
115 andreas 1047
time_t TConfig::getFtpDownloadTime()
1048
{
116 andreas 1049
    DECL_TRACER("TConfig::getFtpDownloadTime()");
1050
 
115 andreas 1051
    return localSettings.ftpLastDownload;
1052
}
1053
 
24 andreas 1054
/**
71 andreas 1055
 * Checks a string if it contains a word which may be interpreted as a
1056
 * boolean TRUE.
1057
 *
1058
 * @param boolean   A string containg a word.
1059
 *
1060
 * @return If the string \p boolean contains a word that can be interpreted as
1061
 * a boolean TRUE, it returns TRUE. In any other case it returns FALSE.
1062
 */
1063
bool TConfig::isTrue(const string& boolean)
1064
{
1065
    if (caseCompare(boolean, "1") == 0 || caseCompare(boolean, "yes") == 0 ||
1066
        caseCompare(boolean, "true") == 0 || caseCompare(boolean, "on") == 0)
1067
        return true;
1068
 
1069
    return false;
1070
}
1071
 
1072
/**
21 andreas 1073
 * @brief TConfig::certCheck check the certificate if the connection is encrypted.
1074
 *
1075
 * Currently not implemented!
1076
 *
1077
 * @return `true` = check the certificate, `false` = accept any certificate (default).
1078
 */
1079
bool TConfig::certCheck()
1080
{
1081
    return localSettings.certCheck;
1082
}
1083
 
1084
/**
59 andreas 1085
 * @brief TConfig::logLevelStrToBits
1086
 * Converts a string containing one or more loglevels into a bit field.
1087
 * @param level A string containing the log levels
1088
 * @return A bit field representing the log levels.
1089
 */
1090
uint TConfig::logLevelStrToBits(const string& level)
1091
{
1092
    uint l = 0;
1093
 
1094
    if (level.find("INFO") != string::npos)
1095
        l |= HLOG_INFO;
1096
 
1097
    if (level.find("WARNING") != string::npos)
1098
        l |= HLOG_WARNING;
1099
 
1100
    if (level.find("ERROR") != string::npos)
1101
        l |= HLOG_ERROR;
1102
 
1103
    if (level.find("TRACE") != string::npos)
1104
        l |= HLOG_TRACE;
1105
 
1106
    if (level.find("DEBUG") != string::npos)
1107
        l |= HLOG_DEBUG;
1108
 
1109
    if (level.find("PROTOCOL") != string::npos)
71 andreas 1110
        l |= HLOG_PROTOCOL;
59 andreas 1111
 
1112
    if (level.find("ALL") != string::npos)
1113
        l = HLOG_ALL;
1114
 
1115
    return l;
1116
}
1117
 
1118
string TConfig::logLevelBitsToString(uint level)
1119
{
1120
    string l;
1121
 
1122
    if (level == 0)
1123
    {
1124
        l = SLOG_NONE;
1125
        return l;
1126
    }
1127
 
1128
    if (level & HLOG_INFO)
1129
    {
1130
        if (l.length() > 0)
1131
            l.append("|");
1132
 
1133
        l.append(SLOG_INFO);
1134
    }
1135
 
1136
    if (level & HLOG_WARNING)
1137
    {
1138
        if (l.length() > 0)
1139
            l.append("|");
1140
 
1141
        l.append(SLOG_WARNING);
1142
    }
1143
 
1144
    if (level & HLOG_ERROR)
1145
    {
1146
        if (l.length() > 0)
1147
            l.append("|");
1148
 
1149
        l.append(SLOG_ERROR);
1150
    }
1151
 
1152
    if (level & HLOG_TRACE)
1153
    {
1154
        if (l.length() > 0)
1155
            l.append("|");
1156
 
1157
        l.append(SLOG_TRACE);
1158
    }
1159
 
1160
    if (level & HLOG_DEBUG)
1161
    {
1162
        if (l.length() > 0)
1163
            l.append("|");
1164
 
1165
        l.append(SLOG_DEBUG);
1166
    }
1167
 
1168
    return l;
1169
}
118 andreas 1170
 
127 andreas 1171
string TConfig::sipFirewallToString(TConfig::SIP_FIREWALL_t fw)
1172
{
1173
    switch(fw)
1174
    {
1175
        case SIP_NO_FIREWALL:   return "SIP_NO_FIREWALL";
1176
        case SIP_NAT_ADDRESS:   return "SIP_NAT_ADDRESS";
1177
        case SIP_STUN:          return "SIP_STUN";
1178
        case SIP_ICE:           return "SIP_ICE";
1179
        case SIP_UPNP:          return "SIP_UPNP";
1180
    }
140 andreas 1181
 
1182
    return string();
127 andreas 1183
}
1184
 
1185
TConfig::SIP_FIREWALL_t TConfig::sipFirewallStrToEnum(const std::string& str)
1186
{
1187
    if (strCaseCompare(str, "SIP_NO_FIREWALL") == 0)
1188
        return SIP_NO_FIREWALL;
1189
    else if (strCaseCompare(str, "SIP_NAT_ADDRESS") == 0)
1190
        return SIP_NAT_ADDRESS;
1191
    else if (strCaseCompare(str, "SIP_STUN") == 0)
1192
        return SIP_STUN;
1193
    else if (strCaseCompare(str, "SIP_ICE") == 0)
1194
        return SIP_ICE;
1195
    else if (strCaseCompare(str, "SIP_UPNP") == 0)
1196
        return SIP_UPNP;
1197
 
1198
    return SIP_NO_FIREWALL;
1199
}
1200
 
118 andreas 1201
string TConfig::makeConfigDefault(const std::string& log, const std::string& project)
1202
{
1203
    string content = "LogFile=" + log + "\n";
131 andreas 1204
#if defined(QT_DEBUG) || defined(NDEBUG)
1205
    content += "LogLevel=PROTOCOL\n";
1206
#else
1207
    content += "LogLevel=NONE\n";
1208
#endif
118 andreas 1209
    content += "ProjectPath=" + project + "\n";
1210
    content += "LongFormat=false\n";
1211
    content += "Address=0.0.0.0\n";
1212
    content += "Port=1319\n";
1213
    content += "Channel=10001\n";
1214
    content += "PanelType=Android\n";
1215
    content += string("Firmware=") + VERSION_STRING() + "\n";
1216
    content += "Scale=true\n";
134 andreas 1217
    content += "ToolbarForce=true\n";
118 andreas 1218
    content += "Profiling=false\n";
1219
    content += "Password1=1988\n";
1220
    content += "Password2=1988\n";
1221
    content += "Password3=1988\n";
1222
    content += "Password4=1988\n";
1223
    content += "SystemSoundFile=singleBeep.wav\n";
1224
    content += "SystemSoundState=ON\n";
1225
    content += "SystemSingleBeep=singleBeep01.wav\n";
1226
    content += "SystemDoubleBeep=doubleBeep01.wav\n";
134 andreas 1227
    content += "SystemRotationFix=" + string(localSettings.systemRotationFix ? "TRUE" : "FALSE") + "\n";
1228
    content += "UUID=" + localSettings.uuid + "\n";
118 andreas 1229
    content += "FTPuser=administrator\n";
1230
    content += "FTPpassword=password\n";
1231
    content += "FTPsurface=tpanel.tp4\n";
1232
    content += "FTPpassive=true\n";
1233
    content += "FTPdownloadTime=0\n";
127 andreas 1234
    content += "SIP_PROXY=" + localSettings.sip_proxy + "\n";
118 andreas 1235
    content += "SIP_PORT=" + std::to_string(localSettings.sip_port) + "\n";
127 andreas 1236
    content += "SIP_PORTTLS=" + std::to_string(localSettings.sip_portTLS) + "\n";
1237
    content += "SIP_STUN=" + localSettings.sip_stun + "\n";
1238
    content += "SIP_DOMAIN=" + localSettings.sip_domain + "\n";
1239
    content += "SIP_USER=" + localSettings.sip_user + "\n";
1240
    content += "SIP_PASSWORD=" + localSettings.sip_password + "\n";
1241
    content += "SIP_IPV4=" + string(localSettings.sip_ipv4 ? "TRUE" : "FALSE") + "\n";
139 andreas 1242
    content += "SIP_IPV6=" + string(localSettings.sip_ipv6 ? "TRUE" : "FALSE") + "\n";
1243
    content += "SIP_IPHONE=" + string(localSettings.sip_iphone ? "TRUE" : "FALSE") + "\n";
127 andreas 1244
    content += "SIP_FIREWALL=" + sipFirewallToString(localSettings.sip_firewall) + "\n";
1245
    content += "SIP_ENABLED=" + string(localSettings.sip_ipv6 ? "TRUE" : "FALSE") + "\n";
118 andreas 1246
 
1247
    return content;
1248
}
1249
 
59 andreas 1250
/**
21 andreas 1251
 * @brief TConfig::findConfig search for the location of the configuration file.
1252
 *
1253
 * If there was no configuration file given on the command line, this method
1254
 * searches for a configuration file on a few standard directories. This are:
1255
 *
1256
 *     /etc/tpanel.conf
1257
 *     /etc/tpanel/tpanel.conf
1258
 *     /usr/etc/tpanel.conf
1259
 *     $HOME/.tpanel.conf
1260
 *
1261
 * On macOS the following additional directories are searched:
1262
 *
1263
 *     /opt/local/etc/tpanel.conf
1264
 *     /opt/local/etc/tpanel/tpanel.conf
1265
 *     /opt/local/usr/etc/tpanel.conf
1266
 *
1267
 * @return On success `true`, otherwise `false`.
1268
 */
2 andreas 1269
bool TConfig::findConfig()
1270
{
90 andreas 1271
    char *HOME = nullptr;
1272
    string sFileName;
22 andreas 1273
 
90 andreas 1274
    if (!mPath.empty())
1275
    {
1276
        size_t pos = mPath.find_last_of("/");
2 andreas 1277
 
90 andreas 1278
        if (pos != string::npos)
1279
        {
1280
            localSettings.path = mPath.substr(0, pos);
1281
            localSettings.name = mPath.substr(pos+1);
1282
            mCFile = mPath;
1283
            return !mCFile.empty();
1284
        }
2 andreas 1285
 
90 andreas 1286
        localSettings.name = mPath;
1287
        mCFile = mPath;
1288
        return !mCFile.empty();
1289
    }
2 andreas 1290
 
90 andreas 1291
    localSettings.name = "tpanel.conf";
51 andreas 1292
    localSettings.password1 = "1988";
1293
    localSettings.password2 = "1988";
1294
    localSettings.password3 = "1988";
1295
    localSettings.password4 = "1988";
71 andreas 1296
    localSettings.systemSound = "singleBeep.wav";
1297
    localSettings.systemSoundState = true;
1298
    localSettings.systemSingleBeep = "singleBeep01.wav";
1299
    localSettings.systemDoubleBeep = "doubleBeep01.wav";
112 andreas 1300
    localSettings.ftpUser = "administrator";
1301
    localSettings.ftpPassword = "password";
115 andreas 1302
    localSettings.ftpSurface = "tpanel.tp4";
21 andreas 1303
#ifdef __ANDROID__
22 andreas 1304
    std::stringstream s;
1305
    TValidateFile vf;
1306
    HOME = getenv("HOME");
2 andreas 1307
 
22 andreas 1308
    if (!HOME || !*HOME)
21 andreas 1309
    {
43 andreas 1310
        s << "Error: Environment variable HOME does not exist!";
22 andreas 1311
        __android_log_print(ANDROID_LOG_ERROR, "tpanel", "%s", s.str().c_str());
1312
        TError::setErrorMsg(s.str());
21 andreas 1313
        return false;
1314
    }
1315
 
22 andreas 1316
    localSettings.path = HOME;
1317
 
88 andreas 1318
    if (!vf.isValidDir(localSettings.path))
21 andreas 1319
    {
22 andreas 1320
        s << "Error: Path " << localSettings.path << " does not exist!";
1321
        __android_log_print(ANDROID_LOG_ERROR, "tpanel", "%s", s.str().c_str());
1322
        TError::setErrorMsg(s.str());
21 andreas 1323
        return false;
1324
    }
1325
 
22 andreas 1326
    sFileName = localSettings.path + "/" + localSettings.name;
21 andreas 1327
 
22 andreas 1328
    if (access(sFileName.c_str(), F_OK) == -1)    // Does the configuration file exist?
21 andreas 1329
    {                                       // No, than create it and also the directory structure
1330
        try
1331
        {
1332
            ofstream cfg(sFileName);
1333
 
118 andreas 1334
            string content = makeConfigDefault(localSettings.path + "/tpanel.log", localSettings.path + "/tpanel");
21 andreas 1335
            cfg.write(content.c_str(), content.size());
1336
            cfg.close();
1337
 
1338
            string path = localSettings.path + "/tpanel";
22 andreas 1339
            TTPInit init(path);
21 andreas 1340
        }
1341
        catch (std::exception& e)
1342
        {
23 andreas 1343
            s << "Error: " << e.what();
22 andreas 1344
            __android_log_print(ANDROID_LOG_ERROR, "tpanel" , "%s", s.str().c_str());
21 andreas 1345
            TError::setErrorMsg(TERRERROR, string("Error: ") + e.what());
1346
            return false;
1347
        }
1348
    }
1349
#else
90 andreas 1350
    if (!(HOME = getenv("HOME")))
116 andreas 1351
        MSG_ERROR("TConfig::findConfig: No environment variable HOME!");
2 andreas 1352
 
90 andreas 1353
    vector<string>::iterator iter;
1354
    bool found = false;
2 andreas 1355
 
90 andreas 1356
    for (iter = mCfgPaths.begin(); iter != mCfgPaths.end(); ++iter)
1357
    {
1358
        string f = *iter + "/tpanel.conf";
1359
 
1360
        if (!access(f.c_str(), R_OK))
1361
        {
1362
            sFileName = f;
1363
            localSettings.path = *iter;
113 andreas 1364
            found = true;
90 andreas 1365
            break;
1366
        }
1367
    }
1368
 
1369
    // The local configuration file has precedence over the global one.
1370
    if (HOME)
1371
    {
1372
        string f = HOME;
113 andreas 1373
#ifndef __ANDROID__
90 andreas 1374
        f += "/.tpanel.conf";
113 andreas 1375
#else
1376
        f += "/tpanel.conf";
1377
#endif
90 andreas 1378
        if (!access(f.data(), R_OK))
1379
        {
1380
            sFileName = f;
1381
            localSettings.path = HOME;
1382
            found = true;
1383
        }
1384
    }
1385
 
1386
    if (!found)
1387
    {
118 andreas 1388
        MSG_WARNING("This seems to be the first start because of missing configuration file. Will try to create a default one ...");
1389
 
1390
        if (HOME)
1391
        {
1392
            localSettings.path = HOME;
1393
            sFileName = string(HOME) + "/.tpanel.conf";
1394
 
1395
            try
1396
            {
1397
                ofstream cfg(sFileName);
1398
 
1399
                string content = makeConfigDefault(localSettings.path + "/tpanel.log", localSettings.path + "/tpanel");
1400
                cfg.write(content.c_str(), content.size());
1401
                cfg.close();
1402
 
1403
                string path = localSettings.path + "/tpanel";
1404
                TTPInit init(path);
1405
            }
1406
            catch (std::exception& e)
1407
            {
1408
                cerr << "Error: " << e.what();
1409
                TError::setErrorMsg(TERRERROR, string("Error: ") + e.what());
1410
                return false;
1411
            }
1412
        }
1413
        else
1414
        {
1415
            MSG_ERROR("TConfig::findConfig: Can't find any configuration file!");
1416
            TError::setError();
1417
            sFileName.clear();
1418
            localSettings.name.clear();
1419
            localSettings.path.clear();
1420
        }
90 andreas 1421
    }
21 andreas 1422
#endif
90 andreas 1423
    mCFile = sFileName;
1424
    return !sFileName.empty();
2 andreas 1425
}
1426
 
21 andreas 1427
/**
1428
 * @brief TConfig::readConfig reads a config file.
1429
 *
1430
 * This method reads a config file and stores the known options into the
1431
 * struct localSettings.
1432
 *
1433
 * @return `true` on success.\n
1434
 * Returns `false` on error and sets the internal error.
1435
 */
2 andreas 1436
bool TConfig::readConfig()
1437
{
35 andreas 1438
    ifstream fs;
2 andreas 1439
 
35 andreas 1440
    // First initialize the defaults
1441
    localSettings.ID = 0;
1442
    localSettings.port = 1397;
1443
    localSettings.ptype = "android";
1444
    localSettings.version = "1.0";
1445
    localSettings.longformat = false;
43 andreas 1446
    localSettings.profiling = false;
71 andreas 1447
    localSettings.systemSoundState = true;
1448
    localSettings.systemSound = "singleBeep.wav";
1449
    localSettings.systemSingleBeep = "singleBeep01.wav";
1450
    localSettings.systemDoubleBeep = "doubleBeep01.wav";
112 andreas 1451
    localSettings.ftpUser = "administrator";
1452
    localSettings.ftpPassword = "password";
115 andreas 1453
    localSettings.ftpSurface = "tpanel.tp4";
116 andreas 1454
    localSettings.sip_port = 5060;
127 andreas 1455
    localSettings.sip_portTLS = 0;
131 andreas 1456
#ifdef __ANDROID__
43 andreas 1457
    localSettings.logLevel = SLOG_NONE;
59 andreas 1458
    localSettings.logLevelBits = HLOG_NONE;
43 andreas 1459
#else
1460
    localSettings.logLevel = SLOG_PROTOCOL;
1461
#endif
2 andreas 1462
 
35 andreas 1463
    // Now get the settings from file
1464
    try
1465
    {
1466
        fs.open(mCFile.c_str(), fstream::in);
1467
    }
1468
    catch (const fstream::failure e)
1469
    {
116 andreas 1470
        cerr << "TConfig::readConfig: Error on file " << mCFile << ": " << e.what() << endl;
35 andreas 1471
        TError::setError();
1472
        return false;
1473
    }
2 andreas 1474
 
35 andreas 1475
    for (string line; getline(fs, line);)
1476
    {
1477
        size_t pos;
2 andreas 1478
 
35 andreas 1479
        if ((pos = line.find("#")) != string::npos)
1480
        {
1481
            if (pos == 0)
1482
                line.clear();
1483
            else
1484
                line = line.substr(0, pos);
1485
        }
2 andreas 1486
 
35 andreas 1487
        if (line.empty() || line.find("=") == string::npos)
1488
            continue;
2 andreas 1489
 
35 andreas 1490
        vector<string> parts = split(line, "=", true);
2 andreas 1491
 
35 andreas 1492
        if (parts.size() == 2)
1493
        {
1494
            string left = parts[0];
1495
            string right = ltrim(parts[1]);
2 andreas 1496
 
35 andreas 1497
            if (caseCompare(left, "PORT") == 0 && !right.empty())
1498
                localSettings.port = atoi(right.c_str());
1499
            else if (caseCompare(left, "LOGFILE") == 0 && !right.empty())
1500
            {
1501
                localSettings.logFile = right;
23 andreas 1502
                TStreamError::setLogFileOnly(right);
35 andreas 1503
            }
1504
            else if (caseCompare(left, "LOGLEVEL") == 0 && !right.empty())
1505
            {
1506
                TStreamError::setLogLevel(right);
1507
                localSettings.logLevel = right;
59 andreas 1508
                localSettings.logLevelBits = logLevelStrToBits(right);
35 andreas 1509
            }
1510
            else if (caseCompare(left, "ProjectPath") == 0 && !right.empty())
43 andreas 1511
            {
35 andreas 1512
                localSettings.project = right;
43 andreas 1513
#ifdef __ANDROID__
1514
                TValidateFile vf;
1515
 
1516
                if (!vf.isValidFile(right))
1517
                {
1518
                    char *HOME = getenv("HOME");
1519
 
1520
                    if (HOME)
1521
                    {
1522
                        localSettings.project = HOME;
1523
                        localSettings.project += "/tpanel";
1524
                    }
1525
                }
1526
#endif
1527
            }
11 andreas 1528
            else if (caseCompare(left, "System") == 0 && !right.empty())
1529
                localSettings.system = atoi(right.c_str());
1530
            else if (caseCompare(left, "PanelType") == 0 && !right.empty())
35 andreas 1531
                localSettings.ptype = right;
1532
            else if (caseCompare(left, "Address") == 0 && !right.empty())
1533
                localSettings.server = right;
1534
            else if (caseCompare(left, "Firmware") == 0 && !right.empty())
1535
                localSettings.version = right;
1536
            else if (caseCompare(left, "LongFormat") == 0 && !right.empty())
71 andreas 1537
                localSettings.longformat = isTrue(right);
35 andreas 1538
            else if (caseCompare(left, "NoBanner") == 0 && !right.empty())
71 andreas 1539
                localSettings.noBanner = isTrue(right);
35 andreas 1540
            else if (caseCompare(left, "CertCheck") == 0 && !right.empty())
71 andreas 1541
                localSettings.certCheck = isTrue(right);
21 andreas 1542
            else if (caseCompare(left, "Channel") == 0 && !right.empty())
35 andreas 1543
            {
1544
                localSettings.ID = atoi(right.c_str());
2 andreas 1545
 
113 andreas 1546
                if (localSettings.ID < 10000 || localSettings.ID >= 29000)
35 andreas 1547
                {
116 andreas 1548
                    cerr << "TConfig::readConfig: Invalid port number " << right << endl;
35 andreas 1549
                    localSettings.ID = 0;
1550
                }
134 andreas 1551
 
1552
                mChannel = localSettings.ID;
35 andreas 1553
            }
26 andreas 1554
            else if (caseCompare(left, "Scale") == 0 && !right.empty())
71 andreas 1555
                localSettings.scale = isTrue(right);
120 andreas 1556
            else if (caseCompare(left, "ToolbarForce") == 0 && !right.empty())
1557
                localSettings.tbforce = isTrue(right);
151 andreas 1558
            else if (caseCompare(left, "ToolbarSuppress") == 0 && !right.empty())
1559
                localSettings.tbsuppress = isTrue(right);
35 andreas 1560
            else if (caseCompare(left, "Profiling") == 0 && !right.empty())
71 andreas 1561
                localSettings.profiling = isTrue(right);
51 andreas 1562
            else if (caseCompare(left, "Password1") == 0 && !right.empty())
1563
                localSettings.password1 = right;
1564
            else if (caseCompare(left, "Password2") == 0 && !right.empty())
1565
                localSettings.password2 = right;
1566
            else if (caseCompare(left, "Password3") == 0 && !right.empty())
1567
                localSettings.password3 = right;
1568
            else if (caseCompare(left, "Password4") == 0 && !right.empty())
1569
                localSettings.password4 = right;
71 andreas 1570
            else if (caseCompare(left, "SystemSoundFile") == 0 && !right.empty())
1571
                localSettings.systemSound = right;
1572
            else if (caseCompare(left, "SystemSoundState") == 0 && !right.empty())
1573
                localSettings.systemSoundState = isTrue(right);
1574
            else if (caseCompare(left, "SystemSingleBeep") == 0 && !right.empty())
1575
                localSettings.systemSingleBeep = right;
1576
            else if (caseCompare(left, "SystemDoubleBeep") == 0 && !right.empty())
1577
                localSettings.systemDoubleBeep = right;
141 andreas 1578
            else if (caseCompare(left, "SystemVolume") == 0 && !right.empty())
1579
            {
1580
                int volume = atoi(right.c_str());
1581
 
1582
                if (volume < 0)
1583
                    volume = 0;
1584
                else if (volume > 100)
1585
                    volume = 100;
1586
 
1587
                localSettings.systemVolume = volume;
1588
            }
1589
            else if (caseCompare(left, "SystemGain") == 0 && !right.empty())
1590
            {
1591
                int gain = atoi(right.c_str());
1592
 
1593
                if (gain < 0)
1594
                    gain = 0;
1595
                else if (gain > 100)
1596
                    gain = 100;
1597
 
1598
                localSettings.systemGain = gain;
1599
            }
134 andreas 1600
            else if (caseCompare(left, "SystemRotationFix") == 0 && !right.empty())
1601
                localSettings.systemRotationFix = isTrue(right);
1602
            else if (caseCompare(left, "UUID") == 0 && !right.empty())
1603
                localSettings.uuid = right;
112 andreas 1604
            else if (caseCompare(left, "FTPuser") == 0 && !right.empty())       // FTP credentials
1605
                localSettings.ftpUser = right;
1606
            else if (caseCompare(left, "FTPpassword") == 0 && !right.empty())
1607
                localSettings.ftpPassword = right;
115 andreas 1608
            else if (caseCompare(left, "FTPsurface") == 0 && !right.empty())
1609
                localSettings.ftpSurface = right;
116 andreas 1610
            else if (caseCompare(left, "FTPpassive") == 0 && !right.empty())
1611
                localSettings.ftpPassive = isTrue(right);
115 andreas 1612
            else if (caseCompare(left, "FTPdownloadTime") == 0 && !right.empty())
1613
                localSettings.ftpLastDownload = atol(right.c_str());
104 andreas 1614
            else if (caseCompare(left, "SIP_PROXY") == 0 && !right.empty())     // SIP settings starting here
1615
                localSettings.sip_proxy = right;
1616
            else if (caseCompare(left, "SIP_PORT") == 0 && !right.empty())
1617
                localSettings.sip_port = atoi(right.c_str());
127 andreas 1618
            else if (caseCompare(left, "SIP_PORTTLS") == 0 && !right.empty())
1619
                localSettings.sip_portTLS = atoi(right.c_str());
104 andreas 1620
            else if (caseCompare(left, "SIP_STUN") == 0 && !right.empty())
1621
                localSettings.sip_stun = right;
1622
            else if (caseCompare(left, "SIP_DOMAIN") == 0 && !right.empty())
1623
                localSettings.sip_domain = right;
1624
            else if (caseCompare(left, "SIP_USER") == 0 && !right.empty())
1625
                localSettings.sip_user = right;
1626
            else if (caseCompare(left, "SIP_PASSWORD") == 0 && !right.empty())
1627
                localSettings.sip_password = right;
127 andreas 1628
            else if (caseCompare(left, "SIP_IPV4") == 0 && !right.empty())
1629
                localSettings.sip_ipv4 = isTrue(right);
1630
            else if (caseCompare(left, "SIP_IPV6") == 0 && !right.empty())
1631
                localSettings.sip_ipv6 = isTrue(right);
139 andreas 1632
            else if (caseCompare(left, "SIP_IPHONE") == 0 && !right.empty())
1633
                localSettings.sip_iphone = isTrue(right);
127 andreas 1634
            else if (caseCompare(left, "SIP_FIREWALL") == 0 && !right.empty())
1635
                localSettings.sip_firewall = sipFirewallStrToEnum(right);
104 andreas 1636
            else if (caseCompare(left, "SIP_ENABLED") == 0 && !right.empty())
1637
                localSettings.sip_enabled = isTrue(right);
26 andreas 1638
        }
35 andreas 1639
    }
2 andreas 1640
 
35 andreas 1641
    fs.close();
116 andreas 1642
    mInitialized = true;
1643
    TStreamError::setLogLevel(localSettings.logLevel);
1644
    TStreamError::setLogFile(localSettings.logFile);
2 andreas 1645
 
134 andreas 1646
    if (localSettings.uuid.empty())
1647
    {
1648
#ifdef __ANDROID__
1649
        QUuid qUid = QUuid::createUuid();
1650
        localSettings.uuid = qUid.toString().toStdString();
1651
#else
1652
        uuid_t uuid;
1653
        char sUUID[256];
1654
 
1655
        uuid_generate_random(uuid);
1656
        uuid_unparse_lower(uuid, sUUID);
1657
        localSettings.uuid.assign(sUUID);
1658
#endif
1659
        saveSettings();
1660
    }
23 andreas 1661
    if (TStreamError::checkFilter(HLOG_DEBUG))
35 andreas 1662
    {
1663
        MSG_INFO("Selected Parameters:");
1664
        MSG_INFO("    Path to cfg.: " << localSettings.path);
1665
        MSG_INFO("    Name of cfg.: " << localSettings.name);
23 andreas 1666
#ifndef __ANDROID__
1667
        MSG_INFO("    Logfile:      " << localSettings.logFile);
1668
#endif
26 andreas 1669
        MSG_INFO("    LogLevel:     " << localSettings.logLevel);
35 andreas 1670
        MSG_INFO("    Long format:  " << (localSettings.longformat ? "YES" : "NO"));
1671
        MSG_INFO("    Project path: " << localSettings.project);
23 andreas 1672
#ifndef __ANDROID__
35 andreas 1673
        MSG_INFO("    Show banner:  " << (localSettings.noBanner ? "NO" : "YES"));
23 andreas 1674
#endif
35 andreas 1675
        MSG_INFO("    Controller:   " << localSettings.server);
1676
        MSG_INFO("    Port:         " << localSettings.port);
1677
        MSG_INFO("    Channel:      " << localSettings.ID);
1678
        MSG_INFO("    Panel type:   " << localSettings.ptype);
1679
        MSG_INFO("    Firmware ver. " << localSettings.version);
26 andreas 1680
        MSG_INFO("    Scaling:      " << (localSettings.scale ? "YES" : "NO"));
35 andreas 1681
        MSG_INFO("    Profiling:    " << (localSettings.profiling ? "YES" : "NO"));
71 andreas 1682
        MSG_INFO("    System Sound: " << localSettings.systemSound);
1683
        MSG_INFO("    Sound state:  " << (localSettings.systemSoundState ? "ACTIVATED" : "DEACTIVATED"));
1684
        MSG_INFO("    Single beep:  " << localSettings.systemSingleBeep);
1685
        MSG_INFO("    Double beep:  " << localSettings.systemDoubleBeep);
141 andreas 1686
        MSG_INFO("    Volume:       " << localSettings.systemVolume);
1687
        MSG_INFO("    Gain:         " << localSettings.systemGain);
134 andreas 1688
        MSG_INFO("    Rotation:     " << (localSettings.systemRotationFix ? "LOCKED" : "UNLOCKED"));
1689
        MSG_INFO("    UUID:         " << localSettings.uuid);
115 andreas 1690
        MSG_INFO("    FTP user:     " << localSettings.ftpUser);
1691
        MSG_INFO("    FTP password: " << localSettings.ftpPassword);
1692
        MSG_INFO("    FTP surface:  " << localSettings.ftpSurface);
116 andreas 1693
        MSG_INFO("    FTP passive:  " << (localSettings.ftpPassive ? "YES" : "NO"));
115 andreas 1694
        MSG_INFO("    FTP dl. time: " << localSettings.ftpLastDownload);
127 andreas 1695
        MSG_INFO("    SIP proxy:    " << localSettings.sip_proxy);
1696
        MSG_INFO("    SIP port:     " << localSettings.sip_port);
1697
        MSG_INFO("    SIP TLS port: " << localSettings.sip_portTLS);
1698
        MSG_INFO("    SIP STUN:     " << localSettings.sip_stun);
1699
        MSG_INFO("    SIP doamain:  " << localSettings.sip_domain);
1700
        MSG_INFO("    SIP user:     " << localSettings.sip_user);
1701
        MSG_INFO("    SIP IPv4:     " << (localSettings.sip_ipv4 ? "YES" : "NO"));
1702
        MSG_INFO("    SIP IPv6:     " << (localSettings.sip_ipv6 ? "YES" : "NO"));
139 andreas 1703
        MSG_INFO("    SIP Int.Phone:" << (localSettings.sip_iphone ? "YES" : "NO"));
127 andreas 1704
        MSG_INFO("    SIP firewall: " << sipFirewallToString(localSettings.sip_firewall));
1705
        MSG_INFO("    SIP enabled:  " << (localSettings.sip_enabled ? "YES" : "NO"));
35 andreas 1706
    }
2 andreas 1707
 
35 andreas 1708
    return true;
2 andreas 1709
}
1710
 
21 andreas 1711
/**
1712
 * @brief TConfig::split splitts a string into parts.
1713
 *
1714
 * The method splitts a string into parts separated by \p seps. It puts the
1715
 * parts into a vector array.
1716
 *
1717
 * @param str           The string to split
1718
 * @param seps          The separator(s)
1719
 * @param trimEmpty     `true` = trum the parts.
1720
 *
1721
 * @return A vector array containing the parts of the string \p str.
1722
 */
2 andreas 1723
vector<string> TConfig::split(const string& str, const string& seps, const bool trimEmpty)
1724
{
116 andreas 1725
    DECL_TRACER("TConfig::split(const string& str, const string& seps, const bool trimEmpty)");
1726
 
2 andreas 1727
	size_t pos = 0, mark = 0;
1728
	vector<string> parts;
1729
 
1730
	for (auto it = str.begin(); it != str.end(); ++it)
1731
	{
1732
		for (auto sepIt = seps.begin(); sepIt != seps.end(); ++sepIt)
1733
		{
1734
			if (*it == *sepIt)
1735
			{
1736
				size_t len = pos - mark;
1737
				parts.push_back(str.substr(mark, len));
1738
				mark = pos + 1;
1739
				break;
1740
			}
1741
		}
1742
 
1743
		pos++;
1744
	}
1745
 
1746
	parts.push_back(str.substr(mark));
1747
 
1748
	if (trimEmpty)
1749
	{
1750
		vector<string> nparts;
1751
 
1752
		for (auto it = parts.begin(); it != parts.end(); ++it)
1753
		{
1754
			if (it->empty())
1755
				continue;
1756
 
1757
			nparts.push_back(*it);
1758
		}
1759
 
1760
		return nparts;
1761
	}
1762
 
1763
	return parts;
1764
}
1765
 
21 andreas 1766
/**
1767
 * @brief TConfig::caseCompare compares 2 strings
1768
 *
1769
 * This method compares 2 strings case insensitive. This means that it ignores
1770
 * the case of the letters. For example:
1771
 *
1772
 *     BLAME
1773
 *     blame
1774
 *     Blame
1775
 *
1776
 * are all the same and would return 0, which means _equal_.
1777
 *
1778
 * @param str1  1st string to compare
1779
 * @param str2  2nd string to compare
1780
 *
1781
 * @return 0 if the strings are equal\n
1782
 * less than 0 if the byte of \p str1 is bigger than the byte of \p str2\n
1783
 * grater than 0 if the byte of \p str1 is smaller than the byte of \p str2.
1784
 */
2 andreas 1785
int TConfig::caseCompare(const string& str1, const string& str2)
1786
{
116 andreas 1787
    DECL_TRACER("TConfig::caseCompare(const string& str1, const string& str2)");
1788
 
2 andreas 1789
	size_t i = 0;
1790
 
1791
	if (str1.length() != str2.length())
1792
		return ((str1.length() < str2.length()) ? -1 : 1);
1793
 
1794
	for (auto it = str1.begin(); it != str1.end(); ++it)
1795
	{
1796
		if (tolower(*it) != tolower(str2.at(i)))
1797
			return (int)(*it - str2.at(i));
1798
 
1799
		i++;
1800
	}
1801
 
1802
	return 0;
1803
}