| 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 |
|