app-manager/fetch.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jul 16 11:07:18 2016 +0100 (2016-07-16)
changeset 61 31fb35727621
parent 14 29d8bb64056c
permissions -rw-r--r--
Support parallel installations. The idea is that for CAD screener, we want
to be able to install this on the same machine as a standard AVOT setup
(most notably for John's laptop). To allow for the possibility of a second
application that might have the same requirements, we add the concept of
vendor-specific distributions. Thus we can have one distribution for CAD
screener and one for The Next Big Thing. It doesn't seem trivial to have
both CAD screener and AVOT under the same vendor tag so we'll have to have
AVOT under "City Occupational" and CAD screener under "City Occupational Ltd"
or some such kludge.

Most of this is done although we are very short of test cases (in particular
we don't test that it's actually possible to install CAD screener in parallel
with AVOT or to update either of them once installed, which is fundamental).

We also have a lot of baggage left over, including an intercept of razor_set.
The problem that this was introduced to debug has been fixed but it looks
like there are a number of memory leaks which it might be useful to help
track down so it has been left in place for now.

There is still a lot of confusion in plover between path-based and URI-based
API. We should review the API, decide what we want and have a general clear up.

There is also confusion as to the purpose of RAZOR_ROOT (and meaning; path or
URI). This is not used at all in librazor (although it is used in razor.exe).
Ideally we shouldn't use it in plover or plover-gtk either although again, we
might want to support it or an equivalent in (some of) the various executables.

Work that would still to nice to do for CAD screener:

- uninstall (ideally as an installed program that hooks into Add/Remove programs
but even re-running the installer would be acceptable).
- xz support (smaller packages).
- repomd.xml and xml:base (would be needed for an Internet installer).
- graphical installer.
ali@14
     1
/*
ali@14
     2
 * A program to explore http support on MS-Windows.
ali@14
     3
 */
ali@14
     4
ali@14
     5
#include "config.h"
ali@14
     6
#include <stdlib.h>
ali@14
     7
#include <stdio.h>
ali@14
     8
#include <glib.h>
ali@14
     9
#include <razor.h>
ali@14
    10
#if HAVE_WINHTTP_H
ali@14
    11
#include <windows.h>
ali@14
    12
#include <winhttp.h>
ali@14
    13
#include <wincrypt.h>
ali@14
    14
ali@14
    15
#ifndef PKCS12_NO_PERSIST_KEY
ali@14
    16
#define PKCS12_NO_PERSIST_KEY 0x00008000
ali@14
    17
#endif
ali@14
    18
ali@14
    19
static gboolean debug=FALSE;
ali@14
    20
ali@14
    21
static GOptionEntry entries[] = 
ali@14
    22
{
ali@14
    23
    { "debug",'d',0,G_OPTION_ARG_NONE,&debug,"Output debugging",NULL },
ali@14
    24
    { NULL }
ali@14
    25
};
ali@14
    26
ali@14
    27
static struct WinHttpFuncs
ali@14
    28
{
ali@14
    29
    WINBOOL (WINAPI *AddRequestHeaders)(HINTERNET,LPCWSTR,DWORD,DWORD);
ali@14
    30
    WINBOOL (WINAPI *DetectAutoProxyConfigUrl)(DWORD,LPWSTR*);
ali@14
    31
    WINBOOL (WINAPI *CheckPlatform)(void);
ali@14
    32
    WINBOOL (WINAPI *CloseHandle)(HINTERNET);
ali@14
    33
    HINTERNET (WINAPI *Connect)(HINTERNET,LPCWSTR,INTERNET_PORT,DWORD);
ali@14
    34
    WINBOOL (WINAPI *CrackUrl)(LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS);
ali@14
    35
    WINBOOL (WINAPI *CreateUrl)(LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD);
ali@14
    36
    WINBOOL (WINAPI *GetDefaultProxyConfiguration)(WINHTTP_PROXY_INFO*);
ali@14
    37
    WINBOOL (WINAPI *GetIEProxyConfigForCurrentUser)(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG*);
ali@14
    38
    WINBOOL (WINAPI *GetProxyForUrl)(HINTERNET,LPCWSTR,WINHTTP_AUTOPROXY_OPTIONS*,WINHTTP_PROXY_INFO*);
ali@14
    39
    HINTERNET (WINAPI *Open)(LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD);
ali@14
    40
    HINTERNET (WINAPI *OpenRequest)(HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD);
ali@14
    41
    WINBOOL (WINAPI *QueryAuthParams)(HINTERNET,DWORD,LPVOID*);
ali@14
    42
    WINBOOL (WINAPI *QueryAuthSchemes)(HINTERNET,LPDWORD,LPDWORD,LPDWORD);
ali@14
    43
    WINBOOL (WINAPI *QueryDataAvailable)(HINTERNET,LPDWORD);
ali@14
    44
    WINBOOL (WINAPI *QueryHeaders)(HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD);
ali@14
    45
    WINBOOL (WINAPI *QueryOption)(HINTERNET,DWORD,LPVOID,LPDWORD);
ali@14
    46
    WINBOOL (WINAPI *ReadData)(HINTERNET,LPVOID,DWORD,LPDWORD);
ali@14
    47
    WINBOOL (WINAPI *ReceiveResponse)(HINTERNET,LPVOID);
ali@14
    48
    WINBOOL (WINAPI *SendRequest)(HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR);
ali@14
    49
    WINBOOL (WINAPI *SetDefaultProxyConfiguration)(WINHTTP_PROXY_INFO*);
ali@14
    50
    WINBOOL (WINAPI *SetCredentials)(HINTERNET,DWORD,DWORD,LPCWSTR,LPCWSTR,LPVOID);
ali@14
    51
    WINBOOL (WINAPI *SetOption)(HINTERNET,DWORD,LPVOID,DWORD);
ali@14
    52
    WINHTTP_STATUS_CALLBACK (WINAPI *SetStatusCallback)(HINTERNET,WINHTTP_STATUS_CALLBACK,DWORD,DWORD_PTR);
ali@14
    53
    WINBOOL (WINAPI *SetTimeouts)(HINTERNET,int,int,int,int);
ali@14
    54
    WINBOOL (WINAPI *TimeFromSystemTime)(CONST SYSTEMTIME *,LPWSTR);
ali@14
    55
    WINBOOL (WINAPI *TimeToSystemTime)(LPCWSTR,SYSTEMTIME*);
ali@14
    56
    WINBOOL (WINAPI *WriteData)(HINTERNET,LPCVOID,DWORD,LPDWORD);
ali@14
    57
} WinHttp;
ali@14
    58
ali@14
    59
static int plover_init_winhttp(void)
ali@14
    60
{
ali@14
    61
    HMODULE module;
ali@14
    62
    if (WinHttp.Open)
ali@14
    63
	return 0;
ali@14
    64
    module=LoadLibraryA("winhttp.dll");
ali@14
    65
    if (!module)
ali@14
    66
	return -1;
ali@14
    67
    WinHttp.AddRequestHeaders=
ali@14
    68
      (WINBOOL (WINAPI *)(HINTERNET,LPCWSTR,DWORD,DWORD))
ali@14
    69
      GetProcAddress(module,"WinHttpAddRequestHeaders");
ali@14
    70
    WinHttp.DetectAutoProxyConfigUrl=
ali@14
    71
      (WINBOOL (WINAPI *)(DWORD,LPWSTR*))
ali@14
    72
      GetProcAddress(module,"WinHttpDetectAutoProxyConfigUrl");
ali@14
    73
    WinHttp.CheckPlatform=(WINBOOL (WINAPI *)(void))
ali@14
    74
      GetProcAddress(module,"WinHttpCheckPlatform");
ali@14
    75
    WinHttp.CloseHandle=(WINBOOL (WINAPI *)(HINTERNET))
ali@14
    76
      GetProcAddress(module,"WinHttpCloseHandle");
ali@14
    77
    WinHttp.Connect=
ali@14
    78
      (HINTERNET (WINAPI *)(HINTERNET,LPCWSTR,INTERNET_PORT,DWORD))
ali@14
    79
      GetProcAddress(module,"WinHttpConnect");
ali@14
    80
    WinHttp.CrackUrl=(WINBOOL (WINAPI *)(LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS))
ali@14
    81
      GetProcAddress(module,"WinHttpCrackUrl");
ali@14
    82
    WinHttp.CreateUrl=
ali@14
    83
      (WINBOOL (WINAPI *)(LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD))
ali@14
    84
      GetProcAddress(module,"WinHttpCreateUrl");
ali@14
    85
    WinHttp.GetDefaultProxyConfiguration=
ali@14
    86
      (WINBOOL (WINAPI *)(WINHTTP_PROXY_INFO*))
ali@14
    87
      GetProcAddress(module,"WinHttpGetDefaultProxyConfiguration");
ali@14
    88
    WinHttp.GetIEProxyConfigForCurrentUser=
ali@14
    89
      (WINBOOL (WINAPI *)(WINHTTP_CURRENT_USER_IE_PROXY_CONFIG*))
ali@14
    90
      GetProcAddress(module,"WinHttpGetIEProxyConfigForCurrentUser");
ali@14
    91
    WinHttp.GetProxyForUrl=
ali@14
    92
      (WINBOOL (WINAPI *)(HINTERNET,LPCWSTR,WINHTTP_AUTOPROXY_OPTIONS*,WINHTTP_PROXY_INFO*))
ali@14
    93
      GetProcAddress(module,"WinHttpGetProxyForUrl");
ali@14
    94
    WinHttp.Open=(HINTERNET (WINAPI *)(LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD))
ali@14
    95
      GetProcAddress(module,"WinHttpOpen");
ali@14
    96
    WinHttp.OpenRequest=
ali@14
    97
      (HINTERNET (WINAPI *)(HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD))
ali@14
    98
      GetProcAddress(module,"WinHttpOpenRequest");
ali@14
    99
    WinHttp.QueryAuthParams=(WINBOOL (WINAPI *)(HINTERNET,DWORD,LPVOID*))
ali@14
   100
      GetProcAddress(module,"WinHttpQueryAuthParams");
ali@14
   101
    WinHttp.QueryAuthSchemes=
ali@14
   102
      (WINBOOL (WINAPI *)(HINTERNET,LPDWORD,LPDWORD,LPDWORD))
ali@14
   103
      GetProcAddress(module,"WinHttpQueryAuthSchemes");
ali@14
   104
    WinHttp.QueryDataAvailable=(WINBOOL (WINAPI *)(HINTERNET,LPDWORD))
ali@14
   105
      GetProcAddress(module,"WinHttpQueryDataAvailable");
ali@14
   106
    WinHttp.QueryHeaders=
ali@14
   107
      (WINBOOL (WINAPI *)(HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD))
ali@14
   108
      GetProcAddress(module,"WinHttpQueryHeaders");
ali@14
   109
    WinHttp.QueryOption=(WINBOOL (WINAPI *)(HINTERNET,DWORD,LPVOID,LPDWORD))
ali@14
   110
      GetProcAddress(module,"WinHttpQueryOption");
ali@14
   111
    WinHttp.ReadData=(WINBOOL (WINAPI *)(HINTERNET,LPVOID,DWORD,LPDWORD))
ali@14
   112
      GetProcAddress(module,"WinHttpReadData");
ali@14
   113
    WinHttp.ReceiveResponse=(WINBOOL (WINAPI *)(HINTERNET,LPVOID))
ali@14
   114
      GetProcAddress(module,"WinHttpReceiveResponse");
ali@14
   115
    WinHttp.SendRequest=
ali@14
   116
      (WINBOOL (WINAPI *)(HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR))
ali@14
   117
      GetProcAddress(module,"WinHttpSendRequest");
ali@14
   118
    WinHttp.SetDefaultProxyConfiguration=
ali@14
   119
      (WINBOOL (WINAPI *)(WINHTTP_PROXY_INFO*))
ali@14
   120
      GetProcAddress(module,"WinHttpSetDefaultProxyConfiguration");
ali@14
   121
    WinHttp.SetCredentials=
ali@14
   122
      (WINBOOL (WINAPI *)(HINTERNET,DWORD,DWORD,LPCWSTR,LPCWSTR,LPVOID))
ali@14
   123
      GetProcAddress(module,"WinHttpSetCredentials");
ali@14
   124
    WinHttp.SetOption=(WINBOOL (WINAPI *)(HINTERNET,DWORD,LPVOID,DWORD))
ali@14
   125
      GetProcAddress(module,"WinHttpSetOption");
ali@14
   126
    WinHttp.SetStatusCallback=
ali@14
   127
      (WINHTTP_STATUS_CALLBACK (WINAPI *)(HINTERNET,WINHTTP_STATUS_CALLBACK,DWORD,DWORD_PTR))
ali@14
   128
      GetProcAddress(module,"WinHttpSetStatusCallback");
ali@14
   129
    WinHttp.SetTimeouts=(WINBOOL (WINAPI *)(HINTERNET,int,int,int,int))
ali@14
   130
      GetProcAddress(module,"WinHttpSetTimeouts");
ali@14
   131
    WinHttp.TimeFromSystemTime=(WINBOOL (WINAPI *)(CONST SYSTEMTIME *,LPWSTR))
ali@14
   132
      GetProcAddress(module,"WinHttpTimeFromSystemTime");
ali@14
   133
    WinHttp.TimeToSystemTime=(WINBOOL (WINAPI *)(LPCWSTR,SYSTEMTIME*))
ali@14
   134
      GetProcAddress(module,"WinHttpTimeToSystemTime");
ali@14
   135
    WinHttp.WriteData=(WINBOOL (WINAPI *)(HINTERNET,LPCVOID,DWORD,LPDWORD))
ali@14
   136
      GetProcAddress(module,"WinHttpWriteData");
ali@14
   137
    if (!WinHttp.CrackUrl || !WinHttp.Open || !WinHttp.Connect ||
ali@14
   138
        !WinHttp.OpenRequest || !WinHttp.SendRequest ||
ali@14
   139
	!WinHttp.ReceiveResponse || !WinHttp.QueryDataAvailable ||
ali@14
   140
	!WinHttp.ReadData || !WinHttp.CloseHandle)
ali@14
   141
    {
ali@14
   142
	FreeLibrary(module);
ali@14
   143
	WinHttp.Open=NULL;
ali@14
   144
	return -1;
ali@14
   145
    }
ali@14
   146
    return 0;
ali@14
   147
}
ali@14
   148
ali@14
   149
/*
ali@14
   150
 * This will find ${PREFIX}/${file} if it exists, but it may also
ali@14
   151
 * find ${PREFIX}/.../${file} if ${PREFIX}/${file} does not exist.
ali@14
   152
 * This seems unlikely and won't do any harm should it occur.
ali@14
   153
 */
ali@14
   154
ali@14
   155
gchar *find_prefixed_file(const char *file)
ali@14
   156
{
ali@14
   157
    int i,len;
ali@14
   158
    const char *name;
ali@14
   159
    char *install_root;
ali@14
   160
    struct razor_set *set;
ali@24
   161
    struct razor_error *error=NULL;
ali@14
   162
    struct razor_package *package;
ali@14
   163
    struct razor_package_iterator *pi;
ali@14
   164
    struct razor_file_iterator *fi;
ali@14
   165
    gchar *retval=NULL;
ali@14
   166
    len=strlen(file);
ali@14
   167
    install_root=getenv("RAZOR_ROOT");
ali@14
   168
    if (!install_root)
ali@14
   169
	install_root="";
ali@24
   170
    set=razor_root_open_read_only(install_root,&error);
ali@14
   171
    if (set)
ali@14
   172
    {
ali@14
   173
	pi=razor_package_iterator_create(set);
ali@14
   174
	while (razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
ali@14
   175
	{
ali@14
   176
	    fi=razor_file_iterator_create(set,package,0);
ali@14
   177
	    while (!retval && razor_file_iterator_next(fi,&name))
ali@14
   178
	    {
ali@14
   179
		i=strlen(name)-len;
ali@14
   180
		if (i>0 && name[i-1]=='/' && !strcmp(name+i,file))
ali@14
   181
		{
ali@14
   182
		    if (!retval || strlen(retval)>strlen(name))
ali@14
   183
		    {
ali@14
   184
			g_free(retval);
ali@14
   185
			retval=g_strdup(name);
ali@14
   186
		    }
ali@14
   187
		}
ali@14
   188
	    }
ali@14
   189
	    razor_file_iterator_destroy(fi);
ali@14
   190
	}
ali@14
   191
	razor_package_iterator_destroy(pi);
ali@14
   192
	razor_set_unref(set);
ali@14
   193
    }
ali@24
   194
    if (error)
ali@24
   195
	razor_error_free(error);
ali@14
   196
    return retval;
ali@14
   197
}
ali@14
   198
ali@14
   199
static HCERTSTORE plover_p12_import(const char *file,const wchar_t *password)
ali@14
   200
{
ali@14
   201
    GError *error=NULL;
ali@14
   202
    gchar *p12,*path,*s;
ali@14
   203
    gsize len;
ali@14
   204
    CRYPT_DATA_BLOB pfx;
ali@14
   205
    HCERTSTORE store;
ali@14
   206
    s=g_build_path("/","etc","pki",file,NULL);
ali@14
   207
    path=find_prefixed_file(s);
ali@14
   208
    if (!path)
ali@14
   209
    {
ali@14
   210
	g_printerr("%s: Not installed\n",s);
ali@14
   211
	g_free(s);
ali@14
   212
	return NULL;
ali@14
   213
    }
ali@14
   214
    g_free(s);
ali@14
   215
    if (!g_file_get_contents(path,&p12,&len,&error))
ali@14
   216
    {
ali@14
   217
	g_printerr("%s: %s\n",path,error->message);
ali@14
   218
	g_free(path);
ali@14
   219
	g_error_free(error);
ali@14
   220
	return NULL;
ali@14
   221
    }
ali@14
   222
    g_free(path);
ali@14
   223
    pfx.pbData=(BYTE *)p12;
ali@14
   224
    pfx.cbData=len;
ali@14
   225
    store=PFXImportCertStore(&pfx,password,PKCS12_NO_PERSIST_KEY);
ali@14
   226
    if (!store)
ali@14
   227
	g_printerr("PFXImportCertStore failed. Err: %lu\n",GetLastError());
ali@14
   228
    g_free(p12);
ali@14
   229
    return store;
ali@14
   230
}
ali@14
   231
ali@14
   232
static const CERT_CONTEXT *plover_get_client_certificate(HCERTSTORE store)
ali@14
   233
{
ali@14
   234
    const CERT_CONTEXT *iter,*cert;
ali@14
   235
    cert=NULL;
ali@14
   236
    iter=CertEnumCertificatesInStore(store,NULL);
ali@14
   237
    while(iter)
ali@14
   238
    {
ali@14
   239
	if (!cert)
ali@14
   240
	    cert=CertDuplicateCertificateContext(iter);
ali@14
   241
	iter=CertEnumCertificatesInStore(store,iter);
ali@14
   242
    }
ali@14
   243
    return cert;
ali@14
   244
}
ali@14
   245
ali@14
   246
void CALLBACK plover_status_callback(HINTERNET handle,DWORD_PTR context,
ali@14
   247
  DWORD status,LPVOID status_information,DWORD status_information_length)
ali@14
   248
{
ali@14
   249
    g_printerr("CB status 0x%lX",status);
ali@14
   250
    if (status==WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
ali@14
   251
	g_printerr(", flag 0x%lX",*(DWORD *)status_information);
ali@14
   252
    g_printerr("\n");
ali@14
   253
}
ali@14
   254
ali@14
   255
int fetch(HINTERNET session,HCERTSTORE store,const char *url)
ali@14
   256
{
ali@14
   257
    URL_COMPONENTS components={0};
ali@14
   258
    HINTERNET connection,request;
ali@14
   259
    DWORD len,nb,options;
ali@14
   260
    char *buffer;
ali@14
   261
    wchar_t *ws;
ali@14
   262
    glong ws_len;
ali@14
   263
    gchar *hostname,*path;
ali@14
   264
    const CERT_CONTEXT *client_cert;
ali@14
   265
    components.dwStructSize=sizeof(components);
ali@14
   266
    components.dwSchemeLength=(DWORD)-1;
ali@14
   267
    components.dwHostNameLength=(DWORD)-1;
ali@14
   268
    components.dwUserNameLength=(DWORD)-1;
ali@14
   269
    components.dwPasswordLength=(DWORD)-1;
ali@14
   270
    components.dwUrlPathLength=(DWORD)-1;
ali@14
   271
    ws=g_utf8_to_utf16(url,-1,NULL,&ws_len,NULL);
ali@14
   272
    if (!ws || !WinHttp.CrackUrl(ws,ws_len,0,&components))
ali@14
   273
    {
ali@14
   274
	g_printerr("%s: Invalid or unsupported URL\n",url);
ali@14
   275
	return -1;
ali@14
   276
    }
ali@14
   277
    /* ICU_REJECT_USERPWD is not supported under Windows XP */
ali@14
   278
    if (components.dwUserNameLength || components.dwPasswordLength)
ali@14
   279
    {
ali@14
   280
	g_printerr("%s: Credentials not supported\n",url);
ali@14
   281
	return -1;
ali@14
   282
    }
ali@14
   283
    hostname=g_utf16_to_utf8(components.lpszHostName,
ali@14
   284
      components.dwHostNameLength,NULL,NULL,NULL);
ali@14
   285
    path=g_utf16_to_utf8(components.lpszUrlPath,components.dwUrlPathLength,NULL,
ali@14
   286
      NULL,NULL);
ali@14
   287
    g_free(ws);
ali@14
   288
    ws=g_utf8_to_utf16(hostname,-1,NULL,NULL,NULL);
ali@14
   289
    connection=WinHttp.Connect(session,ws,
ali@14
   290
      components.nPort?components.nPort:INTERNET_DEFAULT_PORT,0);
ali@14
   291
    g_free(ws);
ali@14
   292
    if (connection)
ali@14
   293
    {
ali@14
   294
	ws=g_utf8_to_utf16(path,-1,NULL,NULL,NULL);
ali@14
   295
	request=WinHttp.OpenRequest(connection,L"GET",ws,NULL,
ali@14
   296
	  WINHTTP_NO_REFERER,WINHTTP_DEFAULT_ACCEPT_TYPES,
ali@14
   297
	  components.nScheme==INTERNET_SCHEME_HTTPS?WINHTTP_FLAG_SECURE:0);
ali@14
   298
	g_free(ws);
ali@14
   299
	if (request)
ali@14
   300
	{
ali@14
   301
	    if (debug)
ali@14
   302
		(void)WinHttp.SetStatusCallback(request,plover_status_callback,
ali@14
   303
		  WINHTTP_CALLBACK_FLAG_ALL_NOTIFICATIONS,0);
ali@14
   304
	    if (components.nScheme==INTERNET_SCHEME_HTTPS && WinHttp.SetOption)
ali@14
   305
	    {
ali@14
   306
		options=SECURITY_FLAG_IGNORE_UNKNOWN_CA;
ali@14
   307
		(void)WinHttp.SetOption(request,WINHTTP_OPTION_SECURITY_FLAGS,
ali@14
   308
		  &options,sizeof(options));
ali@14
   309
		client_cert=plover_get_client_certificate(store);
ali@14
   310
		if (client_cert)
ali@14
   311
		{
ali@14
   312
		    if (!WinHttp.SetOption(request,
ali@14
   313
		      WINHTTP_OPTION_CLIENT_CERT_CONTEXT,(void *)client_cert,
ali@14
   314
		      sizeof(*client_cert)))
ali@14
   315
			g_printerr("Failed to set client certificate (%lu)\n",
ali@14
   316
			  GetLastError());
ali@14
   317
		}
ali@14
   318
		else
ali@14
   319
		    g_printerr("No client certificate found\n");
ali@14
   320
	    }
ali@14
   321
	    if (!WinHttp.SendRequest(request,WINHTTP_NO_ADDITIONAL_HEADERS,
ali@14
   322
	      0,WINHTTP_NO_REQUEST_DATA,0,0,0))
ali@14
   323
		g_printerr("Failed to send request (%lu)\n",GetLastError());
ali@14
   324
	    else if (!WinHttp.ReceiveResponse(request,NULL))
ali@14
   325
		g_printerr("Failed to receive response (%lu)\n",GetLastError());
ali@14
   326
	    else
ali@14
   327
	    {
ali@14
   328
		do
ali@14
   329
		{
ali@14
   330
		    len=0;
ali@14
   331
		    if (!WinHttp.QueryDataAvailable(request,&len))
ali@14
   332
			g_printerr(
ali@14
   333
			  "Error %lu in WinHttpQueryDataAvailable.\n",
ali@14
   334
			  (unsigned long)GetLastError());
ali@14
   335
		    buffer=calloc(len+1,1);
ali@14
   336
		    if (!buffer)
ali@14
   337
			break;
ali@14
   338
		    else
ali@14
   339
		    {
ali@14
   340
			if (!WinHttp.ReadData(request,(void *)buffer,len,&nb))
ali@14
   341
			    g_printerr("Error %lu in WinHttpReadData.\n",
ali@14
   342
			      (unsigned long)GetLastError());
ali@14
   343
			else
ali@14
   344
			    printf("%s\n",buffer);
ali@14
   345
			free(buffer);
ali@14
   346
		    }
ali@14
   347
		} while (len>0);
ali@14
   348
	    }
ali@14
   349
	    WinHttp.CloseHandle(request);
ali@14
   350
	}
ali@14
   351
	else
ali@14
   352
	    g_printerr("Failed to open request for %s (%lu)\n",path,
ali@14
   353
	      GetLastError());
ali@14
   354
	WinHttp.CloseHandle(connection);
ali@14
   355
    }
ali@14
   356
    else
ali@14
   357
	g_printerr("Failed to open connection to %s\n",hostname);
ali@14
   358
    g_free(hostname);
ali@14
   359
    g_free(path);
ali@14
   360
    return 0;
ali@14
   361
}
ali@14
   362
ali@14
   363
int main(int argc,char **argv)
ali@14
   364
{
ali@14
   365
    GError *error=NULL;
ali@14
   366
    GOptionContext *context;
ali@14
   367
    HCERTSTORE store;
ali@14
   368
    HINTERNET session;
ali@14
   369
    wchar_t *ws;
ali@14
   370
    context=g_option_context_new("URL - fetch a URL");
ali@14
   371
    g_option_context_add_main_entries(context,entries,NULL);
ali@14
   372
    if (!g_option_context_parse(context,&argc,&argv,&error))
ali@14
   373
    {
ali@14
   374
	g_printerr("Option parsing failed: %s\n",error->message);
ali@14
   375
	exit(1);
ali@14
   376
    }
ali@14
   377
    if (argc!=2)
ali@14
   378
    {
ali@14
   379
	g_printerr("%s\n",g_option_context_get_help(context,TRUE,NULL));
ali@14
   380
	exit(1);
ali@14
   381
    }
ali@14
   382
    if (plover_init_winhttp())
ali@14
   383
    {
ali@14
   384
	g_printerr("HTTP is not supported on this machine\n");
ali@14
   385
	exit(1);
ali@14
   386
    }
ali@14
   387
    store=plover_p12_import("system.p12",L"xyzzy-ylem");
ali@14
   388
    if (!store)
ali@14
   389
	exit(1);
ali@14
   390
    ws=g_utf8_to_utf16(PACKAGE_NAME "/" PACKAGE_VERSION,-1,NULL,NULL,NULL);
ali@14
   391
    session=WinHttp.Open(ws,WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
ali@14
   392
      WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS,0);
ali@14
   393
    free(ws);
ali@14
   394
    if (!session)
ali@14
   395
    {
ali@14
   396
	g_printerr("Failed to open WinHttp session\n");
ali@14
   397
	exit(1);
ali@14
   398
    }
ali@14
   399
    if (fetch(session,store,argv[1]))
ali@14
   400
	exit(1);
ali@14
   401
    WinHttp.CloseHandle(session);
ali@14
   402
    CertCloseStore(store,CERT_CLOSE_STORE_FORCE_FLAG);
ali@14
   403
    exit(0);
ali@14
   404
}
ali@14
   405
#else	/* !HAVE_WINHTTP_H */
ali@14
   406
main()
ali@14
   407
{
ali@14
   408
    g_printerr("HTTP is not supported on this machine\n");
ali@14
   409
    exit(1);
ali@14
   410
}
ali@14
   411
#endif	/* HAVE_WINHTTP_H */