source: trunk/third/libsoup/tests/get.c @ 21108

Revision 21108, 5.4 KB checked in by ghudson, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21107, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * Copyright (C) 2001-2003, Ximian, Inc.
4 */
5
6#include <ctype.h>
7#include <errno.h>
8#include <fcntl.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <sys/stat.h>
13#include <unistd.h>
14
15#include <libsoup/soup.h>
16
17gboolean recurse = FALSE;
18SoupSession *session;
19GMainLoop *loop;
20char *base;
21SoupUri *base_uri;
22int pending;
23
24static GPtrArray *
25find_hrefs (const SoupUri *base, const char *body, int length)
26{
27        GPtrArray *hrefs = g_ptr_array_new ();
28        char *buf = g_strndup (body, length);
29        char *start = buf, *end;
30        char *href, *frag;
31        SoupUri *uri;
32
33        while ((start = strstr (start, "href"))) {
34                start += 4;
35                while (isspace ((unsigned char) *start))
36                        start++;
37                if (*start++ != '=')
38                        continue;
39                while (isspace ((unsigned char) *start))
40                        start++;
41                if (*start++ != '"')
42                        continue;
43
44                end = strchr (start, '"');
45                if (!end)
46                        break;
47
48                href = g_strndup (start, end - start);
49                start = end;
50                frag = strchr (href, '#');
51                if (frag)
52                        *frag = '\0';
53
54                uri = soup_uri_new_with_base (base, href);
55                g_free (href);
56
57                if (!uri)
58                        continue;
59                if (base->protocol != uri->protocol ||
60                    base->port != uri->port ||
61                    g_strcasecmp (base->host, uri->host) != 0) {
62                        soup_uri_free (uri);
63                        continue;
64                }
65
66                if (strncmp (base->path, uri->path, strlen (base->path)) != 0) {
67                        soup_uri_free (uri);
68                        continue;
69                }
70
71                g_ptr_array_add (hrefs, soup_uri_to_string (uri, FALSE));
72                soup_uri_free (uri);
73        }
74        g_free (buf);
75
76        return hrefs;
77}
78
79static void
80mkdirs (const char *path)
81{
82        char *slash;
83
84        for (slash = strchr (path, '/'); slash; slash = strchr (slash + 1, '/')) {
85                *slash = '\0';
86                if (*path && mkdir (path, 0755) == -1 && errno != EEXIST) {
87                        fprintf (stderr, "Could not create '%s'\n", path);
88                        g_main_loop_quit (loop);
89                        return;
90                }
91                *slash = '/';
92        }
93}
94
95static void get_url (const char *url);
96
97static void
98got_url (SoupMessage *msg, gpointer uri)
99{
100        char *name;
101        int fd, i;
102        GPtrArray *hrefs;
103        const char *header;
104
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);
108                goto DONE;
109        }
110        printf ("%s: %d %s\n", name, msg->status_code, msg->reason_phrase);
111
112        name += strlen (base_uri->path);
113        if (*name == '/')
114                name++;
115
116        if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) {
117                unlink (name);
118                header = soup_message_get_header (msg->response_headers, "Location");
119                if (header) {
120                        printf ("  -> %s\n", header);
121                        get_url (header);
122                }
123                goto DONE;
124        }
125
126        if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
127                goto DONE;
128
129        if (recurse)
130                fd = open (name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
131        else
132                fd = STDOUT_FILENO;
133        write (fd, msg->response.body, msg->response.length);
134        if (!recurse)
135                goto DONE;
136        close (fd);
137
138        header = soup_message_get_header (msg->response_headers, "Content-Type");
139        if (header && g_strncasecmp (header, "text/html", 9) != 0)
140                goto DONE;
141
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]);
146        }
147        g_ptr_array_free (hrefs, TRUE);
148
149 DONE:
150        soup_uri_free (uri);
151        if (!--pending)
152                g_main_quit (loop);
153}
154
155static void
156get_url (const char *url)
157{
158        char *url_to_get, *slash, *name;
159        SoupMessage *msg;
160        int fd;
161
162        if (strncmp (url, base, strlen (base)) != 0)
163                return;
164
165        slash = strrchr (url, '/');
166        if (slash && !slash[1])
167                url_to_get = g_strdup_printf ("%sindex.html", url);
168        else
169                url_to_get = g_strdup (url);
170
171        if (recurse) {
172                /* See if we're already downloading it, and create the
173                 * file if not.
174                 */
175
176                name = url_to_get + strlen (base);
177                if (*name == '/')
178                        name++;
179                if (access (name, F_OK) == 0) {
180                        g_free (url_to_get);
181                        return;
182                }
183
184                mkdirs (name);
185                fd = open (name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
186                close (fd);
187        }
188
189        msg = soup_message_new (SOUP_METHOD_GET, url_to_get);
190        soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT);
191
192        pending++;
193        soup_session_queue_message (session, msg, got_url, soup_uri_new (url));
194        g_free (url_to_get);
195}
196
197static void
198usage (void)
199{
200        fprintf (stderr, "Usage: get [-c CAfile] [-r] URL\n");
201        exit (1);
202}
203
204int
205main (int argc, char **argv)
206{
207        const char *cafile = NULL;
208        SoupUri *proxy = NULL;
209        int opt;
210
211        g_type_init ();
212        g_thread_init (NULL);
213
214        while ((opt = getopt (argc, argv, "c:p:r")) != -1) {
215                switch (opt) {
216                case 'c':
217                        cafile = optarg;
218                        break;
219
220                case 'p':
221                        proxy = soup_uri_new (optarg);
222                        if (!proxy) {
223                                fprintf (stderr, "Could not parse %s as URI\n",
224                                         optarg);
225                                exit (1);
226                        }
227                        break;
228
229                case 'r':
230                        recurse = TRUE;
231                        break;
232
233                case '?':
234                        usage ();
235                        break;
236                }
237        }
238        argc -= optind;
239        argv += optind;
240
241        if (argc != 1)
242                usage ();
243        base = argv[0];
244        base_uri = soup_uri_new (base);
245        if (!base_uri) {
246                fprintf (stderr, "Could not parse '%s' as a URL\n", base);
247                exit (1);
248        }
249
250        session = soup_session_async_new_with_options (
251                SOUP_SESSION_SSL_CA_FILE, cafile,
252                SOUP_SESSION_PROXY_URI, proxy,
253                NULL);
254
255        if (recurse) {
256                char *outdir;
257
258                outdir = g_strdup_printf ("%lu", (unsigned long)getpid ());
259                if (mkdir (outdir, 0755) != 0) {
260                        fprintf (stderr, "Could not make output directory\n");
261                        exit (1);
262                }
263                printf ("Output directory is '%s'\n", outdir);
264                chdir (outdir);
265                g_free (outdir);
266        }
267
268        get_url (base);
269
270        loop = g_main_loop_new (NULL, TRUE);
271        g_main_run (loop);
272        g_main_loop_unref (loop);
273
274        soup_uri_free (base_uri);
275
276        return 0;
277}
Note: See TracBrowser for help on using the repository browser.