1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * gsf-input-http.c: retrieves input via HTTP
5 * Copyright (C) 2006 Michael Lawrence (lawremi@iastate.edu)
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of version 2.1 of the GNU Lesser General Public
9 * License as published by the Free Software Foundation.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 #include <gsf-config.h>
23 #include <gsf/gsf-input-http.h>
24 #include <gsf/gsf-input-impl.h>
25 #include <gsf/gsf-impl-utils.h>
26 #include <libxml/nanohttp.h>
28 struct _GsfInputHTTP {
42 static void gsf_input_http_set_property (GObject *object, guint property_id,
45 static void gsf_input_http_get_property (GObject *object, guint property_id,
46 GValue *value, GParamSpec *pspec);
47 static void gsf_input_http_init (GObject *obj);
48 static void gsf_input_http_class_init (GsfInputHTTPClass *c);
49 static GsfInput *gsf_input_http_dup (GsfInput *src, GError **err);
50 static guint8 const *gsf_input_http_read (GsfInput *input, size_t num_bytes,
52 static gboolean gsf_input_http_seek (GsfInput *input, gsf_off_t offset,
62 /* pointer to the class of our parent */
63 static GsfInputClass *parent_class = NULL;
66 gsf_input_http_finalize (GObject *obj_input)
68 GsfInputHTTP *input = GSF_INPUT_HTTP (obj_input);
73 g_free (input->content_type);
74 input->content_type = NULL;
77 xmlNanoHTTPClose ((gpointer) input->ctx);
84 ((GObjectClass *)parent_class)->finalize (obj_input);
88 gsf_input_http_init (GObject *obj)
90 GsfInputHTTP *http = GSF_INPUT_HTTP (obj);
93 http->content_type = NULL;
100 gsf_input_http_class_init (GsfInputHTTPClass *c)
102 GObjectClass *g_object_class = (GObjectClass *) c;
103 GsfInputClass *gsf_input_class = (GsfInputClass *) c;
104 GParamSpec *param_spec;
106 parent_class = g_type_class_ref (gsf_input_get_type ());
108 gsf_input_class->Dup = gsf_input_http_dup;
109 gsf_input_class->Read = gsf_input_http_read;
110 gsf_input_class->Seek = gsf_input_http_seek;
111 g_object_class->finalize = gsf_input_http_finalize;
112 g_object_class->get_property = gsf_input_http_get_property;
113 g_object_class->set_property = gsf_input_http_set_property;
115 param_spec = g_param_spec_string ("url" /* name */ ,
117 "HTTP URL accessed by this stream"
119 NULL /* default_value */ ,
120 (GParamFlags) (G_PARAM_READABLE |
122 G_PARAM_CONSTRUCT_ONLY));
123 g_object_class_install_property (g_object_class, PROP_URL,
126 param_spec = g_param_spec_string ("content_type" /* name */ ,
127 "mime type" /* nick */ ,
128 "Content-Type in HTTP header" /* blurb */
129 , NULL /* default_value */ ,
130 (GParamFlags) (G_PARAM_READABLE |
132 G_PARAM_CONSTRUCT_ONLY));
133 g_object_class_install_property (g_object_class, PROP_CONTENT_TYPE,
138 gsf_input_http_set_property (GObject *object,
140 GValue const *VAL, GParamSpec *pspec)
145 input = GSF_INPUT_HTTP (object);
147 switch (property_id) {
150 input->url = g_value_dup_string (VAL);
153 case PROP_CONTENT_TYPE:
154 old = input->content_type;
155 input->content_type = g_value_dup_string (VAL);
159 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
166 gsf_input_http_get_property (GObject *object,
168 GValue *VAL, GParamSpec *pspec)
172 input = GSF_INPUT_HTTP (object);
174 switch (property_id) {
176 g_value_set_string (VAL, input->url);
178 case PROP_CONTENT_TYPE:
179 g_value_set_string (VAL, input->content_type);
182 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
189 * gsf_input_http_get_url :
190 * @input: #GsfInputHTTP
192 * Returns: an allocated string containing the URL used for input.
195 gsf_input_http_get_url (GsfInputHTTP *input)
198 g_return_val_if_fail(GSF_IS_INPUT_HTTP(input), NULL);
199 g_object_get (G_OBJECT (input), "url", &url, NULL);
204 * gsf_input_http_get_content_type :
205 * @input: #GsfInputHTTP
207 * Returns: an allocated string containing the Content-Type field of the HTTP response.
210 gsf_input_http_get_content_type (GsfInputHTTP *input)
213 g_return_val_if_fail(GSF_IS_INPUT_HTTP(input), NULL);
214 g_object_get (G_OBJECT (input), "content_type", &content_type, NULL);
219 * gsf_input_http_new :
220 * @url: A string containing the URL to retrieve
221 * @error: Holds any errors encountered when establishing the HTTP connection
223 * Returns: an open HTTP connection, ready for reading.
226 gsf_input_http_new (gchar const * url, GError **error G_GNUC_UNUSED)
232 g_return_val_if_fail(url != NULL, NULL);
234 ctx = xmlNanoHTTPOpen (url, &content_type);
235 if (!ctx) /* no meaningful errors provided by nanohttp */
238 obj = g_object_new (GSF_INPUT_HTTP_TYPE,
240 "content-type", content_type,
242 if (G_UNLIKELY (NULL == obj)) return NULL;
244 gsf_input_set_size (GSF_INPUT (obj), xmlNanoHTTPContentLength (ctx));
245 GSF_INPUT_HTTP (obj)->ctx = ctx;
247 return GSF_INPUT (obj);
251 gsf_input_http_dup (GsfInput *src, GError **err)
253 return gsf_input_http_new (GSF_INPUT_HTTP (src)->url, err);
256 static guint8 const *
257 gsf_input_http_read (GsfInput *input, size_t num_bytes, guint8 *buffer)
261 gpointer ctx = GSF_INPUT_HTTP (input)->ctx;
262 GsfInputHTTP *input_http = GSF_INPUT_HTTP (input);
264 if (buffer == NULL) {
265 if (input_http->buf_size < num_bytes) {
266 input_http->buf_size = num_bytes;
267 g_free (input_http->buf);
268 input_http->buf = g_new (guint8, input_http->buf_size);
270 buffer = input_http->buf;
273 for (total_read = 0; total_read < num_bytes; total_read += nread) {
274 nread = xmlNanoHTTPRead (ctx, buffer, num_bytes - total_read);
282 gsf_input_http_seek (GsfInput *input G_GNUC_UNUSED,
283 gsf_off_t offset G_GNUC_UNUSED, GSeekType whence G_GNUC_UNUSED)
288 GSF_CLASS (GsfInputHTTP, gsf_input_http,
289 gsf_input_http_class_init, gsf_input_http_init,