1 /* 2 * Wininet - Utility functions 3 * 4 * Copyright 1999 Corel Corporation 5 * Copyright 2002 CodeWeavers Inc. 6 * 7 * Ulrich Czekalla 8 * Aric Stewart 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 */ 24 25 #include "internet.h" 26 27 // ReactOS 28 #include "inet_ntop.c" 29 30 #define TIME_STRING_LEN 30 31 32 time_t ConvertTimeString(LPCWSTR asctime) 33 { 34 WCHAR tmpChar[TIME_STRING_LEN]; 35 WCHAR *tmpChar2; 36 struct tm t; 37 int timelen = strlenW(asctime); 38 39 if(!timelen) 40 return 0; 41 42 /* FIXME: the atoiWs below rely on that tmpChar is \0 padded */ 43 memset( tmpChar, 0, sizeof(tmpChar) ); 44 lstrcpynW(tmpChar, asctime, TIME_STRING_LEN); 45 46 /* Assert that the string is the expected length */ 47 if (strlenW(asctime) >= TIME_STRING_LEN) FIXME("\n"); 48 49 /* Convert a time such as 'Mon, 15 Nov 1999 16:09:35 GMT' into a SYSTEMTIME structure 50 * We assume the time is in this format 51 * and divide it into easy to swallow chunks 52 */ 53 tmpChar[3]='\0'; 54 tmpChar[7]='\0'; 55 tmpChar[11]='\0'; 56 tmpChar[16]='\0'; 57 tmpChar[19]='\0'; 58 tmpChar[22]='\0'; 59 tmpChar[25]='\0'; 60 61 memset( &t, 0, sizeof(t) ); 62 t.tm_year = atoiW(tmpChar+12) - 1900; 63 t.tm_mday = atoiW(tmpChar+5); 64 t.tm_hour = atoiW(tmpChar+17); 65 t.tm_min = atoiW(tmpChar+20); 66 t.tm_sec = atoiW(tmpChar+23); 67 68 /* and month */ 69 tmpChar2 = tmpChar + 8; 70 switch(tmpChar2[2]) 71 { 72 case 'n': 73 if(tmpChar2[1]=='a') 74 t.tm_mon = 0; 75 else 76 t.tm_mon = 5; 77 break; 78 case 'b': 79 t.tm_mon = 1; 80 break; 81 case 'r': 82 if(tmpChar2[1]=='a') 83 t.tm_mon = 2; 84 else 85 t.tm_mon = 3; 86 break; 87 case 'y': 88 t.tm_mon = 4; 89 break; 90 case 'l': 91 t.tm_mon = 6; 92 break; 93 case 'g': 94 t.tm_mon = 7; 95 break; 96 case 'p': 97 t.tm_mon = 8; 98 break; 99 case 't': 100 t.tm_mon = 9; 101 break; 102 case 'v': 103 t.tm_mon = 10; 104 break; 105 case 'c': 106 t.tm_mon = 11; 107 break; 108 default: 109 FIXME("\n"); 110 } 111 112 return mktime(&t); 113 } 114 115 116 BOOL GetAddress(const WCHAR *name, INTERNET_PORT port, struct sockaddr *psa, int *sa_len, char *addr_str) 117 { 118 ADDRINFOW *res, hints; 119 void *addr = NULL; 120 int ret; 121 122 TRACE("%s\n", debugstr_w(name)); 123 124 memset( &hints, 0, sizeof(hints) ); 125 /* Prefer IPv4 to IPv6 addresses, since some servers do not listen on 126 * their IPv6 addresses even though they have IPv6 addresses in the DNS. 127 */ 128 hints.ai_family = AF_INET; 129 130 ret = GetAddrInfoW(name, NULL, &hints, &res); 131 if (ret != 0) 132 { 133 TRACE("failed to get IPv4 address of %s, retrying with IPv6\n", debugstr_w(name)); 134 hints.ai_family = AF_INET6; 135 ret = GetAddrInfoW(name, NULL, &hints, &res); 136 } 137 if (ret != 0) 138 { 139 TRACE("failed to get address of %s\n", debugstr_w(name)); 140 return FALSE; 141 } 142 if (*sa_len < res->ai_addrlen) 143 { 144 WARN("address too small\n"); 145 FreeAddrInfoW(res); 146 return FALSE; 147 } 148 *sa_len = res->ai_addrlen; 149 memcpy( psa, res->ai_addr, res->ai_addrlen ); 150 /* Copy port */ 151 switch (res->ai_family) 152 { 153 case AF_INET: 154 addr = &((struct sockaddr_in *)psa)->sin_addr; 155 ((struct sockaddr_in *)psa)->sin_port = htons(port); 156 break; 157 case AF_INET6: 158 addr = &((struct sockaddr_in6 *)psa)->sin6_addr; 159 ((struct sockaddr_in6 *)psa)->sin6_port = htons(port); 160 break; 161 } 162 163 if(addr_str) 164 inet_ntop(res->ai_family, addr, addr_str, INET6_ADDRSTRLEN); 165 FreeAddrInfoW(res); 166 return TRUE; 167 } 168 169 /* 170 * Helper function for sending async Callbacks 171 */ 172 173 static const char *get_callback_name(DWORD dwInternetStatus) { 174 static const wininet_flag_info internet_status[] = { 175 #define FE(x) { x, #x } 176 FE(INTERNET_STATUS_RESOLVING_NAME), 177 FE(INTERNET_STATUS_NAME_RESOLVED), 178 FE(INTERNET_STATUS_CONNECTING_TO_SERVER), 179 FE(INTERNET_STATUS_CONNECTED_TO_SERVER), 180 FE(INTERNET_STATUS_SENDING_REQUEST), 181 FE(INTERNET_STATUS_REQUEST_SENT), 182 FE(INTERNET_STATUS_RECEIVING_RESPONSE), 183 FE(INTERNET_STATUS_RESPONSE_RECEIVED), 184 FE(INTERNET_STATUS_CTL_RESPONSE_RECEIVED), 185 FE(INTERNET_STATUS_PREFETCH), 186 FE(INTERNET_STATUS_CLOSING_CONNECTION), 187 FE(INTERNET_STATUS_CONNECTION_CLOSED), 188 FE(INTERNET_STATUS_HANDLE_CREATED), 189 FE(INTERNET_STATUS_HANDLE_CLOSING), 190 FE(INTERNET_STATUS_REQUEST_COMPLETE), 191 FE(INTERNET_STATUS_REDIRECT), 192 FE(INTERNET_STATUS_INTERMEDIATE_RESPONSE), 193 FE(INTERNET_STATUS_USER_INPUT_REQUIRED), 194 FE(INTERNET_STATUS_STATE_CHANGE), 195 FE(INTERNET_STATUS_COOKIE_SENT), 196 FE(INTERNET_STATUS_COOKIE_RECEIVED), 197 FE(INTERNET_STATUS_PRIVACY_IMPACTED), 198 FE(INTERNET_STATUS_P3P_HEADER), 199 FE(INTERNET_STATUS_P3P_POLICYREF), 200 FE(INTERNET_STATUS_COOKIE_HISTORY) 201 #undef FE 202 }; 203 DWORD i; 204 205 for (i = 0; i < (sizeof(internet_status) / sizeof(internet_status[0])); i++) { 206 if (internet_status[i].val == dwInternetStatus) return internet_status[i].name; 207 } 208 return "Unknown"; 209 } 210 211 static const char *debugstr_status_info(DWORD status, void *info) 212 { 213 switch(status) { 214 case INTERNET_STATUS_REQUEST_COMPLETE: { 215 INTERNET_ASYNC_RESULT *iar = info; 216 return wine_dbg_sprintf("{%s, %d}", wine_dbgstr_longlong(iar->dwResult), iar->dwError); 217 } 218 default: 219 return wine_dbg_sprintf("%p", info); 220 } 221 } 222 223 void INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR context, DWORD status, void *info, DWORD info_len) 224 { 225 void *new_info = info; 226 227 if( !hdr->lpfnStatusCB ) 228 return; 229 230 /* the IE5 version of wininet does not 231 send callbacks if dwContext is zero */ 232 if(!context) 233 return; 234 235 switch(status) { 236 case INTERNET_STATUS_NAME_RESOLVED: 237 case INTERNET_STATUS_CONNECTING_TO_SERVER: 238 case INTERNET_STATUS_CONNECTED_TO_SERVER: 239 new_info = heap_alloc(info_len); 240 if(new_info) 241 memcpy(new_info, info, info_len); 242 break; 243 case INTERNET_STATUS_RESOLVING_NAME: 244 case INTERNET_STATUS_REDIRECT: 245 if(hdr->dwInternalFlags & INET_CALLBACKW) { 246 new_info = heap_strdupW(info); 247 break; 248 }else { 249 new_info = heap_strdupWtoA(info); 250 info_len = strlen(new_info)+1; 251 break; 252 } 253 } 254 255 TRACE(" callback(%p) (%p (%p), %08lx, %d (%s), %s, %d)\n", 256 hdr->lpfnStatusCB, hdr->hInternet, hdr, context, status, get_callback_name(status), 257 debugstr_status_info(status, new_info), info_len); 258 259 hdr->lpfnStatusCB(hdr->hInternet, context, status, new_info, info_len); 260 261 TRACE(" end callback().\n"); 262 263 if(new_info != info) 264 heap_free(new_info); 265 } 266