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