]> cygwin.com Git - cygwin-apps/setup.git/blame - nio-ie5.cc
Indicate test packages in action menu
[cygwin-apps/setup.git] / nio-ie5.cc
CommitLineData
23c9e63c
DD
1/*
2 * Copyright (c) 2000, Red Hat, Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
11 *
12 * Written by DJ Delorie <dj@cygnus.com>
13 *
14 */
15
16/* The purpose of this file is to manage internet downloads using the
17 Internet Explorer version 5 DLLs. To use this method, the user
18 must already have installed and configured IE5. This module is
19 called from netio.cc, which is called from geturl.cc */
20
21#include "win32.h"
22
23#include "resource.h"
24#include "state.h"
25#include "dialog.h"
26#include "msg.h"
27#include "netio.h"
28#include "nio-ie5.h"
a10fdeb9 29#include "LogSingleton.h"
c975851a
JT
30#include "setup_version.h"
31#include "getopt++/StringOption.h"
a70f0d56 32#include <sstream>
c975851a 33
f378fb54
JT
34#ifndef IMAGE_FILE_MACHINE_ARM64
35#define IMAGE_FILE_MACHINE_ARM64 0xAA64
36#endif
37
c975851a 38static StringOption UserAgent ("", '\0', "user-agent", "User agent string for HTTP requests");
23c9e63c 39
50147e20
JT
40const std::string &
41determine_default_useragent(void)
42{
43 static std::string default_useragent;
44
45 if (!default_useragent.empty())
46 return default_useragent;
47
a70f0d56
JT
48 std::stringstream os;
49 os << "Windows NT " << OSMajorVersion() << "." << OSMinorVersion() << "." << OSBuildNumber();
50
51 std::string bitness = "Unknown";
50147e20 52#ifdef __x86_64__
a70f0d56 53 bitness = "Win64";
50147e20 54#else
f378fb54
JT
55 typedef BOOL (WINAPI *PFNISWOW64PROCESS2)(HANDLE, USHORT *, USHORT *);
56 PFNISWOW64PROCESS2 pfnIsWow64Process2 = (PFNISWOW64PROCESS2)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process2");
57
50147e20
JT
58 typedef BOOL (WINAPI *PFNISWOW64PROCESS)(HANDLE, PBOOL);
59 PFNISWOW64PROCESS pfnIsWow64Process = (PFNISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");
f378fb54
JT
60
61 std::stringstream native_desc;
62
63 USHORT processMachine, nativeMachine;
64 if ((pfnIsWow64Process2) &&
65 (pfnIsWow64Process2(GetCurrentProcess(), &processMachine, &nativeMachine))) {
66 switch (nativeMachine)
67 {
d86d832b
JT
68 case IMAGE_FILE_MACHINE_I386:
69 bitness = "Win32";
70 break;
f378fb54
JT
71 case IMAGE_FILE_MACHINE_AMD64:
72 bitness = "WoW64";
73 break;
74 case IMAGE_FILE_MACHINE_ARM64:
75 bitness = "WoW64-ARM64";
76 break;
77 default:
78 native_desc << "WoW64-" << std::hex << nativeMachine;
79 bitness = native_desc.str();
80 }
81 } else if (pfnIsWow64Process) {
50147e20
JT
82 BOOL bIsWow64 = FALSE;
83 if (pfnIsWow64Process(GetCurrentProcess(), &bIsWow64))
a70f0d56 84 bitness = bIsWow64 ? "WoW64" : "Win32";
50147e20
JT
85 }
86#endif
a70f0d56 87 default_useragent = std::string("Cygwin-Setup/") + setup_version + " (" + os.str() + ";" + bitness + ")";
50147e20
JT
88 return default_useragent;
89}
90
150fc845
SG
91
92class Proxy
93{
94 int method;
95 std::string host;
96 int port;
97 std::string hostport; // host:port
98
99public:
100 Proxy (int method, char const *host, int port)
101 : method(method),
102 host(host ? host : ""),
103 port(port),
104 hostport(std::string(host ? host : "") + ":" + std::to_string(port))
105 {};
106
107 bool operator!= (const Proxy &o) const;
108
109 DWORD type (void) const;
110 char const *string (void) const;
111};
112
113bool Proxy::operator!= (const Proxy &o) const
114{
115 if (method != o.method) return true;
116 if (method != IDC_NET_PROXY) return false;
117 // it's only meaningful to compare host:port for method == IDC_NET_PROXY
118 if (host != o.host) return true;
119 if (port != o.port) return true;
120 return false;
121}
122
123char const *Proxy::string(void) const
124{
125 if (method == IDC_NET_PROXY)
126 return hostport.c_str();
127 else
128 return NULL;
129}
130
131DWORD Proxy::type (void) const
132{
133 switch (method)
134 {
135 case IDC_NET_PROXY: return INTERNET_OPEN_TYPE_PROXY;
136 case IDC_NET_PRECONFIG: return INTERNET_OPEN_TYPE_PRECONFIG;
137 default:
138 case IDC_NET_DIRECT: return INTERNET_OPEN_TYPE_DIRECT;
139 }
140}
141
f75381c6
SG
142static HINTERNET internet = 0;
143static Proxy last_proxy = Proxy(-1, "", -1);
144
ccbb34d3 145NetIO_IE5::NetIO_IE5 (char const *url, bool cachable)
23c9e63c 146{
348860fa
DD
147 int resend = 0;
148
f75381c6
SG
149 Proxy proxy = Proxy(net_method, net_proxy_host, net_proxy_port);
150 if (proxy != last_proxy)
4a83b7b0 151 {
f75381c6
SG
152 last_proxy = proxy;
153
154 if (internet != 0)
155 InternetCloseHandle(internet);
156 else
157 InternetAttemptConnect (0);
c975851a 158
50147e20 159 const char *lpszAgent = determine_default_useragent().c_str();
c975851a
JT
160 if (UserAgent.isPresent())
161 {
162 const std::string &user_agent = UserAgent;
163 if (user_agent.length())
164 {
165 // override the default user agent string
166 lpszAgent = user_agent.c_str();
167 Log (LOG_PLAIN) << "User-Agent: header overridden to \"" << lpszAgent << "\"" << endLog;
168 }
169 else
170 {
171 // user-agent option is present, but no string is specified means
172 // don't add a user-agent header
173 lpszAgent = NULL;
174 Log (LOG_PLAIN) << "User-Agent: header suppressed " << lpszAgent << endLog;
175 }
176 }
177
f75381c6 178 internet = InternetOpen (lpszAgent, proxy.type(), proxy.string(), NULL, 0);
4a83b7b0 179 }
23c9e63c
DD
180
181 DWORD flags =
23c9e63c 182 INTERNET_FLAG_KEEP_CONNECTION |
b24c88b3 183 INTERNET_FLAG_EXISTING_CONNECT | INTERNET_FLAG_PASSIVE;
23c9e63c 184
ca875ed3
JT
185 if (!cachable) {
186 flags |= INTERNET_FLAG_NO_CACHE_WRITE;
9b9237fb
JT
187 } else {
188 flags |= INTERNET_FLAG_RESYNCHRONIZE;
ca875ed3
JT
189 }
190
f75381c6 191 connection = InternetOpenUrl (internet, url, NULL, 0, flags, 0);
348860fa 192
b24c88b3 193try_again:
4e8ff53f
DD
194
195 if (net_user && net_passwd)
196 {
348860fa 197 InternetSetOption (connection, INTERNET_OPTION_USERNAME,
4e8ff53f 198 net_user, strlen (net_user));
348860fa 199 InternetSetOption (connection, INTERNET_OPTION_PASSWORD,
4e8ff53f
DD
200 net_passwd, strlen (net_passwd));
201 }
202
23c9e63c
DD
203 if (net_proxy_user && net_proxy_passwd)
204 {
348860fa 205 InternetSetOption (connection, INTERNET_OPTION_PROXY_USERNAME,
23c9e63c 206 net_proxy_user, strlen (net_proxy_user));
348860fa 207 InternetSetOption (connection, INTERNET_OPTION_PROXY_PASSWORD,
23c9e63c
DD
208 net_proxy_passwd, strlen (net_proxy_passwd));
209 }
210
348860fa
DD
211 if (resend)
212 if (!HttpSendRequest (connection, 0, 0, 0, 0))
213 connection = 0;
23c9e63c
DD
214
215 if (!connection)
216 {
a10fdeb9
JT
217 DWORD e = GetLastError ();
218 if (e == ERROR_INTERNET_EXTENDED_ERROR)
23c9e63c
DD
219 {
220 char buf[2000];
b24c88b3 221 DWORD e, l = sizeof (buf);
23c9e63c 222 InternetGetLastResponseInfo (&e, buf, &l);
e0373ab5 223 mbox (0, buf, "Internet Error", MB_OK);
23c9e63c 224 }
a10fdeb9
JT
225 else
226 {
227 Log (LOG_PLAIN) << "connection error: " << e << endLog;
228 }
23c9e63c 229 }
4e8ff53f 230
a7b37e4e
JT
231 ULONG type = 0;
232 DWORD type_s = sizeof (type);
4e8ff53f
DD
233 InternetQueryOption (connection, INTERNET_OPTION_HANDLE_TYPE,
234 &type, &type_s);
235
236 switch (type)
237 {
238 case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
239 case INTERNET_HANDLE_TYPE_CONNECT_HTTP:
240 type_s = sizeof (DWORD);
241 if (HttpQueryInfo (connection,
242 HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
243 &type, &type_s, NULL))
244 {
a10fdeb9
JT
245 if (type != 200)
246 Log (LOG_PLAIN) << "HTTP status " << type << " fetching " << url << endLog;
247
b24c88b3 248 if (type == 401) /* authorization required */
4e8ff53f 249 {
b24c88b3 250 flush_io ();
ab57ceaa 251 get_auth (NULL);
348860fa 252 resend = 1;
4e8ff53f
DD
253 goto try_again;
254 }
b24c88b3 255 else if (type == 407) /* proxy authorization required */
4e8ff53f 256 {
b24c88b3 257 flush_io ();
ab57ceaa 258 get_proxy_auth (NULL);
348860fa 259 resend = 1;
4e8ff53f
DD
260 goto try_again;
261 }
262 else if (type >= 300)
263 {
ca875ed3 264 InternetCloseHandle (connection);
4e8ff53f
DD
265 connection = 0;
266 return;
267 }
268 }
269 }
a7b37e4e
JT
270
271 InternetQueryOption (connection, INTERNET_OPTION_REQUEST_FLAGS,
272 &type, &type_s);
273 if (type & INTERNET_REQFLAG_FROM_CACHE)
274 Log (LOG_BABBLE) << "Request for URL " << url << " satisfied from cache" << endLog;
23c9e63c
DD
275}
276
348860fa
DD
277void
278NetIO_IE5::flush_io ()
279{
280 DWORD actual = 0;
281 char buf[1024];
b24c88b3
RC
282 do
283 {
284 InternetReadFile (connection, buf, 1024, &actual);
285 }
286 while (actual > 0);
348860fa
DD
287}
288
23c9e63c
DD
289NetIO_IE5::~NetIO_IE5 ()
290{
291 if (connection)
292 InternetCloseHandle (connection);
293}
294
295int
296NetIO_IE5::ok ()
297{
298 return (connection == NULL) ? 0 : 1;
299}
300
301int
302NetIO_IE5::read (char *buf, int nbytes)
303{
ca875ed3
JT
304#define READ_CHUNK (64 * 1024)
305 /* Read in chunks rather than the whole file at once, so we can do progress
306 reporting */
307 if (nbytes > READ_CHUNK)
308 nbytes = READ_CHUNK;
309
23c9e63c
DD
310 DWORD actual;
311 if (InternetReadFile (connection, buf, nbytes, &actual))
312 return actual;
ca875ed3 313
23c9e63c
DD
314 return -1;
315}
This page took 0.132852 seconds and 5 git commands to generate.