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