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