/* 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 "gio/gioerror.h"
#include "gio/giomodule.h"
#include "gio/gvfs.h"

#include "gwinhttpfile.h"
#include "gwinhttpvfs.h"

static gboolean lookup_done = FALSE;
static gboolean funcs_found = FALSE;
static GWinHttpDllFuncs funcs;

static void
lookup_funcs (void)
{
  HMODULE winhttp = NULL;
  char winhttp_dll[MAX_PATH + 100];
  int n;

  if (lookup_done)
    return;

  n = GetSystemDirectory (winhttp_dll, MAX_PATH);
  if (n > 0 && n < MAX_PATH)
    {
        if (winhttp_dll[n-1] != '\\' &&
            winhttp_dll[n-1] != '/')
            strcat (winhttp_dll, "\\");
        strcat (winhttp_dll, "winhttp.dll");
        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_type
G_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 void
g_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 void
g_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_free (wagent);
}

/*
 * 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 gboolean
g_winhttp_vfs_is_active (GVfs *vfs)
{
  return TRUE;
}

static void
g_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;
}
