| |
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 /* Thanks to GNU wget for this inet_ntop() implementation */ |
| |
236 const char * |
| |
237 wgaim_inet_ntop (int af, const void *src, char *dst, socklen_t cnt) |
| |
238 { |
| |
239 /* struct sockaddr can't accomodate struct sockaddr_in6. */ |
| |
240 union { |
| |
241 struct sockaddr_in6 sin6; |
| |
242 struct sockaddr_in sin; |
| |
243 } sa; |
| |
244 DWORD dstlen = cnt; |
| |
245 size_t srcsize; |
| |
246 |
| |
247 ZeroMemory(&sa, sizeof(sa)); |
| |
248 switch (af) |
| |
249 { |
| |
250 case AF_INET: |
| |
251 sa.sin.sin_family = AF_INET; |
| |
252 sa.sin.sin_addr = *(struct in_addr *) src; |
| |
253 srcsize = sizeof (sa.sin); |
| |
254 break; |
| |
255 case AF_INET6: |
| |
256 sa.sin6.sin6_family = AF_INET6; |
| |
257 sa.sin6.sin6_addr = *(struct in6_addr *) src; |
| |
258 srcsize = sizeof (sa.sin6); |
| |
259 break; |
| |
260 default: |
| |
261 abort (); |
| |
262 } |
| |
263 |
| |
264 if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0) |
| |
265 { |
| |
266 errno = WSAGetLastError(); |
| |
267 return NULL; |
| |
268 } |
| |
269 return (const char *) dst; |
| |
270 } |
| |
271 |
| |
272 |
| |
273 /* netdb.h */ |
| |
274 struct hostent* wgaim_gethostbyname(const char *name) { |
| |
275 struct hostent *hp; |
| |
276 |
| |
277 if((hp = gethostbyname(name)) == NULL) { |
| |
278 errno = WSAGetLastError(); |
| |
279 return NULL; |
| |
280 } |
| |
281 return hp; |
| |
282 } |
| |
283 |
| |
284 /* string.h */ |
| |
285 char* wgaim_strerror( int errornum ) { |
| |
286 if( errornum > WSABASEERR ) { |
| |
287 sprintf( errbuf, "Windows socket error #%d", errornum ); |
| |
288 return errbuf; |
| |
289 } |
| |
290 else |
| |
291 return strerror( errornum ); |
| |
292 } |
| |
293 |
| |
294 /* unistd.h */ |
| |
295 |
| |
296 /* |
| |
297 * We need to figure out whether fd is a file or socket handle. |
| |
298 */ |
| |
299 int wgaim_read(int fd, void *buf, unsigned int size) { |
| |
300 int ret; |
| |
301 |
| |
302 if(wgaim_is_socket(fd)) { |
| |
303 if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) { |
| |
304 errno = WSAGetLastError(); |
| |
305 if(errno == WSAEWOULDBLOCK) |
| |
306 errno = EAGAIN; |
| |
307 return -1; |
| |
308 } |
| |
309 #if 0 |
| |
310 else if( ret == 0 ) { |
| |
311 /* connection has been gracefully closed */ |
| |
312 errno = WSAENOTCONN; |
| |
313 return -1; |
| |
314 } |
| |
315 #endif |
| |
316 else { |
| |
317 /* success reading socket */ |
| |
318 return ret; |
| |
319 } |
| |
320 } else { |
| |
321 /* fd is not a socket handle.. pass it off to read */ |
| |
322 return read(fd, buf, size); |
| |
323 } |
| |
324 } |
| |
325 |
| |
326 int wgaim_send(int fd, const void *buf, unsigned int size, int flags) { |
| |
327 int ret; |
| |
328 |
| |
329 ret = send(fd, buf, size, flags); |
| |
330 |
| |
331 if (ret == SOCKET_ERROR) { |
| |
332 errno = WSAGetLastError(); |
| |
333 if(errno == WSAEWOULDBLOCK) |
| |
334 errno = EAGAIN; |
| |
335 return -1; |
| |
336 } |
| |
337 return ret; |
| |
338 } |
| |
339 |
| |
340 int wgaim_write(int fd, const void *buf, unsigned int size) { |
| |
341 |
| |
342 if(wgaim_is_socket(fd)) |
| |
343 return wgaim_send(fd, buf, size, 0); |
| |
344 else |
| |
345 return write(fd, buf, size); |
| |
346 } |
| |
347 |
| |
348 int wgaim_recv(int fd, void *buf, size_t len, int flags) { |
| |
349 int ret; |
| |
350 |
| |
351 if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) { |
| |
352 errno = WSAGetLastError(); |
| |
353 if(errno == WSAEWOULDBLOCK) |
| |
354 errno = EAGAIN; |
| |
355 return -1; |
| |
356 } else { |
| |
357 return ret; |
| |
358 } |
| |
359 } |
| |
360 |
| |
361 int wgaim_close(int fd) { |
| |
362 int ret; |
| |
363 |
| |
364 if( wgaim_is_socket(fd) ) { |
| |
365 if( (ret = closesocket(fd)) == SOCKET_ERROR ) { |
| |
366 errno = WSAGetLastError(); |
| |
367 return -1; |
| |
368 } |
| |
369 else |
| |
370 return 0; |
| |
371 } |
| |
372 else |
| |
373 return close(fd); |
| |
374 } |
| |
375 |
| |
376 int wgaim_gethostname(char *name, size_t size) { |
| |
377 if(gethostname(name, size) == SOCKET_ERROR) { |
| |
378 errno = WSAGetLastError(); |
| |
379 return -1; |
| |
380 } |
| |
381 return 0; |
| |
382 } |
| |
383 |
| |
384 /* sys/time.h */ |
| |
385 |
| |
386 int wgaim_gettimeofday(struct timeval *p, struct timezone *z) { |
| |
387 int res = 0; |
| |
388 struct _timeb timebuffer; |
| |
389 |
| |
390 if (z != 0) { |
| |
391 _tzset(); |
| |
392 z->tz_minuteswest = _timezone/60; |
| |
393 z->tz_dsttime = _daylight; |
| |
394 } |
| |
395 |
| |
396 if (p != 0) { |
| |
397 _ftime(&timebuffer); |
| |
398 p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */ |
| |
399 p->tv_usec = timebuffer.millitm*1000; /* microseconds */ |
| |
400 } |
| |
401 |
| |
402 return res; |
| |
403 } |
| |
404 |
| |
405 /* stdio.h */ |
| |
406 |
| |
407 int wgaim_rename (const char *oldname, const char *newname) { |
| |
408 struct stat oldstat, newstat; |
| |
409 |
| |
410 if(g_stat(oldname, &oldstat) == 0) { |
| |
411 /* newname exists */ |
| |
412 if(g_stat(newname, &newstat) == 0) { |
| |
413 /* oldname is a dir */ |
| |
414 if(_S_ISDIR(oldstat.st_mode)) { |
| |
415 if(!_S_ISDIR(newstat.st_mode)) { |
| |
416 return g_rename(oldname, newname); |
| |
417 } |
| |
418 /* newname is a dir */ |
| |
419 else { |
| |
420 /* This is not quite right.. If newname is empty and |
| |
421 is not a sub dir of oldname, newname should be |
| |
422 deleted and oldname should be renamed. |
| |
423 */ |
| |
424 gaim_debug(GAIM_DEBUG_WARNING, "wgaim", "wgaim_rename does not behave here as it should\n"); |
| |
425 return g_rename(oldname, newname); |
| |
426 } |
| |
427 } |
| |
428 /* oldname is not a dir */ |
| |
429 else { |
| |
430 /* newname is a dir */ |
| |
431 if(_S_ISDIR(newstat.st_mode)) { |
| |
432 errno = EISDIR; |
| |
433 return -1; |
| |
434 } |
| |
435 /* newname is not a dir */ |
| |
436 else { |
| |
437 g_remove(newname); |
| |
438 return g_rename(oldname, newname); |
| |
439 } |
| |
440 } |
| |
441 } |
| |
442 /* newname doesn't exist */ |
| |
443 else |
| |
444 return g_rename(oldname, newname); |
| |
445 } |
| |
446 else { |
| |
447 /* oldname doesn't exist */ |
| |
448 errno = ENOENT; |
| |
449 return -1; |
| |
450 } |
| |
451 |
| |
452 } |
| |
453 |
| |
454 /* time.h */ |
| |
455 |
| |
456 struct tm * wgaim_localtime_r (const time_t *time, struct tm *resultp) { |
| |
457 struct tm* tmptm; |
| |
458 |
| |
459 if(!time) |
| |
460 return NULL; |
| |
461 tmptm = localtime(time); |
| |
462 if(resultp && tmptm) |
| |
463 return memcpy(resultp, tmptm, sizeof(struct tm)); |
| |
464 else |
| |
465 return NULL; |
| |
466 } |
| |
467 |
| |
468 /* |
| |
469 * Used by gaim_utf8_strftime() by way of gaim_internal_strftime() |
| |
470 * in src/util.c |
| |
471 * |
| |
472 * Code derived from PostgreSQL src/timezone/pgtz.c: |
| |
473 * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c |
| |
474 */ |
| |
475 |
| |
476 /* |
| |
477 PostgreSQL Database Management System |
| |
478 (formerly known as Postgres, then as Postgres95) |
| |
479 |
| |
480 Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group |
| |
481 |
| |
482 Portions Copyright (c) 1994, The Regents of the University of California |
| |
483 |
| |
484 Permission to use, copy, modify, and distribute this software and its |
| |
485 documentation for any purpose, without fee, and without a written agreement |
| |
486 is hereby granted, provided that the above copyright notice and this |
| |
487 paragraph and the following two paragraphs appear in all copies. |
| |
488 |
| |
489 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
| |
490 DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING |
| |
491 LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS |
| |
492 DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE |
| |
493 POSSIBILITY OF SUCH DAMAGE. |
| |
494 |
| |
495 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
| |
496 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
| |
497 AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
| |
498 ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO |
| |
499 PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| |
500 |
| |
501 */ |
| |
502 static struct |
| |
503 { |
| |
504 char *wstd; /* Windows name of standard timezone */ |
| |
505 char *wdst; /* Windows name of daylight timezone */ |
| |
506 char *ustd; /* Unix name of standard timezone */ |
| |
507 char *udst; /* Unix name of daylight timezone */ |
| |
508 } win32_tzmap[] = |
| |
509 { |
| |
510 { |
| |
511 "", "", |
| |
512 "", "", |
| |
513 }, |
| |
514 /* |
| |
515 * This list was built from the contents of the registry at |
| |
516 * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" |
| |
517 * on Windows XP Professional SP1 |
| |
518 */ |
| |
519 { |
| |
520 "Afghanistan Standard Time", "Afghanistan Daylight Time", |
| |
521 "AFT", "AFT" |
| |
522 }, |
| |
523 { |
| |
524 "Alaskan Standard Time", "Alaskan Daylight Time", |
| |
525 "AKST", "AKDT" |
| |
526 }, |
| |
527 { |
| |
528 "Arab Standard Time", "Arab Daylight Time", |
| |
529 "AST", "AST" |
| |
530 }, |
| |
531 { |
| |
532 "Arabian Standard Time", "Arabian Daylight Time", |
| |
533 "GST", "GST" |
| |
534 }, |
| |
535 { |
| |
536 "Arabic Standard Time", "Arabic Daylight Time", |
| |
537 "AST", "ADT" |
| |
538 }, |
| |
539 { |
| |
540 "Atlantic Standard Time", "Atlantic Daylight Time", |
| |
541 "AST", "ADT" |
| |
542 }, |
| |
543 { |
| |
544 "AUS Central Standard Time", "AUS Central Daylight Time", |
| |
545 "CST", "CST" |
| |
546 }, |
| |
547 { |
| |
548 "AUS Eastern Standard Time", "AUS Eastern Daylight Time", |
| |
549 "EST", "EST" |
| |
550 }, |
| |
551 { |
| |
552 "Azores Standard Time", "Azores Daylight Time", |
| |
553 "AZOT", "AZOST" |
| |
554 }, |
| |
555 { |
| |
556 "Canada Central Standard Time", "Canada Central Daylight Time", |
| |
557 "CST", "MDT" |
| |
558 }, |
| |
559 { |
| |
560 "Cape Verde Standard Time", "Cape Verde Daylight Time", |
| |
561 "CVT", "CVST" |
| |
562 }, |
| |
563 { |
| |
564 "Caucasus Standard Time", "Caucasus Daylight Time", |
| |
565 "AZT", "AZST" |
| |
566 }, |
| |
567 { |
| |
568 "Cen. Australia Standard Time", "Cen. Australia Daylight Time", |
| |
569 "CST", "CST" |
| |
570 }, |
| |
571 { |
| |
572 "Central America Standard Time", "Central America Daylight Time", |
| |
573 "CST", "CDT" |
| |
574 }, |
| |
575 { |
| |
576 "Central Asia Standard Time", "Central Asia Daylight Time", |
| |
577 "BDT", "BDT" |
| |
578 }, |
| |
579 { |
| |
580 "Central Europe Standard Time", "Central Europe Daylight Time", |
| |
581 "CET", "CEST" |
| |
582 }, |
| |
583 { |
| |
584 "Central European Standard Time", "Central European Daylight Time", |
| |
585 "CET", "CEST" |
| |
586 }, |
| |
587 { |
| |
588 "Central Pacific Standard Time", "Central Pacific Daylight Time", |
| |
589 "NCT", "NCST" |
| |
590 }, |
| |
591 { |
| |
592 "Central Standard Time", "Central Daylight Time", |
| |
593 "CST", "CDT" |
| |
594 }, |
| |
595 { |
| |
596 "China Standard Time", "China Daylight Time", |
| |
597 "HKT", "HKST" |
| |
598 }, |
| |
599 { |
| |
600 "Dateline Standard Time", "Dateline Daylight Time", |
| |
601 "GMT+12", "GMT+12" |
| |
602 }, |
| |
603 { |
| |
604 "E. Africa Standard Time", "E. Africa Daylight Time", |
| |
605 "EAT", "EAT" |
| |
606 }, |
| |
607 { |
| |
608 "E. Australia Standard Time", "E. Australia Daylight Time", |
| |
609 "EST", "EST" |
| |
610 }, |
| |
611 { |
| |
612 "E. Europe Standard Time", "E. Europe Daylight Time", |
| |
613 "EET", "EEST" |
| |
614 }, |
| |
615 { |
| |
616 "E. South America Standard Time", "E. South America Daylight Time", |
| |
617 "BRT", "BRST" |
| |
618 }, |
| |
619 { |
| |
620 "Eastern Standard Time", "Eastern Daylight Time", |
| |
621 "EST", "EDT" |
| |
622 }, |
| |
623 { |
| |
624 "Egypt Standard Time", "Egypt Daylight Time", |
| |
625 "EET", "EEST" |
| |
626 }, |
| |
627 { |
| |
628 "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time", |
| |
629 "YEKT", "YEKST" |
| |
630 }, |
| |
631 { |
| |
632 "Fiji Standard Time", "Fiji Daylight Time", |
| |
633 "FJT", "FJST" |
| |
634 }, |
| |
635 { |
| |
636 "FLE Standard Time", "FLE Daylight Time", |
| |
637 "EET", "EEST" |
| |
638 }, |
| |
639 { |
| |
640 "GMT Standard Time", "GMT Daylight Time", |
| |
641 "GMT", "IST" |
| |
642 }, |
| |
643 { |
| |
644 "Greenland Standard Time", "Greenland Daylight Time", |
| |
645 "WGT", "WGST" |
| |
646 }, |
| |
647 { |
| |
648 "Greenwich Standard Time", "Greenwich Daylight Time", |
| |
649 "WET", "WEST" |
| |
650 }, |
| |
651 { |
| |
652 "GTB Standard Time", "GTB Daylight Time", |
| |
653 "EET", "EEST" |
| |
654 }, |
| |
655 { |
| |
656 "Hawaiian Standard Time", "Hawaiian Daylight Time", |
| |
657 "HST", "HPT" |
| |
658 }, |
| |
659 { |
| |
660 "India Standard Time", "India Daylight Time", |
| |
661 "IST", "IST" |
| |
662 }, |
| |
663 { |
| |
664 "Iran Standard Time", "Iran Daylight Time", |
| |
665 "IRST", "IRDT" |
| |
666 }, |
| |
667 { |
| |
668 "Jerusalem Standard Time", "Jerusalem Daylight Time", |
| |
669 "IST", "IDT" |
| |
670 }, |
| |
671 { |
| |
672 "Korea Standard Time", "Korea Daylight Time", |
| |
673 "KST", "KDT" |
| |
674 }, |
| |
675 { |
| |
676 "Mexico Standard Time", "Mexico Daylight Time", |
| |
677 "CST", "CDT" |
| |
678 }, |
| |
679 { |
| |
680 "Mexico Standard Time", "Mexico Daylight Time", |
| |
681 "BOT", "BOST" |
| |
682 }, |
| |
683 { |
| |
684 "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", |
| |
685 "GST", "GST" |
| |
686 }, |
| |
687 { |
| |
688 "Mountain Standard Time", "Mountain Daylight Time", |
| |
689 "MST", "MDT" |
| |
690 }, |
| |
691 { |
| |
692 "Myanmar Standard Time", "Myanmar Daylight Time", |
| |
693 "MMT", "MMT" |
| |
694 }, |
| |
695 { |
| |
696 "N. Central Asia Standard Time", "N. Central Asia Daylight Time", |
| |
697 "ALMT", "ALMST" |
| |
698 }, |
| |
699 { |
| |
700 "Nepal Standard Time", "Nepal Daylight Time", |
| |
701 "NPT", "NPT" |
| |
702 }, |
| |
703 { |
| |
704 "New Zealand Standard Time", "New Zealand Daylight Time", |
| |
705 "NZST", "NZDT" |
| |
706 }, |
| |
707 { |
| |
708 "Newfoundland Standard Time", "Newfoundland Daylight Time", |
| |
709 "NST", "NDT" |
| |
710 }, |
| |
711 { |
| |
712 "North Asia East Standard Time", "North Asia East Daylight Time", |
| |
713 "IRKT", "IRKST" |
| |
714 }, |
| |
715 { |
| |
716 "North Asia Standard Time", "North Asia Daylight Time", |
| |
717 "KRAT", "KRAST" |
| |
718 }, |
| |
719 { |
| |
720 "Pacific SA Standard Time", "Pacific SA Daylight Time", |
| |
721 "CLT", "CLST" |
| |
722 }, |
| |
723 { |
| |
724 "Pacific Standard Time", "Pacific Daylight Time", |
| |
725 "PST", "PDT" |
| |
726 }, |
| |
727 { |
| |
728 "Romance Standard Time", "Romance Daylight Time", |
| |
729 "CET", "CEST" |
| |
730 }, |
| |
731 { |
| |
732 "Russian Standard Time", "Russian Daylight Time", |
| |
733 "MSK", "MSD" |
| |
734 }, |
| |
735 { |
| |
736 "SA Eastern Standard Time", "SA Eastern Daylight Time", |
| |
737 "ART", "ARST" |
| |
738 }, |
| |
739 { |
| |
740 "SA Pacific Standard Time", "SA Pacific Daylight Time", |
| |
741 "COT", "COST" |
| |
742 }, |
| |
743 { |
| |
744 "SA Western Standard Time", "SA Western Daylight Time", |
| |
745 "VET", "VET" |
| |
746 }, |
| |
747 { |
| |
748 "Samoa Standard Time", "Samoa Daylight Time", |
| |
749 "SST", "NDT" |
| |
750 }, |
| |
751 { |
| |
752 "SE Asia Standard Time", "SE Asia Daylight Time", |
| |
753 "ICT", "ICT" |
| |
754 }, |
| |
755 { |
| |
756 "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", |
| |
757 "MYT", "MALST" |
| |
758 }, |
| |
759 { |
| |
760 "South Africa Standard Time", "South Africa Daylight Time", |
| |
761 "CAT", "CAT" |
| |
762 }, |
| |
763 { |
| |
764 "Sri Lanka Standard Time", "Sri Lanka Daylight Time", |
| |
765 "LKT", "IST" |
| |
766 }, |
| |
767 { |
| |
768 "Taipei Standard Time", "Taipei Daylight Time", |
| |
769 "CST", "CDT" |
| |
770 }, |
| |
771 { |
| |
772 "Tasmania Standard Time", "Tasmania Daylight Time", |
| |
773 "EST", "EST" |
| |
774 }, |
| |
775 { |
| |
776 "Tokyo Standard Time", "Tokyo Daylight Time", |
| |
777 "JST", "JDT" |
| |
778 }, |
| |
779 { |
| |
780 "Tonga Standard Time", "Tonga Daylight Time", |
| |
781 "TOT", "TOST" |
| |
782 }, |
| |
783 { |
| |
784 "US Eastern Standard Time", "US Eastern Daylight Time", |
| |
785 "EST", "EDT" |
| |
786 }, |
| |
787 { |
| |
788 "US Mountain Standard Time", "US Mountain Daylight Time", |
| |
789 "MST", "MDT" |
| |
790 }, |
| |
791 { |
| |
792 "Vladivostok Standard Time", "Vladivostok Daylight Time", |
| |
793 "VLAT", "VLAST" |
| |
794 }, |
| |
795 { |
| |
796 "W. Australia Standard Time", "W. Australia Daylight Time", |
| |
797 "WST", "WST" |
| |
798 }, |
| |
799 |
| |
800 /* Not mapped in PostgreSQL. |
| |
801 * |
| |
802 * I mapped this based on the following information... -- rlaager |
| |
803 * $ cd /usr/share/zoneinfo/Africa |
| |
804 * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100 |
| |
805 * +0100 CET Algiers |
| |
806 * +0100 WAT Bangui |
| |
807 * +0100 WAT Brazzaville |
| |
808 * +0100 CET Ceuta |
| |
809 * +0100 WAT Douala |
| |
810 * +0100 WAT Kinshasa |
| |
811 * +0100 WAT Lagos |
| |
812 * +0100 WAT Libreville |
| |
813 * +0100 WAT Luanda |
| |
814 * +0100 WAT Malabo |
| |
815 * +0100 WAT Ndjamena |
| |
816 * +0100 WAT Niamey |
| |
817 * +0100 WAT Porto-Novo |
| |
818 * +0100 CET Tunis |
| |
819 **/ |
| |
820 { |
| |
821 "W. Central Africa Standard Time", "W. Central Africa Daylight Time", |
| |
822 "WAT", "WAT" |
| |
823 }, |
| |
824 |
| |
825 { |
| |
826 "W. Europe Standard Time", "W. Europe Daylight Time", |
| |
827 "CET", "CEST" |
| |
828 }, |
| |
829 { |
| |
830 "West Asia Standard Time", "West Asia Daylight Time", |
| |
831 "PKT", "PKST" |
| |
832 }, |
| |
833 { |
| |
834 "West Pacific Standard Time", "West Pacific Daylight Time", |
| |
835 "ChST", "ChST" |
| |
836 }, |
| |
837 { |
| |
838 "Yakutsk Standard Time", "Yakutsk Daylight Time", |
| |
839 "YAKT", "YAKST" |
| |
840 }, |
| |
841 { |
| |
842 NULL, NULL, |
| |
843 NULL, NULL |
| |
844 } |
| |
845 }; |
| |
846 |
| |
847 const char * |
| |
848 wgaim_get_timezone_abbreviation(const struct tm *tm) |
| |
849 { |
| |
850 int i; |
| |
851 char tzname[128]; |
| |
852 char localtzname[256]; |
| |
853 HKEY rootKey; |
| |
854 int idx; |
| |
855 |
| |
856 if (!tm) |
| |
857 { |
| |
858 gaim_debug_warning("wgaim", "could not determine current date/time: localtime failed\n"); |
| |
859 return ""; |
| |
860 } |
| |
861 |
| |
862 if (strftime(tzname, sizeof(tzname) - 1, "%Z", tm) == 0) |
| |
863 { |
| |
864 gaim_debug_error("wgaim", "timezone name is too long for the buffer\n"); |
| |
865 return ""; |
| |
866 } |
| |
867 |
| |
868 for (i = 0; win32_tzmap[i].wstd != NULL; i++) |
| |
869 { |
| |
870 if (strcmp(tzname, win32_tzmap[i].wstd) == 0) |
| |
871 { |
| |
872 #if 0 |
| |
873 gaim_debug_info("wgaim", "TZ \"%s\" matches Windows timezone \"%s\"\n", |
| |
874 win32_tzmap[i].ustd, tzname); |
| |
875 #endif |
| |
876 /* Cache the Result */ |
| |
877 if (i > 0) { |
| |
878 if (win32_tzmap[0].wstd[0] != '\0') |
| |
879 g_free(win32_tzmap[0].wstd); |
| |
880 win32_tzmap[0].wstd = g_strdup(tzname); |
| |
881 win32_tzmap[0].ustd = win32_tzmap[i].ustd; |
| |
882 } |
| |
883 |
| |
884 return win32_tzmap[i].ustd; |
| |
885 } |
| |
886 if (strcmp(tzname, win32_tzmap[i].wdst) == 0) |
| |
887 { |
| |
888 #if 0 |
| |
889 gaim_debug_info("wgaim", "TZ \"%s\" matches Windows timezone \"%s\"\n", |
| |
890 win32_tzmap[i].udst, tzname); |
| |
891 #endif |
| |
892 /* Cache the Result */ |
| |
893 if (i > 0) { |
| |
894 if (win32_tzmap[0].wdst[0] != '\0') |
| |
895 g_free(win32_tzmap[0].wdst); |
| |
896 win32_tzmap[0].wdst = g_strdup(tzname); |
| |
897 win32_tzmap[0].udst = win32_tzmap[i].udst; |
| |
898 } |
| |
899 |
| |
900 return win32_tzmap[i].udst; |
| |
901 } |
| |
902 } |
| |
903 |
| |
904 /* |
| |
905 * Localized Windows versions return localized names for the timezone. |
| |
906 * Scan the registry to find the English name, and then try matching |
| |
907 * against our table again. |
| |
908 */ |
| |
909 memset(localtzname, 0, sizeof(localtzname)); |
| |
910 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, |
| |
911 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", |
| |
912 0, |
| |
913 KEY_READ, |
| |
914 &rootKey) != ERROR_SUCCESS) |
| |
915 { |
| |
916 gaim_debug_warning("wgaim", "could not open registry key to identify Windows timezone: %i\n", (int) GetLastError()); |
| |
917 return ""; |
| |
918 } |
| |
919 |
| |
920 for (idx = 0;; idx++) |
| |
921 { |
| |
922 char keyname[256]; |
| |
923 char zonename[256]; |
| |
924 DWORD namesize; |
| |
925 FILETIME lastwrite; |
| |
926 HKEY key; |
| |
927 LONG r; |
| |
928 |
| |
929 memset(keyname, 0, sizeof(keyname)); |
| |
930 namesize = sizeof(keyname); |
| |
931 if ((r = RegEnumKeyEx(rootKey, |
| |
932 idx, |
| |
933 keyname, |
| |
934 &namesize, |
| |
935 NULL, |
| |
936 NULL, |
| |
937 NULL, |
| |
938 &lastwrite)) != ERROR_SUCCESS) |
| |
939 { |
| |
940 if (r == ERROR_NO_MORE_ITEMS) |
| |
941 break; |
| |
942 gaim_debug_warning("wgaim", "could not enumerate registry subkeys to identify Windows timezone: %i\n", (int) r); |
| |
943 break; |
| |
944 } |
| |
945 |
| |
946 if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS) |
| |
947 { |
| |
948 gaim_debug_warning("wgaim", "could not open registry subkey to identify Windows timezone: %i\n", (int) r); |
| |
949 break; |
| |
950 } |
| |
951 |
| |
952 memset(zonename, 0, sizeof(zonename)); |
| |
953 namesize = sizeof(zonename); |
| |
954 if ((r = RegQueryValueEx(key, "Std", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS) |
| |
955 { |
| |
956 gaim_debug_warning("wgaim", "could not query value for 'std' to identify Windows timezone: %i\n", (int) r); |
| |
957 RegCloseKey(key); |
| |
958 break; |
| |
959 } |
| |
960 if (strcmp(tzname, zonename) == 0) |
| |
961 { |
| |
962 /* Matched zone */ |
| |
963 strcpy(localtzname, keyname); |
| |
964 RegCloseKey(key); |
| |
965 break; |
| |
966 } |
| |
967 memset(zonename, 0, sizeof(zonename)); |
| |
968 namesize = sizeof(zonename); |
| |
969 if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS) |
| |
970 { |
| |
971 gaim_debug_warning("wgaim", "could not query value for 'dlt' to identify Windows timezone: %i\n", (int) r); |
| |
972 RegCloseKey(key); |
| |
973 break; |
| |
974 } |
| |
975 if (strcmp(tzname, zonename) == 0) |
| |
976 { |
| |
977 /* Matched DST zone */ |
| |
978 strcpy(localtzname, keyname); |
| |
979 RegCloseKey(key); |
| |
980 break; |
| |
981 } |
| |
982 |
| |
983 RegCloseKey(key); |
| |
984 } |
| |
985 |
| |
986 RegCloseKey(rootKey); |
| |
987 |
| |
988 if (localtzname[0]) |
| |
989 { |
| |
990 /* Found a localized name, so scan for that one too */ |
| |
991 for (i = 0; win32_tzmap[i].wstd != NULL; i++) |
| |
992 { |
| |
993 if (strcmp(localtzname, win32_tzmap[i].wstd) == 0) |
| |
994 { |
| |
995 #if 0 |
| |
996 gaim_debug_info("wgaim", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n", |
| |
997 win32_tzmap[i].ustd, tzname, localtzname); |
| |
998 #endif |
| |
999 /* Cache the Result */ |
| |
1000 if (win32_tzmap[0].wstd[0] != '\0') |
| |
1001 g_free(win32_tzmap[0].wstd); |
| |
1002 win32_tzmap[0].wstd = g_strdup(tzname); |
| |
1003 win32_tzmap[0].ustd = win32_tzmap[i].ustd; |
| |
1004 |
| |
1005 return win32_tzmap[i].ustd; |
| |
1006 } |
| |
1007 if (strcmp(localtzname, win32_tzmap[i].wdst) == 0) |
| |
1008 { |
| |
1009 #if 0 |
| |
1010 gaim_debug_info("wgaim", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n", |
| |
1011 win32_tzmap[i].udst, tzname, localtzname); |
| |
1012 #endif |
| |
1013 /* Cache the Result */ |
| |
1014 if (win32_tzmap[0].wdst[0] != '\0') |
| |
1015 g_free(win32_tzmap[0].wdst); |
| |
1016 |
| |
1017 win32_tzmap[0].wdst = g_strdup(tzname); |
| |
1018 win32_tzmap[0].udst = win32_tzmap[i].udst; |
| |
1019 |
| |
1020 return win32_tzmap[i].udst; |
| |
1021 } |
| |
1022 } |
| |
1023 } |
| |
1024 |
| |
1025 gaim_debug_warning("wgaim", "could not find a match for Windows timezone \"%s\"\n", tzname); |
| |
1026 return ""; |
| |
1027 } |
| |
1028 |
| |
1029 #if !GLIB_CHECK_VERSION(2,8,0) |
| |
1030 /** |
| |
1031 * g_access: |
| |
1032 * @filename: a pathname in the GLib file name encoding (UTF-8 on Windows) |
| |
1033 * @mode: as in access() |
| |
1034 * |
| |
1035 * A wrapper for the POSIX access() function. This function is used to |
| |
1036 * test a pathname for one or several of read, write or execute |
| |
1037 * permissions, or just existence. On Windows, the underlying access() |
| |
1038 * function in the C library only checks the READONLY attribute, and |
| |
1039 * does not look at the ACL at all. Software that needs to handle file |
| |
1040 * permissions on Windows more exactly should use the Win32 API. |
| |
1041 * |
| |
1042 * See the C library manual for more details about access(). |
| |
1043 * |
| |
1044 * Returns: zero if the pathname refers to an existing file system |
| |
1045 * object that has all the tested permissions, or -1 otherwise or on |
| |
1046 * error. |
| |
1047 * |
| |
1048 * Since: 2.8 |
| |
1049 */ |
| |
1050 int |
| |
1051 wgaim_g_access (const gchar *filename, |
| |
1052 int mode) |
| |
1053 { |
| |
1054 if (G_WIN32_HAVE_WIDECHAR_API ()) |
| |
1055 { |
| |
1056 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL); |
| |
1057 int retval; |
| |
1058 int save_errno; |
| |
1059 |
| |
1060 if (wfilename == NULL) |
| |
1061 { |
| |
1062 errno = EINVAL; |
| |
1063 return -1; |
| |
1064 } |
| |
1065 |
| |
1066 retval = _waccess (wfilename, mode); |
| |
1067 save_errno = errno; |
| |
1068 |
| |
1069 g_free (wfilename); |
| |
1070 |
| |
1071 errno = save_errno; |
| |
1072 return retval; |
| |
1073 } |
| |
1074 else |
| |
1075 { |
| |
1076 gchar *cp_filename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL); |
| |
1077 int retval; |
| |
1078 int save_errno; |
| |
1079 |
| |
1080 if (cp_filename == NULL) |
| |
1081 { |
| |
1082 errno = EINVAL; |
| |
1083 return -1; |
| |
1084 } |
| |
1085 |
| |
1086 retval = access (cp_filename, mode); |
| |
1087 save_errno = errno; |
| |
1088 |
| |
1089 g_free (cp_filename); |
| |
1090 |
| |
1091 errno = save_errno; |
| |
1092 return retval; |
| |
1093 } |
| |
1094 } |
| |
1095 #endif |
| |
1096 |
| |
1097 |