src/win32/libc_interface.c

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

mercurial