/* * get_http.c-v0.9: * get_http is a simple libcurl-based http client that will display headers * and/or body from a web server. * * Requirements: * libcurl - http://curl.haxx.se/ * * Compiling: * gcc -Wall -O2 `curl-config --cflags` get_http.c -o get_http \ * `curl-config --libs` * * Usage: * see get_http -h * * # displays headers only, follows redirects * get_http -Hf http://www.gozer.org/ * * # execute a request with a specific user-agent id or string (see help) * get_http -a 0 msn.com * get_http -a "Dancin' Jackson 2.0!" https://have.bigger.for-you.com * * # run a request on a protected site * get_http -u user:pass http://staff.example.com/ * * (c) 2003-2006 Mike Hokenson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #define _VERSION "0.9" #define _HOME "http://www.gozer.org/programs/c/" #ifndef isdigit #define isdigit(c) (((c) >= '0') && ((c) <= '9')) #endif #define _N_ELEMENTS(s) (sizeof(s) / sizeof((s)[0])) typedef struct { const char *key; const char *val; } UserAgent; UserAgent useragent_map[] = { { "Internet Explorer 6.0 (Windows XP)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)" }, { "Internet Explorer 5.1 (Mac OS)", "Mozilla/4.0 (compatible; MSIE 5.15; Mac_PowerPC)" }, { "Mozilla Firefox 1.5.0.6 (Windows XP)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6" }, { "Mozilla Firefox 1.5.0.6 (Linux)", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6" }, { "Mozilla 1.7.13 (Windows XP)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.13) Gecko/20060414", }, { "Mozilla 1.7.13 (Linux)", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.13) Gecko/20060417" }, { "Opera 9.01 (Windows XP)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.01" }, { "Opera 9.01 (Linux)", "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera 9.01" }, { "Opera 8.52 (Windows XP)", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 8.52" }, { "Opera 8.52 (Linux)", "Mozilla/4.0 (compatible; MSIE 6.0; X11; Linux i686; en) Opera 8.52" }, { "Safari 2.0.3 (Mac OS X 10.4.5)", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418 (KHTML, like Gecko) Safari/417.9.3" }, { "Safari 1.0 (Mac OS X)", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en-us) AppleWebKit/85 (KHTML, like Gecko) Safari/85" }, { "Konqueror 3.4 (Linux)", "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.0 (like Gecko)" }, { "Netscape 4.8 (Windows XP)", "Mozilla/4.8 [en] (Windows NT 5.1; U)" }, { "Netscape 4.8 (Linux)", "Mozilla/4.8 [en] (X11; U; Linux 2.6.17 i686)" }, { "OmniWeb 4.2.1 (Mac OS)", "Mozilla/4.5 (compatible; OmniWeb/4.2.1-v435.9; Mac_PowerPC)" }, { "WebTV", "Mozilla/4.0 WebTV/2.6 (compatible; MSIE 4.0)" }, { "Googlebot", "Googlebot/2.1 (+http://www.googlebot.com/bot.html)" }, { "MSNBot", "msnbot/0.1 (+http://search.msn.com/msnbot.htm)" }, { NULL, NULL } }; void show_help(void) { int i; fprintf(stderr, "Usage: get_http [OPTS] [URL1 URL2 ...]\n"); fprintf(stderr, " OPTS:\n"); fprintf(stderr, " -a [id/string] set user-agent by id or string\n"); fprintf(stderr, " -b display response body only\n"); fprintf(stderr, " -f follow Location: redirects\n"); fprintf(stderr, " -h display help\n"); fprintf(stderr, " -H display response headers only\n"); fprintf(stderr, " -r [referrer] send HTTP referrer\n"); fprintf(stderr, " -t [timeout] set overall connection timeout\n"); fprintf(stderr, " -T enable transaction timer\n"); fprintf(stderr, " -u [user:pass] set authentication credentials\n"); fprintf(stderr, " -v make verbose (libcurl)\n"); fprintf(stderr, " -V display version\n\n"); fprintf(stderr, " Builtin agents:\n"); for (i = 0; useragent_map[i].key; i++) fprintf(stderr, " %2d: %s\n", i, useragent_map[i].key); } int str_is_digit(const char *str, int *val) { const char *p; if (!str) return 0; for (p = str; *p; p++) if (!isdigit(*p)) return 0; if (val) *val = atoi(str); return 1; } int main(int argc, char **argv) { int option, timer = 0; CURL *curl; char error[CURL_ERROR_SIZE]; if (!(curl = curl_easy_init())) { fprintf(stderr, "Unable to initialize curl\n"); exit(1); } curl_easy_setopt(curl, CURLOPT_HEADER, 1); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, 1); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error); while ((option = getopt(argc, argv, "a:bfhHr:t:Tu:vV")) != EOF) { switch (option) { case 'a': { const char *agent = NULL; int id; if (str_is_digit(optarg, &id)) { if (id >= 0 && id < _N_ELEMENTS(useragent_map)) agent = useragent_map[id].val; } else agent = optarg; if (agent) curl_easy_setopt(curl, CURLOPT_USERAGENT, agent); } break; case 'b': curl_easy_setopt(curl, CURLOPT_HEADER, 0); curl_easy_setopt(curl, CURLOPT_NOBODY, 0); break; case 'f': curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); break; case 'h': show_help(); exit(0); case 'H': curl_easy_setopt(curl, CURLOPT_HEADER, 1); curl_easy_setopt(curl, CURLOPT_NOBODY, 1); break; case 'r': curl_easy_setopt(curl, CURLOPT_REFERER, optarg); break; case 't': { int timeout; if (!str_is_digit(optarg, &timeout)) { show_help(); exit(1); } curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout); } break; case 'T': timer = 1; break; case 'u': curl_easy_setopt(curl, CURLOPT_USERPWD, optarg); break; case 'v': curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); break; case 'V': fprintf(stderr, "get_http/%s (%s)\n", _VERSION, _HOME); exit(0); default: show_help(); exit(1); } } if (optind >= argc) { show_help(); exit(1); } while (optind < argc) { const char *uri = argv[optind++]; error[0] = '\0'; curl_easy_setopt(curl, CURLOPT_URL, uri); if (curl_easy_perform(curl) == CURLE_OK) { if (timer) { double s; curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &s); fprintf(stdout, "Time: %0.3fs\n\n", s); } } else fprintf(stderr, "%s: %s\n\n", uri, (error[0]) ? error : "Unknown Error"); } curl_easy_cleanup(curl); exit(0); } /* * --- Changelog -------------------------------------------------------------- * * 0.1 - 2003/06/26: * initial release. * * 0.2 - 2003/06/27: * added -o, errors are displayed in red, reworked and updated User-Agents * * 0.3 - 2003/06/30: * added resolver and http status stats, individual colors for each stats * item. * * 0.4 - 2003/07/24: * resume transfers (-r), quiet mode (-q), referrer (-R), authentication * (-U), added Safari, Firebird, and WebTV UA's, example usage. * * 0.5 - 2003/07/29: * added more ugliness to download filename handling, added callback to * check for HTTP Content-Disposition: attachment; filename="..." header, * try to include the pathname in the default file (replace / with _). * * 0.6 - 2004/04/27: * reverted to a more simple application: removed stats, file downloads, * and other nonsense. * changed default user-agent from IE6 to CURL's default. * don't verify ssl certs. * now under a BSD license. * * 0.7 - 2004/06/24: * added -b (body only). * updated usage, added missing -V option. * * 0.8 - 2006/08/09: * switch changes (-R to -r, -V to -d, -u to -a, -U to -u) * agent overhaul * * 0.9 - 2006/12/13: * add timer (-T), which displays the duration of each request (in seconds) * more switch changes (-v to -V, -d to -v) * * --- Changelog -------------------------------------------------------------- */