Subversion Repositories tpanel

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 andreas 1
/*
322 andreas 2
 * Copyright (C) 2020 to 2023 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
 */
18
 
19
#include <string>
20
#include <string.h>
21
#include <ios>
22
#include <iomanip>
23
#include <iconv.h>
24
#include <sstream>
25
#include "tnameformat.h"
26
 
322 andreas 27
#ifdef __ANDROID__
28
#if __ANDROID_API__ < 28
29
#error "This module needs Android API level 28 or newer!"
30
#endif
31
#endif
32
 
2 andreas 33
using namespace std;
34
 
35
std::string TNameFormat::mStr;
36
 
21 andreas 37
/**
38
 * @brief TNameFormat::TNameFormat constructor
39
 */
2 andreas 40
TNameFormat::TNameFormat()
41
{
42
	DECL_TRACER("TNameFormat::TNameFormat()");
43
}
44
 
21 andreas 45
/**
46
 * @brief TNameFormat::~TNameFormat destructor
47
 */
2 andreas 48
TNameFormat::~TNameFormat()
49
{
50
	DECL_TRACER("TNameFormat::~TNameFormat()");
51
}
52
 
21 andreas 53
/**
54
 * @brief TNameFormat::toValidName filters invalid characters.
55
 *
56
 * This method filters a string for invalid characters. Allowed are all
57
 * characters between 0 to 9, a to z, A to Z and the underline(_). All other
58
 * characters will be filtered out.
59
 *
60
 * @param str   The string to filter
61
 * @return A string containing only the valid characters.
62
 */
2 andreas 63
string TNameFormat::toValidName(string& str)
64
{
65
	DECL_TRACER("TNameFormat::toValidName(string& str)");
66
	string ret;
67
 
68
	for (size_t i = 0; i < str.length(); i++)
69
	{
70
		char c = str.at(i);
71
 
72
		if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z'))
73
			c = '_';
74
 
75
		ret.push_back(c);
76
	}
77
 
78
	return ret;
79
}
80
 
21 andreas 81
/**
82
 * @brief TNameFormat::cutNumbers filters everything but digit symbols.
83
 *
84
 * This method filters a string for digits. It filters out all characters
85
 * except digits.
86
 *
87
 * @param str   String to filter.
88
 * @return A string containing only digits or an empty string if there were
89
 * no digits in \p str.
90
 */
2 andreas 91
string TNameFormat::cutNumbers(string& str)
92
{
93
	DECL_TRACER("TNameFormat::cutNumbers(string& str)");
94
	string ret;
95
 
96
	for (size_t i = 0; i < str.length(); i++)
97
	{
98
		char c = str.at(i);
99
 
100
		if (c < '0' || c > '9')
101
			continue;
102
 
103
		ret.push_back(c);
104
	}
105
 
106
	return ret;
107
}
108
 
21 andreas 109
/**
110
 * @brief TNameFormat::toShortName filters a sequence starting with a blank and ends with a dot.
111
 *
112
 * This method filters any sequence starting with one or more blanks (' ') and
113
 * end with a dot (.).
114
 *
115
 * @param str   The string to filter
116
 * @return A string containing no sequence equal (" .");
117
 */
2 andreas 118
string TNameFormat::toShortName(string& str)
119
{
120
	DECL_TRACER("TNameFormat::toShortName(string& str)");
121
	string ret;
122
	bool ignore = false;
123
 
124
	for (size_t i = 0; i < str.length(); i++)
125
	{
126
		char c = str.at(i);
127
 
128
		if (c == ' ')
129
			ignore = true;
130
 
131
		if (ignore && c == '.')
132
			ignore = false;
133
 
134
		if (!ignore)
135
			ret.push_back(c);
136
	}
137
 
138
	return ret;
139
}
140
 
21 andreas 141
/**
142
 * @brief TNameFormat::transFontName Replaces blanks and percent to unterline.
143
 *
144
 * This method replaces every blank (' ') and percent (%) with an underline (_).
145
 * Then the seuqence **.ttf** is replace by **.woff**.
146
 *
147
 * @param str   The string to evaluate
148
 * @return A filtered string.
149
 */
2 andreas 150
string TNameFormat::transFontName(string& str)
151
{
152
	DECL_TRACER("TNameFormat::transFontName(string& str)");
153
	string ret;
154
 
155
	for (size_t i = 0; i < str.length(); i++)
156
	{
157
		char c = str.at(i);
158
 
159
		if (c == ' ' || c == '%')
160
			c = '_';
161
 
162
		ret.push_back(c);
163
	}
164
 
165
	replace(ret, ".ttf", ".woff");
166
	return ret;
167
}
168
 
21 andreas 169
/**
170
 * @brief TNameFormat::toURL converts a URL into a safe URL.
171
 *
172
 * This method filters a URL in a way, that all possible dangerous characters
173
 * are replaced by a percent (%) and the byte value.
174
 *
175
 * @param str   An URL to evaluate
176
 * @return A safe URL.
177
 */
2 andreas 178
string TNameFormat::toURL(string& str)
179
{
180
	DECL_TRACER("TNameFormat::toURL(string& str)");
181
	string ret;
182
 
183
	for (size_t i = 0; i < str.length(); i++)
184
	{
185
		char c = str.at(i);
186
 
187
		if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'z') &&
188
			!(c >= 'A' && c <= 'Z') && c != '_' && c != '.' &&
189
			c != '-' && c != '/')
190
		{
191
			ret.append("%");
192
			std::stringstream stream;
193
			stream << std::setfill ('0') << std::setw(2) << std::hex << ((int)c & 0x000000ff);
194
			ret.append(stream.str());
195
		}
196
		else
197
			ret.push_back(c);
198
	}
199
 
200
	return ret;
201
}
202
 
21 andreas 203
/**
204
 * @brief TNameFormat::EncodeTo convert into another character set.
205
 *
206
 * This method takes a string and converts it into another character set.
207
 *
208
 * @param buf   A pointer to a buffer large enough to hold the result.
209
 * @param len   The length of the buffer \p buf.
210
 * @param str   A pointer to a string. The content will be converted.
211
 * @param from  The name of the character set in \p str.
212
 * @param to    The name of the target charcter set.
213
 * @return The pointer \p buf. This buffer is filled up to the length of \p str
214
 * or the zero byte. Whichever comes first.
215
 */
2 andreas 216
char *TNameFormat::EncodeTo(char* buf, size_t *len, const string& str, const string& from, const string& to)
217
{
218
	DECL_TRACER("TNameFormat::EncodeTo(char* buf, size_t *len, const string& str, const string& from, const string& to)");
219
 
220
	if (!buf || str.empty())
221
		return 0;
222
 
22 andreas 223
    iconv_t cd = iconv_open(from.c_str(), to.c_str());
2 andreas 224
 
225
	if (cd == (iconv_t) -1)
226
	{
227
		MSG_ERROR("iconv_open failed!");
228
		TError::setError();
229
		return 0;
230
	}
231
 
232
	char *in_buf = (char *)str.c_str();
233
	size_t in_left = str.length() - 1;
234
 
235
	char *out_buf = buf;
236
	size_t out_left = *len - 1;
237
 
238
	do
239
	{
323 andreas 240
		if (iconv(cd, &in_buf, &in_left, &out_buf, &out_left) == (size_t) -1)
2 andreas 241
		{
242
			MSG_ERROR("iconv failed: " << strerror(errno));
243
			TError::setError();
244
			return 0;
245
		}
246
	}
247
	while (in_left > 0 && out_left > 0);
248
 
249
	*out_buf = 0;
250
	iconv_close(cd);
251
	*len = out_buf - buf;
252
	return buf;
253
}
254
 
255
string TNameFormat::textToWeb(const string& txt)
256
{
257
	DECL_TRACER("TNameFormat::textToWeb(const string& txt)");
258
	string out;
259
 
260
	if (txt.empty())
261
		return out;
262
 
263
	for (size_t i = 0; i < txt.length(); i++)
264
	{
265
		unsigned char c = txt.at(i);
266
 
267
		if (c == '\r')
268
			continue;
269
 
270
		if (c == '\n')
271
			out += "<br>";
272
		else if (c == '&')
273
			out += "&amp;";
274
		else if (c == ';')
275
			out += "&semi;";
276
		else if (c == '<')
277
			out += "&lt;";
278
		else if (c == '>')
279
			out += "&gt;";
280
		else if (c == '\t')
281
			out += "&tab;";
282
		else if (c == '!')
283
			out += "&excl;";
284
		else if (c == '"')
285
			out += "&quot;";
286
		else if (c == '#')
287
			out += "&num;";
288
		else if (c == '\'')
289
			out += "&apos;";
290
		else if (c == '=')
291
			out += "&equals;";
292
		else if (c == '-')
293
			out += "&dash;";
294
		else if (c == '~')
295
			out += "&tilde;";
296
		else if (c == ' ')
297
			out += "&nbsp;";
298
		else
299
			out.push_back(c);
300
	}
301
 
302
	return out;
303
}
304
 
305
string TNameFormat::toHex(int num, int width)
306
{
307
	DECL_TRACER("TNameFormat::toHex(int num, int width)");
308
 
309
	string ret;
310
	std::stringstream stream;
311
	stream << std::setfill ('0') << std::setw(width) << std::hex << num;
312
	ret = stream.str();
313
	return ret;
314
}
315
 
316
string TNameFormat::strToHex(string str, int width, bool format, int indent)
317
{
318
	DECL_TRACER("TNameFormat::strToHex(string str, int width, bool format, int indent)");
319
 
320
	int len = 0, pos = 0, old = 0;
321
	int w = (format) ? 1 : width;
322
	string out, left, right;
323
	string ind;
324
 
325
	if (indent > 0)
326
	{
327
		for (int j = 0; j < indent; j++)
328
			ind.append(" ");
329
	}
330
 
331
	for (size_t i = 0; i < str.length(); i++)
332
	{
333
		if (len >= w)
334
		{
335
			left.append(" ");
336
			len = 0;
337
		}
338
 
339
		if (format && i > 0 && (pos % width) == 0)
340
		{
341
			out += ind + toHex(old, 4) + ": " + left + " | " + right + "\n";
342
			left.clear();
343
			right.clear();
344
			old = pos;
345
		}
346
 
347
		int c = str.at(i) & 0x000000ff;
348
		left.append(toHex(c, 2));
349
 
350
		if (format)
351
		{
352
			if (std::isprint(c))
353
				right.push_back(c);
354
			else
355
				right.push_back('.');
356
		}
357
 
358
		len++;
359
		pos++;
360
	}
361
 
362
	if (!format)
363
		return left;
364
	else if (pos > 0)
365
	{
366
		if ((pos % width) != 0)
367
		{
368
			for (int i = 0; i < (width - (pos % width)); i++)
369
				left.append("   ");
370
		}
371
 
372
		out += ind + toHex(old, 4)+": "+left + "  | " + right;
373
	}
374
 
375
	return out;
376
}
377
 
67 andreas 378
string TNameFormat::strToHex(const unsigned char *str, size_t length, int width, bool format, int indent)
379
{
380
    DECL_TRACER("TNameFormat::strToHex(const unsigned char *str, int width, bool format, int indent)");
381
 
382
    int len = 0, pos = 0, old = 0;
383
    int w = (format) ? 1 : width;
384
    string out, left, right;
385
    string ind;
386
 
387
    if (indent > 0)
388
    {
389
        for (int j = 0; j < indent; j++)
390
            ind.append(" ");
391
    }
392
 
393
    for (size_t i = 0; i < length; i++)
394
    {
395
        if (len >= w)
396
        {
397
            left.append(" ");
398
            len = 0;
399
        }
400
 
401
        if (format && i > 0 && (pos % width) == 0)
402
        {
403
            out += ind + toHex(old, 4) + ": " + left + " | " + right + "\n";
404
            left.clear();
405
            right.clear();
406
            old = pos;
407
        }
408
 
409
        int c = *(str+i) & 0x000000ff;
410
        left.append(toHex(c, 2));
411
 
412
        if (format)
413
        {
414
            if (std::isprint(c))
415
                right.push_back(c);
416
            else
417
                right.push_back('.');
418
        }
419
 
420
        len++;
421
        pos++;
422
    }
423
 
424
    if (!format)
425
        return left;
426
    else if (pos > 0)
427
    {
428
        if ((pos % width) != 0)
429
        {
430
            for (int i = 0; i < (width - (pos % width)); i++)
431
                left.append("   ");
432
        }
433
 
434
        out += ind + toHex(old, 4)+": "+left + "  | " + right;
435
    }
436
 
437
    return out;
438
}
439
 
2 andreas 440
string TNameFormat::latin1ToUTF8(const string& str)
441
{
442
	DECL_TRACER("TNameFormat::latin1ToUTF8(const string& str)");
443
 
444
	string out;
445
 
446
	for (size_t i = 0; i < str.length(); i++)
447
	{
448
		uint8_t ch = str.at(i);
449
 
450
		if (ch < 0x80)
451
		{
452
			out.push_back(ch);
453
		}
454
		else
455
		{
456
			out.push_back(0xc0 | ch >> 6);
457
			out.push_back(0x80 | (ch & 0x3f));
458
		}
459
	}
460
 
461
	return out;
462
}
463
 
464
string TNameFormat::cp1250ToUTF8(const string& str)
465
{
466
	DECL_TRACER("TNameFormat::cp1250ToUTF8(const string& str)");
467
 
468
	string out;
469
 
470
	for (size_t j = 0; j < str.length(); j++)
471
	{
472
		int i = -1;
473
		unsigned char ch = str.at(j);
474
		short utf = -1;
475
 
476
		if (ch < 0x80)
477
		{
478
			do
479
			{
480
				i++;
481
 
482
				if (__cht[i].ch == ch)
483
				{
484
					utf = __cht[i].byte;
485
					break;
486
				}
487
			}
488
			while (__cht[i].ch != 0xff);
489
 
490
			if (utf < 0)
491
				utf = ch;
492
		}
493
		else
494
			utf = ch;
495
 
496
		if (utf > 0x00ff)
497
		{
498
			out.push_back((utf >> 8) & 0x00ff);
499
			out.push_back(utf & 0x00ff);
500
		}
501
		else if (ch > 0x7f)
502
		{
503
			out.push_back(0xc0 | ch >> 6);
504
			out.push_back(0x80 | (ch & 0x3f));
505
		}
506
		else
507
			out.push_back(ch);
508
	}
509
 
510
	return out;
511
}
512
 
513
string TNameFormat::UTF8ToCp1250(const string& str)
514
{
515
	DECL_TRACER("TNameFormat::UTF8ToCp1250(const string& str)");
516
 
517
	char dst[1024];
518
	size_t srclen = 0;
519
	char* pIn, *pInSave;
520
 
521
	srclen = str.length();
522
	memset(&dst[0], 0, sizeof(dst));
523
 
524
	try
525
	{
526
		pIn = new char[srclen + 1];
527
		memcpy(pIn, str.c_str(), srclen);
528
		*(pIn+srclen) = 0;
529
		pInSave = pIn;
530
	}
531
	catch(std::exception& e)
532
	{
533
		MSG_ERROR(e.what());
534
		TError::setError();
535
		return "";
536
	}
537
 
538
	size_t dstlen = sizeof(dst) - 1;
539
	char* pOut = (char *)dst;
540
 
541
	iconv_t conv = iconv_open("CP1250", "UTF-8");
542
 
543
	if (conv == (iconv_t)-1)
544
	{
545
		MSG_ERROR("Error opening iconv!");
546
		TError::setError();
547
		delete[] pInSave;
548
		return str;
549
	}
550
 
551
	size_t ret = iconv(conv, &pIn, &srclen, &pOut, &dstlen);
552
	iconv_close(conv);
553
	delete[] pInSave;
554
 
555
	if (ret == (size_t)-1)
556
	{
557
		MSG_ERROR("Error converting a string!");
558
		TError::setError();
559
		return str;
560
	}
561
 
562
	return string(dst);
563
}
564
 
44 andreas 565
string TNameFormat::trimXML(const string& str)
566
{
567
    DECL_TRACER("TNameFormat::trimXML(const string& str)");
568
 
569
    string::const_iterator iter;
570
    string buffer;
571
    bool inEname = false;
572
    bool isEnd = false;
573
    bool isEEnd = false;
574
    bool isHead = false;
575
    char byte[2];
576
    byte[1] = 0;
577
 
578
    for (iter = str.begin(); iter != str.end(); ++iter)
579
    {
580
        if (*iter == '<')
581
            inEname = true;
582
 
583
        if (inEname && !isHead && *iter == '/')
584
            isEnd = true;
585
 
586
        if (inEname && !isHead && *iter == '?')
587
            isHead = true;
588
 
589
        if (inEname && isEnd && *iter == '>')
590
            inEname = isEnd = false;
591
 
592
        if (inEname && !isEEnd && *iter == '>')
593
            isEEnd = true;
594
 
595
        if (inEname && isHead && *iter == '>')
596
        {
597
            inEname = isHead = isEEnd = isEnd = false;
598
            buffer.append(">\n");
599
            continue;
600
        }
601
 
602
        if ((!inEname || isEEnd) && (*iter == ' ' || *iter == '\t' || *iter == '\r' || *iter == '\n'))
603
        {
604
            isEEnd = false;
605
 
606
            if (*iter == '\r' || *iter == '\n')
607
                inEname = false;
608
 
609
            continue;
610
        }
611
 
612
        byte[0] = *iter;
613
        buffer.append(byte);
614
    }
615
 
616
    return buffer;
617
}
618
 
2 andreas 619
string& TNameFormat::replace(const string& str, const string& old, const string& neu)
620
{
621
	mStr = str;
622
	size_t pos = mStr.find(old);
623
 
624
	while (pos != string::npos)
625
	{
626
		mStr.replace(pos, old.size(), neu);
627
		pos = str.find(old, pos + neu.size());
628
	}
629
 
630
	return mStr;
631
}
632