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__
26
#include <android/log.h>
27
#include "tvalidatefile.h"
28
#include "ttpinit.h"
29
#endif
30
#include "tconfig.h"
2 andreas 31
#include "terror.h"
32
 
33
using std::string;
34
using std::ifstream;
21 andreas 35
using std::ofstream;
2 andreas 36
using std::fstream;
37
using std::vector;
21 andreas 38
using std::cout;
39
using std::cerr;
40
using std::endl;
2 andreas 41
 
21 andreas 42
/**
43
 * @struct SETTINGS
44
 * @brief The SETTINGS struct bundles the configuration options.
45
 *
46
 * This structure contains variables for all possible configuration options.
47
 * It is used by the class TConfig. Through this class it's possible to
48
 * access all configuration options.
49
 */
2 andreas 50
struct SETTINGS
51
{
21 andreas 52
    string pname{"tpanel"};     //!< Name of the program (default "tpanel")
53
    string path;                //!< The path where the configuration file is located
54
    string name;                //!< The name of the configuration file
55
    string project;             //!< The path where the original project files are located
56
    string server;              //!< The name or IP address of the server to connect
57
    int system{0};              //!< The number of the AMX system
58
    int port{0};                //!< The port number
59
    int ID{0};                  //!< the panel ID (a number starting by 10000)
60
    string ptype;               //!< The type of the panel (android, ipad, iphone, ...)
61
    string version;             //!< The "firmware" version
62
    string logFile;             //!< Optional path and name of a logfile
63
    string logLevel;            //!< The log level(s).
64
    bool longformat{false};     //!< TRUE = long format
65
    bool noBanner{false};       //!< Startup without showing a banner on the command line.
66
    bool certCheck{false};      //!< TRUE = Check certificate for SSL connection
24 andreas 67
    bool scale{false};          //!< TRUE = Images are scaled to fit the whole screen
2 andreas 68
};
69
 
70
typedef struct SETTINGS settings_t;
21 andreas 71
static settings_t localSettings;    //!< Global defines settings used in class TConfig.
2 andreas 72
 
21 andreas 73
/**
74
 * @brief TConfig::TConfig constructor
75
 *
76
 * @param path  A path and name of a configuration file.
77
 */
2 andreas 78
TConfig::TConfig(const std::string& path)
79
	: mPath(path)
80
{
81
	if (findConfig())
82
		readConfig();
83
}
84
 
23 andreas 85
bool TConfig::reReadConfig()
86
{
87
    return readConfig();
88
}
89
 
21 andreas 90
/**
91
 * @brief TConfig::setProgName Sets the name of the application.
92
 * @param pname The name of the application.
93
 */
2 andreas 94
void TConfig::setProgName(const std::string& pname)
95
{
96
	localSettings.pname = pname;
97
}
98
 
21 andreas 99
/**
100
 * @brief TConfig::getProgName Retrieves the prevously stored application name.
101
 * @return The name of this application.
102
 */
2 andreas 103
std::string & TConfig::getProgName()
104
{
105
	return localSettings.pname;
106
}
107
 
21 andreas 108
/**
109
 * @brief TConfig::getChannel returns the AMX channel to use.
110
 *
111
 * The AMX channels an AMX panel can use start at 10000. This method returns
112
 * the channel number found in the configuration file. If there was no
113
 * channel defination found, it returns the default channel 10001.
114
 *
115
 * @return The AMX channel number to use.
116
 */
2 andreas 117
int TConfig::getChannel()
118
{
119
	return localSettings.ID;
120
}
121
 
21 andreas 122
/**
123
 * @brief TConfig::getConfigFileName returns the name of the configuration file.
124
 *
125
 * @return The name of the configuration file.
126
 */
2 andreas 127
std::string& TConfig::getConfigFileName()
128
{
129
	return localSettings.name;
130
}
131
 
21 andreas 132
/**
133
 * @brief TConfig::getConfigPath returns the path configuration file.
134
 *
135
 * The path was defined on the command line or found by searching the standard
136
 * directories.
137
 *
138
 * @return The path of the configuration file.
139
 */
2 andreas 140
std::string& TConfig::getConfigPath()
141
{
142
	return localSettings.path;
143
}
144
 
21 andreas 145
/**
146
 * @brief TConfig::getController returns the network name or IP address of the AMX controller.
147
 *
148
 * The network name or the IP address was read from the configuration file.
149
 *
150
 * @return The network name of the AMX controller.
151
 */
2 andreas 152
std::string& TConfig::getController()
153
{
154
	return localSettings.server;
155
}
156
 
21 andreas 157
/**
158
 * @brief TConfig::getSystem return the AMX system number.
159
 *
160
 * This number was read from the configuration file. If there was no system
161
 * number defined in the configuration file, then the default number 0 is
162
 * returned.
163
 *
164
 * @return The AMX system number.
165
 */
11 andreas 166
int TConfig::getSystem()
167
{
168
    return localSettings.system;
169
}
170
 
21 andreas 171
/**
172
 * @brief TConfig::getFirmVersion returns the version of the firmware.
173
 *
174
 * This option was read from the configuration file. There can be any version
175
 * number defined. But you must keep in mind, that the AMX controller may not
176
 * accept any number. If there was no version number defined, the standard
177
 * version number 1.0 is returned.
178
 *
179
 * @return The firmware version of this panel.
180
 */
2 andreas 181
std::string& TConfig::getFirmVersion()
182
{
183
	return localSettings.version;
184
}
185
 
21 andreas 186
/**
187
 * @brief TConfig::getLogFile the path and name of a logfile.
188
 *
189
 * If there is a logfile name defined in the configuration file, it is used
190
 * to write messages there. It depends on the _log level_ what is logged.
191
 *
192
 * @return The path and name of a logfile.
193
 */
2 andreas 194
std::string& TConfig::getLogFile()
195
{
196
	return localSettings.logFile;
197
}
198
 
21 andreas 199
/**
200
 * @brief TConfig::getLogLevel returns the defined log level.
201
 *
202
 * The loglevel can be one of the following values:
203
 *
204
 *     NONE         Logs nothing (default for Android)
205
 *     INFO         Logs only informations
206
 *     WARNING      Logs only warnings
207
 *     ERROR        Logs onls errors
208
 *     TRACE        Logs only trace messages
209
 *     DEBUG        Logs only debug messages
210
 *     PROTOCOL     Logs only INFO and ERROR (default if NOT Android)
211
 *     ALL          Logs everything
212
 *
213
 * All log levels can be combined by concatenating them with the | symbol.
214
 *
215
 * @return The log level(s) as a string.
216
 */
2 andreas 217
string& TConfig::getLogLevel()
218
{
219
	return localSettings.logLevel;
220
}
221
 
21 andreas 222
/**
223
 * @brief TConfig::getPanelType the AMX type name of the panel.
224
 *
225
 * The type name of the panel is defined in the configuration file. If this
226
 * option was not defined, the default panel _android_ is returned.
227
 *
228
 * @return The type name of the panel.
229
 */
2 andreas 230
std::string& TConfig::getPanelType()
231
{
232
	return localSettings.ptype;
233
}
234
 
21 andreas 235
/**
236
 * @brief TConfig::getPort returnes the AMX port number to connect to.
237
 *
238
 * The port number can be defined in the configuration file. If there is no
239
 * configuration the default number 1319 is returned.
240
 *
241
 * @return The AMX network port number.
242
 */
2 andreas 243
int TConfig::getPort()
244
{
245
	return localSettings.port;
246
}
247
 
21 andreas 248
/**
249
 * @brief TConfig::getProjectPath returns the path to the AMX configuration files.
250
 *
251
 * The path was read from the configuration file. This path contains all the
252
 * files needed to display the elements of the surface.
253
 *
254
 * @return The path to the AMX configuration files.
255
 */
2 andreas 256
std::string& TConfig::getProjectPath()
257
{
258
	return localSettings.project;
259
}
260
 
23 andreas 261
bool TConfig::saveLogFile(const string &file)
262
{
263
    DECL_TRACER("TConfig::saveLogFile(const string &file)");
264
 
265
    if (file.empty() || localSettings.logFile.compare(file) == 0)
266
        return false;
267
 
268
    localSettings.logFile = file;
269
    return true;
270
}
271
 
272
bool TConfig::saveLogLevel(const string &level)
273
{
274
    DECL_TRACER("TConfig::saveLogLevel(const string &level)");
275
 
276
    if (level.compare(SLOG_NONE) && level.compare(SLOG_INFO) && level.compare(SLOG_WARNING) &&
277
            level.compare(SLOG_ERROR) && level.compare(SLOG_TRACE) && level.compare(SLOG_DEBUG) &&
278
            level.compare(SLOG_PROTOCOL) && level.compare(SLOG_ALL))
279
        return false;
280
 
281
    localSettings.logLevel = level;
282
    return true;
283
}
284
 
285
bool TConfig::saveChannel(int channel)
286
{
287
    DECL_TRACER("TConfig::saveChannel(int channel)");
288
 
289
    if (channel < 10000 || channel > 12000)
290
        return false;
291
 
292
    localSettings.ID = channel;
293
    return true;
294
}
295
 
296
bool TConfig::saveController(const string &cnt)
297
{
298
    DECL_TRACER("TConfig::saveController(const string &cnt)");
299
 
300
    localSettings.server = cnt;
301
    return true;
302
}
303
 
304
bool TConfig::savePanelType(const string &pt)
305
{
306
    DECL_TRACER("TConfig::savePanelType(const string &pt)");
307
 
308
    localSettings.ptype = pt;
309
    return true;
310
}
311
 
312
bool TConfig::savePort(int port)
313
{
314
    DECL_TRACER("TConfig::savePort(int port)");
315
 
316
    if (port < 1024 || port > 32767)
317
        return false;
318
 
319
    localSettings.port = port;
320
    return true;
321
}
322
 
323
bool TConfig::saveProjectPath(const string &path)
324
{
325
    DECL_TRACER("TConfig::saveProjectPath(const string &path)");
326
 
327
    if (path.empty())
328
        return false;
329
 
330
    localSettings.project = path;
331
    return true;
332
}
333
 
334
void TConfig::saveFormat(bool format)
335
{
336
    DECL_TRACER("TConfig::saveFormat(bool format)");
337
 
338
    localSettings.longformat = format;
339
}
340
 
24 andreas 341
void TConfig::saveScale(bool scale)
342
{
343
    DECL_TRACER("TConfig::saveScale(bool scale)");
344
 
345
    localSettings.scale = scale;
346
}
347
 
23 andreas 348
bool TConfig::saveSettings()
349
{
350
    DECL_TRACER("TConfig::saveSettings()");
351
 
352
    try
353
    {
354
        string fname = localSettings.path + "/" + localSettings.name;
355
        ofstream file(fname);
356
        string lines = "LogFile=" + localSettings.logFile + "\n";
357
        lines += "LogLevel=" + localSettings.logLevel + "\n";
358
        lines += "ProjectPath=" + localSettings.project + "\n";
359
        lines += string("NoBanner=") + (localSettings.noBanner ? "true" : "false") + "\n";
360
        lines += string("LongFormat=") + (localSettings.longformat ? "true" : "false") + "\n";
361
        lines += "Address=" + localSettings.server + "\n";
362
        lines += "Port=" + std::to_string(localSettings.port) + "\n";
363
        lines += "Channel=" + std::to_string(localSettings.ID) + "\n";
364
        lines += "System=" + std::to_string(localSettings.system) + "\n";
365
        lines += "PanelType=" + localSettings.ptype + "\n";
366
        lines += "Firmware=" + localSettings.version + "\n";
367
        lines += string("CertCheck=") + (localSettings.certCheck ? "true" : "false") + "\n";
24 andreas 368
        lines += string("Scale=") + (localSettings.scale ? "true" : "false") + "\n";
23 andreas 369
        file.write(lines.c_str(), lines.size());
370
        file.close();
371
    }
372
    catch (std::exception& e)
373
    {
374
        MSG_ERROR("Couldn't write configs: " << e.what());
375
        return false;
376
    }
377
 
378
    TError::Current()->setLogFile(localSettings.logFile);
379
    TError::Current()->setLogLevel(localSettings.logLevel);
380
    return true;
381
}
382
 
21 andreas 383
/**
384
 * @brief TConfig::isLongFormat defines the format in the logfile.
385
 *
386
 * If this returns `true` the format in the logfile is a long format. This
387
 * means, that in front of each message is an additional timestamp.
388
 *
389
 * @return `true` = long format, `false` = short format (default).
390
 */
2 andreas 391
bool TConfig::isLongFormat()
392
{
393
	return localSettings.longformat;
394
}
395
 
21 andreas 396
/**
397
 * @brief TConfig::showBanner defines whether the banner should be showed or not.
398
 *
399
 * If this method returns `false` the banner on startup is not displayed.
400
 *
401
 * @return `true` = display the banner (default), `false` = show no banner.
402
 */
2 andreas 403
bool TConfig::showBanner()
404
{
405
	return !localSettings.noBanner;
406
}
407
 
21 andreas 408
/**
24 andreas 409
 * @brief TConfig::getScale returns the scale setting
410
 *
411
 * If this is set to TRUE, all images are scaled to fit the screen.
412
 *
413
 * @return scale state
414
 */
415
bool TConfig::getScale()
416
{
417
    return localSettings.scale;
418
}
419
 
420
/**
21 andreas 421
 * @brief TConfig::certCheck check the certificate if the connection is encrypted.
422
 *
423
 * Currently not implemented!
424
 *
425
 * @return `true` = check the certificate, `false` = accept any certificate (default).
426
 */
427
bool TConfig::certCheck()
428
{
429
    return localSettings.certCheck;
430
}
431
 
432
/**
433
 * @brief TConfig::findConfig search for the location of the configuration file.
434
 *
435
 * If there was no configuration file given on the command line, this method
436
 * searches for a configuration file on a few standard directories. This are:
437
 *
438
 *     /etc/tpanel.conf
439
 *     /etc/tpanel/tpanel.conf
440
 *     /usr/etc/tpanel.conf
441
 *     $HOME/.tpanel.conf
442
 *
443
 * On macOS the following additional directories are searched:
444
 *
445
 *     /opt/local/etc/tpanel.conf
446
 *     /opt/local/etc/tpanel/tpanel.conf
447
 *     /opt/local/usr/etc/tpanel.conf
448
 *
449
 * @return On success `true`, otherwise `false`.
450
 */
2 andreas 451
bool TConfig::findConfig()
452
{
453
	char *HOME = nullptr;
22 andreas 454
 
2 andreas 455
	string sFileName;
456
 
457
	if (!mPath.empty())
458
	{
459
		size_t pos = mPath.find_last_of("/");
460
 
461
		if (pos != string::npos)
462
		{
463
			localSettings.path = mPath.substr(0, pos);
464
			localSettings.name = mPath.substr(pos+1);
465
			mCFile = mPath;
466
			return !mCFile.empty();
467
		}
468
 
469
		localSettings.name = mPath;
470
		mCFile = mPath;
471
		return !mCFile.empty();
472
	}
473
 
474
	localSettings.name = "tpanel.conf";
21 andreas 475
#ifdef __ANDROID__
22 andreas 476
    std::stringstream s;
477
    TValidateFile vf;
478
    HOME = getenv("HOME");
2 andreas 479
 
22 andreas 480
    if (!HOME || !*HOME)
21 andreas 481
    {
22 andreas 482
        s << "Error: Environment variable HOME dores not exist!";
483
        __android_log_print(ANDROID_LOG_ERROR, "tpanel", "%s", s.str().c_str());
484
        TError::setErrorMsg(s.str());
21 andreas 485
        return false;
486
    }
487
 
22 andreas 488
    localSettings.path = HOME;
489
 
490
    if (!vf.isValidFile(localSettings.path))
21 andreas 491
    {
22 andreas 492
        s << "Error: Path " << localSettings.path << " does not exist!";
493
        __android_log_print(ANDROID_LOG_ERROR, "tpanel", "%s", s.str().c_str());
494
        TError::setErrorMsg(s.str());
21 andreas 495
        return false;
496
    }
497
 
22 andreas 498
    sFileName = localSettings.path + "/" + localSettings.name;
21 andreas 499
 
22 andreas 500
    if (access(sFileName.c_str(), F_OK) == -1)    // Does the configuration file exist?
21 andreas 501
    {                                       // No, than create it and also the directory structure
502
        try
503
        {
504
            ofstream cfg(sFileName);
505
 
506
            string content = "LogFile=" + localSettings.path + "/tpanel.log\n";
23 andreas 507
            content += "LogLevel=NONE\n";
21 andreas 508
            content += "ProjectPath=" + localSettings.path + "/tpanel\n";
509
            content += "LongFormat=false\n";
510
            content += "Address=0.0.0.0\n";
511
            content += "Port=1319\n";
512
            content += "Channel=10001\n";
513
            content += "PanelType=Android\n";
26 andreas 514
            content += string("Firmware=") + VERSION_STRING() + "\n";
515
            content += "Scale=false\n";
21 andreas 516
            cfg.write(content.c_str(), content.size());
517
            cfg.close();
518
 
519
            string path = localSettings.path + "/tpanel";
520
            mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
521
            string syspath = path + "/fonts";
522
            mkdir(syspath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
523
            syspath = path + "/images";
524
            mkdir(syspath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
525
            syspath = path + "/sounds";
526
            mkdir(syspath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
527
            syspath = path + "/__system";
528
            mkdir(syspath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
22 andreas 529
            TTPInit init(path);
21 andreas 530
        }
531
        catch (std::exception& e)
532
        {
23 andreas 533
            s << "Error: " << e.what();
22 andreas 534
            __android_log_print(ANDROID_LOG_ERROR, "tpanel" , "%s", s.str().c_str());
21 andreas 535
            TError::setErrorMsg(TERRERROR, string("Error: ") + e.what());
536
            return false;
537
        }
538
    }
539
#else
2 andreas 540
	if (!(HOME = getenv("HOME")))
541
		std::cerr << "TConfig::findConfig: No environment variable HOME!" << std::endl;
542
 
543
	if (!access("/etc/tpanel.conf", R_OK))
544
	{
545
		sFileName = "/etc/tpanel.conf";
546
		localSettings.path = "/etc";
547
	}
548
	else if (!access("/etc/tpanel/tpanel.conf", R_OK))
549
	{
550
		sFileName = "/etc/tpanel/tpanel.conf";
551
		localSettings.path = "/etc/tpanel";
552
	}
553
	else if (!access("/usr/etc/tpanel.conf", R_OK))
554
	{
555
		sFileName = "/usr/etc/tpanel.conf";
556
		localSettings.path = "/usr/etc";
557
	}
558
#ifdef __APPLE__
559
	if (!access("/opt/local/etc/tpanel.conf", R_OK))
560
	{
561
		sFileName = "/opt/local/etc/tpanel.conf";
562
		localSettings.path = "/opt/local/etc";
563
	}
564
	else if (!access("/opt/local/etc/tpanel/tpanel.conf", R_OK))
565
	{
566
		sFileName = "/opt/local/etc/tpanel/tpanel.conf";
567
		localSettings.path = "/opt/local/etc/tpanel";
568
	}
569
	else if (!access("/opt/local/usr/etc/tpanel.conf", R_OK))
570
	{
571
		sFileName = "/opt/local/usr/etc/tpanel.conf";
572
		localSettings.path = "/opt/local/usr/etc";
573
	}
574
#endif
575
	else if (HOME)
576
	{
577
		sFileName = HOME;
578
		sFileName += "/.amxpanel.conf";
579
		localSettings.path = HOME;
580
 
581
		if (access(sFileName.data(), R_OK))
582
		{
583
			std::cerr << "TConfig::findConfig: Can't find any configuration file!" << std::endl;
584
			TError::setError();
585
			sFileName.clear();
586
			localSettings.name.clear();
587
		}
588
		else
589
			localSettings.name = ".amxpanel.conf";
590
	}
591
	else
592
	{
593
		sFileName.clear();
594
		localSettings.name.clear();
595
		localSettings.path.clear();
596
	}
21 andreas 597
#endif
2 andreas 598
	mCFile = sFileName;
599
	return !sFileName.empty();
600
}
601
 
21 andreas 602
/**
603
 * @brief TConfig::readConfig reads a config file.
604
 *
605
 * This method reads a config file and stores the known options into the
606
 * struct localSettings.
607
 *
608
 * @return `true` on success.\n
609
 * Returns `false` on error and sets the internal error.
610
 */
2 andreas 611
bool TConfig::readConfig()
612
{
613
	ifstream fs;
614
 
615
	// First initialize the defaults
616
	localSettings.ID = 0;
617
	localSettings.port = 1397;
618
	localSettings.ptype = "android";
619
	localSettings.version = "1.0";
620
	localSettings.longformat = false;
621
 
622
	// Now get the settings from file
623
	try
624
	{
625
		fs.open(mCFile.c_str(), fstream::in);
626
	}
627
	catch (const fstream::failure e)
628
	{
629
		std::cerr << "TConfig::readConfig: Error on file " << mCFile << ": " << e.what() << std::endl;
630
		TError::setError();
631
		return false;
632
	}
633
 
634
	for (string line; getline(fs, line);)
635
	{
636
		size_t pos;
637
 
638
		if ((pos = line.find("#")) != string::npos)
639
		{
640
			if (pos == 0)
641
				line.clear();
642
			else
643
				line = line.substr(0, pos);
644
		}
645
 
646
		if (line.empty() || line.find("=") == string::npos)
647
			continue;
648
 
649
		vector<string> parts = split(line, "=", true);
650
 
651
		if (parts.size() == 2)
652
		{
653
			string left = parts[0];
654
			string right = ltrim(parts[1]);
655
 
656
			if (caseCompare(left, "PORT") == 0 && !right.empty())
657
				localSettings.port = atoi(right.c_str());
658
			else if (caseCompare(left, "LOGFILE") == 0 && !right.empty())
659
			{
660
				localSettings.logFile = right;
23 andreas 661
                TStreamError::setLogFileOnly(right);
2 andreas 662
			}
663
			else if (caseCompare(left, "LOGLEVEL") == 0 && !right.empty())
664
			{
665
				TStreamError::setLogLevel(right);
666
				localSettings.logLevel = right;
667
			}
668
			else if (caseCompare(left, "ProjectPath") == 0 && !right.empty())
669
				localSettings.project = right;
11 andreas 670
            else if (caseCompare(left, "System") == 0 && !right.empty())
671
                localSettings.system = atoi(right.c_str());
672
            else if (caseCompare(left, "PanelType") == 0 && !right.empty())
2 andreas 673
				localSettings.ptype = right;
674
			else if (caseCompare(left, "Address") == 0 && !right.empty())
675
				localSettings.server = right;
676
			else if (caseCompare(left, "Firmware") == 0 && !right.empty())
677
				localSettings.version = right;
678
			else if (caseCompare(left, "LongFormat") == 0 && !right.empty())
679
			{
680
				if (caseCompare(right, "1") == 0 || caseCompare(right, "yes") == 0 ||
681
					caseCompare(right, "true") == 0)
682
					localSettings.longformat = true;
683
				else
684
					localSettings.longformat = false;
685
			}
686
			else if (caseCompare(left, "NoBanner") == 0 && !right.empty())
687
			{
688
				if (caseCompare(right, "1") == 0 || caseCompare(right, "yes") == 0 ||
689
					caseCompare(right, "true") == 0)
690
					localSettings.noBanner = true;
691
				else
692
					localSettings.noBanner = false;
693
			}
21 andreas 694
			else if (caseCompare(left, "CertCheck") == 0 && !right.empty())
695
            {
696
                if (caseCompare(right, "1") == 0 || caseCompare(right, "yes") == 0 ||
697
                    caseCompare(right, "true") == 0 || caseCompare(right, "on") == 0)
698
                    localSettings.certCheck = true;
699
                else
700
                    localSettings.certCheck = false;
701
            }
702
            else if (caseCompare(left, "Channel") == 0 && !right.empty())
2 andreas 703
			{
704
				localSettings.ID = atoi(right.c_str());
705
 
706
				if (localSettings.ID < 10000 || localSettings.ID >= 11000)
707
				{
708
					std::cerr << "TConfig::readConfig: Invalid port number " << right << std::endl;
709
					localSettings.ID = 0;
710
				}
711
			}
26 andreas 712
            else if (caseCompare(left, "Scale") == 0 && !right.empty())
713
            {
714
                if (caseCompare(right, "1") == 0 || caseCompare(right, "yes") == 0 ||
715
                    caseCompare(right, "true") == 0 || caseCompare(right, "on") == 0)
716
                    localSettings.scale = true;
717
                else
718
                    localSettings.scale = false;
719
            }
720
        }
2 andreas 721
	}
722
 
723
	fs.close();
724
 
23 andreas 725
    if (TStreamError::checkFilter(HLOG_DEBUG))
2 andreas 726
	{
727
		MSG_INFO("Selected Parameters:");
728
		MSG_INFO("    Path to cfg.: " << localSettings.path);
729
		MSG_INFO("    Name of cfg.: " << localSettings.name);
23 andreas 730
#ifndef __ANDROID__
731
        MSG_INFO("    Logfile:      " << localSettings.logFile);
732
#endif
26 andreas 733
        MSG_INFO("    LogLevel:     " << localSettings.logLevel);
2 andreas 734
		MSG_INFO("    Long format:  " << (localSettings.longformat ? "YES" : "NO"));
735
		MSG_INFO("    Project path: " << localSettings.project);
23 andreas 736
#ifndef __ANDROID__
2 andreas 737
		MSG_INFO("    Show banner:  " << (localSettings.noBanner ? "NO" : "YES"));
23 andreas 738
#endif
2 andreas 739
		MSG_INFO("    Controller:   " << localSettings.server);
740
		MSG_INFO("    Port:         " << localSettings.port);
741
		MSG_INFO("    Channel:      " << localSettings.ID);
742
		MSG_INFO("    Panel type:   " << localSettings.ptype);
743
		MSG_INFO("    Firmware ver. " << localSettings.version);
26 andreas 744
        MSG_INFO("    Scaling:      " << (localSettings.scale ? "YES" : "NO"));
2 andreas 745
	}
746
 
747
	return true;
748
}
749
 
21 andreas 750
/**
751
 * @brief TConfig::split splitts a string into parts.
752
 *
753
 * The method splitts a string into parts separated by \p seps. It puts the
754
 * parts into a vector array.
755
 *
756
 * @param str           The string to split
757
 * @param seps          The separator(s)
758
 * @param trimEmpty     `true` = trum the parts.
759
 *
760
 * @return A vector array containing the parts of the string \p str.
761
 */
2 andreas 762
vector<string> TConfig::split(const string& str, const string& seps, const bool trimEmpty)
763
{
764
	size_t pos = 0, mark = 0;
765
	vector<string> parts;
766
 
767
	for (auto it = str.begin(); it != str.end(); ++it)
768
	{
769
		for (auto sepIt = seps.begin(); sepIt != seps.end(); ++sepIt)
770
		{
771
			if (*it == *sepIt)
772
			{
773
				size_t len = pos - mark;
774
				parts.push_back(str.substr(mark, len));
775
				mark = pos + 1;
776
				break;
777
			}
778
		}
779
 
780
		pos++;
781
	}
782
 
783
	parts.push_back(str.substr(mark));
784
 
785
	if (trimEmpty)
786
	{
787
		vector<string> nparts;
788
 
789
		for (auto it = parts.begin(); it != parts.end(); ++it)
790
		{
791
			if (it->empty())
792
				continue;
793
 
794
			nparts.push_back(*it);
795
		}
796
 
797
		return nparts;
798
	}
799
 
800
	return parts;
801
}
802
 
21 andreas 803
/**
804
 * @brief TConfig::caseCompare compares 2 strings
805
 *
806
 * This method compares 2 strings case insensitive. This means that it ignores
807
 * the case of the letters. For example:
808
 *
809
 *     BLAME
810
 *     blame
811
 *     Blame
812
 *
813
 * are all the same and would return 0, which means _equal_.
814
 *
815
 * @param str1  1st string to compare
816
 * @param str2  2nd string to compare
817
 *
818
 * @return 0 if the strings are equal\n
819
 * less than 0 if the byte of \p str1 is bigger than the byte of \p str2\n
820
 * grater than 0 if the byte of \p str1 is smaller than the byte of \p str2.
821
 */
2 andreas 822
int TConfig::caseCompare(const string& str1, const string& str2)
823
{
824
	size_t i = 0;
825
 
826
	if (str1.length() != str2.length())
827
		return ((str1.length() < str2.length()) ? -1 : 1);
828
 
829
	for (auto it = str1.begin(); it != str1.end(); ++it)
830
	{
831
		if (tolower(*it) != tolower(str2.at(i)))
832
			return (int)(*it - str2.at(i));
833
 
834
		i++;
835
	}
836
 
837
	return 0;
838
}