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