]> git.stg.codes - stg.git/blob - stglibs/common.lib/common.cpp
Uniform error reporting for services managment.
[stg.git] / stglibs / common.lib / common.cpp
1 /*
2  *    This program is free software; you can redistribute it and/or modify
3  *    it under the terms of the GNU General Public License as published by
4  *    the Free Software Foundation; either version 2 of the License, or
5  *    (at your option) any later version.
6  *
7  *    This program is distributed in the hope that it will be useful,
8  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *    GNU General Public License for more details.
11  *
12  *    You should have received a copy of the GNU General Public License
13  *    along with this program; if not, write to the Free Software
14  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  */
16
17 /*
18  *    Date: 27.10.2002
19  */
20
21 /*
22  *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
23  */
24
25  /*
26  $Revision: 1.42 $
27  $Date: 2010/11/08 10:11:19 $
28  $Author: faust $
29  */
30
31 // For old and dub systems
32 // Like FreeBSD4
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <unistd.h>
36
37 #include <sys/select.h>
38
39 #ifdef WIN32
40 #include <winsock2.h>
41 #else
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <sys/select.h>
46 #endif
47
48 #include <iconv.h>
49
50 #include <cstdlib>
51 #include <cstdarg>
52 #include <cstdio>
53 #include <cstring>
54 #include <cerrno>
55 #include <cassert>
56
57 #include "stg/common.h"
58
59 #ifndef INET_ADDRSTRLEN
60 #   define INET_ADDRSTRLEN 16
61 #endif
62
63 namespace
64 {
65 //---------------------------------------------------------------------------
66 unsigned char koi2win[] = {
67         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
68         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
69         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
70         0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
71         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
72         0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
73         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
74         0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
75         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
76         0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
77         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
78         0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
79         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
80         0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
81         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
82         0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
83         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
84         0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
85         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
86         0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
87         0xA0, 0xA1, 0xA2, 0xB8, 0xBA, 0xA5, 0xB3, 0xBF,
88         0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xB4, 0xAE, 0xAF,
89         0xB0, 0xB1, 0xB2, 0xA8, 0xAA, 0xB5, 0xB2, 0xAF,
90         0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xA5, 0xBE, 0xBF,
91         0xFE, 0xE0, 0xE1, 0xF6, 0xE4, 0xE5, 0xF4, 0xE3,
92         0xF5, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE,
93         0xEF, 0xFF, 0xF0, 0xF1, 0xF2, 0xF3, 0xE6, 0xE2,
94         0xFC, 0xFB, 0xE7, 0xF8, 0xFD, 0xF9, 0xF7, 0xFA,
95         0xDE, 0xC0, 0xC1, 0xD6, 0xC4, 0xC5, 0xD4, 0xC3,
96         0xD5, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE,
97         0xCF, 0xDF, 0xD0, 0xD1, 0xD2, 0xD3, 0xC6, 0xC2,
98         0xDC, 0xDB, 0xC7, 0xD8, 0xDD, 0xD9, 0xD7, 0xDA};
99
100
101 unsigned char win2koi[] = {
102         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
103         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
104         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
105         0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
106         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
107         0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
108         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
109         0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
110         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
111         0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
112         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
113         0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
114         0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
115         0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
116         0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
117         0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
118         0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
119         0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
120         0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
121         0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
122         0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xBD, 0xA6, 0xA7,
123         0xB3, 0xA9, 0xB4, 0xAB, 0xAC, 0xAD, 0xAE, 0xB7,
124         0xB0, 0xB1, 0xB6, 0xA6, 0xAD, 0xB5, 0xB6, 0xB7,
125         0xA3, 0xB9, 0xA4, 0xBB, 0xBC, 0xBD, 0xBE, 0xA7,
126         0xE1, 0xE2, 0xF7, 0xE7, 0xE4, 0xE5, 0xF6, 0xFA,
127         0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF0,
128         0xF2, 0xF3, 0xF4, 0xF5, 0xE6, 0xE8, 0xE3, 0xFE,
129         0xFB, 0xFD, 0xFF, 0xF9, 0xF8, 0xFC, 0xE0, 0xF1,
130         0xC1, 0xC2, 0xD7, 0xC7, 0xC4, 0xC5, 0xD6, 0xDA,
131         0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0,
132         0xD2, 0xD3, 0xD4, 0xD5, 0xC6, 0xC8, 0xC3, 0xDE,
133         0xDB, 0xDD, 0xDF, 0xD9, 0xD8, 0xDC, 0xC0, 0xD1};
134 }
135
136 #ifdef WIN32
137 //-----------------------------------------------------------------------------
138 const char * inet_ntop(int af, const void * src, char * dst, unsigned long length)
139 {
140 struct sockaddr_in addr;
141 addr.sin_family = af;
142 addr.sin_port = 0;
143 memcpy(&addr.sin_addr.s_addr, src, sizeof(addr.sin_addr.s_addr));
144 if (WSAAddressToStringA(reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr), 0, dst, &length))
145     {
146     return NULL;
147     }
148 return dst;
149 }
150 //-----------------------------------------------------------------------------
151 int inet_pton(int af, const char * src, void * dst)
152 {
153 // Fuck you Microsoft!
154 // Why the hell not to use const char *?
155 size_t slen = strlen(src);
156 char * buf = new char[slen + 1];
157 strncpy(buf, src, slen + 1);
158 buf[slen] = 0;
159 struct sockaddr_in addr;
160 addr.sin_family = af;
161 addr.sin_port = 0;
162 addr.sin_addr.s_addr = 0;
163 int length = sizeof(addr);
164 if (WSAStringToAddressA(buf, af, 0, reinterpret_cast<struct sockaddr *>(&addr), &length))
165     {
166     delete[] buf;
167     return -1;
168     }
169 memcpy(dst, &addr, sizeof(addr));
170 delete[] buf;
171 return 1;
172 }
173 #endif
174 //-----------------------------------------------------------------------------
175 int strtodouble2(const char * s, double &a)
176 {
177 char *res;
178
179 a = strtod(s, &res);
180
181 if (*res != 0)
182     return EINVAL;
183
184 return 0;
185 }
186 //-----------------------------------------------------------------------------
187 #ifdef DEBUG
188 int printfd(const char * __file__, const char * fmt, ...)
189 #else
190 int printfd(const char *, const char *, ...)
191 #endif
192 {
193 #ifdef DEBUG
194 char buff[1024];
195
196 time_t t = time(NULL);
197
198 va_list vl;
199 va_start(vl, fmt);
200 vsnprintf(buff, sizeof(buff), fmt, vl);
201 va_end(vl);
202
203 printf("%18s > %s > ", __file__, LogDate(t)+11);
204 printf("%s", buff);
205
206 #endif
207 return 0;
208 }
209 //-----------------------------------------------------------------------------
210 int strprintf(std::string * str, const char * fmt, ...)
211 {
212 char buff[1024];
213
214 va_list vl;
215 va_start(vl, fmt);
216 int n = vsnprintf(buff, sizeof(buff), fmt, vl);
217 va_end(vl);
218 buff[1023] = 0;
219 *str = buff;
220
221 return n;
222 }
223 //-----------------------------------------------------------------------------
224 const char *IntToKMG(int64_t a, int stat)
225 {
226 static const double K = 1024;
227 static const double M = 1024 * 1024;
228 static const double G = 1024 * 1024 * 1024;
229 static char str[30];
230 double value = a;
231
232 switch (stat)
233     {
234     case ST_B:
235         #ifdef __WIN32__
236         sprintf(str, "%Ld", a);
237         #else
238         sprintf(str, "%lld", a);
239         #endif
240         break;
241     case ST_KB:
242         sprintf(str, "%.2f kb", value / K);
243         break;
244     case ST_MB:
245         sprintf(str, "%.2f Mb", value / M);
246         break;
247     default:
248         if (a > G)
249             {
250             sprintf(str, "%.2f Gb", value / G);
251             return &str[0];
252             }
253         if (a < -G)
254             {
255             sprintf(str, "%.2f Gb", value / G);
256             return &str[0];
257             }
258         if (a > M)
259             {
260             sprintf(str, "%.2f Mb", value / M);
261             return &str[0];
262             }
263         if (a < -M)
264             {
265             sprintf(str, "%.2f Mb", value / M);
266             return &str[0];
267             }
268
269         sprintf(str, "%.2f kb", value / K);
270         break;
271     }
272 return str;
273 }
274 //---------------------------------------------------------------------------
275 void KOIToWin(const char * s1, char * s2, int l)
276 {
277 for (int j = 0; j < l; j++)
278     {
279     unsigned char t = s1[j];
280     s2[j] = koi2win[t];
281
282     if (s1[j] == 0)
283         break;
284     }
285 }
286 //---------------------------------------------------------------------------
287 void WinToKOI(const char * s1, char * s2, int l)
288 {
289 for (int j = 0; j < l; j++)
290     {
291     unsigned char t = s1[j];
292     s2[j] = win2koi[t];
293
294     if (s1[j] == 0)
295         break;
296     }
297 }
298 //---------------------------------------------------------------------------
299 void KOIToWin(const std::string & s1, std::string * s2)
300 {
301 s2->erase(s2->begin(), s2->end());
302 s2->reserve(s1.length());
303 for (int j = 0; j < (int)s1.length(); j++)
304     {
305     unsigned char t = s1[j];
306     s2->push_back(koi2win[t]);
307     }
308 }
309 //---------------------------------------------------------------------------
310 void WinToKOI(const std::string & s1, std::string * s2)
311 {
312 s2->erase(s2->begin(), s2->end());
313 s2->reserve(s1.length());
314 for (int j = 0; j < (int)s1.length(); j++)
315     {
316     unsigned char t = s1[j];
317     s2->push_back(win2koi[t]);
318     }
319 }
320 //---------------------------------------------------------------------------
321 void Encode12str(std::string & dst, const std::string & src)
322 {
323 dst.erase(dst.begin(), dst.end());
324 for (size_t i = 0; i < src.length(); i++)
325     {
326     dst.push_back('a' + (src[i] & 0x0f));
327     dst.push_back('a' + ((src[i] & 0xf0) >> 4));
328     }
329 }
330 //---------------------------------------------------------------------------
331 void Decode21str(std::string & dst, const std::string & src)
332 {
333 dst.erase(dst.begin(), dst.end());
334 for (size_t i = 0; i < src.length() / 2; i++)
335     {
336     char c1 = src[i * 2];
337     char c2 = src[i * 2 + 1];
338
339     c1 -= 'a';
340     c2 -= 'a';
341
342     dst.push_back(static_cast<char>(c1 + (c2 << 4)));
343     }
344 }
345 //---------------------------------------------------------------------------
346 std::string Encode12str(const std::string & src)
347 {
348 std::string res;
349 Encode12str(res, src);
350 return res;
351 }
352 //---------------------------------------------------------------------------
353 std::string Decode21str(const std::string & src)
354 {
355 std::string res;
356 Decode21str(res, src);
357 return res;
358 }
359 //---------------------------------------------------------------------------
360 void Encode12(char * dst, const char * src, size_t srcLen)
361 {
362 for (size_t i = 0; i <= srcLen; i++)
363     {
364     char c1 = src[i] & 0x0f;
365     char c2 = (src[i] & 0xf0) >> 4;
366
367     c1 += 'a';
368     c2 += 'a';
369
370     dst[i * 2] = c1;
371     dst[i * 2 + 1] = c2;
372     }
373 dst[srcLen * 2] = 0;
374 }
375 //---------------------------------------------------------------------------
376 void Decode21(char * dst, const char * src)
377 {
378 for (size_t i = 0; ; i++)
379     {
380     if (src[i * 2] == 0)
381         break;
382
383     char c1 = src[i * 2];
384     char c2 = src[i * 2 + 1];
385
386     c1 -= 'a';
387     c2 -= 'a';
388
389     dst[i] = static_cast<char>(c1 + (c2 << 4));
390     }
391 dst[strlen(src) / 2] = 0;
392 }
393 //---------------------------------------------------------------------------
394 int ParseIPString(const char * str, uint32_t * ips, int maxIP)
395 {
396 /*
397  *Function Name:ParseIPString
398  *
399  *Parameters:
400  ÓÔÒÏËÁ ÄÌÑ ÒÁÚÂÏÒÁ É ÍÁÓÓÉ× ËÕÄÁ ÚÁÎÏÓÉÔØ ÐÏÌÕÞÅÎÎÙÅ ÁÄÒÅÓÁ
401  *
402  *Description:
403  îÁ ×ÈÏÄÅ ÄÏÌÖÎÁ ÂÙÔØ ÓÔÒÏËÁ ×ÉÄÁ "ip1,ip2,ip3" ÉÌÉ "*"
404  ÷ ÐÅÒ×ÏÍ ÓÌÕÞÁÅ × ÍÁÓÓÉ× ÚÁÎÏÓÑÔÓÑ ÒÁÚÏÂÒÁÎÎÙÅ ÁÄÒÅÓÁ.
405  åÓÌÉ ÉÈ ÍÅÎØÛÅ MAX_IP?, ÔÏ ÐÏÓÌÅÄÎÉÊ ÁÄÒÅÓ ÂÕÄÅÔ 255.255.255.255
406  åÓÌÉ ÓÔÒÏËÁ * , ÔÏ ÐÅÒ×ÁÙÊ ÁÄÒÅÓ ÂÕÄÅÔ 0.0.0.0, Ô.Å. ÌÀÂÏÊ
407  *
408  *Returns: 0 ÅÓÌÉ ×ÓÅ ïë
409  *
410  */
411
412 char p[255];
413 int n = 0;
414
415 strncpy(p, str, 254);
416 char * pp = p;
417
418 memset(ips, 0xFF, sizeof(unsigned long) * maxIP);
419
420 if (str[0] == '*' && strlen(str) == 1)
421     {
422     ips[0] = 0;
423     return 0;
424     }
425
426 for (int i = 0; i < maxIP; i++)
427     {
428     char * p1 = strtok(pp, ",\n ");
429     pp = NULL;
430
431     if (p1 == NULL && n == 0)// ÕËÁÚÁÔÅÌØ ÎÕÌØ É ÐÒÏÞÉÔÁÎÏ ÁÄÒÅÓÏ× ÔÏÖÅ ÎÏÌØ
432         {
433         return EINVAL;
434         }
435
436     if (p1 == NULL && n)
437         {
438         return 0;
439         }
440
441     struct in_addr in;
442     if (inet_pton(AF_INET, p1, &in) != 1)
443         {
444         //printf("INADDR_NONE\n");
445         return EINVAL;
446         }
447
448     ips[n] = in.s_addr;
449
450     /*if (ips[n] == INADDR_NONE)
451         return EINVAL;*/
452
453     n++;
454
455     if (n >= maxIP)
456         return 0;
457
458     }
459
460 return 0;
461 }
462 //-----------------------------------------------------------------------------
463 int DaysInCurrentMonth()
464 {
465 time_t t = time(NULL);
466
467 struct tm * lt = localtime(&t);
468
469 return DaysInMonth(lt->tm_year, lt->tm_mon);
470 }
471 //-----------------------------------------------------------------------------
472 int DaysInMonth(unsigned year, unsigned mon)
473 {
474 assert(mon < 12 && "Month number should be 0 - 11");
475 switch (mon)
476     {
477     case 0: return 31;  //jan
478     case 1:
479         if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))
480             return 29;
481         return 28;      //feb
482     case 2: return 31;  //mar
483     case 3: return 30;  //apr
484     case 4: return 31;  //may
485     case 5: return 30;  //june
486     case 6: return 31;  //jule
487     case 7: return 31;  //aug
488     case 8: return 30;  //sep
489     case 9: return 31;  //oct
490     case 10: return 30; //nov
491     case 11: return 31; //dec
492     }
493 return -1; // We will never reach here
494 }
495 //-----------------------------------------------------------------------------
496 int Min8(int a)
497 {
498 /*
499 æÕÎËÃÉÑ ×ÏÚ×ÒÁÝÁÅÔ ÎÁÉÍÅÎØÛÅÅ ÞÉÓÌÏ ËÒÁÔÎÏÅ 8-ÍÉ ÂÏÌØÛÅÅ ÉÌÉ ÒÁ×ÎÏÅ ÚÁÄÁÎÎÏÍÕ
500  * */
501 if (a % 8 == 0)
502     return a;
503
504 return a + (8 - a % 8);
505 }
506 //-----------------------------------------------------------------------------
507 /*char * inet_ntostr(unsigned long ip)
508 {
509 struct in_addr addr = {ip};
510 return inet_ntoa(addr);
511 }*/
512 //-----------------------------------------------------------------------------
513 std::string inet_ntostring(uint32_t ip)
514 {
515     char buf[INET_ADDRSTRLEN + 1];
516     return inet_ntop(AF_INET, &ip, buf, INET_ADDRSTRLEN);
517 }
518 //-----------------------------------------------------------------------------
519 uint32_t inet_strington(const std::string & value)
520 {
521     uint32_t result;
522
523     if (inet_pton(AF_INET, value.c_str(), &result) <= 0)
524         return 0;
525
526     return result;
527 }
528 //-----------------------------------------------------------------------------
529 std::string TimeToString(time_t time)
530 {
531 struct tm brokenTime;
532
533 brokenTime.tm_wday = 0;
534 brokenTime.tm_yday = 0;
535 brokenTime.tm_isdst = 0;
536
537 gmtime_r(&time, &brokenTime);
538
539 char buf[32];
540 strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime);
541
542 return buf;
543 }
544 //-----------------------------------------------------------------------------
545 int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2)
546 {
547 char hs1[10], ms1[10], hs2[10], ms2[10];
548 char s1[25], s2[25];
549 char ss[49];
550 char *p1, *p2;
551
552 strncpy(ss, str, 48);
553
554 p1 = strtok(ss, "-");
555 if (!p1)
556     return -1;
557
558 strncpy(s1, p1, 24);
559
560 p2 = strtok(NULL, "-");
561 if (!p2)
562     return -1;
563
564 strncpy(s2, p2, 24);
565
566 p1 = strtok(s1, ":");
567 if (!p1)
568     return -1;
569
570 strncpy(hs1, p1, 9);
571
572 p2 = strtok(NULL, ":");
573 if (!p2)
574     return -1;
575
576 strncpy(ms1, p2, 9);
577
578 p1 = strtok(s2, ":");
579 if (!p1)
580     return -1;
581
582 strncpy(hs2, p1, 9);
583
584 p2 = strtok(NULL, ":");
585 if (!p2)
586     return -1;
587
588 strncpy(ms2, p2, 9);
589
590 if (str2x(hs1, h1) != 0)
591     return -1;
592
593 if (str2x(ms1, m1) != 0)
594     return -1;
595
596 if (str2x(hs2, h2) != 0)
597     return -1;
598
599 if (str2x(ms2, m2) != 0)
600     return -1;
601
602 return 0;
603 }
604 /*//---------------------------------------------------------------------------
605 bool IsDigit(char c)
606 {
607 if (c >= '0' && c <= '9')
608     return true;
609 return false;
610 }
611 //-----------------------------------------------------------------------------
612 bool IsAlpha(char c)
613 {
614 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
615     return true;
616 return false;
617 }*/
618 //-----------------------------------------------------------------------------
619 const char * LogDate(time_t t)
620 {
621 static char s[32];
622 struct tm * tt = localtime(&t);
623
624 snprintf(s, 20, "%d-%s%d-%s%d %s%d:%s%d:%s%d",
625          tt->tm_year + 1900,
626          tt->tm_mon + 1 < 10 ? "0" : "", tt->tm_mon + 1,
627          tt->tm_mday    < 10 ? "0" : "", tt->tm_mday,
628          tt->tm_hour    < 10 ? "0" : "", tt->tm_hour,
629          tt->tm_min     < 10 ? "0" : "", tt->tm_min,
630          tt->tm_sec     < 10 ? "0" : "", tt->tm_sec);
631
632 return s;
633 }
634 //-----------------------------------------------------------------------------
635 uint32_t CalcMask(uint32_t msk)
636 {
637 if (msk >= 32) return 0xFFffFFff;
638 if (msk == 0) return 0;
639 return htonl(0xFFffFFff << (32 - msk));
640 }
641 //---------------------------------------------------------------------------
642 void TouchFile(const std::string & fileName)
643 {
644 FILE * f = fopen(fileName.c_str(), "w");
645 if (f)
646     fclose(f);
647 }
648 //---------------------------------------------------------------------------
649 #ifdef WIN32
650 void EncodeStr(char * str, unsigned long serial, int useHDD)
651 {
652 int len = strlen(str);
653 char stren[100];
654 int i, j = 0;
655 char c1, c2;
656 char serial_c[sizeof(serial)];
657 memcpy(serial_c, &serial, sizeof(serial));
658
659 for (i = 0; i < len; i++)
660     {
661     if (!useHDD)
662         str[i] = str[i]^49;
663     else
664         {
665         str[i] = str[i]^serial_c[j%sizeof(serial)];
666         j++;
667         }
668     }
669
670 for (i = 0; i < 2*len; i++)
671     {
672     if (i%2)
673         {
674         c1 = (str[i/2] >> 4);
675         c1 = c1 + 50;
676         stren[i] = c1;
677         }
678     else
679         {
680         c2 = (str[i/2] & 0x0f);
681         c2 += 50;
682         stren[i] = c2;
683         }
684     }
685 stren[i] = 0;
686 strcpy(str, stren);
687 }
688 //---------------------------------------------------------------------------
689 void DecodeStr(char * str, unsigned long serial, int useHDD)
690 {
691 size_t len = strlen(str);
692 char strdc[100];
693 char serial_c[sizeof(serial)];
694 memcpy(serial_c, &serial, sizeof(serial));
695
696 for (size_t i = 0; i < len; i += 2)
697     {
698     char c1 = (str[i] - 50);
699     char c2 = (str[i+1] - 50)<<4;
700     strdc[i/2] = c1+c2;
701     }
702 for (size_t i = 0; i < len/2; i++)
703     {
704     if (!useHDD)
705         strdc[i] = strdc[i]^49;
706     else
707         {
708         strdc[i] = strdc[i]^serial_c[j%sizeof(serial)];
709         j++;
710         }
711     }
712 strdc[i] = 0;
713 strcpy(str, strdc);
714 }
715 //---------------------------------------------------------------------------
716 #endif //WIN32
717 void SwapBytes(uint16_t & value)
718 {
719     value = static_cast<uint16_t>((value >> 8) |
720                                   (value << 8));
721 }
722 //---------------------------------------------------------------------------
723 void SwapBytes(uint32_t & value)
724 {
725     value = static_cast<uint32_t>((value >> 24) |
726                                   ((value << 8) &  0x00FF0000L) |
727                                   ((value >> 8) &  0x0000FF00L) |
728                                   (value << 24));
729 }
730 //---------------------------------------------------------------------------
731 void SwapBytes(uint64_t & value)
732 {
733     value = static_cast<uint64_t>((value >> 56) |
734                                   ((value << 40) & 0x00FF000000000000LL) |
735                                   ((value << 24) & 0x0000FF0000000000LL) |
736                                   ((value << 8)  & 0x000000FF00000000LL) |
737                                   ((value >> 8)  & 0x00000000FF000000LL) |
738                                   ((value >> 24) & 0x0000000000FF0000LL) |
739                                   ((value >> 40) & 0x000000000000FF00LL) |
740                                   (value << 56));
741 }
742 //---------------------------------------------------------------------------
743 void SwapBytes(int16_t & value)
744 {
745     uint16_t temp = value;
746     SwapBytes(temp);
747     value = temp;
748 }
749 //---------------------------------------------------------------------------
750 void SwapBytes(int32_t & value)
751 {
752     uint32_t temp = value;
753     SwapBytes(temp);
754     value = temp;
755 }
756 //---------------------------------------------------------------------------
757 void SwapBytes(int64_t & value)
758 {
759     uint64_t temp = value;
760     SwapBytes(temp);
761     value = temp;
762 }
763 //---------------------------------------------------------------------------
764 int str2x(const std::string & str, int32_t & x)
765 {
766 x = static_cast<int32_t>(strtol(str.c_str(), NULL, 10));
767
768 if (errno == ERANGE)
769     return -1;
770
771 return 0;
772 }
773 //---------------------------------------------------------------------------
774 int str2x(const std::string & str, uint32_t & x)
775 {
776 x = static_cast<uint32_t>(strtoul(str.c_str(), NULL, 10));
777
778 if (errno == ERANGE)
779     return -1;
780
781 return 0;
782 }
783 #ifndef WIN32
784 //---------------------------------------------------------------------------
785 int str2x(const std::string & str, int64_t & x)
786 {
787 x = strtoll(str.c_str(), NULL, 10);
788
789 if (errno == ERANGE)
790     return -1;
791
792 return 0;
793 }
794 //---------------------------------------------------------------------------
795 int str2x(const std::string & str, uint64_t & x)
796 {
797 x = strtoull(str.c_str(), NULL, 10);
798
799 if (errno == ERANGE)
800     return -1;
801
802 return 0;
803 }
804 #endif
805 //---------------------------------------------------------------------------
806 const std::string & x2str(uint32_t x, std::string & s)
807 {
808 return unsigned2str(x, s);
809 }
810 //---------------------------------------------------------------------------
811 const std::string & x2str(uint64_t x, std::string & s)
812 {
813 return unsigned2str(x, s);
814 }
815 //---------------------------------------------------------------------------
816 const std::string & x2str(double x, std::string & s)
817 {
818 char buf[256];
819 snprintf(buf, sizeof(buf), "%f", x);
820 s = buf;
821 return s;
822 }
823 //---------------------------------------------------------------------------
824 std::string & TrimL(std::string & val)
825 {
826 size_t pos = val.find_first_not_of(" \t");
827 if (pos == std::string::npos)
828     {
829     val.erase(val.begin(), val.end());
830     }
831 else
832     {
833     val.erase(0, pos);
834     }
835 return val;
836 }
837 //---------------------------------------------------------------------------
838 std::string & TrimR(std::string & val)
839 {
840 size_t pos = val.find_last_not_of(" \t");
841 if (pos != std::string::npos)
842     {
843     val.erase(pos + 1);
844     }
845 return val;
846 }
847 //---------------------------------------------------------------------------
848 std::string & Trim(std::string & val)
849 {
850 return TrimR(TrimL(val));
851 }
852 //---------------------------------------------------------------------------
853 std::string Trim(const std::string & val)
854 {
855 std::string res(val);
856 return TrimR(TrimL(res));
857 }
858 //---------------------------------------------------------------------------
859 std::string ToLower(const std::string & value)
860 {
861     std::string res;
862     for (std::string::size_type pos = 0; pos < value.length(); ++pos)
863         res += tolower(value[pos]);
864     return res;
865 }
866 //---------------------------------------------------------------------------
867 std::string ToUpper(const std::string & value)
868 {
869     std::string res;
870     for (std::string::size_type pos = 0; pos < value.length(); ++pos)
871         res += toupper(value[pos]);
872     return res;
873 }
874 //---------------------------------------------------------------------------
875 #ifdef WIN32
876 static int is_leap(unsigned y)
877 {
878     y += 1900;
879     return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
880 }
881 #endif
882 //---------------------------------------------------------------------------
883
884 time_t stg_timegm(struct tm * brokenTime)
885 {
886 #ifdef WIN32
887 static const unsigned ndays[2][12] ={
888     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
889     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
890 time_t res = 0;
891 for (int i = 70; i < brokenTime->tm_year; ++i)
892     res += is_leap(i) ? 366 : 365;
893 for (int i = 0; i < brokenTime->tm_mon; ++i)
894     res += ndays[is_leap(brokenTime->tm_year)][i];
895 res += brokenTime->tm_mday - 1;
896 res *= 24;
897 res += brokenTime->tm_hour;
898 res *= 60;
899 res += brokenTime->tm_min;
900 res *= 60;
901 res += brokenTime->tm_sec;
902 return res;
903 #else
904 #ifdef HAVE_TIMEGM
905 return timegm(brokenTime);
906 #else
907 time_t ret;
908 char *tz;
909 tz = getenv("TZ");
910 setenv("TZ", "", 1);
911 tzset();
912 ret = mktime(brokenTime);
913 if (tz)
914     setenv("TZ", tz, 1);
915 else
916     unsetenv("TZ");
917 tzset();
918 return ret;
919 #endif // HAVE_TIMEGM
920 #endif // WIN32
921 }
922 //---------------------------------------------------------------------------
923 std::string IconvString(const std::string & source,
924                         const std::string & from,
925                         const std::string & to)
926 {
927 if (source.empty())
928     return std::string();
929
930 size_t inBytesLeft = source.length() + 1;
931 size_t outBytesLeft = source.length() * 2 + 1;
932
933 char * inBuf = new char[inBytesLeft];
934 char * outBuf = new char[outBytesLeft];
935
936 strncpy(inBuf, source.c_str(), source.length());
937
938 inBuf[source.length()] = 0;
939
940 #if defined(FREE_BSD) || defined(FREE_BSD5) || defined(WIN32)
941 const char * srcPos = inBuf;
942 #else
943 char * srcPos = inBuf;
944 #endif
945 char * dstPos = outBuf;
946
947 iconv_t handle = iconv_open(to.c_str(),
948                             from.c_str());
949
950 if (handle == iconv_t(-1))
951     {
952     if (errno == EINVAL)
953         {
954         printfd(__FILE__, "IconvString(): iconv from %s to %s failed\n", from.c_str(), to.c_str());
955         delete[] outBuf;
956         delete[] inBuf;
957         return source;
958         }
959     else
960         printfd(__FILE__, "IconvString(): iconv_open error\n");
961
962     delete[] outBuf;
963     delete[] inBuf;
964     return source;
965     }
966
967 size_t res = iconv(handle,
968                    &srcPos, &inBytesLeft,
969                    &dstPos, &outBytesLeft);
970
971 if (res == size_t(-1))
972     {
973     printfd(__FILE__, "IconvString(): '%s'\n", strerror(errno));
974
975     iconv_close(handle);
976     delete[] outBuf;
977     delete[] inBuf;
978     return source;
979     }
980
981 dstPos = 0;
982
983 std::string dst(outBuf);
984
985 iconv_close(handle);
986
987 delete[] outBuf;
988 delete[] inBuf;
989
990 return dst;
991 }
992
993 int ParseYesNo(const std::string & str, bool * val)
994 {
995 if (0 == strncasecmp(str.c_str(), "yes", 3))
996     {
997     *val = true;
998     return 0;
999     }
1000
1001 if (0 == strncasecmp(str.c_str(), "no", 2))
1002     {
1003     *val = false;
1004     return 0;
1005     }
1006
1007 return -1;
1008 }
1009
1010 int ParseInt(const std::string & str, int * val)
1011 {
1012 if (str2x<int>(str, *val))
1013     return -1;
1014 return 0;
1015 }
1016
1017 int ParseUnsigned(const std::string & str, unsigned * val)
1018 {
1019 if (str2x<unsigned>(str, *val))
1020     return -1;
1021 return 0;
1022 }
1023
1024 int ParseIntInRange(const std::string & str, int min, int max, int * val)
1025 {
1026 if (ParseInt(str, val) != 0)
1027     return -1;
1028
1029 if (*val < min || *val > max)
1030     return -1;
1031
1032 return 0;
1033 }
1034
1035 int ParseUnsignedInRange(const std::string & str, unsigned min,
1036                          unsigned max, unsigned * val)
1037 {
1038 if (ParseUnsigned(str, val) != 0)
1039     return -1;
1040
1041 if (*val < min || *val > max)
1042     return -1;
1043
1044 return 0;
1045 }
1046
1047 bool WaitPackets(int sd)
1048 {
1049 fd_set rfds;
1050 FD_ZERO(&rfds);
1051 FD_SET(sd, &rfds);
1052
1053 struct timeval tv;
1054 tv.tv_sec = 0;
1055 tv.tv_usec = 500000;
1056
1057 int res = select(sd + 1, &rfds, NULL, NULL, &tv);
1058 if (res == -1) // Error
1059     {
1060     if (errno != EINTR)
1061         printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
1062     return false;
1063     }
1064
1065 if (res == 0) // Timeout
1066     return false;
1067
1068 return true;
1069 }
1070
1071 bool ReadAll(int sd, void * dest, size_t size)
1072 {
1073 size_t done = 0;
1074 char * ptr = static_cast<char *>(dest);
1075 while (done < size)
1076     {
1077     if (!WaitPackets(sd))
1078         return false;
1079     ssize_t res = read(sd, ptr + done, size - done);
1080     if (res < 0)
1081         return false;
1082     if (res == 0)
1083         return true;
1084     done += res;
1085     }
1086 return true;
1087 }
1088
1089 bool WriteAll(int sd, const void * source, size_t size)
1090 {
1091 size_t done = 0;
1092 const char * ptr = static_cast<const char *>(source);
1093 while (done < size)
1094     {
1095     ssize_t res = write(sd, ptr + done, size - done);
1096     if (res <= 0)
1097         return false;
1098     done += res;
1099     }
1100 return true;
1101 }
1102
1103 std::string ToPrintable(const std::string & src)
1104 {
1105     std::string dest;
1106
1107     for (size_t i = 0; i < src.size(); ++i)
1108         if (std::isprint(src[i]))
1109             dest += src[i];
1110         else
1111             dest += "\\" + x2str(src[i]);
1112
1113     return dest;
1114 }