Git init
[profile/ivi/libsoup2.4.git] / libsoup / soup-requester.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-requester.c:
4  *
5  * Copyright (C) 2010, Igalia S.L.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24
25 #include <glib/gi18n.h>
26
27 #define LIBSOUP_USE_UNSTABLE_REQUEST_API
28
29 #include "soup-requester.h"
30 #include "soup-request-data.h"
31 #include "soup-request-file.h"
32 #include "soup-request-http.h"
33 #include "soup-session-feature.h"
34 #include "soup-uri.h"
35
36 static SoupSessionFeatureInterface *soup_requester_default_feature_interface;
37 static void soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
38
39 struct _SoupRequesterPrivate {
40         SoupSession *session;
41         GHashTable *request_types;
42 };
43
44 G_DEFINE_TYPE_WITH_CODE (SoupRequester, soup_requester, G_TYPE_OBJECT,
45                          G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
46                                                 soup_requester_session_feature_init))
47
48 static void
49 soup_requester_init (SoupRequester *requester)
50 {
51         SoupSessionFeature *feature;
52
53         requester->priv = G_TYPE_INSTANCE_GET_PRIVATE (requester,
54                                                        SOUP_TYPE_REQUESTER,
55                                                        SoupRequesterPrivate);
56
57         requester->priv->request_types = g_hash_table_new (soup_str_case_hash,
58                                                            soup_str_case_equal);
59
60         feature = SOUP_SESSION_FEATURE (requester);
61         soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_HTTP);
62         soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_FILE);
63         soup_session_feature_add_feature (feature, SOUP_TYPE_REQUEST_DATA);
64 }
65
66 static void
67 finalize (GObject *object)
68 {
69         SoupRequester *requester = SOUP_REQUESTER (object);
70
71         g_hash_table_destroy (requester->priv->request_types);
72
73         G_OBJECT_CLASS (soup_requester_parent_class)->finalize (object);
74 }
75
76 static void
77 soup_requester_class_init (SoupRequesterClass *requester_class)
78 {
79         GObjectClass *object_class = G_OBJECT_CLASS (requester_class);
80
81         g_type_class_add_private (requester_class, sizeof (SoupRequesterPrivate));
82
83         /* virtual method override */
84         object_class->finalize = finalize;
85 }
86
87 static void
88 attach (SoupSessionFeature *feature, SoupSession *session)
89 {
90         SoupRequester *requester = SOUP_REQUESTER (feature);
91
92         requester->priv->session = session;
93
94         soup_requester_default_feature_interface->attach (feature, session);
95 }
96
97 static void
98 detach (SoupSessionFeature *feature, SoupSession *session)
99 {
100         SoupRequester *requester = SOUP_REQUESTER (feature);
101
102         requester->priv->session = NULL;
103
104         soup_requester_default_feature_interface->detach (feature, session);
105 }
106
107 static gboolean
108 add_feature (SoupSessionFeature *feature, GType type)
109 {
110         SoupRequester *requester = SOUP_REQUESTER (feature);
111         SoupRequestClass *request_class;
112         int i;
113
114         if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
115                 return FALSE;
116
117         request_class = g_type_class_ref (type);
118         for (i = 0; request_class->schemes[i]; i++) {
119                 g_hash_table_insert (requester->priv->request_types,
120                                      (char *)request_class->schemes[i],
121                                      GSIZE_TO_POINTER (type));
122         }
123         return TRUE;
124 }
125
126 static gboolean
127 remove_feature (SoupSessionFeature *feature, GType type)
128 {
129         SoupRequester *requester = SOUP_REQUESTER (feature);
130         SoupRequestClass *request_class;
131         int i, orig_size;
132
133         if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
134                 return FALSE;
135
136         request_class = g_type_class_peek (type);
137         if (!request_class)
138                 return FALSE;
139
140         orig_size = g_hash_table_size (requester->priv->request_types);
141         for (i = 0; request_class->schemes[i]; i++) {
142                 g_hash_table_remove (requester->priv->request_types,
143                                      request_class->schemes[i]);
144         }
145
146         return g_hash_table_size (requester->priv->request_types) != orig_size;
147 }
148
149 static gboolean
150 has_feature (SoupSessionFeature *feature, GType type)
151 {
152         SoupRequester *requester = SOUP_REQUESTER (feature);
153         GHashTableIter iter;
154         gpointer key, value;
155
156         if (!g_type_is_a (type, SOUP_TYPE_REQUEST))
157                 return FALSE;
158
159         g_hash_table_iter_init (&iter, requester->priv->request_types);
160         while (g_hash_table_iter_next (&iter, &key, &value)) {
161                 if (value == GSIZE_TO_POINTER (type))
162                         return TRUE;
163         }
164         return FALSE;
165 }
166
167 static void
168 soup_requester_session_feature_init (SoupSessionFeatureInterface *feature_interface,
169                                      gpointer interface_data)
170 {
171         soup_requester_default_feature_interface =
172                 g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
173
174         feature_interface->attach = attach;
175         feature_interface->detach = detach;
176         feature_interface->add_feature = add_feature;
177         feature_interface->remove_feature = remove_feature;
178         feature_interface->has_feature = has_feature;
179 }
180
181 SoupRequester *
182 soup_requester_new (void)
183 {
184         return g_object_new (SOUP_TYPE_REQUESTER, NULL);
185 }
186
187 SoupRequest *
188 soup_requester_request (SoupRequester *requester, const char *uri_string,
189                         GError **error)
190 {
191         SoupURI *uri;
192         SoupRequest *req;
193
194         uri = soup_uri_new (uri_string);
195         if (!uri) {
196                 g_set_error (error, SOUP_REQUESTER_ERROR, SOUP_REQUESTER_ERROR_BAD_URI,
197                              _("Could not parse URI '%s'"), uri_string);
198                 return NULL;
199         }
200
201         req = soup_requester_request_uri (requester, uri, error);
202         soup_uri_free (uri);
203         return req;
204 }
205
206 SoupRequest *
207 soup_requester_request_uri (SoupRequester *requester, SoupURI *uri,
208                             GError **error)
209 {
210         GType request_type;
211
212         g_return_val_if_fail (SOUP_IS_REQUESTER (requester), NULL);
213
214         request_type = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (requester->priv->request_types, uri->scheme));
215         if (!request_type) {
216                 g_set_error (error, SOUP_REQUESTER_ERROR,
217                              SOUP_REQUESTER_ERROR_UNSUPPORTED_URI_SCHEME,
218                              _("Unsupported URI scheme '%s'"), uri->scheme);
219                 return NULL;
220         }
221
222         return g_initable_new (request_type, NULL, error,
223                                "uri", uri,
224                                "session", requester->priv->session,
225                                NULL);
226 }
227
228 GQuark
229 soup_requester_error_quark (void)
230 {
231         static GQuark error;
232         if (!error)
233                 error = g_quark_from_static_string ("soup_requester_error_quark");
234         return error;
235 }