1/* GIO - GLib Input, Output and Streaming Library 2 * 3 * Copyright (C) 2006-2007 Red Hat, Inc. 4 * Copyright (C) 2008 Novell, Inc. 5 * 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. 10 * 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. 15 * 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. 20 * 21 * Author: Alexander Larsson <alexl@redhat.com> 22 * Author: Tor Lillqvist <tml@novell.com> 23 */ 24 25#include "config.h" 26 27#include <glib.h> 28 29#include "gcancellable.h" 30#include "gioerror.h" 31#include "gwinhttpfileinputstream.h" 32#include "glibintl.h" 33 34#include "gioalias.h" 35 36struct _GWinHttpFileInputStream 37{ 38 GFileInputStream parent_instance; 39 40 GWinHttpFile *file; 41 gboolean request_sent; 42 HINTERNET connection; 43 HINTERNET request; 44}; 45 46struct _GWinHttpFileInputStreamClass 47{ 48 GFileInputStreamClass parent_class; 49}; 50 51#define g_winhttp_file_input_stream_get_type _g_winhttp_file_input_stream_get_type 52G_DEFINE_TYPE (GWinHttpFileInputStream, g_winhttp_file_input_stream, G_TYPE_FILE_INPUT_STREAM); 53 54static gssize g_winhttp_file_input_stream_read (GInputStream *stream, 55 void *buffer, 56 gsize count, 57 GCancellable *cancellable, 58 GError **error); 59 60static gboolean g_winhttp_file_input_stream_close (GInputStream *stream, 61 GCancellable *cancellable, 62 GError **error); 63 64static void 65g_winhttp_file_input_stream_finalize (GObject *object) 66{ 67 GWinHttpFileInputStream *winhttp_stream; 68 69 winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (object); 70 71 if (winhttp_stream->request != NULL) 72 G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->request); 73 if (winhttp_stream->connection != NULL) 74 G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection); 75 76 g_object_unref (winhttp_stream->file); 77 winhttp_stream->file = NULL; 78 79 G_OBJECT_CLASS (g_winhttp_file_input_stream_parent_class)->finalize (object); 80} 81 82static void 83g_winhttp_file_input_stream_class_init (GWinHttpFileInputStreamClass *klass) 84{ 85 GObjectClass *gobject_class = G_OBJECT_CLASS (klass); 86 GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass); 87 88 gobject_class->finalize = g_winhttp_file_input_stream_finalize; 89 90 stream_class->read_fn = g_winhttp_file_input_stream_read; 91 stream_class->close_fn = g_winhttp_file_input_stream_close; 92} 93 94static void 95g_winhttp_file_input_stream_init (GWinHttpFileInputStream *info) 96{ 97} 98 99/** 100 * g_winhttp_file_input_stream_new: 101 * @file: the GWinHttpFile being read 102 * @connection: handle to the HTTP connection, as from WinHttpConnect() 103 * @request: handle to the HTTP request, as from WinHttpOpenRequest 104 * 105 * Returns: #GFileInputStream for the given request 106 **/ 107GFileInputStream * 108_g_winhttp_file_input_stream_new (GWinHttpFile *file, 109 HINTERNET connection, 110 HINTERNET request) 111{ 112 GWinHttpFileInputStream *stream; 113 114 stream = g_object_new (G_TYPE_WINHTTP_FILE_INPUT_STREAM, NULL); 115 116 stream->file = g_object_ref (file); 117 stream->request_sent = FALSE; 118 stream->connection = connection; 119 stream->request = request; 120 121 return G_FILE_INPUT_STREAM (stream); 122} 123 124static gssize 125g_winhttp_file_input_stream_read (GInputStream *stream, 126 void *buffer, 127 gsize count, 128 GCancellable *cancellable, 129 GError **error) 130{ 131 GWinHttpFileInputStream *winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (stream); 132 DWORD bytes_read; 133 134 if (!winhttp_stream->request_sent) 135 { 136 if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpSendRequest 137 (winhttp_stream->request, 138 NULL, 0, 139 NULL, 0, 140 0, 141 0)) 142 { 143 _g_winhttp_set_error (error, GetLastError (), "GET request"); 144 145 return -1; 146 } 147 148 if (!_g_winhttp_response (winhttp_stream->file->vfs, 149 winhttp_stream->request, 150 error, 151 "GET request")) 152 return -1; 153 154 winhttp_stream->request_sent = TRUE; 155 } 156 157 if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpReadData 158 (winhttp_stream->request, buffer, count, &bytes_read)) 159 { 160 _g_winhttp_set_error (error, GetLastError (), "GET request"); 161 162 return -1; 163 } 164 165 return bytes_read; 166} 167 168static gboolean 169g_winhttp_file_input_stream_close (GInputStream *stream, 170 GCancellable *cancellable, 171 GError **error) 172{ 173 GWinHttpFileInputStream *winhttp_stream = G_WINHTTP_FILE_INPUT_STREAM (stream); 174 175 if (winhttp_stream->connection != NULL) 176 G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection); 177 winhttp_stream->connection = NULL; 178 return TRUE; 179} 180