Revise Overview: Webscripts
[quvi.git] / examples / callback_libsoup.c
blobafdb11ceda754cc45cbe07e222180918bef39b86
1 /* quvi
2 * Copyright (C) 2011 Toni Gundogdu <legatvs@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301 USA
20 /* callback_libsoup.c -- Use libsoup (async) instead of libcurl (easy) */
22 #include "config.h"
24 #include <stdio.h>
25 #include <string.h>
27 #include <quvi/quvi.h>
28 #include <quvi/net.h>
30 #ifdef HAVE_LIBSOUP_GNOME
31 #include <libsoup/soup-gnome.h>
32 #else
33 #include <libsoup/soup.h>
34 #endif
36 #include "common.h"
38 static QUVIcode status_callback(long param, void *data)
40 quvi_word status, type;
42 status = quvi_loword(param);
43 type = quvi_hiword(param);
45 switch (status)
47 case QUVISTATUS_RESOLVE:
48 handle_resolve_status(type);
49 break;
51 case QUVISTATUS_FETCH:
52 handle_fetch_status(type, data);
53 break;
55 case QUVISTATUS_VERIFY:
56 handle_verify_status(type);
57 break;
60 fflush(stderr);
62 return (QUVI_OK);
65 static void set_feat(quvi_net_t n, SoupMessage *m,
66 QUVInetPropertyFeatureName feature,
67 const char *hdr)
69 char *s = quvi_net_get_one_prop_feat(n, feature);
70 if (s)
71 soup_message_headers_append(m->request_headers, hdr, s);
74 static void set_feats_from_lua_script(quvi_net_t n, SoupMessage *m)
76 set_feat(n, m, QUVI_NET_PROPERTY_FEATURE_ARBITRARYCOOKIE, "Cookie");
77 set_feat(n, m, QUVI_NET_PROPERTY_FEATURE_USERAGENT, "User-Agent");
80 #ifdef _0
81 /* Same as set_feats_from_lua_script above. quvi_net_get_one_prop_feat
82 * is a convinience function that can be used instead unless the
83 * application is expected handle >1 of the same features (e.g. multiple
84 * instances of QUVI_NET_PROPERTY_FEATURE_ARBITRARYCOOKIE in the
85 * features list. */
86 static void set_feats_from_lua_script_alt(quvi_net_t n, SoupMessage *m)
88 quvi_llst_node_t feature;
89 quvi_net_getprop(n, QUVI_NET_PROPERTY_FEATURES, &feature);
91 while (feature)
93 char *feature_name, *feature_value;
94 quvi_net_propfeat_t pfeat;
96 pfeat = (quvi_net_propfeat_t) quvi_llst_data(feature);
98 quvi_net_getprop_feat(pfeat,
99 QUVI_NET_PROPERTY_FEATURE_NAME, &feature_name);
101 quvi_net_getprop_feat(pfeat,
102 QUVI_NET_PROPERTY_FEATURE_VALUE, &feature_value);
104 if (strcmp(feature_name, "arbitrary_cookie") == 0)
106 soup_message_headers_append(
107 m->request_headers, "Cookie", feature_value);
110 if (strcmp(feature_name, "user_agent") == 0)
112 soup_message_headers_append(
113 m->request_headers, "User-Agent", feature_value);
116 feature = quvi_llst_next(feature);
119 #endif
121 static SoupSession *session = NULL;
123 static void send_message(quvi_net_t n, SoupMessage **message,
124 guint *status, SoupMessageFlags msg_flags,
125 const int head_flag, const int lua_feats)
127 char *url = NULL;
129 quvi_net_getprop(n, QUVI_NET_PROPERTY_URL, &url);
131 *message = soup_message_new(head_flag ? "HEAD":"GET", url);
133 if (msg_flags)
134 soup_message_set_flags(*message, msg_flags);
136 /* In reality, the library sets these only for quvi.fetch. */
137 if (lua_feats)
138 set_feats_from_lua_script(n, *message);
140 *status = soup_session_send_message(session, *message);
142 quvi_net_setprop(n, QUVI_NET_PROPERTY_RESPONSECODE, *status);
145 static QUVIcode fetch_callback(quvi_net_t n)
147 SoupMessage *m;
148 guint status;
150 send_message(n, &m, &status,
151 0, /* Session flags */
152 0, /* 'HEAD' flag */
153 1); /* Set features from quvi.fetch */
155 if (SOUP_STATUS_IS_SUCCESSFUL(status))
157 quvi_net_setprop(n, QUVI_NET_PROPERTY_CONTENT, m->response_body->data);
158 return (QUVI_OK);
161 quvi_net_seterr(n, "%s (http/%d)", m->reason_phrase, status);
163 return (QUVI_CALLBACK);
166 static QUVIcode resolve_callback(quvi_net_t n)
168 SoupMessage *m;
169 guint status;
171 send_message(n, &m, &status,
172 SOUP_MESSAGE_NO_REDIRECT, /* Session flags */
173 0, /* 'HEAD' flag */
174 0); /* Set features from quvi.fetch */
176 if (SOUP_STATUS_IS_REDIRECTION(status))
178 const char *r_url =
179 soup_message_headers_get_one(m->response_headers, "Location");
181 quvi_net_setprop(n, QUVI_NET_PROPERTY_REDIRECTURL, r_url);
183 else if (!SOUP_STATUS_IS_SUCCESSFUL(status))
185 quvi_net_seterr(n, "%s (http/%d)", m->reason_phrase, status);
186 return (QUVI_CALLBACK);
189 return (QUVI_OK);
192 static QUVIcode verify_callback(quvi_net_t n)
194 SoupMessage *m;
195 guint status;
197 send_message(n, &m, &status,
198 0, /* Session flags */
199 1, /* 'HEAD' flag */
200 0); /* Set features from quvi.fetch */
202 if (SOUP_STATUS_IS_SUCCESSFUL(status))
204 goffset cl =
205 soup_message_headers_get_content_length(m->response_headers);
207 const char *ct =
208 soup_message_headers_get_content_type(m->response_headers, NULL);
210 quvi_net_setprop(n, QUVI_NET_PROPERTY_CONTENTTYPE, ct);
211 quvi_net_setprop(n, QUVI_NET_PROPERTY_CONTENTLENGTH, cl);
213 return (QUVI_OK);
216 quvi_net_seterr(n, "%s (http/%d)", m->reason_phrase, status);
218 return (QUVI_CALLBACK);
221 static void dump_media(quvi_media_t m)
223 char *m_url, *m_ct, *m_suffix;
224 double m_cl;
226 quvi_getprop(m, QUVIPROP_MEDIAURL, &m_url);
227 quvi_getprop(m, QUVIPROP_MEDIACONTENTTYPE, &m_ct);
228 quvi_getprop(m, QUVIPROP_MEDIACONTENTLENGTH, &m_cl);
229 quvi_getprop(m, QUVIPROP_FILESUFFIX, &m_suffix);
231 spew_e(
232 "%s\n"
233 "url: %s\n"
234 "content-type: %s\n"
235 "content-length: %.0f\n"
236 "file suffix: %s\n",
237 __func__, m_url, m_ct, m_cl, m_suffix);
240 static void help()
242 printf(
243 "Usage: callback_libsoup [--help|--log] [URL]\n\n"
244 " -h,--help .. Print help and exit\n"
245 " -l,--logger .. Enable logger\n\n"
246 "Note: Unless URL is specified, the default URL will be used\n");
247 exit(0);
250 int main (int argc, char *argv[])
252 char *url = "http://is.gd/yFNPMR";
253 quvi_media_t m;
254 int log_flag;
255 QUVIcode rc;
256 quvi_t q;
258 log_flag = 0;
260 if (argc > 1)
262 int i;
263 for (i=1; i<argc; ++i)
265 if (strcmp(argv[i], "-l") == 0
266 || strcmp(argv[i], "--logger") == 0)
268 log_flag = 1;
270 else if (strcmp(argv[i], "-h") == 0
271 || strcmp(argv[i], "--help") == 0)
273 help();
275 else
276 url = argv[i];
280 rc = quvi_init(&q);
281 check_error(q,rc);
283 quvi_setopt(q, QUVIOPT_STATUSFUNCTION, &status_callback);
284 quvi_setopt(q, QUVIOPT_FETCHFUNCTION, &fetch_callback);
285 quvi_setopt(q, QUVIOPT_RESOLVEFUNCTION, &resolve_callback);
286 quvi_setopt(q, QUVIOPT_VERIFYFUNCTION, &verify_callback);
288 g_type_init();
290 #ifdef HAVE_LIBSOUP_GNOME
291 session = soup_session_async_new_with_options(
292 SOUP_SESSION_ADD_FEATURE_BY_TYPE,
293 SOUP_TYPE_PROXY_RESOLVER_GNOME,
294 NULL
296 #else
297 session = soup_session_async_new();
298 #endif
300 if (log_flag)
302 SoupLogger *log = soup_logger_new(SOUP_LOGGER_LOG_HEADERS, -1);
303 soup_session_add_feature(session, SOUP_SESSION_FEATURE(log));
304 g_object_unref(log);
307 rc = quvi_parse(q, url, &m);
308 check_error(q, rc);
310 dump_media(m);
312 quvi_parse_close(&m);
313 quvi_close(&q);
315 return (0);
318 /* vim: set ts=2 sw=2 tw=72 expandtab: */