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 (at) redhat.com> 22 * Author: Tor Lillqvist <tml (at) 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 36 struct _GWinHttpFileInputStream 37 { 38 GFileInputStream parent_instance; 39 40 GWinHttpFile *file; 41 gboolean request_sent; 42 HINTERNET connection; 43 HINTERNET request; 44 }; 45 46 struct _GWinHttpFileInputStreamClass 47 { 48 GFileInputStreamClass parent_class; 49 }; 50 51 #define g_winhttp_file_input_stream_get_type _g_winhttp_file_input_stream_get_type 52 G_DEFINE_TYPE (GWinHttpFileInputStream, g_winhttp_file_input_stream, G_TYPE_FILE_INPUT_STREAM); 53 54 static gssize g_winhttp_file_input_stream_read (GInputStream *stream, 55 void *buffer, 56 gsize count, 57 GCancellable *cancellable, 58 GError **error); 59 60 static gboolean g_winhttp_file_input_stream_close (GInputStream *stream, 61 GCancellable *cancellable, 62 GError **error); 63 64 static void 65 g_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 82 static void 83 g_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 94 static void 95 g_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 **/ 107 GFileInputStream * 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 124 static gssize 125 g_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 168 static gboolean 169 g_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