1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright (C) 2006-2007 Red Hat, Inc.
4 * Copyright (C) 2008 Novell, Inc.
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.
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.
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.
21 * Author: Alexander Larsson <alexl@redhat.com>
22 * Author: Tor Lillqvist <tml@novell.com>
30 #include "gfileattribute.h"
31 #include "gwinhttpfile.h"
32 #include "gwinhttpfileinputstream.h"
33 #include "gwinhttpfileoutputstream.h"
40 static void g_winhttp_file_file_iface_init (GFileIface *iface);
42 #define g_winhttp_file_get_type _g_winhttp_file_get_type
43 G_DEFINE_TYPE_WITH_CODE (GWinHttpFile, g_winhttp_file, G_TYPE_OBJECT,
44 G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
45 g_winhttp_file_file_iface_init))
48 g_winhttp_file_finalize (GObject *object)
52 file = G_WINHTTP_FILE (object);
54 g_free (file->url.lpszScheme);
55 g_free (file->url.lpszHostName);
56 g_free (file->url.lpszUserName);
57 g_free (file->url.lpszPassword);
58 g_free (file->url.lpszUrlPath);
59 g_free (file->url.lpszExtraInfo);
61 G_OBJECT_CLASS (g_winhttp_file_parent_class)->finalize (object);
65 g_winhttp_file_class_init (GWinHttpFileClass *klass)
67 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
69 gobject_class->finalize = g_winhttp_file_finalize;
73 g_winhttp_file_init (GWinHttpFile *winhttp)
78 * _g_winhttp_file_new:
79 * @vfs: GWinHttpVfs to use
80 * @uri: URI of the GWinHttpFile to create.
82 * Returns: new winhttp #GFile.
85 _g_winhttp_file_new (GWinHttpVfs *vfs,
91 wuri = g_utf8_to_utf16 (uri, -1, NULL, NULL, NULL);
96 file = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
99 memset (&file->url, 0, sizeof (file->url));
100 file->url.dwStructSize = sizeof (file->url);
101 file->url.dwSchemeLength = 1;
102 file->url.dwHostNameLength = 1;
103 file->url.dwUserNameLength = 1;
104 file->url.dwPasswordLength = 1;
105 file->url.dwUrlPathLength = 1;
106 file->url.dwExtraInfoLength = 1;
108 if (!G_WINHTTP_VFS_GET_CLASS (vfs)->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
114 file->url.lpszScheme = g_new (wchar_t, ++file->url.dwSchemeLength);
115 file->url.lpszHostName = g_new (wchar_t, ++file->url.dwHostNameLength);
116 file->url.lpszUserName = g_new (wchar_t, ++file->url.dwUserNameLength);
117 file->url.lpszPassword = g_new (wchar_t, ++file->url.dwPasswordLength);
118 file->url.lpszUrlPath = g_new (wchar_t, ++file->url.dwUrlPathLength);
119 file->url.lpszExtraInfo = g_new (wchar_t, ++file->url.dwExtraInfoLength);
121 if (!G_WINHTTP_VFS_GET_CLASS (vfs)->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
123 g_free (file->url.lpszScheme);
124 g_free (file->url.lpszHostName);
125 g_free (file->url.lpszUserName);
126 g_free (file->url.lpszPassword);
127 g_free (file->url.lpszUrlPath);
128 g_free (file->url.lpszExtraInfo);
134 return G_FILE (file);
138 g_winhttp_file_is_native (GFile *file)
144 g_winhttp_file_has_uri_scheme (GFile *file,
145 const char *uri_scheme)
147 return (g_ascii_strcasecmp (uri_scheme, "http") == 0 ||
148 g_ascii_strcasecmp (uri_scheme, "https") == 0);
152 g_winhttp_file_get_uri_scheme (GFile *file)
154 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
156 return g_utf16_to_utf8 (winhttp_file->url.lpszScheme, -1, NULL, NULL, NULL);
160 g_winhttp_file_get_basename (GFile *file)
162 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
167 basename = g_utf16_to_utf8 (winhttp_file->url.lpszUrlPath, -1, NULL, NULL, NULL);
168 last_slash = strrchr (basename, '/');
169 /* If no slash, or only "/" fallback to full path part of URI */
170 if (last_slash == NULL || last_slash[1] == '\0')
173 retval = g_strdup (last_slash + 1);
180 g_winhttp_file_get_path (GFile *file)
186 g_winhttp_file_get_uri (GFile *file)
188 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
194 if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, NULL, &len) &&
195 GetLastError () != ERROR_INSUFFICIENT_BUFFER)
198 wuri = g_new (wchar_t, ++len);
200 if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, wuri, &len))
206 retval = g_utf16_to_utf8 (wuri, -1, NULL, NULL, NULL);
213 g_winhttp_file_get_parse_name (GFile *file)
215 /* FIXME: More hair surely needed */
217 return g_winhttp_file_get_uri (file);
221 g_winhttp_file_get_parent (GFile *file)
223 GWinHttpFile *winhttp_file;
228 winhttp_file = G_WINHTTP_FILE (file);
230 uri = g_winhttp_file_get_uri (file);
234 last_slash = strrchr (uri, '/');
235 if (last_slash == NULL || *(last_slash+1) == 0)
241 while (last_slash > uri && *last_slash == '/')
244 last_slash[1] = '\0';
246 parent = _g_winhttp_file_new (winhttp_file->vfs, uri);
253 g_winhttp_file_dup (GFile *file)
255 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
256 char *uri = g_winhttp_file_get_uri (file);
257 GFile *retval = _g_winhttp_file_new (winhttp_file->vfs, uri);
265 g_winhttp_file_hash (GFile *file)
267 char *uri = g_winhttp_file_get_uri (file);
268 guint retval = g_str_hash (uri);
276 g_winhttp_file_equal (GFile *file1,
279 char *uri1 = g_winhttp_file_get_uri (file1);
280 char *uri2 = g_winhttp_file_get_uri (file2);
281 gboolean retval = g_str_equal (uri1, uri2);
290 match_prefix (const char *path,
295 prefix_len = strlen (prefix);
296 if (strncmp (path, prefix, prefix_len) != 0)
299 if (prefix_len > 0 && prefix[prefix_len-1] == '/')
302 return path + prefix_len;
306 g_winhttp_file_prefix_matches (GFile *parent,
309 char *parent_uri = g_winhttp_file_get_uri (parent);
310 char *descendant_uri = g_winhttp_file_get_uri (descendant);
311 const char *remainder;
314 remainder = match_prefix (descendant_uri, parent_uri);
316 if (remainder != NULL && *remainder == '/')
322 g_free (descendant_uri);
328 g_winhttp_file_get_relative_path (GFile *parent,
331 char *parent_uri = g_winhttp_file_get_uri (parent);
332 char *descendant_uri = g_winhttp_file_get_uri (descendant);
333 const char *remainder;
336 remainder = match_prefix (descendant_uri, parent_uri);
338 if (remainder != NULL && *remainder == '/')
339 retval = g_strdup (remainder + 1);
344 g_free (descendant_uri);
350 g_winhttp_file_resolve_relative_path (GFile *file,
351 const char *relative_path)
353 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
355 wchar_t *wnew_path = g_utf8_to_utf16 (relative_path, -1, NULL, NULL, NULL);
357 if (wnew_path == NULL)
360 if (*wnew_path != '/')
362 wchar_t *tmp = g_new (wchar_t, wcslen (winhttp_file->url.lpszUrlPath) + 1 + wcslen (wnew_path) + 1);
363 wcscpy (tmp, winhttp_file->url.lpszUrlPath);
365 wcscat (tmp, wnew_path);
371 child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
372 child->vfs = winhttp_file->vfs;
373 child->url = winhttp_file->url;
374 child->url.lpszScheme = g_memdup (winhttp_file->url.lpszScheme, winhttp_file->url.dwSchemeLength*2);
375 child->url.lpszHostName = g_memdup (winhttp_file->url.lpszHostName, winhttp_file->url.dwHostNameLength*2);
376 child->url.lpszUserName = g_memdup (winhttp_file->url.lpszUserName, winhttp_file->url.dwUserNameLength*2);
377 child->url.lpszPassword = g_memdup (winhttp_file->url.lpszPassword, winhttp_file->url.dwPasswordLength*2);
378 child->url.lpszUrlPath = wnew_path;
379 child->url.dwUrlPathLength = 2*(wcslen (wnew_path)+1);
380 child->url.lpszExtraInfo = NULL;
381 child->url.dwExtraInfoLength = 0;
383 return (GFile *) child;
387 g_winhttp_file_get_child_for_display_name (GFile *file,
388 const char *display_name,
394 basename = g_locale_from_utf8 (display_name, -1, NULL, NULL, NULL);
395 if (basename == NULL)
397 g_set_error (error, G_IO_ERROR,
398 G_IO_ERROR_INVALID_FILENAME,
399 _("Invalid filename %s"), display_name);
403 new_file = g_file_get_child (file, basename);
410 g_winhttp_file_set_display_name (GFile *file,
411 const char *display_name,
412 GCancellable *cancellable,
415 g_set_error_literal (error, G_IO_ERROR,
416 G_IO_ERROR_NOT_SUPPORTED,
417 _("Operation not supported"));
422 static GFileInputStream *
423 g_winhttp_file_read (GFile *file,
424 GCancellable *cancellable,
427 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
428 HINTERNET connection, request;
429 const wchar_t *accept_types[] =
435 connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->pWinHttpConnect
436 (G_WINHTTP_VFS (winhttp_file->vfs)->session,
437 winhttp_file->url.lpszHostName,
438 winhttp_file->url.nPort,
441 if (connection == NULL)
443 char *emsg = _g_winhttp_error_message (GetLastError ());
445 g_set_error (error, G_IO_ERROR,
453 request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->pWinHttpOpenRequest
456 winhttp_file->url.lpszUrlPath,
460 winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
464 char *emsg = _g_winhttp_error_message (GetLastError ());
466 g_set_error (error, G_IO_ERROR,
474 return _g_winhttp_file_input_stream_new (winhttp_file, connection, request);
477 static GFileOutputStream *
478 g_winhttp_file_create (GFile *file,
479 GFileCreateFlags flags,
480 GCancellable *cancellable,
483 GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
484 HINTERNET connection, request;
486 connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->pWinHttpConnect
487 (G_WINHTTP_VFS (winhttp_file->vfs)->session,
488 winhttp_file->url.lpszHostName,
489 winhttp_file->url.nPort,
492 if (connection == NULL)
494 char *emsg = _g_winhttp_error_message (GetLastError ());
496 g_set_error (error, G_IO_ERROR,
504 return _g_winhttp_file_output_stream_new (winhttp_file, connection);
509 static GFileOutputStream *
510 g_winhttp_file_replace (GFile *file,
512 gboolean make_backup,
513 GFileCreateFlags flags,
514 GCancellable *cancellable,
517 /* FIXME: Implement */
524 g_winhttp_file_delete (GFile *file,
525 GCancellable *cancellable,
528 /* FIXME: Implement */
534 g_winhttp_file_make_directory (GFile *file,
535 GCancellable *cancellable,
538 /* FIXME: Implement */
544 g_winhttp_file_copy (GFile *source,
546 GFileCopyFlags flags,
547 GCancellable *cancellable,
548 GFileProgressCallback progress_callback,
549 gpointer progress_callback_data,
552 /* Fall back to default copy?? */
553 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Copy not supported");
559 g_winhttp_file_move (GFile *source,
561 GFileCopyFlags flags,
562 GCancellable *cancellable,
563 GFileProgressCallback progress_callback,
564 gpointer progress_callback_data,
567 /* FIXME: Implement */
575 g_winhttp_file_file_iface_init (GFileIface *iface)
577 iface->dup = g_winhttp_file_dup;
578 iface->hash = g_winhttp_file_hash;
579 iface->equal = g_winhttp_file_equal;
580 iface->is_native = g_winhttp_file_is_native;
581 iface->has_uri_scheme = g_winhttp_file_has_uri_scheme;
582 iface->get_uri_scheme = g_winhttp_file_get_uri_scheme;
583 iface->get_basename = g_winhttp_file_get_basename;
584 iface->get_path = g_winhttp_file_get_path;
585 iface->get_uri = g_winhttp_file_get_uri;
586 iface->get_parse_name = g_winhttp_file_get_parse_name;
587 iface->get_parent = g_winhttp_file_get_parent;
588 iface->prefix_matches = g_winhttp_file_prefix_matches;
589 iface->get_relative_path = g_winhttp_file_get_relative_path;
590 iface->resolve_relative_path = g_winhttp_file_resolve_relative_path;
591 iface->get_child_for_display_name = g_winhttp_file_get_child_for_display_name;
592 iface->set_display_name = g_winhttp_file_set_display_name;
593 iface->read_fn = g_winhttp_file_read;
594 iface->create = g_winhttp_file_create;
596 iface->replace = g_winhttp_file_replace;
597 iface->delete_file = g_winhttp_file_delete;
598 iface->make_directory = g_winhttp_file_make_directory;
599 iface->copy = g_winhttp_file_copy;
600 iface->move = g_winhttp_file_move;