1 /*
2 * purple
3 *
4 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
19 *
20 */
21 #include <winsock2.h>
22 #include <ws2tcpip.h>
23 #include <io.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <sys/timeb.h>
28 #include <sys/stat.h>
29 #include <time.h>
30 #include <glib.h>
31 #include "config.h"
32 #include "debug.h"
33 #include "libc_internal.h"
34 #include "util.h"
35 #include <glib/gstdio.h>
36
37 /** This is redefined here because we can't include internal.h */
38 #ifdef ENABLE_NLS
39 # include <locale.h>
40 # include <libintl.h>
41 # define _(String) ((const char *)dgettext(PACKAGE, String))
42 # ifdef gettext_noop
43 # define N_(String) gettext_noop (String)
44 # else
45 # define N_(String) (String)
46 # endif
47 #else
48 # include <locale.h>
49 # define N_(String) (String)
50 # ifndef _
51 # define _(String) ((const char *)String)
52 # endif
53 # define ngettext(Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
54 # define dngettext(Domain, Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
55 #endif
56
57 #ifndef S_ISDIR
58 # define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR)
59 #endif
60
61 static char errbuf[1024];
62
63 /* helpers */
wpurple_is_socket(int fd)64 static int wpurple_is_socket( int fd ) {
65 int optval;
66 int optlen = sizeof(int);
67
68 if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) {
69 int error = WSAGetLastError();
70 if( error == WSAENOTSOCK )
71 return FALSE;
72 else {
73 purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_is_socket: getsockopt returned error: %d\n", error);
74 return FALSE;
75 }
76 }
77 return TRUE;
78 }
79
80 /* socket.h */
wpurple_socket(int namespace,int style,int protocol)81 int wpurple_socket (int namespace, int style, int protocol) {
82 int ret;
83
84 ret = socket( namespace, style, protocol );
85
86 if( ret == INVALID_SOCKET ) {
87 errno = WSAGetLastError();
88 return -1;
89 }
90 return ret;
91 }
92
wpurple_connect(int socket,struct sockaddr * addr,u_long length)93 int wpurple_connect(int socket, struct sockaddr *addr, u_long length) {
94 int ret;
95
96 ret = connect( socket, addr, length );
97
98 if( ret == SOCKET_ERROR ) {
99 errno = WSAGetLastError();
100 if( errno == WSAEWOULDBLOCK )
101 errno = WSAEINPROGRESS;
102 return -1;
103 }
104 return 0;
105 }
106
wpurple_getsockopt(int socket,int level,int optname,void * optval,socklen_t * optlenptr)107 int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) {
108 if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) {
109 errno = WSAGetLastError();
110 return -1;
111 }
112 return 0;
113 }
114
wpurple_setsockopt(int socket,int level,int optname,const void * optval,socklen_t optlen)115 int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
116 if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) {
117 errno = WSAGetLastError();
118 return -1;
119 }
120 return 0;
121 }
122
wpurple_getsockname(int socket,struct sockaddr * addr,socklen_t * lenptr)123 int wpurple_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) {
124 if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) {
125 errno = WSAGetLastError();
126 return -1;
127 }
128 return 0;
129 }
130
wpurple_bind(int socket,struct sockaddr * addr,socklen_t length)131 int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length) {
132 if(bind(socket, addr, length) == SOCKET_ERROR) {
133 errno = WSAGetLastError();
134 return -1;
135 }
136 return 0;
137 }
138
wpurple_listen(int socket,unsigned int n)139 int wpurple_listen(int socket, unsigned int n) {
140 if(listen(socket, n) == SOCKET_ERROR) {
141 errno = WSAGetLastError();
142 return -1;
143 }
144 return 0;
145 }
146
wpurple_sendto(int socket,const void * buf,size_t len,int flags,const struct sockaddr * to,socklen_t tolen)147 int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) {
148 int ret;
149 if ((ret = sendto(socket, buf, len, flags, to, tolen)
150 ) == SOCKET_ERROR) {
151 errno = WSAGetLastError();
152 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
153 errno = EAGAIN;
154 return -1;
155 }
156 return ret;
157 }
158
159 /* fcntl.h */
160 /* This is not a full implementation of fcntl. Update as needed.. */
wpurple_fcntl(int socket,int command,...)161 int wpurple_fcntl(int socket, int command, ...) {
162
163 switch( command ) {
164 case F_GETFL:
165 return 0;
166
167 case F_SETFL:
168 {
169 va_list args;
170 int val;
171 int ret=0;
172
173 va_start(args, command);
174 val = va_arg(args, int);
175 va_end(args);
176
177 switch( val ) {
178 case O_NONBLOCK:
179 {
180 u_long imode=1;
181 ret = ioctlsocket(socket, FIONBIO, &imode);
182 break;
183 }
184 case 0:
185 {
186 u_long imode=0;
187 ret = ioctlsocket(socket, FIONBIO, &imode);
188 break;
189 }
190 default:
191 errno = EINVAL;
192 return -1;
193 }/*end switch*/
194 if( ret == SOCKET_ERROR ) {
195 errno = WSAGetLastError();
196 return -1;
197 }
198 return 0;
199 }
200 default:
201 purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_fcntl: Unsupported command\n");
202 return -1;
203 }/*end switch*/
204 }
205
206 /* sys/ioctl.h */
wpurple_ioctl(int fd,int command,void * val)207 int wpurple_ioctl(int fd, int command, void* val) {
208 switch( command ) {
209 case FIONBIO:
210 {
211 if (ioctlsocket(fd, FIONBIO, (unsigned long *)val) == SOCKET_ERROR) {
212 errno = WSAGetLastError();
213 return -1;
214 }
215 return 0;
216 }
217 case SIOCGIFCONF:
218 {
219 INTERFACE_INFO InterfaceList[20];
220 unsigned long nBytesReturned;
221 if (WSAIoctl(fd, SIO_GET_INTERFACE_LIST,
222 0, 0, &InterfaceList,
223 sizeof(InterfaceList), &nBytesReturned,
224 0, 0) == SOCKET_ERROR) {
225 errno = WSAGetLastError();
226 return -1;
227 } else {
228 int i;
229 struct ifconf *ifc = val;
230 char *tmp = ifc->ifc_buf;
231 int nNumInterfaces =
232 nBytesReturned / sizeof(INTERFACE_INFO);
233 for (i = 0; i < nNumInterfaces; i++) {
234 INTERFACE_INFO ii = InterfaceList[i];
235 struct ifreq *ifr = (struct ifreq *) tmp;
236 struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr;
237
238 sa->sin_family = ii.iiAddress.AddressIn.sin_family;
239 sa->sin_port = ii.iiAddress.AddressIn.sin_port;
240 sa->sin_addr.s_addr = ii.iiAddress.AddressIn.sin_addr.s_addr;
241 tmp += sizeof(struct ifreq);
242
243 /* Make sure that we can fit in the original buffer */
244 if (tmp >= (ifc->ifc_buf + ifc->ifc_len + sizeof(struct ifreq))) {
245 break;
246 }
247 }
248 /* Replace the length with the actually used length */
249 ifc->ifc_len = ifc->ifc_len - (ifc->ifc_buf - tmp);
250 return 0;
251 }
252 }
253 default:
254 errno = EINVAL;
255 return -1;
256 }/*end switch*/
257 }
258
259 /* arpa/inet.h */
wpurple_inet_aton(const char * name,struct in_addr * addr)260 int wpurple_inet_aton(const char *name, struct in_addr *addr) {
261 if((addr->s_addr = inet_addr(name)) == INADDR_NONE)
262 return 0;
263 else
264 return 1;
265 }
266
267 /* Thanks to GNU wget for this inet_ntop() implementation */
268 const char *
wpurple_inet_ntop(int af,const void * src,char * dst,socklen_t cnt)269 wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
270 {
271 /* struct sockaddr can't accomodate struct sockaddr_in6. */
272 union {
273 struct sockaddr_in6 sin6;
274 struct sockaddr_in sin;
275 } sa;
276 DWORD dstlen = cnt;
277 size_t srcsize;
278
279 ZeroMemory(&sa, sizeof(sa));
280 switch (af)
281 {
282 case AF_INET:
283 sa.sin.sin_family = AF_INET;
284 sa.sin.sin_addr = *(struct in_addr *) src;
285 srcsize = sizeof (sa.sin);
286 break;
287 case AF_INET6:
288 sa.sin6.sin6_family = AF_INET6;
289 sa.sin6.sin6_addr = *(struct in6_addr *) src;
290 srcsize = sizeof (sa.sin6);
291 break;
292 default:
293 abort ();
294 }
295
296 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
297 {
298 errno = WSAGetLastError();
299 return NULL;
300 }
301 return (const char *) dst;
302 }
303
304 int
wpurple_inet_pton(int af,const char * src,void * dst)305 wpurple_inet_pton(int af, const char *src, void *dst)
306 {
307 /* struct sockaddr can't accomodate struct sockaddr_in6. */
308 union {
309 struct sockaddr_in6 sin6;
310 struct sockaddr_in sin;
311 } sa;
312 size_t srcsize;
313
314 switch(af)
315 {
316 case AF_INET:
317 sa.sin.sin_family = AF_INET;
318 srcsize = sizeof (sa.sin);
319 break;
320 case AF_INET6:
321 sa.sin6.sin6_family = AF_INET6;
322 srcsize = sizeof (sa.sin6);
323 break;
324 default:
325 errno = WSAEPFNOSUPPORT;
326 return -1;
327 }
328
329 if (WSAStringToAddress(src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
330 {
331 errno = WSAGetLastError();
332 return -1;
333 }
334
335 switch(af)
336 {
337 case AF_INET:
338 memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
339 break;
340 case AF_INET6:
341 memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
342 break;
343 }
344
345 return 1;
346 }
347
348
349 /* netdb.h */
wpurple_gethostbyname(const char * name)350 struct hostent* wpurple_gethostbyname(const char *name) {
351 struct hostent *hp;
352
353 if((hp = gethostbyname(name)) == NULL) {
354 errno = WSAGetLastError();
355 return NULL;
356 }
357 return hp;
358 }
359
360 /* string.h */
wpurple_strerror(int errornum)361 char* wpurple_strerror(int errornum) {
362 if (errornum > WSABASEERR) {
363 switch(errornum) {
364 case WSAECONNABORTED: /* 10053 */
365 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection interrupted by other software on your computer."));
366 break;
367 case WSAECONNRESET: /* 10054 */
368 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Remote host closed connection."));
369 break;
370 case WSAETIMEDOUT: /* 10060 */
371 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection timed out."));
372 break;
373 case WSAECONNREFUSED: /* 10061 */
374 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection refused."));
375 break;
376 case WSAEADDRINUSE: /* 10048 */
377 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Address already in use."));
378 break;
379 default:
380 g_snprintf(errbuf, sizeof(errbuf), "Windows socket error #%d", errornum);
381 }
382 } else {
383 const char *tmp = g_strerror(errornum);
384 g_snprintf(errbuf, sizeof(errbuf), "%s", tmp);
385 }
386 return errbuf;
387 }
388
389 /* unistd.h */
390
391 /*
392 * We need to figure out whether fd is a file or socket handle.
393 */
wpurple_read(int fd,void * buf,unsigned int size)394 int wpurple_read(int fd, void *buf, unsigned int size) {
395 int ret;
396
397 if (fd < 0) {
398 errno = EBADF;
399 g_return_val_if_reached(-1);
400 }
401
402 if(wpurple_is_socket(fd)) {
403 if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) {
404 errno = WSAGetLastError();
405 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
406 errno = EAGAIN;
407 return -1;
408 }
409 #if 0
410 else if( ret == 0 ) {
411 /* connection has been gracefully closed */
412 errno = WSAENOTCONN;
413 return -1;
414 }
415 #endif
416 else {
417 /* success reading socket */
418 return ret;
419 }
420 } else {
421 /* fd is not a socket handle.. pass it off to read */
422 return _read(fd, buf, size);
423 }
424 }
425
wpurple_send(int fd,const void * buf,unsigned int size,int flags)426 int wpurple_send(int fd, const void *buf, unsigned int size, int flags) {
427 int ret;
428
429 ret = send(fd, buf, size, flags);
430
431 if (ret == SOCKET_ERROR) {
432 errno = WSAGetLastError();
433 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
434 errno = EAGAIN;
435 return -1;
436 }
437 return ret;
438 }
439
wpurple_write(int fd,const void * buf,unsigned int size)440 int wpurple_write(int fd, const void *buf, unsigned int size) {
441
442 if (fd < 0) {
443 errno = EBADF;
444 g_return_val_if_reached(-1);
445 }
446
447 if(wpurple_is_socket(fd))
448 return wpurple_send(fd, buf, size, 0);
449 else
450 return _write(fd, buf, size);
451 }
452
wpurple_recv(int fd,void * buf,size_t len,int flags)453 int wpurple_recv(int fd, void *buf, size_t len, int flags) {
454 int ret;
455
456 if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) {
457 errno = WSAGetLastError();
458 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
459 errno = EAGAIN;
460 return -1;
461 } else {
462 return ret;
463 }
464 }
465
wpurple_close(int fd)466 int wpurple_close(int fd) {
467 int ret;
468
469 if (fd < 0) {
470 errno = EBADF;
471 g_return_val_if_reached(-1);
472 }
473
474 if( wpurple_is_socket(fd) ) {
475 if( (ret = closesocket(fd)) == SOCKET_ERROR ) {
476 errno = WSAGetLastError();
477 return -1;
478 }
479 else
480 return 0;
481 }
482 else
483 return _close(fd);
484 }
485
wpurple_gethostname(char * name,size_t size)486 int wpurple_gethostname(char *name, size_t size) {
487 if(gethostname(name, size) == SOCKET_ERROR) {
488 errno = WSAGetLastError();
489 return -1;
490 }
491 return 0;
492 }
493
494 /* sys/time.h */
495
wpurple_gettimeofday(struct timeval * p,struct timezone * z)496 int wpurple_gettimeofday(struct timeval *p, struct timezone *z) {
497 int res = 0;
498 struct _timeb timebuffer;
499
500 if (z != 0) {
501 _tzset();
502 z->tz_minuteswest = _timezone/60;
503 z->tz_dsttime = _daylight;
504 }
505
506 if (p != 0) {
507 _ftime(&timebuffer);
508 p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */
509 p->tv_usec = timebuffer.millitm*1000; /* microseconds */
510 }
511
512 return res;
513 }
514
515 /* stdio.h */
516
wpurple_rename(const char * oldname,const char * newname)517 int wpurple_rename (const char *oldname, const char *newname) {
518 return g_rename(oldname, newname);
519 }
520
521 /* time.h */
522
wpurple_localtime_r(const time_t * time,struct tm * resultp)523 struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) {
524 struct tm* tmptm;
525
526 if(!time)
527 return NULL;
528 tmptm = localtime(time);
529 if(resultp && tmptm)
530 return memcpy(resultp, tmptm, sizeof(struct tm));
531 else
532 return NULL;
533 }
534
535 /*
536 * Used by purple_utf8_strftime() by way of purple_internal_strftime()
537 * in src/util.c
538 *
539 * Code derived from PostgreSQL src/timezone/pgtz.c:
540 * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c
541 */
542
543 /*
544 PostgreSQL Database Management System
545 (formerly known as Postgres, then as Postgres95)
546
547 Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
548
549 Portions Copyright (c) 1994, The Regents of the University of California
550
551 Permission to use, copy, modify, and distribute this software and its
552 documentation for any purpose, without fee, and without a written agreement
553 is hereby granted, provided that the above copyright notice and this
554 paragraph and the following two paragraphs appear in all copies.
555
556 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
557 DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
558 LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
559 DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
560 POSSIBILITY OF SUCH DAMAGE.
561
562 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
563 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
564 AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
565 ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
566 PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
567
568 */
569 static struct
570 {
571 char *wstd; /* Windows name of standard timezone */
572 char *wdst; /* Windows name of daylight timezone */
573 char *ustd; /* Unix name of standard timezone */
574 char *udst; /* Unix name of daylight timezone */
575 } win32_tzmap[] =
576 {
577 {
578 "", "",
579 "", "",
580 },
581 /*
582 * This list was built from the contents of the registry at
583 * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
584 * on Windows XP Professional SP1
585 */
586 {
587 "Afghanistan Standard Time", "Afghanistan Daylight Time",
588 "AFT", "AFT"
589 },
590 {
591 "Alaskan Standard Time", "Alaskan Daylight Time",
592 "AKST", "AKDT"
593 },
594 {
595 "Arab Standard Time", "Arab Daylight Time",
596 "AST", "AST"
597 },
598 {
599 "Arabian Standard Time", "Arabian Daylight Time",
600 "GST", "GST"
601 },
602 {
603 "Arabic Standard Time", "Arabic Daylight Time",
604 "AST", "ADT"
605 },
606 {
607 "Atlantic Standard Time", "Atlantic Daylight Time",
608 "AST", "ADT"
609 },
610 {
611 "AUS Central Standard Time", "AUS Central Daylight Time",
612 "CST", "CST"
613 },
614 {
615 "AUS Eastern Standard Time", "AUS Eastern Daylight Time",
616 "EST", "EST"
617 },
618 {
619 "Azores Standard Time", "Azores Daylight Time",
620 "AZOT", "AZOST"
621 },
622 {
623 "Canada Central Standard Time", "Canada Central Daylight Time",
624 "CST", "MDT"
625 },
626 {
627 "Cape Verde Standard Time", "Cape Verde Daylight Time",
628 "CVT", "CVST"
629 },
630 {
631 "Caucasus Standard Time", "Caucasus Daylight Time",
632 "AZT", "AZST"
633 },
634 {
635 "Cen. Australia Standard Time", "Cen. Australia Daylight Time",
636 "CST", "CST"
637 },
638 {
639 "Central America Standard Time", "Central America Daylight Time",
640 "CST", "CDT"
641 },
642 {
643 "Central Asia Standard Time", "Central Asia Daylight Time",
644 "BDT", "BDT"
645 },
646 {
647 "Central Europe Standard Time", "Central Europe Daylight Time",
648 "CET", "CEST"
649 },
650 {
651 "Central European Standard Time", "Central European Daylight Time",
652 "CET", "CEST"
653 },
654 {
655 "Central Pacific Standard Time", "Central Pacific Daylight Time",
656 "NCT", "NCST"
657 },
658 {
659 "Central Standard Time", "Central Daylight Time",
660 "CST", "CDT"
661 },
662 {
663 "China Standard Time", "China Daylight Time",
664 "HKT", "HKST"
665 },
666 {
667 "Dateline Standard Time", "Dateline Daylight Time",
668 "GMT+12", "GMT+12"
669 },
670 {
671 "E. Africa Standard Time", "E. Africa Daylight Time",
672 "EAT", "EAT"
673 },
674 {
675 "E. Australia Standard Time", "E. Australia Daylight Time",
676 "EST", "EST"
677 },
678 {
679 "E. Europe Standard Time", "E. Europe Daylight Time",
680 "EET", "EEST"
681 },
682 {
683 "E. South America Standard Time", "E. South America Daylight Time",
684 "BRT", "BRST"
685 },
686 {
687 "Eastern Standard Time", "Eastern Daylight Time",
688 "EST", "EDT"
689 },
690 {
691 "Egypt Standard Time", "Egypt Daylight Time",
692 "EET", "EEST"
693 },
694 {
695 "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time",
696 "YEKT", "YEKST"
697 },
698 {
699 "Fiji Standard Time", "Fiji Daylight Time",
700 "FJT", "FJST"
701 },
702 {
703 "FLE Standard Time", "FLE Daylight Time",
704 "EET", "EEST"
705 },
706 {
707 "GMT Standard Time", "GMT Daylight Time",
708 "GMT", "IST"
709 },
710 {
711 "Greenland Standard Time", "Greenland Daylight Time",
712 "WGT", "WGST"
713 },
714 {
715 "Greenwich Standard Time", "Greenwich Daylight Time",
716 "WET", "WEST"
717 },
718 {
719 "GTB Standard Time", "GTB Daylight Time",
720 "EET", "EEST"
721 },
722 {
723 "Hawaiian Standard Time", "Hawaiian Daylight Time",
724 "HST", "HPT"
725 },
726 {
727 "India Standard Time", "India Daylight Time",
728 "IST", "IST"
729 },
730 {
731 "Iran Standard Time", "Iran Daylight Time",
732 "IRST", "IRDT"
733 },
734 {
735 "Jerusalem Standard Time", "Jerusalem Daylight Time",
736 "IST", "IDT"
737 },
738 {
739 "Korea Standard Time", "Korea Daylight Time",
740 "KST", "KDT"
741 },
742 {
743 "Mexico Standard Time", "Mexico Daylight Time",
744 "CST", "CDT"
745 },
746 {
747 "Mexico Standard Time", "Mexico Daylight Time",
748 "BOT", "BOST"
749 },
750 {
751 "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time",
752 "GST", "GST"
753 },
754 {
755 "Mountain Standard Time", "Mountain Daylight Time",
756 "MST", "MDT"
757 },
758 {
759 "Myanmar Standard Time", "Myanmar Daylight Time",
760 "MMT", "MMT"
761 },
762 {
763 "N. Central Asia Standard Time", "N. Central Asia Daylight Time",
764 "ALMT", "ALMST"
765 },
766 {
767 "Nepal Standard Time", "Nepal Daylight Time",
768 "NPT", "NPT"
769 },
770 {
771 "New Zealand Standard Time", "New Zealand Daylight Time",
772 "NZST", "NZDT"
773 },
774 {
775 "Newfoundland Standard Time", "Newfoundland Daylight Time",
776 "NST", "NDT"
777 },
778 {
779 "North Asia East Standard Time", "North Asia East Daylight Time",
780 "IRKT", "IRKST"
781 },
782 {
783 "North Asia Standard Time", "North Asia Daylight Time",
784 "KRAT", "KRAST"
785 },
786 {
787 "Pacific SA Standard Time", "Pacific SA Daylight Time",
788 "CLT", "CLST"
789 },
790 {
791 "Pacific Standard Time", "Pacific Daylight Time",
792 "PST", "PDT"
793 },
794 {
795 "Romance Standard Time", "Romance Daylight Time",
796 "CET", "CEST"
797 },
798 {
799 "Russian Standard Time", "Russian Daylight Time",
800 "MSK", "MSD"
801 },
802 {
803 "SA Eastern Standard Time", "SA Eastern Daylight Time",
804 "ART", "ARST"
805 },
806 {
807 "SA Pacific Standard Time", "SA Pacific Daylight Time",
808 "COT", "COST"
809 },
810 {
811 "SA Western Standard Time", "SA Western Daylight Time",
812 "VET", "VET"
813 },
814 {
815 "Samoa Standard Time", "Samoa Daylight Time",
816 "SST", "NDT"
817 },
818 {
819 "SE Asia Standard Time", "SE Asia Daylight Time",
820 "ICT", "ICT"
821 },
822 {
823 "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time",
824 "MYT", "MALST"
825 },
826 {
827 "South Africa Standard Time", "South Africa Daylight Time",
828 "CAT", "CAT"
829 },
830 {
831 "Sri Lanka Standard Time", "Sri Lanka Daylight Time",
832 "LKT", "IST"
833 },
834 {
835 "Taipei Standard Time", "Taipei Daylight Time",
836 "CST", "CDT"
837 },
838 {
839 "Tasmania Standard Time", "Tasmania Daylight Time",
840 "EST", "EST"
841 },
842 {
843 "Tokyo Standard Time", "Tokyo Daylight Time",
844 "JST", "JDT"
845 },
846 {
847 "Tonga Standard Time", "Tonga Daylight Time",
848 "TOT", "TOST"
849 },
850 {
851 "US Eastern Standard Time", "US Eastern Daylight Time",
852 "EST", "EDT"
853 },
854 {
855 "US Mountain Standard Time", "US Mountain Daylight Time",
856 "MST", "MDT"
857 },
858 {
859 "Vladivostok Standard Time", "Vladivostok Daylight Time",
860 "VLAT", "VLAST"
861 },
862 {
863 "W. Australia Standard Time", "W. Australia Daylight Time",
864 "WST", "WST"
865 },
866
867 /* Not mapped in PostgreSQL.
868 *
869 * I mapped this based on the following information... -- rlaager
870 * $ cd /usr/share/zoneinfo/Africa
871 * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100
872 * +0100 CET Algiers
873 * +0100 WAT Bangui
874 * +0100 WAT Brazzaville
875 * +0100 CET Ceuta
876 * +0100 WAT Douala
877 * +0100 WAT Kinshasa
878 * +0100 WAT Lagos
879 * +0100 WAT Libreville
880 * +0100 WAT Luanda
881 * +0100 WAT Malabo
882 * +0100 WAT Ndjamena
883 * +0100 WAT Niamey
884 * +0100 WAT Porto-Novo
885 * +0100 CET Tunis
886 **/
887 {
888 "W. Central Africa Standard Time", "W. Central Africa Daylight Time",
889 "WAT", "WAT"
890 },
891
892 {
893 "W. Europe Standard Time", "W. Europe Daylight Time",
894 "CET", "CEST"
895 },
896 {
897 "West Asia Standard Time", "West Asia Daylight Time",
898 "PKT", "PKST"
899 },
900 {
901 "West Pacific Standard Time", "West Pacific Daylight Time",
902 "ChST", "ChST"
903 },
904 {
905 "Yakutsk Standard Time", "Yakutsk Daylight Time",
906 "YAKT", "YAKST"
907 },
908 {
909 NULL, NULL,
910 NULL, NULL
911 }
912 };
913
914 const char *
wpurple_get_timezone_abbreviation(const struct tm * tm)915 wpurple_get_timezone_abbreviation(const struct tm *tm)
916 {
917 int i;
918 char tzname[128];
919 char localtzname[256];
920 HKEY rootKey;
921 int idx;
922
923 if (!tm)
924 {
925 purple_debug_warning("wpurple", "could not determine current date/time: localtime failed\n");
926 return "";
927 }
928
929 if (strftime(tzname, sizeof(tzname) - 1, "%Z", tm) == 0)
930 {
931 purple_debug_error("wpurple", "timezone name is too long for the buffer\n");
932 return "";
933 }
934
935 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
936 {
937 if (purple_strequal(tzname, win32_tzmap[i].wstd))
938 {
939 #if 0
940 purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
941 win32_tzmap[i].ustd, tzname);
942 #endif
943 /* Cache the Result */
944 if (i > 0) {
945 if (win32_tzmap[0].wstd[0] != '\0')
946 g_free(win32_tzmap[0].wstd);
947 win32_tzmap[0].wstd = g_strdup(tzname);
948 win32_tzmap[0].ustd = win32_tzmap[i].ustd;
949 }
950
951 return win32_tzmap[i].ustd;
952 }
953 if (purple_strequal(tzname, win32_tzmap[i].wdst))
954 {
955 #if 0
956 purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
957 win32_tzmap[i].udst, tzname);
958 #endif
959 /* Cache the Result */
960 if (i > 0) {
961 if (win32_tzmap[0].wdst[0] != '\0')
962 g_free(win32_tzmap[0].wdst);
963 win32_tzmap[0].wdst = g_strdup(tzname);
964 win32_tzmap[0].udst = win32_tzmap[i].udst;
965 }
966
967 return win32_tzmap[i].udst;
968 }
969 }
970
971 /*
972 * Localized Windows versions return localized names for the timezone.
973 * Scan the registry to find the English name, and then try matching
974 * against our table again.
975 */
976 memset(localtzname, 0, sizeof(localtzname));
977 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
978 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
979 0,
980 KEY_READ,
981 &rootKey) != ERROR_SUCCESS)
982 {
983 purple_debug_warning("wpurple", "could not open registry key to identify Windows timezone: %i\n", (int) GetLastError());
984 return "";
985 }
986
987 for (idx = 0;; idx++)
988 {
989 char keyname[256];
990 char zonename[256];
991 DWORD namesize;
992 FILETIME lastwrite;
993 HKEY key;
994 LONG r;
995
996 memset(keyname, 0, sizeof(keyname));
997 namesize = sizeof(keyname);
998 if ((r = RegEnumKeyEx(rootKey,
999 idx,
1000 keyname,
1001 &namesize,
1002 NULL,
1003 NULL,
1004 NULL,
1005 &lastwrite)) != ERROR_SUCCESS)
1006 {
1007 if (r == ERROR_NO_MORE_ITEMS)
1008 break;
1009 purple_debug_warning("wpurple", "could not enumerate registry subkeys to identify Windows timezone: %i\n", (int) r);
1010 break;
1011 }
1012
1013 if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS)
1014 {
1015 purple_debug_warning("wpurple", "could not open registry subkey to identify Windows timezone: %i\n", (int) r);
1016 break;
1017 }
1018
1019 memset(zonename, 0, sizeof(zonename));
1020 namesize = sizeof(zonename);
1021 if ((r = RegQueryValueEx(key, "Std", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
1022 {
1023 purple_debug_warning("wpurple", "could not query value for 'std' to identify Windows timezone: %i\n", (int) r);
1024 RegCloseKey(key);
1025 break;
1026 }
1027 if (purple_strequal(tzname, zonename))
1028 {
1029 /* Matched zone */
1030 g_strlcpy(localtzname, keyname, sizeof(localtzname));
1031 RegCloseKey(key);
1032 break;
1033 }
1034 memset(zonename, 0, sizeof(zonename));
1035 namesize = sizeof(zonename);
1036 if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
1037 {
1038 purple_debug_warning("wpurple", "could not query value for 'dlt' to identify Windows timezone: %i\n", (int) r);
1039 RegCloseKey(key);
1040 break;
1041 }
1042 if (purple_strequal(tzname, zonename))
1043 {
1044 /* Matched DST zone */
1045 g_strlcpy(localtzname, keyname, sizeof(localtzname));
1046 RegCloseKey(key);
1047 break;
1048 }
1049
1050 RegCloseKey(key);
1051 }
1052
1053 RegCloseKey(rootKey);
1054
1055 if (localtzname[0])
1056 {
1057 /* Found a localized name, so scan for that one too */
1058 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
1059 {
1060 if (purple_strequal(localtzname, win32_tzmap[i].wstd))
1061 {
1062 #if 0
1063 purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
1064 win32_tzmap[i].ustd, tzname, localtzname);
1065 #endif
1066 /* Cache the Result */
1067 if (win32_tzmap[0].wstd[0] != '\0')
1068 g_free(win32_tzmap[0].wstd);
1069 win32_tzmap[0].wstd = g_strdup(tzname);
1070 win32_tzmap[0].ustd = win32_tzmap[i].ustd;
1071
1072 return win32_tzmap[i].ustd;
1073 }
1074 if (purple_strequal(localtzname, win32_tzmap[i].wdst))
1075 {
1076 #if 0
1077 purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
1078 win32_tzmap[i].udst, tzname, localtzname);
1079 #endif
1080 /* Cache the Result */
1081 if (win32_tzmap[0].wdst[0] != '\0')
1082 g_free(win32_tzmap[0].wdst);
1083
1084 win32_tzmap[0].wdst = g_strdup(tzname);
1085 win32_tzmap[0].udst = win32_tzmap[i].udst;
1086
1087 return win32_tzmap[i].udst;
1088 }
1089 }
1090 }
1091
1092 purple_debug_warning("wpurple", "could not find a match for Windows timezone \"%s\"\n", tzname);
1093 return "";
1094 }
1095
1096 int wpurple_g_access (const gchar *filename, int mode);
1097 /**
1098 * @deprecated - remove for 3.0.0
1099 */
1100 int
wpurple_g_access(const gchar * filename,int mode)1101 wpurple_g_access (const gchar *filename, int mode)
1102 {
1103 return g_access(filename, mode);
1104 }
1105
1106
1107