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