⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gwinhttpvfs.c

📁 this is a glib for c language
💻 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 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, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * * Author: Alexander Larsson <alexl@redhat.com> * Author: Tor Lillqvist <tml@novell.com> */#include "config.h"#include <wchar.h>#include "gioerror.h"#include "giomodule.h"#include "gvfs.h"#include "gwinhttpfile.h"#include "gwinhttpvfs.h"#include "gioalias.h"static gboolean lookup_done = FALSE;static gboolean funcs_found = FALSE;static GWinHttpDllFuncs funcs;static voidlookup_funcs (void){  HMODULE winhttp;  if (lookup_done)    return;  winhttp = LoadLibrary ("winhttp.dll");  if (winhttp != NULL)    {      funcs.pWinHttpCloseHandle = (BOOL (WINAPI *) (HINTERNET)) GetProcAddress (winhttp, "WinHttpCloseHandle");      funcs.pWinHttpCrackUrl = (BOOL (WINAPI *) (LPCWSTR,DWORD,DWORD,LPURL_COMPONENTS)) GetProcAddress (winhttp, "WinHttpCrackUrl");      funcs.pWinHttpConnect = (HINTERNET (WINAPI *) (HINTERNET,LPCWSTR,INTERNET_PORT,DWORD)) GetProcAddress (winhttp, "WinHttpConnect");      funcs.pWinHttpCreateUrl = (BOOL (WINAPI *) (LPURL_COMPONENTS,DWORD,LPWSTR,LPDWORD)) GetProcAddress (winhttp, "WinHttpCreateUrl");      funcs.pWinHttpOpen = (HINTERNET (WINAPI *) (LPCWSTR,DWORD,LPCWSTR,LPCWSTR,DWORD)) GetProcAddress (winhttp, "WinHttpOpen");      funcs.pWinHttpOpenRequest = (HINTERNET (WINAPI *) (HINTERNET,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR*,DWORD)) GetProcAddress (winhttp, "WinHttpOpenRequest");      funcs.pWinHttpQueryDataAvailable = (BOOL (WINAPI *) (HINTERNET,LPDWORD)) GetProcAddress (winhttp, "WinHttpQueryDataAvailable");      funcs.pWinHttpQueryHeaders = (BOOL (WINAPI *) (HINTERNET,DWORD,LPCWSTR,LPVOID,LPDWORD,LPDWORD)) GetProcAddress (winhttp, "WinHttpQueryHeaders");      funcs.pWinHttpReadData = (BOOL (WINAPI *) (HINTERNET,LPVOID,DWORD,LPDWORD)) GetProcAddress (winhttp, "WinHttpReadData");      funcs.pWinHttpReceiveResponse = (BOOL (WINAPI *) (HINTERNET,LPVOID)) GetProcAddress (winhttp, "WinHttpReceiveResponse");      funcs.pWinHttpSendRequest = (BOOL (WINAPI *) (HINTERNET,LPCWSTR,DWORD,LPVOID,DWORD,DWORD,DWORD_PTR)) GetProcAddress (winhttp, "WinHttpSendRequest");      funcs.pWinHttpWriteData = (BOOL (WINAPI *) (HINTERNET,LPCVOID,DWORD,LPDWORD)) GetProcAddress (winhttp, "WinHttpWriteData");      if (funcs.pWinHttpCloseHandle &&	  funcs.pWinHttpCrackUrl &&	  funcs.pWinHttpConnect &&	  funcs.pWinHttpCreateUrl &&	  funcs.pWinHttpOpen &&	  funcs.pWinHttpOpenRequest &&	  funcs.pWinHttpQueryDataAvailable &&	  funcs.pWinHttpQueryHeaders &&	  funcs.pWinHttpReadData &&	  funcs.pWinHttpReceiveResponse &&	  funcs.pWinHttpSendRequest &&	  funcs.pWinHttpWriteData)	funcs_found = TRUE;    }  lookup_done = TRUE;}#define g_winhttp_vfs_get_type _g_winhttp_vfs_get_typeG_DEFINE_TYPE_WITH_CODE (GWinHttpVfs, g_winhttp_vfs, G_TYPE_VFS,			 {			   lookup_funcs ();			   if (funcs_found)			     g_io_extension_point_implement (G_VFS_EXTENSION_POINT_NAME,							     g_define_type_id,							     "winhttp",							     10);			 })static const gchar *winhttp_uri_schemes[] = { "http", "https" };static voidg_winhttp_vfs_finalize (GObject *object){  GWinHttpVfs *vfs;  vfs = G_WINHTTP_VFS (object);  (G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpCloseHandle) (vfs->session);  vfs->session = NULL;  if (vfs->wrapped_vfs)    g_object_unref (vfs->wrapped_vfs);  vfs->wrapped_vfs = NULL;  G_OBJECT_CLASS (g_winhttp_vfs_parent_class)->finalize (object);}static voidg_winhttp_vfs_init (GWinHttpVfs *vfs){  wchar_t *wagent;  vfs->wrapped_vfs = g_vfs_get_local ();  wagent = g_utf8_to_utf16 (g_get_prgname (), -1, NULL, NULL, NULL);  if (!wagent)    wagent = g_utf8_to_utf16 ("GWinHttpVfs", -1, NULL, NULL, NULL);  vfs->session = (G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpOpen)    (wagent,     WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,     WINHTTP_NO_PROXY_NAME,     WINHTTP_NO_PROXY_BYPASS,     0);}/** * g_winhttp_vfs_new: * * Returns a new #GVfs handle for a WinHttp vfs. * * Returns: a new #GVfs handle. **/GVfs *_g_winhttp_vfs_new (void){  return g_object_new (G_TYPE_WINHTTP_VFS, NULL);}static GFile *g_winhttp_vfs_get_file_for_path (GVfs       *vfs,                                 const char *path){  return g_vfs_get_file_for_path (G_WINHTTP_VFS (vfs)->wrapped_vfs, path);}static GFile *g_winhttp_vfs_get_file_for_uri (GVfs       *vfs,                                const char *uri){  GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs);  int i;  /* If it matches one of "our" schemes, handle it */  for (i = 0; i < G_N_ELEMENTS (winhttp_uri_schemes); i++)    if (g_ascii_strncasecmp (uri, winhttp_uri_schemes[i], strlen (winhttp_uri_schemes[i])) == 0 &&        uri[strlen (winhttp_uri_schemes[i])] == ':')      return _g_winhttp_file_new (winhttp_vfs, uri);  /* For other URIs fallback to the wrapped GVfs */  return g_vfs_parse_name (winhttp_vfs->wrapped_vfs, uri);}static const gchar * const *g_winhttp_vfs_get_supported_uri_schemes (GVfs *vfs){  GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs);  const gchar * const *wrapped_vfs_uri_schemes = g_vfs_get_supported_uri_schemes (winhttp_vfs->wrapped_vfs);  int i, n;  const gchar **retval;  n = 0;  while (wrapped_vfs_uri_schemes[n] != NULL)    n++;  retval = g_new (const gchar *, n + G_N_ELEMENTS (winhttp_uri_schemes) + 1);  n = 0;  while (wrapped_vfs_uri_schemes[n] != NULL)    {      retval[n] = wrapped_vfs_uri_schemes[n];      n++;    }  for (i = 0; i < G_N_ELEMENTS (winhttp_uri_schemes); i++)    {      retval[n] = winhttp_uri_schemes[i];      n++;    }  retval[n] = NULL;  return retval;}static GFile *g_winhttp_vfs_parse_name (GVfs       *vfs,                          const char *parse_name){  GWinHttpVfs *winhttp_vfs = G_WINHTTP_VFS (vfs);  g_return_val_if_fail (G_IS_VFS (vfs), NULL);  g_return_val_if_fail (parse_name != NULL, NULL);  /* For plain file paths fallback to the wrapped GVfs */  if (g_path_is_absolute (parse_name))    return g_vfs_parse_name (winhttp_vfs->wrapped_vfs, parse_name);  /* Otherwise assume it is an URI, so pass on to   * g_winhttp_vfs_get_file_for_uri().   */  return g_winhttp_vfs_get_file_for_uri (vfs, parse_name);}static gbooleang_winhttp_vfs_is_active (GVfs *vfs){  return TRUE;}static voidg_winhttp_vfs_class_init (GWinHttpVfsClass *class){  GObjectClass *object_class;  GVfsClass *vfs_class;  object_class = (GObjectClass *) class;  object_class->finalize = g_winhttp_vfs_finalize;  vfs_class = G_VFS_CLASS (class);  vfs_class->is_active = g_winhttp_vfs_is_active;  vfs_class->get_file_for_path = g_winhttp_vfs_get_file_for_path;  vfs_class->get_file_for_uri = g_winhttp_vfs_get_file_for_uri;  vfs_class->get_supported_uri_schemes = g_winhttp_vfs_get_supported_uri_schemes;  vfs_class->parse_name = g_winhttp_vfs_parse_name;  lookup_funcs ();  if (funcs_found)    class->funcs = &funcs;  else    class->funcs = NULL;}char *_g_winhttp_error_message (DWORD error_code){  /* The FormatMessage() API that g_win32_error_message() uses doesn't   * seem to know about WinHttp errors, unfortunately.   */  if (error_code >= WINHTTP_ERROR_BASE && error_code < WINHTTP_ERROR_BASE + 200)    {      switch (error_code)        {          /* FIXME: Use meaningful error messages */#define CASE(x) case ERROR_WINHTTP_##x: return g_strdup ("WinHttp error: " #x);          CASE (AUTO_PROXY_SERVICE_ERROR);          CASE (AUTODETECTION_FAILED);          CASE (BAD_AUTO_PROXY_SCRIPT);          CASE (CANNOT_CALL_AFTER_OPEN);          CASE (CANNOT_CALL_AFTER_SEND);          CASE (CANNOT_CALL_BEFORE_OPEN);          CASE (CANNOT_CALL_BEFORE_SEND);          CASE (CANNOT_CONNECT);          CASE (CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW);          CASE (CLIENT_AUTH_CERT_NEEDED);          CASE (CONNECTION_ERROR);          CASE (HEADER_ALREADY_EXISTS);          CASE (HEADER_COUNT_EXCEEDED);          CASE (HEADER_NOT_FOUND);          CASE (HEADER_SIZE_OVERFLOW);          CASE (INCORRECT_HANDLE_STATE);          CASE (INCORRECT_HANDLE_TYPE);          CASE (INTERNAL_ERROR);          CASE (INVALID_OPTION);          CASE (INVALID_QUERY_REQUEST);          CASE (INVALID_SERVER_RESPONSE);          CASE (INVALID_URL);          CASE (LOGIN_FAILURE);          CASE (NAME_NOT_RESOLVED);          CASE (NOT_INITIALIZED);          CASE (OPERATION_CANCELLED);          CASE (OPTION_NOT_SETTABLE);          CASE (OUT_OF_HANDLES);          CASE (REDIRECT_FAILED);          CASE (RESEND_REQUEST);          CASE (RESPONSE_DRAIN_OVERFLOW);          CASE (SECURE_CERT_CN_INVALID);          CASE (SECURE_CERT_DATE_INVALID);          CASE (SECURE_CERT_REV_FAILED);          CASE (SECURE_CERT_REVOKED);          CASE (SECURE_CERT_WRONG_USAGE);          CASE (SECURE_CHANNEL_ERROR);          CASE (SECURE_FAILURE);          CASE (SECURE_INVALID_CA);          CASE (SECURE_INVALID_CERT);          CASE (SHUTDOWN);          CASE (TIMEOUT);          CASE (UNABLE_TO_DOWNLOAD_SCRIPT);          CASE (UNRECOGNIZED_SCHEME);          #undef CASE        default:          return g_strdup_printf ("WinHttp error %ld", error_code);        }    }  else    return g_win32_error_message (error_code);}void_g_winhttp_set_error (GError     **error,                      DWORD        error_code,                      const char  *what){  char *emsg = _g_winhttp_error_message (error_code);  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,               "%s failed: %s", what, emsg);  g_free (emsg);}gboolean_g_winhttp_response (GWinHttpVfs *vfs,                     HINTERNET    request,                     GError     **error,                     const char  *what){  wchar_t *status_code;  DWORD status_code_len;  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpReceiveResponse (request, NULL))    {      _g_winhttp_set_error (error, GetLastError (), what);      return FALSE;    }  status_code_len = 0;  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders      (request,       WINHTTP_QUERY_STATUS_CODE,       NULL,       NULL,       &status_code_len,       NULL) &&      GetLastError () != ERROR_INSUFFICIENT_BUFFER)    {      _g_winhttp_set_error (error, GetLastError (), what);      return FALSE;    }  status_code = g_malloc (status_code_len);  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders      (request,       WINHTTP_QUERY_STATUS_CODE,       NULL,       status_code,       &status_code_len,       NULL))    {      _g_winhttp_set_error (error, GetLastError (), what);      g_free (status_code);      return FALSE;    }  if (status_code[0] != L'2')    {      wchar_t *status_text = NULL;      DWORD status_text_len;      if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders          (request,           WINHTTP_QUERY_STATUS_TEXT,           NULL,           NULL,           &status_text_len,           NULL) &&          GetLastError () == ERROR_INSUFFICIENT_BUFFER)        {          status_text = g_malloc (status_text_len);          if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders              (request,               WINHTTP_QUERY_STATUS_TEXT,               NULL,               status_text,               &status_text_len,               NULL))            {              g_free (status_text);              status_text = NULL;            }        }      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,                   "%s failed: %S %S",                   what, status_code, status_text ? status_text : L"");      g_free (status_code);      g_free (status_text);      return FALSE;    }  g_free (status_code);  return TRUE;}gboolean_g_winhttp_query_header (GWinHttpVfs *vfs,                         HINTERNET    request,                         const char  *request_description,                         DWORD        which_header,                         wchar_t    **header,                         GError     **error){  DWORD header_len = 0;  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders      (request,       which_header,       NULL,       NULL,       &header_len,       NULL) &&      GetLastError () != ERROR_INSUFFICIENT_BUFFER)    {      _g_winhttp_set_error (error, GetLastError (), request_description);      return FALSE;    }  *header = g_malloc (header_len);  if (!G_WINHTTP_VFS_GET_CLASS (vfs)->funcs->pWinHttpQueryHeaders      (request,       which_header,       NULL,       *header,       &header_len,       NULL))    {      _g_winhttp_set_error (error, GetLastError (), request_description);      g_free (*header);      *header = NULL;      return FALSE;    }  return TRUE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -