mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 16:32:18 +01:00 
			
		
		
		
	Basically various trivial instances of the following MSVC compiler warning: ``` ../gio/gio-tool-set.c(50): warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data ``` Signed-off-by: Philip Withnall <pwithnall@gnome.org>
		
			
				
	
	
		
			801 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			801 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* GIO - GLib Input, Output and Streaming Library
 | |
|  *
 | |
|  * Copyright (C) 2006-2007 Red Hat, Inc.
 | |
|  * Copyright (C) 2008 Novell, Inc.
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or
 | |
|  * modify it under the terms of the GNU Lesser General Public
 | |
|  * License as published by the Free Software Foundation; either
 | |
|  * version 2.1 of the License, or (at your option) any later version.
 | |
|  *
 | |
|  * This library is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
|  * Lesser General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU Lesser General
 | |
|  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
 | |
|  *
 | |
|  * Author: Alexander Larsson <alexl@redhat.com>
 | |
|  * Author: Tor Lillqvist <tml@novell.com>
 | |
|  */
 | |
| 
 | |
| #include "config.h"
 | |
| 
 | |
| #include <stdio.h>
 | |
| #include <string.h>
 | |
| #include <wchar.h>
 | |
| 
 | |
| #include "gio/gfile.h"
 | |
| #include "gio/gfileattribute.h"
 | |
| #include "gio/gfileinfo.h"
 | |
| #include "gio/gfileinfo-priv.h"
 | |
| #include "gwinhttpfile.h"
 | |
| #include "gwinhttpfileinputstream.h"
 | |
| #include "gwinhttpfileoutputstream.h"
 | |
| #include "gio/gioerror.h"
 | |
| 
 | |
| #include "glibintl.h"
 | |
| 
 | |
| static void g_winhttp_file_file_iface_init (GFileIface *iface);
 | |
| 
 | |
| #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))
 | |
| 
 | |
| static void
 | |
| g_winhttp_file_finalize (GObject *object)
 | |
| {
 | |
|   GWinHttpFile *file;
 | |
| 
 | |
|   file = G_WINHTTP_FILE (object);
 | |
| 
 | |
|   g_free (file->url.lpszScheme);
 | |
|   g_free (file->url.lpszHostName);
 | |
|   g_free (file->url.lpszUserName);
 | |
|   g_free (file->url.lpszPassword);
 | |
|   g_free (file->url.lpszUrlPath);
 | |
|   g_free (file->url.lpszExtraInfo);
 | |
| 
 | |
|   g_object_unref (file->vfs);
 | |
| 
 | |
|   G_OBJECT_CLASS (g_winhttp_file_parent_class)->finalize (object);
 | |
| }
 | |
| 
 | |
| static void
 | |
| g_winhttp_file_class_init (GWinHttpFileClass *klass)
 | |
| {
 | |
|   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | |
| 
 | |
|   gobject_class->finalize = g_winhttp_file_finalize;
 | |
| }
 | |
| 
 | |
| static void
 | |
| g_winhttp_file_init (GWinHttpFile *winhttp)
 | |
| {
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * _g_winhttp_file_new:
 | |
|  * @vfs: GWinHttpVfs to use
 | |
|  * @uri: URI of the GWinHttpFile to create.
 | |
|  *
 | |
|  * Returns: (nullable): new winhttp #GFile, or %NULL if there was an error constructing it.
 | |
|  */
 | |
| GFile *
 | |
| _g_winhttp_file_new (GWinHttpVfs *vfs,
 | |
|                      const char  *uri)
 | |
| {
 | |
|   wchar_t *wuri;
 | |
|   GWinHttpFile *file;
 | |
| 
 | |
|   wuri = g_utf8_to_utf16 (uri, -1, NULL, NULL, NULL);
 | |
| 
 | |
|   if (wuri == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   file = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
 | |
|   file->vfs = g_object_ref (vfs);
 | |
| 
 | |
|   memset (&file->url, 0, sizeof (file->url));
 | |
|   file->url.dwStructSize = sizeof (file->url);
 | |
|   file->url.dwSchemeLength = 1;
 | |
|   file->url.dwHostNameLength = 1;
 | |
|   file->url.dwUserNameLength = 1;
 | |
|   file->url.dwPasswordLength = 1;
 | |
|   file->url.dwUrlPathLength = 1;
 | |
|   file->url.dwExtraInfoLength = 1;
 | |
| 
 | |
|   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
 | |
|     {
 | |
|       g_free (wuri);
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   file->url.lpszScheme = g_new (wchar_t, ++file->url.dwSchemeLength);
 | |
|   file->url.lpszHostName = g_new (wchar_t, ++file->url.dwHostNameLength);
 | |
|   file->url.lpszUserName = g_new (wchar_t, ++file->url.dwUserNameLength);
 | |
|   file->url.lpszPassword = g_new (wchar_t, ++file->url.dwPasswordLength);
 | |
|   file->url.lpszUrlPath = g_new (wchar_t, ++file->url.dwUrlPathLength);
 | |
|   file->url.lpszExtraInfo = g_new (wchar_t, ++file->url.dwExtraInfoLength);
 | |
| 
 | |
|   if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCrackUrl (wuri, 0, 0, &file->url))
 | |
|     {
 | |
|       g_free (file->url.lpszScheme);
 | |
|       g_free (file->url.lpszHostName);
 | |
|       g_free (file->url.lpszUserName);
 | |
|       g_free (file->url.lpszPassword);
 | |
|       g_free (file->url.lpszUrlPath);
 | |
|       g_free (file->url.lpszExtraInfo);
 | |
|       g_free (wuri);
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   g_free (wuri);
 | |
|   return G_FILE (file);
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_is_native (GFile *file)
 | |
| {
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_has_uri_scheme (GFile      *file,
 | |
|                                const char *uri_scheme)
 | |
| {
 | |
|   return (g_ascii_strcasecmp (uri_scheme, "http") == 0 ||
 | |
|           g_ascii_strcasecmp (uri_scheme, "https") == 0);
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_uri_scheme (GFile *file)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
| 
 | |
|   return g_utf16_to_utf8 (winhttp_file->url.lpszScheme, -1, NULL, NULL, NULL);
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_basename (GFile *file)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   char *basename;
 | |
|   char *last_slash;
 | |
|   char *retval;
 | |
| 
 | |
|   basename = g_utf16_to_utf8 (winhttp_file->url.lpszUrlPath, -1, NULL, NULL, NULL);
 | |
|   last_slash = strrchr (basename, '/');
 | |
|   /* If no slash, or only "/" fallback to full path part of URI */
 | |
|   if (last_slash == NULL || last_slash[1] == '\0')
 | |
|     return basename;
 | |
| 
 | |
|   retval = g_strdup (last_slash + 1);
 | |
|   g_free (basename);
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_display_name (GFile *file)
 | |
| {
 | |
|   char *basename;
 | |
| 
 | |
|   /* FIXME: This could be improved by using a new g_utf16_make_valid() function
 | |
|    * to recover what we can from the URI, and then suffixing it with
 | |
|    * “ (invalid encoding)” as per g_filename_display_basename(). */
 | |
|   basename = g_winhttp_file_get_basename (file);
 | |
|   if (!basename)
 | |
|     return g_strdup (_(" (invalid encoding)"));
 | |
| 
 | |
|   return g_steal_pointer (&basename);
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_path (GFile *file)
 | |
| {
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_uri (GFile *file)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   DWORD len;
 | |
|   wchar_t *wuri;
 | |
|   char *retval;
 | |
| 
 | |
|   len = 0;
 | |
|   if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, NULL, &len) &&
 | |
|       GetLastError () != ERROR_INSUFFICIENT_BUFFER)
 | |
|     return NULL;
 | |
| 
 | |
|   wuri = g_new (wchar_t, ++len);
 | |
| 
 | |
|   if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpCreateUrl (&winhttp_file->url, ICU_ESCAPE, wuri, &len))
 | |
|     {
 | |
|       g_free (wuri);
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   retval = g_utf16_to_utf8 (wuri, -1, NULL, NULL, NULL);
 | |
|   g_free (wuri);
 | |
| 
 | |
|   if (g_str_has_prefix (retval, "http://:@"))
 | |
|     {
 | |
|       memmove (retval + 7, retval + 9, strlen (retval) - 9);
 | |
|       retval[strlen (retval) - 2] = '\0';
 | |
|     }
 | |
|   else if (g_str_has_prefix (retval, "https://:@"))
 | |
|     {
 | |
|       memmove (retval + 8, retval + 10, strlen (retval) - 10);
 | |
|       retval[strlen (retval) - 2] = '\0';
 | |
|     }
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_parse_name (GFile *file)
 | |
| {
 | |
|   /* FIXME: More hair surely needed */
 | |
| 
 | |
|   return g_winhttp_file_get_uri (file);
 | |
| }
 | |
| 
 | |
| static GFile *
 | |
| g_winhttp_file_get_parent (GFile *file)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file;
 | |
|   char *uri;
 | |
|   char *last_slash;
 | |
|   GFile *parent;
 | |
| 
 | |
|   winhttp_file = G_WINHTTP_FILE (file);
 | |
| 
 | |
|   uri = g_winhttp_file_get_uri (file);
 | |
|   if (uri == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   last_slash = strrchr (uri, '/');
 | |
|   if (last_slash == NULL || *(last_slash+1) == 0)
 | |
|     {
 | |
|       g_free (uri);
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   while (last_slash > uri && *last_slash == '/')
 | |
|     last_slash--;
 | |
| 
 | |
|   last_slash[1] = '\0';
 | |
| 
 | |
|   parent = _g_winhttp_file_new (winhttp_file->vfs, uri);
 | |
|   g_free (uri);
 | |
| 
 | |
|   return parent;
 | |
| }
 | |
| 
 | |
| static GFile *
 | |
| g_winhttp_file_dup (GFile *file)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   char *uri = g_winhttp_file_get_uri (file);
 | |
|   GFile *retval = _g_winhttp_file_new (winhttp_file->vfs, uri);
 | |
| 
 | |
|   g_free (uri);
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static guint
 | |
| g_winhttp_file_hash (GFile *file)
 | |
| {
 | |
|   char *uri = g_winhttp_file_get_uri (file);
 | |
|   guint retval = g_str_hash (uri);
 | |
| 
 | |
|   g_free (uri);
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_equal (GFile *file1,
 | |
|                       GFile *file2)
 | |
| {
 | |
|   char *uri1 = g_winhttp_file_get_uri (file1);
 | |
|   char *uri2 = g_winhttp_file_get_uri (file2);
 | |
|   gboolean retval = g_str_equal (uri1, uri2);
 | |
| 
 | |
|   g_free (uri1);
 | |
|   g_free (uri2);
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static const char *
 | |
| match_prefix (const char *path,
 | |
|               const char *prefix)
 | |
| {
 | |
|   size_t prefix_len;
 | |
| 
 | |
|   prefix_len = strlen (prefix);
 | |
|   if (strncmp (path, prefix, prefix_len) != 0)
 | |
|     return NULL;
 | |
| 
 | |
|   if (prefix_len > 0 && prefix[prefix_len-1] == '/')
 | |
|     prefix_len--;
 | |
| 
 | |
|   return path + prefix_len;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_prefix_matches (GFile *parent,
 | |
|                                GFile *descendant)
 | |
| {
 | |
|   char *parent_uri = g_winhttp_file_get_uri (parent);
 | |
|   char *descendant_uri = g_winhttp_file_get_uri (descendant);
 | |
|   const char *remainder;
 | |
|   gboolean retval;
 | |
| 
 | |
|   remainder = match_prefix (descendant_uri, parent_uri);
 | |
| 
 | |
|   if (remainder != NULL && *remainder == '/')
 | |
|     retval = TRUE;
 | |
|   else
 | |
|     retval = FALSE;
 | |
| 
 | |
|   g_free (parent_uri);
 | |
|   g_free (descendant_uri);
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static char *
 | |
| g_winhttp_file_get_relative_path (GFile *parent,
 | |
|                                   GFile *descendant)
 | |
| {
 | |
|   char *parent_uri = g_winhttp_file_get_uri (parent);
 | |
|   char *descendant_uri = g_winhttp_file_get_uri (descendant);
 | |
|   const char *remainder;
 | |
|   char *retval;
 | |
| 
 | |
|   remainder = match_prefix (descendant_uri, parent_uri);
 | |
| 
 | |
|   if (remainder != NULL && *remainder == '/')
 | |
|     retval = g_strdup (remainder + 1);
 | |
|   else
 | |
|     retval = NULL;
 | |
| 
 | |
|   g_free (parent_uri);
 | |
|   g_free (descendant_uri);
 | |
| 
 | |
|   return retval;
 | |
| }
 | |
| 
 | |
| static GFile *
 | |
| g_winhttp_file_resolve_relative_path (GFile      *file,
 | |
|                                       const char *relative_path)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   GWinHttpFile *child;
 | |
|   wchar_t *wnew_path = g_utf8_to_utf16 (relative_path, -1, NULL, NULL, NULL);
 | |
| 
 | |
|   if (wnew_path == NULL)
 | |
|     return NULL;
 | |
| 
 | |
|   if (*wnew_path != '/')
 | |
|     {
 | |
|       wchar_t *tmp = NULL;
 | |
|       int trailing_slash = winhttp_file->url.lpszUrlPath[winhttp_file->url.dwUrlPathLength-1] == L'/'? 1 : 0;
 | |
|       if (trailing_slash)
 | |
| 	{
 | |
| 	  tmp = g_new (wchar_t, wcslen (winhttp_file->url.lpszUrlPath) + wcslen (wnew_path) + 1);
 | |
| 	  wcscpy (tmp, winhttp_file->url.lpszUrlPath);
 | |
| 	}
 | |
|       else
 | |
| 	{
 | |
| 	  tmp = g_new (wchar_t, wcslen (winhttp_file->url.lpszUrlPath) + 1 + wcslen (wnew_path) + 1);
 | |
| 	  wcscpy (tmp, winhttp_file->url.lpszUrlPath);
 | |
| 	  wcscat (tmp, L"/");
 | |
| 	}
 | |
|       wcscat (tmp, wnew_path);
 | |
| 
 | |
|       g_free (wnew_path);
 | |
|       wnew_path = tmp;
 | |
|     }
 | |
| 
 | |
|   child = g_object_new (G_TYPE_WINHTTP_FILE, NULL);
 | |
|   child->vfs = winhttp_file->vfs;
 | |
|   child->url = winhttp_file->url;
 | |
|   child->url.lpszScheme = g_memdup2 (winhttp_file->url.lpszScheme, ((gsize) winhttp_file->url.dwSchemeLength + 1) * 2);
 | |
|   child->url.lpszHostName = g_memdup2 (winhttp_file->url.lpszHostName, ((gsize) winhttp_file->url.dwHostNameLength + 1) * 2);
 | |
|   child->url.lpszUserName = g_memdup2 (winhttp_file->url.lpszUserName, ((gsize) winhttp_file->url.dwUserNameLength + 1) * 2);
 | |
|   child->url.lpszPassword = g_memdup2 (winhttp_file->url.lpszPassword, ((gsize) winhttp_file->url.dwPasswordLength + 1) * 2);
 | |
|   child->url.lpszUrlPath = wnew_path;
 | |
|   child->url.dwUrlPathLength = wcslen (wnew_path);
 | |
|   child->url.lpszExtraInfo = NULL;
 | |
|   child->url.dwExtraInfoLength = 0;
 | |
| 
 | |
|   return (GFile *) child;
 | |
| }
 | |
| 
 | |
| static GFile *
 | |
| g_winhttp_file_get_child_for_display_name (GFile        *file,
 | |
|                                            const char   *display_name,
 | |
|                                            GError      **error)
 | |
| {
 | |
|   GFile *new_file;
 | |
|   char *basename;
 | |
| 
 | |
|   basename = g_locale_from_utf8 (display_name, -1, NULL, NULL, NULL);
 | |
|   if (basename == NULL)
 | |
|     {
 | |
|       g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME,
 | |
|                    _("Invalid filename %s"), display_name);
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   new_file = g_file_get_child (file, basename);
 | |
|   g_free (basename);
 | |
| 
 | |
|   return new_file;
 | |
| }
 | |
| 
 | |
| static GFile *
 | |
| g_winhttp_file_set_display_name (GFile         *file,
 | |
|                                  const char    *display_name,
 | |
|                                  GCancellable  *cancellable,
 | |
|                                  GError       **error)
 | |
| {
 | |
|   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
 | |
|                        _("Operation not supported"));
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| static GFileInfo *
 | |
| g_winhttp_file_query_info (GFile                *file,
 | |
|                            const char           *attributes,
 | |
|                            GFileQueryInfoFlags   flags,
 | |
|                            GCancellable         *cancellable,
 | |
|                            GError              **error)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   HINTERNET connection, request;
 | |
|   const wchar_t *accept_types[] =
 | |
|     {
 | |
|       L"*/*",
 | |
|       NULL,
 | |
|     };
 | |
|   GFileInfo *info;
 | |
|   GFileAttributeMatcher *matcher;
 | |
|   char *basename;
 | |
|   wchar_t *content_length;
 | |
|   wchar_t *content_type;
 | |
|   SYSTEMTIME last_modified;
 | |
|   DWORD last_modified_len;
 | |
| 
 | |
|   matcher = g_file_attribute_matcher_new (attributes);
 | |
|   info = g_file_info_new ();
 | |
|   g_file_info_set_attribute_mask (info, matcher);
 | |
| 
 | |
|   basename = g_winhttp_file_get_basename (file);
 | |
|   g_file_info_set_name (info, basename);
 | |
|   g_free (basename);
 | |
| 
 | |
|   if (_g_file_attribute_matcher_matches_id (matcher,
 | |
|                                             G_FILE_ATTRIBUTE_ID_STANDARD_DISPLAY_NAME))
 | |
|     {
 | |
|       char *display_name = g_winhttp_file_get_display_name (file);
 | |
|       g_file_info_set_display_name (info, display_name);
 | |
|       g_free (display_name);
 | |
|     }
 | |
| 
 | |
|   if (_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_TYPE))
 | |
|     g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR);
 | |
| 
 | |
|   if (!(_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_SIZE) ||
 | |
|         _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE) ||
 | |
|         _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED) ||
 | |
|         _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_NSEC) ||
 | |
|         _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC)))
 | |
|     {
 | |
|       return info;
 | |
|     }
 | |
| 
 | |
|   connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
 | |
|     (G_WINHTTP_VFS (winhttp_file->vfs)->session,
 | |
|      winhttp_file->url.lpszHostName,
 | |
|      winhttp_file->url.nPort,
 | |
|      0);
 | |
| 
 | |
|   if (connection == NULL)
 | |
|     {
 | |
|       _g_winhttp_set_error (error, GetLastError (), "HTTP connection");
 | |
| 
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpOpenRequest
 | |
|     (connection,
 | |
|      L"HEAD",
 | |
|      winhttp_file->url.lpszUrlPath,
 | |
|      NULL,
 | |
|      WINHTTP_NO_REFERER,
 | |
|      accept_types,
 | |
|      winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
 | |
| 
 | |
|   if (request == NULL)
 | |
|     {
 | |
|       _g_winhttp_set_error (error, GetLastError (), "HEAD request");
 | |
| 
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   if (!G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpSendRequest
 | |
|       (request,
 | |
|        NULL, 0,
 | |
|        NULL, 0,
 | |
|        0,
 | |
|        0))
 | |
|     {
 | |
|       _g_winhttp_set_error (error, GetLastError (), "HEAD request");
 | |
| 
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   if (!_g_winhttp_response (winhttp_file->vfs, request, error, "HEAD request"))
 | |
|     return NULL;
 | |
| 
 | |
|   content_length = NULL;
 | |
|   if (_g_winhttp_query_header (winhttp_file->vfs,
 | |
|                                request,
 | |
|                                "HEAD request",
 | |
|                                WINHTTP_QUERY_CONTENT_LENGTH,
 | |
|                                &content_length,
 | |
|                                NULL))
 | |
|     {
 | |
|       gint64 cl;
 | |
|       size_t n;
 | |
|       const char *gint64_format = "%"G_GINT64_FORMAT"%n";
 | |
|       wchar_t *gint64_format_w = g_utf8_to_utf16 (gint64_format, -1, NULL, NULL, NULL);
 | |
| 
 | |
|       if (swscanf (content_length, gint64_format_w, &cl, &n) == 1 &&
 | |
|           n == wcslen (content_length))
 | |
|         g_file_info_set_size (info, cl);
 | |
| 
 | |
|       g_free (content_length);
 | |
|       g_free (gint64_format_w);
 | |
|     }
 | |
| 
 | |
|   if (matcher == NULL)
 | |
|     return info;
 | |
| 
 | |
|   content_type = NULL;
 | |
|   if (_g_winhttp_query_header (winhttp_file->vfs,
 | |
|                                request,
 | |
|                                "HEAD request",
 | |
|                                WINHTTP_QUERY_CONTENT_TYPE,
 | |
|                                &content_type,
 | |
|                                NULL))
 | |
|     {
 | |
|       char *ct = g_utf16_to_utf8 (content_type, -1, NULL, NULL, NULL);
 | |
| 
 | |
|       if (ct != NULL)
 | |
|         {
 | |
|           char *p = strchr (ct, ';');
 | |
| 
 | |
|           if (p != NULL)
 | |
|             {
 | |
|               char *tmp = g_strndup (ct, p - ct);
 | |
| 
 | |
|               g_file_info_set_content_type (info, tmp);
 | |
|               g_free (tmp);
 | |
|             }
 | |
|           else
 | |
|             g_file_info_set_content_type (info, ct);
 | |
|         }
 | |
| 
 | |
|       g_free (ct);
 | |
|     }
 | |
| 
 | |
|   last_modified_len = sizeof (last_modified);
 | |
|   if (G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpQueryHeaders
 | |
|       (request,
 | |
|        WINHTTP_QUERY_LAST_MODIFIED | WINHTTP_QUERY_FLAG_SYSTEMTIME,
 | |
|        NULL,
 | |
|        &last_modified,
 | |
|        &last_modified_len,
 | |
|        NULL) &&
 | |
|       last_modified_len == sizeof (last_modified) &&
 | |
|       /* Don't bother comparing to the exact Y2038 moment */
 | |
|       last_modified.wYear >= 1970 &&
 | |
|       last_modified.wYear < 2038)
 | |
|     {
 | |
|       GDateTime *dt = NULL, *dt2 = NULL;
 | |
| 
 | |
|       dt = g_date_time_new_from_unix_utc (last_modified.wMilliseconds / 1000);
 | |
|       dt2 = g_date_time_add_seconds (dt, (last_modified.wMilliseconds % 1000) / 1000);
 | |
| 
 | |
|       g_file_info_set_modification_date_time (info, dt2);
 | |
| 
 | |
|       g_date_time_unref (dt2);
 | |
|       g_date_time_unref (dt);
 | |
|     }
 | |
| 
 | |
|   g_file_attribute_matcher_unref (matcher);
 | |
| 
 | |
|   return info;
 | |
| }
 | |
| 
 | |
| static GFileInputStream *
 | |
| g_winhttp_file_read (GFile         *file,
 | |
|                      GCancellable  *cancellable,
 | |
|                      GError       **error)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   HINTERNET connection, request;
 | |
|   const wchar_t *accept_types[] =
 | |
|     {
 | |
|       L"*/*",
 | |
|       NULL,
 | |
|     };
 | |
| 
 | |
|   connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
 | |
|     (G_WINHTTP_VFS (winhttp_file->vfs)->session,
 | |
|      winhttp_file->url.lpszHostName,
 | |
|      winhttp_file->url.nPort,
 | |
|      0);
 | |
| 
 | |
|   if (connection == NULL)
 | |
|     {
 | |
|       _g_winhttp_set_error (error, GetLastError (), "HTTP connection");
 | |
| 
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   request = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpOpenRequest
 | |
|     (connection,
 | |
|      L"GET",
 | |
|      winhttp_file->url.lpszUrlPath,
 | |
|      NULL,
 | |
|      WINHTTP_NO_REFERER,
 | |
|      accept_types,
 | |
|      winhttp_file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
 | |
| 
 | |
|   if (request == NULL)
 | |
|     {
 | |
|       _g_winhttp_set_error (error, GetLastError (), "GET request");
 | |
| 
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   return _g_winhttp_file_input_stream_new (winhttp_file, connection, request);
 | |
| }
 | |
| 
 | |
| static GFileOutputStream *
 | |
| g_winhttp_file_create (GFile             *file,
 | |
|                        GFileCreateFlags   flags,
 | |
|                        GCancellable      *cancellable,
 | |
|                        GError           **error)
 | |
| {
 | |
|   GWinHttpFile *winhttp_file = G_WINHTTP_FILE (file);
 | |
|   HINTERNET connection;
 | |
| 
 | |
|   connection = G_WINHTTP_VFS_GET_CLASS (winhttp_file->vfs)->funcs->pWinHttpConnect
 | |
|     (G_WINHTTP_VFS (winhttp_file->vfs)->session,
 | |
|      winhttp_file->url.lpszHostName,
 | |
|      winhttp_file->url.nPort,
 | |
|      0);
 | |
| 
 | |
|   if (connection == NULL)
 | |
|     {
 | |
|       _g_winhttp_set_error (error, GetLastError (), "HTTP connection");
 | |
| 
 | |
|       return NULL;
 | |
|     }
 | |
| 
 | |
|   return _g_winhttp_file_output_stream_new (winhttp_file, connection);
 | |
| }
 | |
| 
 | |
| #if 0
 | |
| 
 | |
| static GFileOutputStream *
 | |
| g_winhttp_file_replace (GFile             *file,
 | |
|                         const char        *etag,
 | |
|                         gboolean           make_backup,
 | |
|                         GFileCreateFlags   flags,
 | |
|                         GCancellable      *cancellable,
 | |
|                         GError           **error)
 | |
| {
 | |
|   /* FIXME: Implement */
 | |
| 
 | |
|   return NULL;
 | |
| }
 | |
| 
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_delete (GFile         *file,
 | |
|                        GCancellable  *cancellable,
 | |
|                        GError       **error)
 | |
| {
 | |
|   /* FIXME: Implement */
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_make_directory (GFile         *file,
 | |
|                                GCancellable  *cancellable,
 | |
|                                GError       **error)
 | |
| {
 | |
|   /* FIXME: Implement */
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_copy (GFile                  *source,
 | |
|                      GFile                  *destination,
 | |
|                      GFileCopyFlags          flags,
 | |
|                      GCancellable           *cancellable,
 | |
|                      GFileProgressCallback   progress_callback,
 | |
|                      gpointer                progress_callback_data,
 | |
|                      GError                **error)
 | |
| {
 | |
|   /* Fall back to default copy?? */
 | |
|   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
 | |
|                        "Copy not supported");
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| static gboolean
 | |
| g_winhttp_file_move (GFile                  *source,
 | |
|                      GFile                  *destination,
 | |
|                      GFileCopyFlags          flags,
 | |
|                      GCancellable           *cancellable,
 | |
|                      GFileProgressCallback   progress_callback,
 | |
|                      gpointer                progress_callback_data,
 | |
|                      GError                **error)
 | |
| {
 | |
|   /* FIXME: Implement */
 | |
| 
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| static void
 | |
| g_winhttp_file_file_iface_init (GFileIface *iface)
 | |
| {
 | |
|   iface->dup = g_winhttp_file_dup;
 | |
|   iface->hash = g_winhttp_file_hash;
 | |
|   iface->equal = g_winhttp_file_equal;
 | |
|   iface->is_native = g_winhttp_file_is_native;
 | |
|   iface->has_uri_scheme = g_winhttp_file_has_uri_scheme;
 | |
|   iface->get_uri_scheme = g_winhttp_file_get_uri_scheme;
 | |
|   iface->get_basename = g_winhttp_file_get_basename;
 | |
|   iface->get_path = g_winhttp_file_get_path;
 | |
|   iface->get_uri = g_winhttp_file_get_uri;
 | |
|   iface->get_parse_name = g_winhttp_file_get_parse_name;
 | |
|   iface->get_parent = g_winhttp_file_get_parent;
 | |
|   iface->prefix_matches = g_winhttp_file_prefix_matches;
 | |
|   iface->get_relative_path = g_winhttp_file_get_relative_path;
 | |
|   iface->resolve_relative_path = g_winhttp_file_resolve_relative_path;
 | |
|   iface->get_child_for_display_name = g_winhttp_file_get_child_for_display_name;
 | |
|   iface->set_display_name = g_winhttp_file_set_display_name;
 | |
|   iface->query_info = g_winhttp_file_query_info;
 | |
|   iface->read_fn = g_winhttp_file_read;
 | |
|   iface->create = g_winhttp_file_create;
 | |
| #if 0
 | |
|   iface->replace = g_winhttp_file_replace;
 | |
|   iface->delete_file = g_winhttp_file_delete;
 | |
|   iface->make_directory = g_winhttp_file_make_directory;
 | |
|   iface->copy = g_winhttp_file_copy;
 | |
|   iface->move = g_winhttp_file_move;
 | |
| #endif
 | |
| }
 |