Import Upstream version 2.72.4
This commit is contained in:
commit
4ef3ff9793
2003 changed files with 1332420 additions and 0 deletions
788
gio/win32/gwinhttpfile.c
Normal file
788
gio/win32/gwinhttpfile.c
Normal file
|
|
@ -0,0 +1,788 @@
|
|||
/* 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)
|
||||
{
|
||||
int 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;
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue