~ubuntu-branches/debian/jessie/glib2.0/jessie

« back to all changes in this revision

Viewing changes to gio/win32/gwinhttpfile.c

  • Committer: Bazaar Package Importer
  • Author(s): Gustavo Noronha Silva
  • Date: 2009-02-15 13:00:43 UTC
  • mfrom: (1.3.1 upstream) (69.1.10 intrepid)
  • Revision ID: james.westby@ubuntu.com-20090215130043-q47fbt3owmt42m2f
Tags: 2.18.4-2
* Release to unstable
* debian/rules:
- bump SHVER, since we are already forcing a 2.18.0 dependecy on the
  symbols introduced in the development versions
* debian/control.in:
- added Homepage and Vcs-* control fields

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GIO - GLib Input, Output and Streaming Library
 
2
 *
 
3
 * Copyright (C) 2006-2007 Red Hat, Inc.
 
4
 * Copyright (C) 2008 Novell, Inc.
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Lesser General Public
 
8
 * License as published by the Free Software Foundation; either
 
9
 * version 2 of the License, or (at your option) any later version.
 
10
 *
 
11
 * This library 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 GNU
 
14
 * Lesser General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU Lesser General
 
17
 * Public License along with this library; if not, write to the
 
18
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 
19
 * Boston, MA 02111-1307, USA.
 
20
 *
 
21
 * Author: Alexander Larsson <alexl@redhat.com>
 
22
 * Author: Tor Lillqvist <tml@novell.com>
 
23
 */
 
24
 
 
25
#include "config.h"
 
26
 
 
27
#include <string.h>
 
28
#include <wchar.h>
 
29
 
 
30
#include "gfile.h"
 
31
#include "gfileattribute.h"
 
32
#include "gfileinfo.h"
 
33
#include "gwinhttpfile.h"
 
34
#include "gwinhttpfileinputstream.h"
 
35
#include "gwinhttpfileoutputstream.h"
 
36
#include "gioerror.h"
 
37
 
 
38
#include "glibintl.h"
 
39
 
 
40
#include "gioalias.h"
 
41
 
 
42
static void g_winhttp_file_file_iface_init (GFileIface *iface);
 
43
 
 
44
#define g_winhttp_file_get_type _g_winhttp_file_get_type
 
45
G_DEFINE_TYPE_WITH_CODE (GWinHttpFile, g_winhttp_file, G_TYPE_OBJECT,
 
46
                         G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
 
47
                                                g_winhttp_file_file_iface_init))
 
48
 
 
49
static void
 
50
g_winhttp_file_finalize (GObject *object)
 
51
{
 
52
  GWinHttpFile *file;
 
53
 
 
54
  file = G_WINHTTP_FILE (object);
 
55
 
 
56
  g_free (file->url.lpszScheme);
 
57
  g_free (file->url.lpszHostName);
 
58
  g_free (file->url.lpszUserName);
 
59
  g_free (file->url.lpszPassword);
 
60
  g_free (file->url.lpszUrlPath);
 
61
  g_free (file->url.lpszExtraInfo);
 
62
 
 
63
  G_OBJECT_CLASS (g_winhttp_file_parent_class)->finalize (object);
 
64
}
 
65
 
 
66
static void
 
67
g_winhttp_file_class_init (GWinHttpFileClass *klass)
 
68
{
 
69
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
70
 
 
71
  gobject_class->finalize = g_winhttp_file_finalize;
 
72
}
 
73
 
 
74
static void
 
75
g_winhttp_file_init (GWinHttpFile *winhttp)
 
76
{
 
77
}
 
78
 
 
79
/**
 
80
 * _g_winhttp_file_new:
 
81
 * @vfs: GWinHttpVfs to use
 
82
 * @uri: URI of the GWinHttpFile to create.
 
83
 *
 
84
 * Returns: new winhttp #GFile.
 
85
 **/
 
86
GFile *
 
87
_g_winhttp_file_new (GWinHttpVfs *vfs,
 
88
                     const char  *uri)
 
89
{
 
90
  wchar_t *wuri;
 
91
  GWinHttpFile *file;
 
92
 
 
93
  wuri = g_utf8_to_utf16 (uri, -1, NULL, NULL, NULL);
 
94
 
 
95
  if (wuri == NULL)
 
96
    return NULL;
 
97
 
 
98
  file = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
 
99
  file->vfs = vfs;
 
100
 
 
101
  memset (&file->url, 0, sizeof (file->url));
 
102
  file->url.dwStructSize = sizeof (file->url);
 
103
  file->url.dwSchemeLength = 1;
 
104
  file->url.dwHostNameLength = 1;
 
105
  file->url.dwUserNameLength = 1;
 
106
  file->url.dwPasswordLength = 1;
 
107
  file->url.dwUrlPathLength = 1;
 
108
  file->url.dwExtraInfoLength = 1;
 
109
 
 
110
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
 
111
    {
 
112
      g_free (wuri);
 
113
      return NULL;
 
114
    }
 
115
 
 
116
  file->url.lpszScheme = g_new (wchar_t, ++file->url.dwSchemeLength);
 
117
  file->url.lpszHostName = g_new (wchar_t, ++file->url.dwHostNameLength);
 
118
  file->url.lpszUserName = g_new (wchar_t, ++file->url.dwUserNameLength);
 
119
  file->url.lpszPassword = g_new (wchar_t, ++file->url.dwPasswordLength);
 
120
  file->url.lpszUrlPath = g_new (wchar_t, ++file->url.dwUrlPathLength);
 
121
  file->url.lpszExtraInfo = g_new (wchar_t, ++file->url.dwExtraInfoLength);
 
122
 
 
123
  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
 
124
    {
 
125
      g_free (file->url.lpszScheme);
 
126
      g_free (file->url.lpszHostName);
 
127
      g_free (file->url.lpszUserName);
 
128
      g_free (file->url.lpszPassword);
 
129
      g_free (file->url.lpszUrlPath);
 
130
      g_free (file->url.lpszExtraInfo);
 
131
      g_free (wuri);
 
132
      return NULL;
 
133
    }
 
134
 
 
135
  g_free (wuri);
 
136
  return G_FILE (file);
 
137
}
 
138
 
 
139
static gboolean
 
140
g_winhttp_file_is_native (GFile *file)
 
141
{
 
142
  return FALSE;
 
143
}
 
144
 
 
145
static gboolean
 
146
g_winhttp_file_has_uri_scheme (GFile      *file,
 
147
                               const char *uri_scheme)
 
148
{
 
149
  return (g_ascii_strcasecmp (uri_scheme, "http") == 0 ||
 
150
          g_ascii_strcasecmp (uri_scheme, "https") == 0);
 
151
}
 
152
 
 
153
static char *
 
154
g_winhttp_file_get_uri_scheme (GFile *file)
 
155
{
 
156
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
157
 
 
158
  return g_utf16_to_utf8 (winhttp_file->url.lpszScheme, -1, NULL, NULL, NULL);
 
159
}
 
160
 
 
161
static char *
 
162
g_winhttp_file_get_basename (GFile *file)
 
163
{
 
164
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
165
  char *basename;
 
166
  char *last_slash;
 
167
  char *retval;
 
168
 
 
169
  basename = g_utf16_to_utf8 (winhttp_file->url.lpszUrlPath, -1, NULL, NULL, NULL);
 
170
  last_slash = strrchr (basename, '/');
 
171
  /* If no slash, or only "/" fallback to full path part of URI */
 
172
  if (last_slash == NULL || last_slash[1] == '\0')
 
173
    return basename;
 
174
 
 
175
  retval = g_strdup (last_slash + 1);
 
176
  g_free (basename);
 
177
 
 
178
  return retval;
 
179
}
 
180
 
 
181
static char *
 
182
g_winhttp_file_get_path (GFile *file)
 
183
{
 
184
  return NULL;
 
185
}
 
186
 
 
187
static char *
 
188
g_winhttp_file_get_uri (GFile *file)
 
189
{
 
190
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
191
  DWORD len;
 
192
  wchar_t *wuri;
 
193
  char *retval;
 
194
 
 
195
  len = 0;
 
196
  if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, NULL, &len) &&
 
197
      GetLastError () != ERROR_INSUFFICIENT_BUFFER)
 
198
    return NULL;
 
199
 
 
200
  wuri = g_new (wchar_t, ++len);
 
201
 
 
202
  if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, wuri, &len))
 
203
    {
 
204
      g_free (wuri);
 
205
      return NULL;
 
206
    }
 
207
 
 
208
  retval = g_utf16_to_utf8 (wuri, -1, NULL, NULL, NULL);
 
209
  g_free (wuri);
 
210
 
 
211
  if (g_str_has_prefix (retval, "http://:@"))
 
212
    {
 
213
      memmove (retval + 7, retval + 9, strlen (retval) - 9);
 
214
      retval[strlen (retval) - 2] = '\0';
 
215
    }
 
216
  else if (g_str_has_prefix (retval, "https://:@"))
 
217
    {
 
218
      memmove (retval + 8, retval + 10, strlen (retval) - 10);
 
219
      retval[strlen (retval) - 2] = '\0';
 
220
    }
 
221
 
 
222
  return retval;
 
223
}
 
224
 
 
225
static char *
 
226
g_winhttp_file_get_parse_name (GFile *file)
 
227
{
 
228
  /* FIXME: More hair surely needed */
 
229
 
 
230
  return g_winhttp_file_get_uri (file);
 
231
}
 
232
 
 
233
static GFile *
 
234
g_winhttp_file_get_parent (GFile *file)
 
235
{
 
236
  GWinHttpFile *winhttp_file;
 
237
  char *uri;
 
238
  char *last_slash;
 
239
  GFile *parent;
 
240
 
 
241
  winhttp_file = G_WINHTTP_FILE (file);
 
242
 
 
243
  uri = g_winhttp_file_get_uri (file);
 
244
  if (uri == NULL)
 
245
    return NULL;
 
246
 
 
247
  last_slash = strrchr (uri, '/');
 
248
  if (last_slash == NULL || *(last_slash+1) == 0)
 
249
    {
 
250
      g_free (uri);
 
251
      return NULL;
 
252
    }
 
253
 
 
254
  while (last_slash > uri && *last_slash == '/')
 
255
    last_slash--;
 
256
 
 
257
  last_slash[1] = '\0';
 
258
 
 
259
  parent = _g_winhttp_file_new (winhttp_file->vfs, uri);
 
260
  g_free (uri);
 
261
 
 
262
  return parent;
 
263
}
 
264
 
 
265
static GFile *
 
266
g_winhttp_file_dup (GFile *file)
 
267
{
 
268
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
269
  char *uri = g_winhttp_file_get_uri (file);
 
270
  GFile *retval = _g_winhttp_file_new (winhttp_file->vfs, uri);
 
271
 
 
272
  g_free (uri);
 
273
 
 
274
  return retval;
 
275
}
 
276
 
 
277
static guint
 
278
g_winhttp_file_hash (GFile *file)
 
279
{
 
280
  char *uri = g_winhttp_file_get_uri (file);
 
281
  guint retval = g_str_hash (uri);
 
282
 
 
283
  g_free (uri);
 
284
 
 
285
  return retval;
 
286
}
 
287
 
 
288
static gboolean
 
289
g_winhttp_file_equal (GFile *file1,
 
290
                      GFile *file2)
 
291
{
 
292
  char *uri1 = g_winhttp_file_get_uri (file1);
 
293
  char *uri2 = g_winhttp_file_get_uri (file2);
 
294
  gboolean retval = g_str_equal (uri1, uri2);
 
295
 
 
296
  g_free (uri1);
 
297
  g_free (uri2);
 
298
 
 
299
  return retval;
 
300
}
 
301
 
 
302
static const char *
 
303
match_prefix (const char *path,
 
304
              const char *prefix)
 
305
{
 
306
  int prefix_len;
 
307
 
 
308
  prefix_len = strlen (prefix);
 
309
  if (strncmp (path, prefix, prefix_len) != 0)
 
310
    return NULL;
 
311
 
 
312
  if (prefix_len > 0 && prefix[prefix_len-1] == '/')
 
313
    prefix_len--;
 
314
 
 
315
  return path + prefix_len;
 
316
}
 
317
 
 
318
static gboolean
 
319
g_winhttp_file_prefix_matches (GFile *parent,
 
320
                               GFile *descendant)
 
321
{
 
322
  char *parent_uri = g_winhttp_file_get_uri (parent);
 
323
  char *descendant_uri = g_winhttp_file_get_uri (descendant);
 
324
  const char *remainder;
 
325
  gboolean retval;
 
326
 
 
327
  remainder = match_prefix (descendant_uri, parent_uri);
 
328
 
 
329
  if (remainder != NULL && *remainder == '/')
 
330
    retval = TRUE;
 
331
  else
 
332
    retval = FALSE;
 
333
 
 
334
  g_free (parent_uri);
 
335
  g_free (descendant_uri);
 
336
 
 
337
  return retval;
 
338
}
 
339
 
 
340
static char *
 
341
g_winhttp_file_get_relative_path (GFile *parent,
 
342
                                  GFile *descendant)
 
343
{
 
344
  char *parent_uri = g_winhttp_file_get_uri (parent);
 
345
  char *descendant_uri = g_winhttp_file_get_uri (descendant);
 
346
  const char *remainder;
 
347
  char *retval;
 
348
 
 
349
  remainder = match_prefix (descendant_uri, parent_uri);
 
350
 
 
351
  if (remainder != NULL && *remainder == '/')
 
352
    retval = g_strdup (remainder + 1);
 
353
  else
 
354
    retval = NULL;
 
355
 
 
356
  g_free (parent_uri);
 
357
  g_free (descendant_uri);
 
358
 
 
359
  return retval;
 
360
}
 
361
 
 
362
static GFile *
 
363
g_winhttp_file_resolve_relative_path (GFile      *file,
 
364
                                      const char *relative_path)
 
365
{
 
366
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
367
  GWinHttpFile *child;
 
368
  wchar_t *wnew_path = g_utf8_to_utf16 (relative_path, -1, NULL, NULL, NULL);
 
369
 
 
370
  if (wnew_path == NULL)
 
371
    return NULL;
 
372
 
 
373
  if (*wnew_path != '/')
 
374
    {
 
375
      wchar_t *tmp = g_new (wchar_t, wcslen (winhttp_file->url.lpszUrlPath) + 1 + wcslen (wnew_path) + 1);
 
376
      wcscpy (tmp, winhttp_file->url.lpszUrlPath);
 
377
      wcscat (tmp, L"/");
 
378
      wcscat (tmp, wnew_path);
 
379
 
 
380
      g_free (wnew_path);
 
381
      wnew_path = tmp;
 
382
    }
 
383
 
 
384
  child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
 
385
  child->vfs = winhttp_file->vfs;
 
386
  child->url = winhttp_file->url;
 
387
  child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, winhttp_file->url.dwSchemeLength*2);
 
388
  child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, winhttp_file->url.dwHostNameLength*2);
 
389
  child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, winhttp_file->url.dwUserNameLength*2);
 
390
  child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, winhttp_file->url.dwPasswordLength*2);
 
391
  child->url.lpszUrlPath = wnew_path;
 
392
  child->url.dwUrlPathLength = 2*(wcslen (wnew_path)+1);
 
393
  child->url.lpszExtraInfo = NULL;
 
394
  child->url.dwExtraInfoLength = 0;
 
395
 
 
396
  return (GFile *) child;
 
397
}
 
398
 
 
399
static GFile *
 
400
g_winhttp_file_get_child_for_display_name (GFile        *file,
 
401
                                           const char   *display_name,
 
402
                                           GError      **error)
 
403
{
 
404
  GFile *new_file;
 
405
  char *basename;
 
406
 
 
407
  basename = g_locale_from_utf8 (display_name, -1, NULL, NULL, NULL);
 
408
  if (basename == NULL)
 
409
    {
 
410
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME,
 
411
                   _("Invalid filename %s"), display_name);
 
412
      return NULL;
 
413
    }
 
414
 
 
415
  new_file = g_file_get_child (file, basename);
 
416
  g_free (basename);
 
417
 
 
418
  return new_file;
 
419
}
 
420
 
 
421
static GFile *
 
422
g_winhttp_file_set_display_name (GFile         *file,
 
423
                                 const char    *display_name,
 
424
                                 GCancellable  *cancellable,
 
425
                                 GError       **error)
 
426
{
 
427
  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
 
428
                       _("Operation not supported"));
 
429
 
 
430
  return NULL;
 
431
}
 
432
 
 
433
static time_t
 
434
mktime_utc (SYSTEMTIME *t)
 
435
{
 
436
  time_t retval;
 
437
 
 
438
  static const gint days_before[] =
 
439
  {
 
440
    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
 
441
  };
 
442
 
 
443
  if (t->wMonth < 1 || t->wMonth > 12)
 
444
    return (time_t) -1;
 
445
 
 
446
  retval = (t->wYear - 1970) * 365;
 
447
  retval += (t->wYear - 1968) / 4;
 
448
  retval += days_before[t->wMonth-1] + t->wDay - 1;
 
449
 
 
450
  if (t->wYear % 4 == 0 && t->wMonth < 3)
 
451
    retval -= 1;
 
452
 
 
453
  retval = ((((retval * 24) + t->wHour) * 60) + t->wMinute) * 60 + t->wSecond;
 
454
 
 
455
  return retval;
 
456
}
 
457
 
 
458
static GFileInfo *
 
459
g_winhttp_file_query_info (GFile                *file,
 
460
                           const char           *attributes,
 
461
                           GFileQueryInfoFlags   flags,
 
462
                           GCancellable         *cancellable,
 
463
                           GError              **error)
 
464
{
 
465
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
466
  HINTERNET connection, request;
 
467
  const wchar_t *accept_types[] =
 
468
    {
 
469
      L"*/*",
 
470
      NULL,
 
471
    };
 
472
  GFileInfo *info;
 
473
  GFileAttributeMatcher *matcher;
 
474
  char *basename;
 
475
  wchar_t *content_length;
 
476
  wchar_t *content_type;
 
477
  SYSTEMTIME last_modified;
 
478
  DWORD last_modified_len;
 
479
 
 
480
  connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
 
481
    (G_WINHTTP_VFS (winhttp_file->vfs)->session,
 
482
     winhttp_file->url.lpszHostName,
 
483
     winhttp_file->url.nPort,
 
484
     0);
 
485
 
 
486
  if (connection == NULL)
 
487
    {
 
488
      _g_winhttp_set_error (error, GetLastError (), "HTTP connection");
 
489
 
 
490
      return NULL;
 
491
    }
 
492
 
 
493
  request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpOpenRequest
 
494
    (connection,
 
495
     L"HEAD",
 
496
     winhttp_file->url.lpszUrlPath,
 
497
     NULL,
 
498
     WINHTTP_NO_REFERER,
 
499
     accept_types,
 
500
     winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
 
501
 
 
502
  if (request == NULL)
 
503
    {
 
504
      _g_winhttp_set_error (error, GetLastError (), "HEAD request");
 
505
 
 
506
      return NULL;
 
507
    }
 
508
 
 
509
  if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpSendRequest
 
510
      (request,
 
511
       NULL, 0,
 
512
       NULL, 0,
 
513
       0,
 
514
       0))
 
515
    {
 
516
      _g_winhttp_set_error (error, GetLastError (), "HEAD request");
 
517
 
 
518
      return NULL;
 
519
    }
 
520
 
 
521
  if (!_g_winhttp_response (winhttp_file->vfs, request, error, "HEAD request"))
 
522
    return NULL;
 
523
 
 
524
  matcher = g_file_attribute_matcher_new (attributes);
 
525
  info = g_file_info_new ();
 
526
  g_file_info_set_attribute_mask (info, matcher);
 
527
 
 
528
  basename = g_winhttp_file_get_basename (file);
 
529
  g_file_info_set_name (info, basename);
 
530
  g_free (basename);
 
531
 
 
532
  content_length = NULL;
 
533
  if (_g_winhttp_query_header (winhttp_file->vfs,
 
534
                               request,
 
535
                               "HEAD request",
 
536
                               WINHTTP_QUERY_CONTENT_LENGTH,
 
537
                               &content_length,
 
538
                               NULL))
 
539
    {
 
540
      gint64 cl;
 
541
      int n;
 
542
 
 
543
      if (swscanf (content_length, L"%I64d%n", &cl, &n) == 1 &&
 
544
          n == wcslen (content_length))
 
545
        g_file_info_set_size (info, cl);
 
546
 
 
547
      g_free (content_length);
 
548
    }
 
549
 
 
550
  if (matcher == NULL)
 
551
    return info;
 
552
 
 
553
  content_type = NULL;
 
554
  if (_g_winhttp_query_header (winhttp_file->vfs,
 
555
                               request,
 
556
                               "HEAD request",
 
557
                               WINHTTP_QUERY_CONTENT_TYPE,
 
558
                               &content_type,
 
559
                               NULL))
 
560
    {
 
561
      char *ct = g_utf16_to_utf8 (content_type, -1, NULL, NULL, NULL);
 
562
 
 
563
      if (ct != NULL)
 
564
        {
 
565
          char *p = strchr (ct, ';');
 
566
 
 
567
          if (p != NULL)
 
568
            {
 
569
              char *tmp = g_strndup (ct, p - ct);
 
570
 
 
571
              g_file_info_set_content_type (info, tmp);
 
572
              g_free (tmp);
 
573
            }
 
574
          else
 
575
            g_file_info_set_content_type (info, ct);
 
576
        }
 
577
 
 
578
      g_free (ct);
 
579
    }
 
580
 
 
581
  last_modified_len = sizeof (last_modified);
 
582
  if (G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpQueryHeaders
 
583
      (request,
 
584
       WINHTTP_QUERY_LAST_MODIFIED | WINHTTP_QUERY_FLAG_SYSTEMTIME,
 
585
       NULL,
 
586
       &last_modified,
 
587
       &last_modified_len,
 
588
       NULL) &&
 
589
      last_modified_len == sizeof (last_modified) &&
 
590
      /* Don't bother comparing to the exact Y2038 moment */
 
591
      last_modified.wYear >= 1970 &&
 
592
      last_modified.wYear < 2038)
 
593
    {
 
594
      GTimeVal tv;
 
595
 
 
596
      tv.tv_sec = mktime_utc (&last_modified);
 
597
      tv.tv_usec = last_modified.wMilliseconds * 1000;
 
598
 
 
599
      g_file_info_set_modification_time (info, &tv);
 
600
    }
 
601
 
 
602
  g_file_attribute_matcher_unref (matcher);
 
603
 
 
604
  return info;
 
605
}
 
606
 
 
607
static GFileInputStream *
 
608
g_winhttp_file_read (GFile         *file,
 
609
                     GCancellable  *cancellable,
 
610
                     GError       **error)
 
611
{
 
612
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
613
  HINTERNET connection, request;
 
614
  const wchar_t *accept_types[] =
 
615
    {
 
616
      L"*/*",
 
617
      NULL,
 
618
    };
 
619
 
 
620
  connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
 
621
    (G_WINHTTP_VFS (winhttp_file->vfs)->session,
 
622
     winhttp_file->url.lpszHostName,
 
623
     winhttp_file->url.nPort,
 
624
     0);
 
625
 
 
626
  if (connection == NULL)
 
627
    {
 
628
      _g_winhttp_set_error (error, GetLastError (), "HTTP connection");
 
629
 
 
630
      return NULL;
 
631
    }
 
632
 
 
633
  request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpOpenRequest
 
634
    (connection,
 
635
     L"GET",
 
636
     winhttp_file->url.lpszUrlPath,
 
637
     NULL,
 
638
     WINHTTP_NO_REFERER,
 
639
     accept_types,
 
640
     winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
 
641
 
 
642
  if (request == NULL)
 
643
    {
 
644
      _g_winhttp_set_error (error, GetLastError (), "GET request");
 
645
 
 
646
      return NULL;
 
647
    }
 
648
 
 
649
  return _g_winhttp_file_input_stream_new (winhttp_file, connection, request);
 
650
}
 
651
 
 
652
static GFileOutputStream *
 
653
g_winhttp_file_create (GFile             *file,
 
654
                       GFileCreateFlags   flags,
 
655
                       GCancellable      *cancellable,
 
656
                       GError           **error)
 
657
{
 
658
  GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 
659
  HINTERNET connection;
 
660
 
 
661
  connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
 
662
    (G_WINHTTP_VFS (winhttp_file->vfs)->session,
 
663
     winhttp_file->url.lpszHostName,
 
664
     winhttp_file->url.nPort,
 
665
     0);
 
666
 
 
667
  if (connection == NULL)
 
668
    {
 
669
      _g_winhttp_set_error (error, GetLastError (), "HTTP connection");
 
670
 
 
671
      return NULL;
 
672
    }
 
673
 
 
674
  return _g_winhttp_file_output_stream_new (winhttp_file, connection);
 
675
}
 
676
 
 
677
#if 0
 
678
 
 
679
static GFileOutputStream *
 
680
g_winhttp_file_replace (GFile             *file,
 
681
                        const char        *etag,
 
682
                        gboolean           make_backup,
 
683
                        GFileCreateFlags   flags,
 
684
                        GCancellable      *cancellable,
 
685
                        GError           **error)
 
686
{
 
687
  /* FIXME: Implement */
 
688
 
 
689
  return NULL;
 
690
}
 
691
 
 
692
 
 
693
static gboolean
 
694
g_winhttp_file_delete (GFile         *file,
 
695
                       GCancellable  *cancellable,
 
696
                       GError       **error)
 
697
{
 
698
  /* FIXME: Implement */
 
699
 
 
700
  return FALSE;
 
701
}
 
702
 
 
703
static gboolean
 
704
g_winhttp_file_make_directory (GFile         *file,
 
705
                               GCancellable  *cancellable,
 
706
                               GError       **error)
 
707
{
 
708
  /* FIXME: Implement */
 
709
 
 
710
  return FALSE;
 
711
}
 
712
 
 
713
static gboolean
 
714
g_winhttp_file_copy (GFile                  *source,
 
715
                     GFile                  *destination,
 
716
                     GFileCopyFlags          flags,
 
717
                     GCancellable           *cancellable,
 
718
                     GFileProgressCallback   progress_callback,
 
719
                     gpointer                progress_callback_data,
 
720
                     GError                **error)
 
721
{
 
722
  /* Fall back to default copy?? */
 
723
  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
 
724
                       "Copy not supported");
 
725
 
 
726
  return FALSE;
 
727
}
 
728
 
 
729
static gboolean
 
730
g_winhttp_file_move (GFile                  *source,
 
731
                     GFile                  *destination,
 
732
                     GFileCopyFlags          flags,
 
733
                     GCancellable           *cancellable,
 
734
                     GFileProgressCallback   progress_callback,
 
735
                     gpointer                progress_callback_data,
 
736
                     GError                **error)
 
737
{
 
738
  /* FIXME: Implement */
 
739
 
 
740
  return FALSE;
 
741
}
 
742
 
 
743
#endif
 
744
 
 
745
static void
 
746
g_winhttp_file_file_iface_init (GFileIface *iface)
 
747
{
 
748
  iface->dup = g_winhttp_file_dup;
 
749
  iface->hash = g_winhttp_file_hash;
 
750
  iface->equal = g_winhttp_file_equal;
 
751
  iface->is_native = g_winhttp_file_is_native;
 
752
  iface->has_uri_scheme = g_winhttp_file_has_uri_scheme;
 
753
  iface->get_uri_scheme = g_winhttp_file_get_uri_scheme;
 
754
  iface->get_basename = g_winhttp_file_get_basename;
 
755
  iface->get_path = g_winhttp_file_get_path;
 
756
  iface->get_uri = g_winhttp_file_get_uri;
 
757
  iface->get_parse_name = g_winhttp_file_get_parse_name;
 
758
  iface->get_parent = g_winhttp_file_get_parent;
 
759
  iface->prefix_matches = g_winhttp_file_prefix_matches;
 
760
  iface->get_relative_path = g_winhttp_file_get_relative_path;
 
761
  iface->resolve_relative_path = g_winhttp_file_resolve_relative_path;
 
762
  iface->get_child_for_display_name = g_winhttp_file_get_child_for_display_name;
 
763
  iface->set_display_name = g_winhttp_file_set_display_name;
 
764
  iface->query_info = g_winhttp_file_query_info;
 
765
  iface->read_fn = g_winhttp_file_read;
 
766
  iface->create = g_winhttp_file_create;
 
767
#if 0
 
768
  iface->replace = g_winhttp_file_replace;
 
769
  iface->delete_file = g_winhttp_file_delete;
 
770
  iface->make_directory = g_winhttp_file_make_directory;
 
771
  iface->copy = g_winhttp_file_copy;
 
772
  iface->move = g_winhttp_file_move;
 
773
#endif
 
774
}