Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

483 lines (387 sloc) 10.373 kb
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/* Cherokee
*
* Authors:
* Alvaro Lopez Ortega <alvaro@alobbs.com>
*
* Copyright (C) 2001-2011 Alvaro Lopez Ortega
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
#include "common-internal.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_TIME_H
# include <time.h>
#endif
#ifdef HAVE_GETOPT_LONG
# include <getopt.h>
#else
# include "getopt/getopt.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include "init.h"
#include "util.h"
#include "url.h"
#include "header.h"
#include "fdpoll.h"
#include "request.h"
#include "downloader.h"
#include "downloader-protected.h"
#include "socket.h"
#include "header-protected.h" /* FIXME! */
#include "proxy.h"
#define EXIT_OK 0
#define EXIT_ERROR 1
#define POLL_TIME 1000
#define UNSET_FD -1
#define COLUM_NUM 20
#define COLUM_SEP ":"
#define ENTRIES "cget"
/* Globals..
*/
static int output_fd = UNSET_FD;
static int global_fd = UNSET_FD;
static cherokee_boolean_t quiet = false;
static cherokee_boolean_t save_headers = false;
static void
print_help (void)
{
printf ("Cherokee Downloader %s\n"
"Usage: cget [options] URL\n\n"
"Mandatory arguments to long options are mandatory for short options too.\n\n"
"Startup:\n"
" -V, --version Print version and exit\n"
" -h, --help Print this help\n"
"\n"
"Logging and input file:\n"
" -q, --quiet Quiet (no output)\n"
"\n"
"Download:\n"
" -O --output-document=FILE Write documents to FILE\n"
"\n"
"HTTP options:\n"
" -s, --save-headers Save the HTTP headers to file\n"
" --header=STRING insert STRING among the headers\n"
"\n"
"Report bugs to alvaro@alobbs.com\n", PACKAGE_VERSION);
}
static void
print_usage (void)
{
printf ("Cherokee Downloader %s\n"
"Usage: cget [options] URL\n\n"
"Try `cget --help' for more options.\n", PACKAGE_VERSION);
}
static void
print_tuple_str (const char *title, const char *info)
{
int whites;
char *tmp;
if (quiet == true)
return;
whites = COLUM_NUM - strlen(title);
fprintf (stderr, "%s ", title);
while (whites-- > 0) {
fprintf (stderr, " ");
}
fprintf (stderr, COLUM_SEP " %s\n", info);
}
static void
print_tuple_int (const char *title, int num)
{
char tmp[128];
snprintf (tmp, 128, "%d", num);
print_tuple_str (title, tmp);
}
static ret_t
do_download__init (cherokee_downloader_t *downloader, void *param)
{
cherokee_url_t *url;
UNUSED(param);
url = &downloader->request.url;
print_tuple_str ("Host", url->host.buf);
print_tuple_str ("Request", url->request.buf);
print_tuple_int ("Port", url->port);
return ret_ok;
}
static ret_t
do_download__has_headers (cherokee_downloader_t *downloader, void *param)
{
cherokee_url_t *url;
cherokee_buffer_t *req;
cherokee_header_t *hdr;
UNUSED(param);
url = &downloader->request.url;
req = &url->request;
hdr = downloader->header;
TRACE(ENTRIES, "quiet=%d http_code=%d\n", quiet, hdr->response);
/* Check the response
*/
if (quiet == false) {
cherokee_buffer_t tmp = CHEROKEE_BUF_INIT;
cherokee_http_code_copy (HDR_RESPONSE(hdr), &tmp);
print_tuple_str ("Response", tmp.buf);
cherokee_buffer_mrproper (&tmp);
}
/* Open a new file if needed
*/
if (global_fd == UNSET_FD) {
char *name;
name = strrchr (req->buf, '/');
if (name == NULL) {
name = "index.html";
}
output_fd = open (name, O_WRONLY, O_CREAT);
if (output_fd < 0) {
return ret_error;
}
} else {
output_fd = global_fd;
}
/* Save the headers?
*/
if (save_headers == true) {
ssize_t written;
uint32_t len;
cherokee_header_get_length (hdr, &len);
written = write (output_fd, hdr->input_buffer->buf, len);
if (written < 0) {
PRINT_MSG_S ("ERROR: Can not write to output file\n");
return ret_error;
}
}
return ret_ok;
}
static ret_t
do_download__read_body (cherokee_downloader_t *downloader, void *param)
{
ret_t ret;
ssize_t len;
cherokee_buffer_t tmp = CHEROKEE_BUF_INIT;
UNUSED(param);
/* Write down
*/
len = write (output_fd, downloader->body.buf, downloader->body.len);
if (len > 0) {
ret = cherokee_buffer_move_to_begin (&downloader->body, len);
if (ret != ret_ok) return ret;
}
/* Print info
*/
cherokee_buffer_add_fsize (&tmp, downloader->content_length);
cherokee_buffer_add_str (&tmp, " of ");
cherokee_buffer_add_fsize (&tmp, downloader->info.body_recv);
if (! quiet) {
fprintf (stderr, "\rDownloading: %s", tmp.buf);
fflush(stderr);
}
cherokee_buffer_mrproper (&tmp);
return ret_ok;
}
static ret_t
do_download__finish (cherokee_downloader_t *downloader, void *param)
{
UNUSED (downloader);
UNUSED (param);
fprintf (stderr, "\n");
return ret_ok;
}
static ret_t
do_download (cherokee_downloader_t *downloader)
{
ret_t ret;
cherokee_downloader_status_t status;
cherokee_boolean_t got_headers = false;
cherokee_boolean_t reading = false;
do_download__init(downloader,NULL);
for (;;) {
/* Do some real work
*/
ret = cherokee_downloader_step (downloader, NULL, NULL);
cherokee_downloader_get_status(downloader, &status);
TRACE(ENTRIES, "ret=%d status=%d\n", ret, status);
switch (ret) {
case ret_ok:
if ( !reading && (status & downloader_status_post_sent)) {
reading = true;
}
if ( (status & downloader_status_headers_received) && !got_headers) {
do_download__has_headers (downloader, NULL);
got_headers = true;
}
if (status & downloader_status_data_available) {
do_download__read_body (downloader, NULL);
}
if (status & downloader_status_finished) {
do_download__finish (downloader, NULL);
}
break;
case ret_eagain:
/* It's going on..
*/
break;
case ret_eof_have_data:
if ((status & downloader_status_headers_received) && !got_headers) {
do_download__has_headers (downloader, NULL);
got_headers = true;
}
if (status & downloader_status_data_available) {
do_download__read_body (downloader, NULL);
}
/* fall down */
case ret_eof:
if (status & downloader_status_finished) {
do_download__finish (downloader, NULL);
}
/* fall down */
case ret_error:
/* Finished or critical error
*/
return ret;
default:
SHOULDNT_HAPPEN;
return ret_error;
}
}
return ret_ok;
}
int
main (int argc, char **argv)
{
int re;
ret_t ret;
cint_t val;
cint_t param_num;
cint_t long_index;
cherokee_downloader_t *downloader;
cherokee_buffer_t proxy = CHEROKEE_BUF_INIT;
cuint_t proxy_port;
struct option long_options[] = {
/* Options without arguments */
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{"quiet", no_argument, NULL, 'q'},
{"save-headers", no_argument, NULL, 's'},
{"header", required_argument, NULL, 0 },
{NULL, 0, NULL, 0}
};
/* Parse known parameters
*/
while ((val = getopt_long (argc, argv, "VshqO:", long_options, &long_index)) != -1) {
switch (val) {
case 'V':
printf ("Cherokee Downloader %s\n"
"Written by Alvaro Lopez Ortega <alvaro@alobbs.com>\n\n"
"Copyright (C) 2001-2011 Alvaro Lopez Ortega.\n"
"This is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
PACKAGE_VERSION);
return EXIT_OK;
case 'O':
if (global_fd != UNSET_FD) {
close (global_fd);
}
if ((strlen(optarg) == 1) && (optarg[0] == '-')) {
global_fd = fileno(stdout);
} else {
global_fd = open (optarg, O_WRONLY | O_CREAT, 0644);
}
if (global_fd < 0) {
PRINT_MSG ("ERROR: Can not open %s\n", optarg);
return EXIT_ERROR;
}
break;
case 0:
break;
case 'q':
quiet = true;
break;
case 's':
save_headers = true;
break;
case 'h':
case '?':
default:
print_help();
return EXIT_OK;
}
}
/* The rest..
*/
param_num = argc - optind;
if (param_num <= 0) {
print_usage();
return EXIT_OK;
}
/* Tracing and proxy discovering..
*/
cherokee_init();
cget_find_proxy (&proxy, &proxy_port);
for (val=optind; val<optind+param_num; val++) {
cherokee_buffer_t url = CHEROKEE_BUF_INIT;
/* Build the url buffer
*/
ret = cherokee_buffer_add_va (&url, "%s", argv[val]);
if (ret != ret_ok)
exit (EXIT_ERROR);
/* Create the downloader object..
*/
ret = cherokee_downloader_new (&downloader);
if (ret != ret_ok)
exit (EXIT_ERROR);
ret = cherokee_downloader_init(downloader);
if (ret != ret_ok)
exit (EXIT_ERROR);
if (! cherokee_buffer_is_empty (&proxy)) {
ret = cherokee_downloader_set_proxy (downloader, &proxy, proxy_port);
if (ret != ret_ok)
exit (EXIT_ERROR);
}
ret = cherokee_downloader_set_url (downloader, &url);
if (ret != ret_ok)
exit (EXIT_ERROR);
ret = cherokee_downloader_connect (downloader);
if (ret != ret_ok)
exit (EXIT_ERROR);
/* Download it!
*/
ret = do_download (downloader);
if ((ret != ret_ok) && (ret != ret_eof)) {
exit (EXIT_ERROR);
}
/* Free the objects..
*/
cherokee_buffer_mrproper (&url);
cherokee_downloader_free (downloader);
}
/* Close the output file
*/
re = close (output_fd);
if (re != 0)
exit (EXIT_ERROR);
cherokee_mrproper();
return EXIT_OK;
}
Jump to Line
Something went wrong with that request. Please try again.