[kdbus] Add new library API for common tasks on dbus/kdbus
[platform/upstream/glib.git] / gio / win32 / gwinhttpfileoutputstream.c
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, see <http://www.gnu.org/licenses/>.
18  *
19  * Author: Alexander Larsson <alexl@redhat.com>
20  * Author: Tor Lillqvist <tml@novell.com>
21  */
22
23 #include "config.h"
24
25 #include <glib.h>
26
27 #include "gio/gcancellable.h"
28 #include "gio/gioerror.h"
29 #include "gwinhttpfileoutputstream.h"
30 #include "glibintl.h"
31
32 struct _GWinHttpFileOutputStream
33 {
34   GFileOutputStream parent_instance;
35
36   GWinHttpFile *file;
37   HINTERNET connection;
38   goffset offset;
39 };
40
41 struct _GWinHttpFileOutputStreamClass
42 {
43   GFileOutputStreamClass parent_class;
44 };
45
46 #define g_winhttp_file_output_stream_get_type _g_winhttp_file_output_stream_get_type
47 G_DEFINE_TYPE (GWinHttpFileOutputStream, g_winhttp_file_output_stream, G_TYPE_FILE_OUTPUT_STREAM);
48
49 static gssize     g_winhttp_file_output_stream_write      (GOutputStream     *stream,
50                                                            const void        *buffer,
51                                                            gsize              count,
52                                                            GCancellable      *cancellable,
53                                                            GError           **error);
54
55 static void
56 g_winhttp_file_output_stream_finalize (GObject *object)
57 {
58   GWinHttpFileOutputStream *winhttp_stream;
59
60   winhttp_stream = G_WINHTTP_FILE_OUTPUT_STREAM (object);
61
62   if (winhttp_stream->connection != NULL)
63     G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (winhttp_stream->connection);
64
65   G_OBJECT_CLASS (g_winhttp_file_output_stream_parent_class)->finalize (object);
66 }
67
68 static void
69 g_winhttp_file_output_stream_class_init (GWinHttpFileOutputStreamClass *klass)
70 {
71   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
72   GOutputStreamClass *stream_class = G_OUTPUT_STREAM_CLASS (klass);
73
74   gobject_class->finalize = g_winhttp_file_output_stream_finalize;
75
76   stream_class->write_fn = g_winhttp_file_output_stream_write;
77 }
78
79 static void
80 g_winhttp_file_output_stream_init (GWinHttpFileOutputStream *info)
81 {
82 }
83
84 /**
85  * g_winhttp_file_output_stream_new:
86  * @file: the GWinHttpFile being read
87  * @connection: handle to the HTTP connection, as from WinHttpConnect()
88  * @request: handle to the HTTP request, as from WinHttpOpenRequest
89  *
90  * Returns: #GFileOutputStream for the given request
91  */
92 GFileOutputStream *
93 _g_winhttp_file_output_stream_new (GWinHttpFile *file,
94                                    HINTERNET     connection)
95 {
96   GWinHttpFileOutputStream *stream;
97
98   stream = g_object_new (G_TYPE_WINHTTP_FILE_OUTPUT_STREAM, NULL);
99
100   stream->file = file;
101   stream->connection = connection;
102   stream->offset = 0;
103
104   return G_FILE_OUTPUT_STREAM (stream);
105 }
106
107 static gssize
108 g_winhttp_file_output_stream_write (GOutputStream  *stream,
109                                     const void     *buffer,
110                                     gsize           count,
111                                     GCancellable   *cancellable,
112                                     GError        **error)
113 {
114   GWinHttpFileOutputStream *winhttp_stream = G_WINHTTP_FILE_OUTPUT_STREAM (stream);
115   HINTERNET request;
116   char *headers;
117   wchar_t *wheaders;
118   DWORD bytes_written;
119
120   request = G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpOpenRequest
121     (winhttp_stream->connection,
122      L"PUT",
123      winhttp_stream->file->url.lpszUrlPath,
124      NULL,
125      WINHTTP_NO_REFERER,
126      NULL,
127      winhttp_stream->file->url.nScheme == INTERNET_SCHEME_HTTPS ? WINHTTP_FLAG_SECURE : 0);
128
129   if (request == NULL)
130     {
131       _g_winhttp_set_error (error, GetLastError (), "PUT request");
132
133       return -1;
134     }
135
136   headers = g_strdup_printf ("Content-Range: bytes %" G_GINT64_FORMAT "-%" G_GINT64_FORMAT "/*\r\n",
137                              winhttp_stream->offset, winhttp_stream->offset + count);
138   wheaders = g_utf8_to_utf16 (headers, -1, NULL, NULL, NULL);
139   g_free (headers);
140
141   if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpSendRequest
142       (request,
143        wheaders, -1,
144        NULL, 0,
145        count,
146        0))
147     {
148       _g_winhttp_set_error (error, GetLastError (), "PUT request");
149
150       G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
151       g_free (wheaders);
152
153       return -1;
154     }
155
156   g_free (wheaders);
157
158   if (!G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpWriteData
159       (request, buffer, count, &bytes_written))
160     {
161       _g_winhttp_set_error (error, GetLastError (), "PUT request");
162
163       G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
164
165       return -1;
166     }
167
168   winhttp_stream->offset += bytes_written;
169
170   if (!_g_winhttp_response (winhttp_stream->file->vfs,
171                             request,
172                             error,
173                             "PUT request"))
174     {
175       G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
176
177       return -1;
178     }
179
180   G_WINHTTP_VFS_GET_CLASS (winhttp_stream->file->vfs)->funcs->pWinHttpCloseHandle (request);
181
182   return bytes_written;
183 }