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