Doh. Upon further investigation I think these translations were made
[pidgin-git.git] / libpurple / win32 / libc_interface.c
blob493dfca53fc37296410b8c0971f61b327e62beee
1 /*
2 * purple
4 * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
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.
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.
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
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 <glib/gstdio.h>
36 /** This is redefined here because we can't include internal.h */
37 #ifdef ENABLE_NLS
38 # include <locale.h>
39 # include <libintl.h>
40 # define _(String) ((const char *)dgettext(PACKAGE, String))
41 # ifdef gettext_noop
42 # define N_(String) gettext_noop (String)
43 # else
44 # define N_(String) (String)
45 # endif
46 #else
47 # include <locale.h>
48 # define N_(String) (String)
49 # ifndef _
50 # define _(String) ((const char *)String)
51 # endif
52 # define ngettext(Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
53 # define dngettext(Domain, Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
54 #endif
56 #ifndef S_ISDIR
57 # define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR)
58 #endif
60 static char errbuf[1024];
62 /* helpers */
63 static int wpurple_is_socket( int fd ) {
64 int optval;
65 int optlen = sizeof(int);
67 if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) {
68 int error = WSAGetLastError();
69 if( error == WSAENOTSOCK )
70 return FALSE;
71 else {
72 purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_is_socket: getsockopt returned error: %d\n", error);
73 return FALSE;
76 return TRUE;
79 /* socket.h */
80 int wpurple_socket (int namespace, int style, int protocol) {
81 int ret;
83 ret = socket( namespace, style, protocol );
85 if( ret == INVALID_SOCKET ) {
86 errno = WSAGetLastError();
87 return -1;
89 return ret;
92 int wpurple_connect(int socket, struct sockaddr *addr, u_long length) {
93 int ret;
95 ret = connect( socket, addr, length );
97 if( ret == SOCKET_ERROR ) {
98 errno = WSAGetLastError();
99 if( errno == WSAEWOULDBLOCK )
100 errno = WSAEINPROGRESS;
101 return -1;
103 return 0;
106 int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) {
107 if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) {
108 errno = WSAGetLastError();
109 return -1;
111 return 0;
114 int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
115 if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) {
116 errno = WSAGetLastError();
117 return -1;
119 return 0;
122 int wpurple_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) {
123 if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) {
124 errno = WSAGetLastError();
125 return -1;
127 return 0;
130 int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length) {
131 if(bind(socket, addr, length) == SOCKET_ERROR) {
132 errno = WSAGetLastError();
133 return -1;
135 return 0;
138 int wpurple_listen(int socket, unsigned int n) {
139 if(listen(socket, n) == SOCKET_ERROR) {
140 errno = WSAGetLastError();
141 return -1;
143 return 0;
146 int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) {
147 int ret;
148 if ((ret = sendto(socket, buf, len, flags, to, tolen)
149 ) == SOCKET_ERROR) {
150 errno = WSAGetLastError();
151 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
152 errno = EAGAIN;
153 return -1;
155 return ret;
158 /* fcntl.h */
159 /* This is not a full implementation of fcntl. Update as needed.. */
160 int wpurple_fcntl(int socket, int command, ...) {
162 switch( command ) {
163 case F_GETFL:
164 return 0;
166 case F_SETFL:
168 va_list args;
169 int val;
170 int ret=0;
172 va_start(args, command);
173 val = va_arg(args, int);
174 va_end(args);
176 switch( val ) {
177 case O_NONBLOCK:
179 u_long imode=1;
180 ret = ioctlsocket(socket, FIONBIO, &imode);
181 break;
183 case 0:
185 u_long imode=0;
186 ret = ioctlsocket(socket, FIONBIO, &imode);
187 break;
189 default:
190 errno = EINVAL;
191 return -1;
192 }/*end switch*/
193 if( ret == SOCKET_ERROR ) {
194 errno = WSAGetLastError();
195 return -1;
197 return 0;
199 default:
200 purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_fcntl: Unsupported command\n");
201 return -1;
202 }/*end switch*/
205 /* sys/ioctl.h */
206 int wpurple_ioctl(int fd, int command, void* val) {
207 switch( command ) {
208 case FIONBIO:
210 if (ioctlsocket(fd, FIONBIO, (unsigned long *)val) == SOCKET_ERROR) {
211 errno = WSAGetLastError();
212 return -1;
214 return 0;
216 case SIOCGIFCONF:
218 INTERFACE_INFO InterfaceList[20];
219 unsigned long nBytesReturned;
220 if (WSAIoctl(fd, SIO_GET_INTERFACE_LIST,
221 0, 0, &InterfaceList,
222 sizeof(InterfaceList), &nBytesReturned,
223 0, 0) == SOCKET_ERROR) {
224 errno = WSAGetLastError();
225 return -1;
226 } else {
227 int i;
228 struct ifconf *ifc = val;
229 char *tmp = ifc->ifc_buf;
230 int nNumInterfaces =
231 nBytesReturned / sizeof(INTERFACE_INFO);
232 for (i = 0; i < nNumInterfaces; i++) {
233 INTERFACE_INFO ii = InterfaceList[i];
234 struct ifreq *ifr = (struct ifreq *) tmp;
235 struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr;
237 sa->sin_family = ii.iiAddress.AddressIn.sin_family;
238 sa->sin_port = ii.iiAddress.AddressIn.sin_port;
239 sa->sin_addr.s_addr = ii.iiAddress.AddressIn.sin_addr.s_addr;
240 tmp += sizeof(struct ifreq);
242 /* Make sure that we can fit in the original buffer */
243 if (tmp >= (ifc->ifc_buf + ifc->ifc_len + sizeof(struct ifreq))) {
244 break;
247 /* Replace the length with the actually used length */
248 ifc->ifc_len = ifc->ifc_len - (ifc->ifc_buf - tmp);
249 return 0;
252 default:
253 errno = EINVAL;
254 return -1;
255 }/*end switch*/
258 /* arpa/inet.h */
259 int wpurple_inet_aton(const char *name, struct in_addr *addr) {
260 if((addr->s_addr = inet_addr(name)) == INADDR_NONE)
261 return 0;
262 else
263 return 1;
266 /* Thanks to GNU wget for this inet_ntop() implementation */
267 const char *
268 wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
270 /* struct sockaddr can't accomodate struct sockaddr_in6. */
271 union {
272 struct sockaddr_in6 sin6;
273 struct sockaddr_in sin;
274 } sa;
275 DWORD dstlen = cnt;
276 size_t srcsize;
278 ZeroMemory(&sa, sizeof(sa));
279 switch (af)
281 case AF_INET:
282 sa.sin.sin_family = AF_INET;
283 sa.sin.sin_addr = *(struct in_addr *) src;
284 srcsize = sizeof (sa.sin);
285 break;
286 case AF_INET6:
287 sa.sin6.sin6_family = AF_INET6;
288 sa.sin6.sin6_addr = *(struct in6_addr *) src;
289 srcsize = sizeof (sa.sin6);
290 break;
291 default:
292 abort ();
295 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
297 errno = WSAGetLastError();
298 return NULL;
300 return (const char *) dst;
304 wpurple_inet_pton(int af, const char *src, void *dst)
306 /* struct sockaddr can't accomodate struct sockaddr_in6. */
307 union {
308 struct sockaddr_in6 sin6;
309 struct sockaddr_in sin;
310 } sa;
311 size_t srcsize;
313 switch(af)
315 case AF_INET:
316 sa.sin.sin_family = AF_INET;
317 srcsize = sizeof (sa.sin);
318 break;
319 case AF_INET6:
320 sa.sin6.sin6_family = AF_INET6;
321 srcsize = sizeof (sa.sin6);
322 break;
323 default:
324 errno = WSAEPFNOSUPPORT;
325 return -1;
328 if (WSAStringToAddress(src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
330 errno = WSAGetLastError();
331 return -1;
334 switch(af)
336 case AF_INET:
337 memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
338 break;
339 case AF_INET6:
340 memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
341 break;
344 return 1;
348 /* netdb.h */
349 struct hostent* wpurple_gethostbyname(const char *name) {
350 struct hostent *hp;
352 if((hp = gethostbyname(name)) == NULL) {
353 errno = WSAGetLastError();
354 return NULL;
356 return hp;
359 /* string.h */
360 char* wpurple_strerror(int errornum) {
361 if (errornum > WSABASEERR) {
362 switch(errornum) {
363 case WSAECONNABORTED: /* 10053 */
364 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection interrupted by other software on your computer."));
365 break;
366 case WSAECONNRESET: /* 10054 */
367 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Remote host closed connection."));
368 break;
369 case WSAETIMEDOUT: /* 10060 */
370 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection timed out."));
371 break;
372 case WSAECONNREFUSED: /* 10061 */
373 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection refused."));
374 break;
375 case WSAEADDRINUSE: /* 10048 */
376 g_snprintf(errbuf, sizeof(errbuf), "%s", _("Address already in use."));
377 break;
378 default:
379 g_snprintf(errbuf, sizeof(errbuf), "Windows socket error #%d", errornum);
381 } else {
382 const char *tmp = g_strerror(errornum);
383 g_snprintf(errbuf, sizeof(errbuf), "%s", tmp);
385 return errbuf;
388 /* unistd.h */
391 * We need to figure out whether fd is a file or socket handle.
393 int wpurple_read(int fd, void *buf, unsigned int size) {
394 int ret;
396 if (fd < 0) {
397 errno = EBADF;
398 g_return_val_if_reached(-1);
401 if(wpurple_is_socket(fd)) {
402 if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) {
403 errno = WSAGetLastError();
404 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
405 errno = EAGAIN;
406 return -1;
408 #if 0
409 else if( ret == 0 ) {
410 /* connection has been gracefully closed */
411 errno = WSAENOTCONN;
412 return -1;
414 #endif
415 else {
416 /* success reading socket */
417 return ret;
419 } else {
420 /* fd is not a socket handle.. pass it off to read */
421 return _read(fd, buf, size);
425 int wpurple_send(int fd, const void *buf, unsigned int size, int flags) {
426 int ret;
428 ret = send(fd, buf, size, flags);
430 if (ret == SOCKET_ERROR) {
431 errno = WSAGetLastError();
432 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
433 errno = EAGAIN;
434 return -1;
436 return ret;
439 int wpurple_write(int fd, const void *buf, unsigned int size) {
441 if (fd < 0) {
442 errno = EBADF;
443 g_return_val_if_reached(-1);
446 if(wpurple_is_socket(fd))
447 return wpurple_send(fd, buf, size, 0);
448 else
449 return _write(fd, buf, size);
452 int wpurple_recv(int fd, void *buf, size_t len, int flags) {
453 int ret;
455 if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) {
456 errno = WSAGetLastError();
457 if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
458 errno = EAGAIN;
459 return -1;
460 } else {
461 return ret;
465 int wpurple_close(int fd) {
466 int ret;
468 if (fd < 0) {
469 errno = EBADF;
470 g_return_val_if_reached(-1);
473 if( wpurple_is_socket(fd) ) {
474 if( (ret = closesocket(fd)) == SOCKET_ERROR ) {
475 errno = WSAGetLastError();
476 return -1;
478 else
479 return 0;
481 else
482 return _close(fd);
485 int wpurple_gethostname(char *name, size_t size) {
486 if(gethostname(name, size) == SOCKET_ERROR) {
487 errno = WSAGetLastError();
488 return -1;
490 return 0;
493 /* sys/time.h */
495 int wpurple_gettimeofday(struct timeval *p, struct timezone *z) {
496 int res = 0;
497 struct _timeb timebuffer;
499 if (z != 0) {
500 _tzset();
501 z->tz_minuteswest = _timezone/60;
502 z->tz_dsttime = _daylight;
505 if (p != 0) {
506 _ftime(&timebuffer);
507 p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */
508 p->tv_usec = timebuffer.millitm*1000; /* microseconds */
511 return res;
514 /* stdio.h */
516 int wpurple_rename (const char *oldname, const char *newname) {
517 return g_rename(oldname, newname);
520 /* time.h */
522 struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) {
523 struct tm* tmptm;
525 if(!time)
526 return NULL;
527 tmptm = localtime(time);
528 if(resultp && tmptm)
529 return memcpy(resultp, tmptm, sizeof(struct tm));
530 else
531 return NULL;
535 * Used by purple_utf8_strftime() by way of purple_internal_strftime()
536 * in src/util.c
538 * Code derived from PostgreSQL src/timezone/pgtz.c:
539 * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c
543 PostgreSQL Database Management System
544 (formerly known as Postgres, then as Postgres95)
546 Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
548 Portions Copyright (c) 1994, The Regents of the University of California
550 Permission to use, copy, modify, and distribute this software and its
551 documentation for any purpose, without fee, and without a written agreement
552 is hereby granted, provided that the above copyright notice and this
553 paragraph and the following two paragraphs appear in all copies.
555 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
556 DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
557 LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
558 DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
559 POSSIBILITY OF SUCH DAMAGE.
561 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
562 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
563 AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
564 ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
565 PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
568 static struct
570 char *wstd; /* Windows name of standard timezone */
571 char *wdst; /* Windows name of daylight timezone */
572 char *ustd; /* Unix name of standard timezone */
573 char *udst; /* Unix name of daylight timezone */
574 } win32_tzmap[] =
577 "", "",
578 "", "",
581 * This list was built from the contents of the registry at
582 * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
583 * on Windows XP Professional SP1
586 "Afghanistan Standard Time", "Afghanistan Daylight Time",
587 "AFT", "AFT"
590 "Alaskan Standard Time", "Alaskan Daylight Time",
591 "AKST", "AKDT"
594 "Arab Standard Time", "Arab Daylight Time",
595 "AST", "AST"
598 "Arabian Standard Time", "Arabian Daylight Time",
599 "GST", "GST"
602 "Arabic Standard Time", "Arabic Daylight Time",
603 "AST", "ADT"
606 "Atlantic Standard Time", "Atlantic Daylight Time",
607 "AST", "ADT"
610 "AUS Central Standard Time", "AUS Central Daylight Time",
611 "CST", "CST"
614 "AUS Eastern Standard Time", "AUS Eastern Daylight Time",
615 "EST", "EST"
618 "Azores Standard Time", "Azores Daylight Time",
619 "AZOT", "AZOST"
622 "Canada Central Standard Time", "Canada Central Daylight Time",
623 "CST", "MDT"
626 "Cape Verde Standard Time", "Cape Verde Daylight Time",
627 "CVT", "CVST"
630 "Caucasus Standard Time", "Caucasus Daylight Time",
631 "AZT", "AZST"
634 "Cen. Australia Standard Time", "Cen. Australia Daylight Time",
635 "CST", "CST"
638 "Central America Standard Time", "Central America Daylight Time",
639 "CST", "CDT"
642 "Central Asia Standard Time", "Central Asia Daylight Time",
643 "BDT", "BDT"
646 "Central Europe Standard Time", "Central Europe Daylight Time",
647 "CET", "CEST"
650 "Central European Standard Time", "Central European Daylight Time",
651 "CET", "CEST"
654 "Central Pacific Standard Time", "Central Pacific Daylight Time",
655 "NCT", "NCST"
658 "Central Standard Time", "Central Daylight Time",
659 "CST", "CDT"
662 "China Standard Time", "China Daylight Time",
663 "HKT", "HKST"
666 "Dateline Standard Time", "Dateline Daylight Time",
667 "GMT+12", "GMT+12"
670 "E. Africa Standard Time", "E. Africa Daylight Time",
671 "EAT", "EAT"
674 "E. Australia Standard Time", "E. Australia Daylight Time",
675 "EST", "EST"
678 "E. Europe Standard Time", "E. Europe Daylight Time",
679 "EET", "EEST"
682 "E. South America Standard Time", "E. South America Daylight Time",
683 "BRT", "BRST"
686 "Eastern Standard Time", "Eastern Daylight Time",
687 "EST", "EDT"
690 "Egypt Standard Time", "Egypt Daylight Time",
691 "EET", "EEST"
694 "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time",
695 "YEKT", "YEKST"
698 "Fiji Standard Time", "Fiji Daylight Time",
699 "FJT", "FJST"
702 "FLE Standard Time", "FLE Daylight Time",
703 "EET", "EEST"
706 "GMT Standard Time", "GMT Daylight Time",
707 "GMT", "IST"
710 "Greenland Standard Time", "Greenland Daylight Time",
711 "WGT", "WGST"
714 "Greenwich Standard Time", "Greenwich Daylight Time",
715 "WET", "WEST"
718 "GTB Standard Time", "GTB Daylight Time",
719 "EET", "EEST"
722 "Hawaiian Standard Time", "Hawaiian Daylight Time",
723 "HST", "HPT"
726 "India Standard Time", "India Daylight Time",
727 "IST", "IST"
730 "Iran Standard Time", "Iran Daylight Time",
731 "IRST", "IRDT"
734 "Jerusalem Standard Time", "Jerusalem Daylight Time",
735 "IST", "IDT"
738 "Korea Standard Time", "Korea Daylight Time",
739 "KST", "KDT"
742 "Mexico Standard Time", "Mexico Daylight Time",
743 "CST", "CDT"
746 "Mexico Standard Time", "Mexico Daylight Time",
747 "BOT", "BOST"
750 "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time",
751 "GST", "GST"
754 "Mountain Standard Time", "Mountain Daylight Time",
755 "MST", "MDT"
758 "Myanmar Standard Time", "Myanmar Daylight Time",
759 "MMT", "MMT"
762 "N. Central Asia Standard Time", "N. Central Asia Daylight Time",
763 "ALMT", "ALMST"
766 "Nepal Standard Time", "Nepal Daylight Time",
767 "NPT", "NPT"
770 "New Zealand Standard Time", "New Zealand Daylight Time",
771 "NZST", "NZDT"
774 "Newfoundland Standard Time", "Newfoundland Daylight Time",
775 "NST", "NDT"
778 "North Asia East Standard Time", "North Asia East Daylight Time",
779 "IRKT", "IRKST"
782 "North Asia Standard Time", "North Asia Daylight Time",
783 "KRAT", "KRAST"
786 "Pacific SA Standard Time", "Pacific SA Daylight Time",
787 "CLT", "CLST"
790 "Pacific Standard Time", "Pacific Daylight Time",
791 "PST", "PDT"
794 "Romance Standard Time", "Romance Daylight Time",
795 "CET", "CEST"
798 "Russian Standard Time", "Russian Daylight Time",
799 "MSK", "MSD"
802 "SA Eastern Standard Time", "SA Eastern Daylight Time",
803 "ART", "ARST"
806 "SA Pacific Standard Time", "SA Pacific Daylight Time",
807 "COT", "COST"
810 "SA Western Standard Time", "SA Western Daylight Time",
811 "VET", "VET"
814 "Samoa Standard Time", "Samoa Daylight Time",
815 "SST", "NDT"
818 "SE Asia Standard Time", "SE Asia Daylight Time",
819 "ICT", "ICT"
822 "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time",
823 "MYT", "MALST"
826 "South Africa Standard Time", "South Africa Daylight Time",
827 "CAT", "CAT"
830 "Sri Lanka Standard Time", "Sri Lanka Daylight Time",
831 "LKT", "IST"
834 "Taipei Standard Time", "Taipei Daylight Time",
835 "CST", "CDT"
838 "Tasmania Standard Time", "Tasmania Daylight Time",
839 "EST", "EST"
842 "Tokyo Standard Time", "Tokyo Daylight Time",
843 "JST", "JDT"
846 "Tonga Standard Time", "Tonga Daylight Time",
847 "TOT", "TOST"
850 "US Eastern Standard Time", "US Eastern Daylight Time",
851 "EST", "EDT"
854 "US Mountain Standard Time", "US Mountain Daylight Time",
855 "MST", "MDT"
858 "Vladivostok Standard Time", "Vladivostok Daylight Time",
859 "VLAT", "VLAST"
862 "W. Australia Standard Time", "W. Australia Daylight Time",
863 "WST", "WST"
866 /* Not mapped in PostgreSQL.
868 * I mapped this based on the following information... -- rlaager
869 * $ cd /usr/share/zoneinfo/Africa
870 * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100
871 * +0100 CET Algiers
872 * +0100 WAT Bangui
873 * +0100 WAT Brazzaville
874 * +0100 CET Ceuta
875 * +0100 WAT Douala
876 * +0100 WAT Kinshasa
877 * +0100 WAT Lagos
878 * +0100 WAT Libreville
879 * +0100 WAT Luanda
880 * +0100 WAT Malabo
881 * +0100 WAT Ndjamena
882 * +0100 WAT Niamey
883 * +0100 WAT Porto-Novo
884 * +0100 CET Tunis
887 "W. Central Africa Standard Time", "W. Central Africa Daylight Time",
888 "WAT", "WAT"
892 "W. Europe Standard Time", "W. Europe Daylight Time",
893 "CET", "CEST"
896 "West Asia Standard Time", "West Asia Daylight Time",
897 "PKT", "PKST"
900 "West Pacific Standard Time", "West Pacific Daylight Time",
901 "ChST", "ChST"
904 "Yakutsk Standard Time", "Yakutsk Daylight Time",
905 "YAKT", "YAKST"
908 NULL, NULL,
909 NULL, NULL
913 const char *
914 wpurple_get_timezone_abbreviation(const struct tm *tm)
916 int i;
917 char tzname[128];
918 char localtzname[256];
919 HKEY rootKey;
920 int idx;
922 if (!tm)
924 purple_debug_warning("wpurple", "could not determine current date/time: localtime failed\n");
925 return "";
928 if (strftime(tzname, sizeof(tzname) - 1, "%Z", tm) == 0)
930 purple_debug_error("wpurple", "timezone name is too long for the buffer\n");
931 return "";
934 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
936 if (strcmp(tzname, win32_tzmap[i].wstd) == 0)
938 #if 0
939 purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
940 win32_tzmap[i].ustd, tzname);
941 #endif
942 /* Cache the Result */
943 if (i > 0) {
944 if (win32_tzmap[0].wstd[0] != '\0')
945 g_free(win32_tzmap[0].wstd);
946 win32_tzmap[0].wstd = g_strdup(tzname);
947 win32_tzmap[0].ustd = win32_tzmap[i].ustd;
950 return win32_tzmap[i].ustd;
952 if (strcmp(tzname, win32_tzmap[i].wdst) == 0)
954 #if 0
955 purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
956 win32_tzmap[i].udst, tzname);
957 #endif
958 /* Cache the Result */
959 if (i > 0) {
960 if (win32_tzmap[0].wdst[0] != '\0')
961 g_free(win32_tzmap[0].wdst);
962 win32_tzmap[0].wdst = g_strdup(tzname);
963 win32_tzmap[0].udst = win32_tzmap[i].udst;
966 return win32_tzmap[i].udst;
971 * Localized Windows versions return localized names for the timezone.
972 * Scan the registry to find the English name, and then try matching
973 * against our table again.
975 memset(localtzname, 0, sizeof(localtzname));
976 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
977 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
979 KEY_READ,
980 &rootKey) != ERROR_SUCCESS)
982 purple_debug_warning("wpurple", "could not open registry key to identify Windows timezone: %i\n", (int) GetLastError());
983 return "";
986 for (idx = 0;; idx++)
988 char keyname[256];
989 char zonename[256];
990 DWORD namesize;
991 FILETIME lastwrite;
992 HKEY key;
993 LONG r;
995 memset(keyname, 0, sizeof(keyname));
996 namesize = sizeof(keyname);
997 if ((r = RegEnumKeyEx(rootKey,
998 idx,
999 keyname,
1000 &namesize,
1001 NULL,
1002 NULL,
1003 NULL,
1004 &lastwrite)) != ERROR_SUCCESS)
1006 if (r == ERROR_NO_MORE_ITEMS)
1007 break;
1008 purple_debug_warning("wpurple", "could not enumerate registry subkeys to identify Windows timezone: %i\n", (int) r);
1009 break;
1012 if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS)
1014 purple_debug_warning("wpurple", "could not open registry subkey to identify Windows timezone: %i\n", (int) r);
1015 break;
1018 memset(zonename, 0, sizeof(zonename));
1019 namesize = sizeof(zonename);
1020 if ((r = RegQueryValueEx(key, "Std", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
1022 purple_debug_warning("wpurple", "could not query value for 'std' to identify Windows timezone: %i\n", (int) r);
1023 RegCloseKey(key);
1024 break;
1026 if (strcmp(tzname, zonename) == 0)
1028 /* Matched zone */
1029 g_strlcpy(localtzname, keyname, sizeof(localtzname));
1030 RegCloseKey(key);
1031 break;
1033 memset(zonename, 0, sizeof(zonename));
1034 namesize = sizeof(zonename);
1035 if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
1037 purple_debug_warning("wpurple", "could not query value for 'dlt' to identify Windows timezone: %i\n", (int) r);
1038 RegCloseKey(key);
1039 break;
1041 if (strcmp(tzname, zonename) == 0)
1043 /* Matched DST zone */
1044 g_strlcpy(localtzname, keyname, sizeof(localtzname));
1045 RegCloseKey(key);
1046 break;
1049 RegCloseKey(key);
1052 RegCloseKey(rootKey);
1054 if (localtzname[0])
1056 /* Found a localized name, so scan for that one too */
1057 for (i = 0; win32_tzmap[i].wstd != NULL; i++)
1059 if (strcmp(localtzname, win32_tzmap[i].wstd) == 0)
1061 #if 0
1062 purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
1063 win32_tzmap[i].ustd, tzname, localtzname);
1064 #endif
1065 /* Cache the Result */
1066 if (win32_tzmap[0].wstd[0] != '\0')
1067 g_free(win32_tzmap[0].wstd);
1068 win32_tzmap[0].wstd = g_strdup(tzname);
1069 win32_tzmap[0].ustd = win32_tzmap[i].ustd;
1071 return win32_tzmap[i].ustd;
1073 if (strcmp(localtzname, win32_tzmap[i].wdst) == 0)
1075 #if 0
1076 purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
1077 win32_tzmap[i].udst, tzname, localtzname);
1078 #endif
1079 /* Cache the Result */
1080 if (win32_tzmap[0].wdst[0] != '\0')
1081 g_free(win32_tzmap[0].wdst);
1083 win32_tzmap[0].wdst = g_strdup(tzname);
1084 win32_tzmap[0].udst = win32_tzmap[i].udst;
1086 return win32_tzmap[i].udst;
1091 purple_debug_warning("wpurple", "could not find a match for Windows timezone \"%s\"\n", tzname);
1092 return "";
1095 int wpurple_g_access (const gchar *filename, int mode);
1097 * @deprecated - remove for 3.0.0
1100 wpurple_g_access (const gchar *filename, int mode)
1102 return g_access(filename, mode);