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
 
373
string TNameFormat::latin1ToUTF8(const string& str)
374
{
375
	DECL_TRACER("TNameFormat::latin1ToUTF8(const string& str)");
376
 
377
	string out;
378
 
379
	for (size_t i = 0; i < str.length(); i++)
380
	{
381
		uint8_t ch = str.at(i);
382
 
383
		if (ch < 0x80)
384
		{
385
			out.push_back(ch);
386
		}
387
		else
388
		{
389
			out.push_back(0xc0 | ch >> 6);
390
			out.push_back(0x80 | (ch & 0x3f));
391
		}
392
	}
393
 
394
	return out;
395
}
396
 
397
string TNameFormat::cp1250ToUTF8(const string& str)
398
{
399
	DECL_TRACER("TNameFormat::cp1250ToUTF8(const string& str)");
400
 
401
	string out;
402
 
403
	for (size_t j = 0; j < str.length(); j++)
404
	{
405
		int i = -1;
406
		unsigned char ch = str.at(j);
407
		short utf = -1;
408
 
409
		if (ch < 0x80)
410
		{
411
			do
412
			{
413
				i++;
414
 
415
				if (__cht[i].ch == ch)
416
				{
417
					utf = __cht[i].byte;
418
					break;
419
				}
420
			}
421
			while (__cht[i].ch != 0xff);
422
 
423
			if (utf < 0)
424
				utf = ch;
425
		}
426
		else
427
			utf = ch;
428
 
429
		if (utf > 0x00ff)
430
		{
431
			out.push_back((utf >> 8) & 0x00ff);
432
			out.push_back(utf & 0x00ff);
433
		}
434
		else if (ch > 0x7f)
435
		{
436
			out.push_back(0xc0 | ch >> 6);
437
			out.push_back(0x80 | (ch & 0x3f));
438
		}
439
		else
440
			out.push_back(ch);
441
	}
442
 
443
	return out;
444
}
445
 
446
string TNameFormat::UTF8ToCp1250(const string& str)
447
{
448
	DECL_TRACER("TNameFormat::UTF8ToCp1250(const string& str)");
449
 
450
	char dst[1024];
451
	size_t srclen = 0;
452
	char* pIn, *pInSave;
453
 
454
	srclen = str.length();
455
	memset(&dst[0], 0, sizeof(dst));
456
 
457
	try
458
	{
459
		pIn = new char[srclen + 1];
460
		memcpy(pIn, str.c_str(), srclen);
461
		*(pIn+srclen) = 0;
462
		pInSave = pIn;
463
	}
464
	catch(std::exception& e)
465
	{
466
		MSG_ERROR(e.what());
467
		TError::setError();
468
		return "";
469
	}
470
 
471
	size_t dstlen = sizeof(dst) - 1;
472
	char* pOut = (char *)dst;
473
 
474
	iconv_t conv = iconv_open("CP1250", "UTF-8");
475
 
476
	if (conv == (iconv_t)-1)
477
	{
478
		MSG_ERROR("Error opening iconv!");
479
		TError::setError();
480
		delete[] pInSave;
481
		return str;
482
	}
483
 
484
	size_t ret = iconv(conv, &pIn, &srclen, &pOut, &dstlen);
485
	iconv_close(conv);
486
	delete[] pInSave;
487
 
488
	if (ret == (size_t)-1)
489
	{
490
		MSG_ERROR("Error converting a string!");
491
		TError::setError();
492
		return str;
493
	}
494
 
495
	return string(dst);
496
}
497
 
498
string& TNameFormat::replace(const string& str, const string& old, const string& neu)
499
{
500
	mStr = str;
501
	size_t pos = mStr.find(old);
502
 
503
	while (pos != string::npos)
504
	{
505
		mStr.replace(pos, old.size(), neu);
506
		pos = str.find(old, pos + neu.size());
507
	}
508
 
509
	return mStr;
510
}
511