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