1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * Copyright (C) 2001-2003, Ximian, Inc.
15 #include <libsoup/soup.h>
17 gboolean recurse = FALSE;
25 find_hrefs (const SoupUri *base, const char *body, int length)
27 GPtrArray *hrefs = g_ptr_array_new ();
28 char *buf = g_strndup (body, length);
29 char *start = buf, *end;
33 while ((start = strstr (start, "href"))) {
35 while (isspace ((unsigned char) *start))
39 while (isspace ((unsigned char) *start))
44 end = strchr (start, '"');
48 href = g_strndup (start, end - start);
50 frag = strchr (href, '#');
54 uri = soup_uri_new_with_base (base, href);
59 if (base->protocol != uri->protocol ||
60 base->port != uri->port ||
61 g_strcasecmp (base->host, uri->host) != 0) {
66 if (strncmp (base->path, uri->path, strlen (base->path)) != 0) {
71 g_ptr_array_add (hrefs, soup_uri_to_string (uri, FALSE));
80 mkdirs (const char *path)
84 for (slash = strchr (path, '/'); slash; slash = strchr (slash + 1, '/')) {
86 if (*path && mkdir (path, 0755) == -1 && errno != EEXIST) {
87 fprintf (stderr, "Could not create '%s'\n", path);
88 g_main_loop_quit (loop);
95 static void get_url (const char *url);
98 got_url (SoupMessage *msg, gpointer uri)
105 name = soup_message_get_uri (msg)->path;
106 if (strncmp (base_uri->path, name, strlen (base_uri->path)) != 0) {
107 fprintf (stderr, " Error: not under %s\n", base_uri->path);
110 printf ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase);
112 name += strlen (base_uri->path);
116 if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
118 header = soup_message_get_header (msg->response_headers, "Location");
120 printf (" -> %s\n", header);
126 if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
130 fd = open (name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
133 write (fd, msg->response.body, msg->response.length);
138 header = soup_message_get_header (msg->response_headers, "Content-Type");
139 if (header && g_strncasecmp (header, "text/html", 9) != 0)
142 hrefs = find_hrefs (uri, msg->response.body, msg->response.length);
143 for (i = 0; i < hrefs->len; i++) {
144 get_url (hrefs->pdata[i]);
145 g_free (hrefs->pdata[i]);
147 g_ptr_array_free (hrefs, TRUE);
156 get_url (const char *url)
158 char *url_to_get, *slash, *name;
162 if (strncmp (url, base, strlen (base)) != 0)
165 slash = strrchr (url, '/');
166 if (slash && !slash[1])
167 url_to_get = g_strdup_printf ("%sindex.html", url);
169 url_to_get = g_strdup (url);
172 /* See if we're already downloading it, and create the
176 name = url_to_get + strlen (base);
179 if (access (name, F_OK) == 0) {
185 fd = open (name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
189 msg = soup_message_new (SOUP_METHOD_GET, url_to_get);
190 soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
193 soup_session_queue_message (session, msg, got_url, soup_uri_new (url));
200 fprintf (stderr, "Usage: get [-c CAfile] [-r] URL\n");
205 main (int argc, char **argv)
207 const char *cafile = NULL;
208 SoupUri *proxy = NULL;
212 g_thread_init (NULL);
214 while ((opt = getopt (argc, argv, "c:p:r")) != -1) {
221 proxy = soup_uri_new (optarg);
223 fprintf (stderr, "Could not parse %s as URI\n",
244 base_uri = soup_uri_new (base);
246 fprintf (stderr, "Could not parse '%s' as a URL\n", base);
250 session = soup_session_async_new_with_options (
251 SOUP_SESSION_SSL_CA_FILE, cafile,
252 SOUP_SESSION_PROXY_URI, proxy,
258 outdir = g_strdup_printf ("%lu", (unsigned long)getpid ());
259 if (mkdir (outdir, 0755) != 0) {
260 fprintf (stderr, "Could not make output directory\n");
263 printf ("Output directory is '%s'\n", outdir);
270 loop = g_main_loop_new (NULL, TRUE);
272 g_main_loop_unref (loop);
274 soup_uri_free (base_uri);