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