1
// *************************************************************************
6
// * Purpose: Various utilities
8
// * Author: Peter Hofmann (software@pxh.de)
10
// * Created: 4.5.1999
11
// *************************************************************************
14
#include <gsm_config.h>
16
#include <gsmlib/gsm_nls.h>
17
#include <gsmlib/gsm_util.h>
18
#include <gsmlib/gsm_sysdep.h>
26
#if !defined(HAVE_CONFIG_H) || defined(HAVE_UNISTD_H)
29
#if !defined(HAVE_CONFIG_H) || defined(HAVE_MALLOC_H)
34
// switch on vsnprintf() prototype in stdio.h
42
using namespace gsmlib;
44
// Latin-1 undefined character (code 172 (Latin-1 boolean not, "�"))
47
// GSM undefined character (code 16 (GSM Delta))
48
const int GSM_NOP = 16;
50
// conversion tables, Latin1 to GSM and GSM to Latin1
52
static unsigned char gsmToLatin1Table[] =
54
// 0 '@', '�', '$', '�', '�', '�', '�', '�',
55
'@', 163, '$', 165, 232, 233, 249, 236,
56
// 8 '�', '�', LF, '�', '�', CR, '�', '�',
57
242, 199, 10, 216, 248, 13, 197, 229,
58
// 16 '�', '_', '�', '�', '�', '�', '�', '�',
59
NOP, '_', NOP, NOP, NOP, NOP, NOP, NOP,
60
// 24 '�', '�', '�', '�', '�', '�', '�', '�',
61
NOP, NOP, NOP, NOP, 198, 230, 223, 201,
62
// 32 ' ', '!', '"', '#', '�', '%', '&', ''',
63
' ', '!', '"', '#', 164, '%', '&', '\'',
64
// 40 '(', ')', '*', '+', ',', '-', '.', '/',
65
'(', ')', '*', '+', ',', '-', '.', '/',
66
// 48 '0', '1', '2', '3', '4', '5', '6', '7',
67
'0', '1', '2', '3', '4', '5', '6', '7',
68
// 56 '8', '9', ':', ';', '<', '=', '>', '?',
69
'8', '9', ':', ';', '<', '=', '>', '?',
70
// 64 '�', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
71
161, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
72
// 72 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
73
'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
74
// 80 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
75
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
76
// 88 'X', 'Y', 'Z', '�', '�', '�', '�', '�',
77
'X', 'Y', 'Z', 196, 214, 209, 220, 167,
78
// 96 '�', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
79
191, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
80
// 104 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
81
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
82
// 112 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
83
'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
84
// 120 'x', 'y', 'z', '�', '�', '�', '�', '�',
85
'x', 'y', 'z', 228, 246, 241, 252, 224
88
static unsigned char latin1ToGsmTable[256];
90
static class Latin1ToGsmTableInit
93
Latin1ToGsmTableInit()
95
memset((void*)latin1ToGsmTable, GSM_NOP, 256);
96
for (int i = 0; i < 128; i++)
97
if (gsmToLatin1Table[i] != NOP)
98
latin1ToGsmTable[gsmToLatin1Table[i]] = i;
100
} latin1ToGsmTableInit;
102
string gsmlib::gsmToLatin1(string s)
104
string result(s.length(), 0);
105
for (string::size_type i = 0; i < s.length(); i++)
106
result[i] = (unsigned char)s[i] > 127 ? NOP : gsmToLatin1Table[s[i]];
110
string gsmlib::latin1ToGsm(string s)
112
string result(s.length(), 0);
113
for (string::size_type i = 0; i < s.length(); i++)
114
result[i] = latin1ToGsmTable[(unsigned char)s[i]];
118
static unsigned char byteToHex[] =
119
{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
120
'A', 'B', 'C', 'D', 'E', 'F'};
122
string gsmlib::bufToHex(const unsigned char *buf, unsigned long length)
124
const unsigned char *bb = buf;
126
result.reserve(length * 2);
128
for (unsigned long i = 0; i < length; ++i)
130
result += byteToHex[*bb >> 4];
131
result += byteToHex[*bb++ & 0xf];
136
bool gsmlib::hexToBuf(const string &hexString, unsigned char *buf)
138
if (hexString.length() % 2 != 0)
141
unsigned char *bb = buf;
142
for (unsigned int i = 0; i < hexString.length(); i += 2)
144
unsigned char c = hexString[i];
145
if (! isdigit(c) && ! ('a' <= c && c <= 'f') && ! ('A' <= c && c <= 'F'))
147
*bb = (isdigit(c) ? c - '0' :
148
((('a' <= c && c <= 'f') ? c - 'a' : c - 'A')) + 10) << 4;
149
c = hexString[i + 1];
150
if (! isdigit(c) && ! ('a' <= c && c <= 'f') && ! ('A' <= c && c <= 'F'))
152
*bb++ |= isdigit(c) ? c - '0' :
153
((('a' <= c && c <= 'f') ? c - 'a' : c - 'A') + 10);
158
string gsmlib::intToStr(int i)
168
string gsmlib::removeWhiteSpace(string s)
171
for (unsigned int i = 0; i < s.length(); ++i)
179
// helper routine, find out whether filename starts with "COM"
180
static bool isCom(string filename)
182
filename = removeWhiteSpace(lowercase(filename));
184
if ( filename.compare(0,4,"\\\\.\\") == 0 )
186
return filename.length() < 3 || filename.substr(0, 3) == "com";
190
bool gsmlib::isFile(string filename)
193
// stat does not work reliably under Win32 to indicate devices
203
if (stat(filename.c_str(), &statBuf) != 0)
205
stringPrintf(_("error when calling stat('%s') (errno: %d/%s)"),
206
filename.c_str(), errno, strerror(errno)),
210
if (S_ISLNK(statBuf.st_mode))
215
char *buffer = (char*)malloc(size);
216
int nchars = readlink(filename.c_str(), buffer, size);
219
filename.assign(buffer, nchars);
228
else if (S_ISCHR(statBuf.st_mode))
232
if (S_ISREG(statBuf.st_mode))
236
stringPrintf(_("file '%s' is neither file nor character device"),
240
throw GsmException(_("maxmimum number of symbolic links exceeded"),
244
void gsmlib::renameToBackupFile(string filename) throw(GsmException)
246
string backupFilename = filename + "~";
247
unlink(backupFilename.c_str());
248
if (rename(filename.c_str(), backupFilename.c_str()) < 0)
250
stringPrintf(_("error renaming '%s' to '%s'"),
251
filename.c_str(), backupFilename.c_str()),
259
NoCopy::NoCopy(NoCopy &n)
261
cerr << "ABORT: NoCopy copy constructor used" << endl;
265
NoCopy &NoCopy::operator=(NoCopy &n)
267
cerr << "ABORT: NoCopy::operator= used" << endl;
273
string gsmlib::lowercase(string s)
276
for (unsigned int i = 0; i < s.length(); ++i)
277
result += tolower(s[i]);
281
int gsmlib::checkNumber(string s) throw(GsmException)
283
for (unsigned int i = 0; i < s.length(); ++i)
285
throw GsmException(stringPrintf(_("expected number, got '%s'"),
286
s.c_str()), ParameterError);
288
istrstream is(s.c_str());
293
#ifdef HAVE_VSNPRINTF
294
string gsmlib::stringPrintf(const char *format, ...)
297
va_start(args, format);
301
char *buf = (char*)alloca(sizeof(char) * size);
302
int nchars = vsnprintf(buf, size, format, args);
306
return string(buf, nchars);
314
char gsmlib::__s[20000]; // buffer for the replacement macro
315
#endif // HAVE_VSNPRINTF
318
int gsmlib::debugLevel()
320
char *s = getenv("GSMLIB_DEBUG");
321
if (s == NULL) return 0;
322
return checkNumber(s);
326
// interrupt interface
330
static InterruptBase *interruptObject = NULL;
333
void gsmlib::setInterruptObject(InterruptBase *intObject)
335
interruptObject = intObject;
338
bool gsmlib::interrupted()
340
return interruptObject != NULL && interruptObject->interrupted();
343
void gsmlib::checkTextAndTelephone(string text, string telephone)
346
if (text.find('"') != string::npos)
348
stringPrintf(_("text '%s' contains illegal character '\"'"),
352
for (unsigned int i = 0; i < telephone.length(); ++i)
353
if (! isdigit(telephone[i]) && ! (telephone[i] == '+') &&
354
! (telephone[i] == '*') && ! (telephone[i] == '#') &&
355
! (telephone[i] == 'p') && ! (telephone[i] == 'w') &&
356
! (telephone[i] == 'P') && ! (telephone[i] == 'W'))
358
stringPrintf(_("illegal character in telephone number '%s'"),
359
telephone.c_str()), ParameterError);
362
// progress interface
366
static ProgressBase *progressObject = NULL;
369
void gsmlib::setProgressObject(ProgressBase *progObject)
371
progressObject = progObject;
374
void gsmlib::reportProgress(int part, int total)
376
if (progressObject != NULL)
377
progressObject->reportProgress(part, total);