156 lines
3.0 KiB
C
Raw Normal View History

2015-08-12 17:01:38 -07:00
/* vim: ts=4 sw=4 noexpandtab
* This file is part of ToaruOS and is released under the terms
* of the NCSA / University of Illinois License - see LICENSE.md
* Copyright (C) 2015 Kevin Lange
*
* fetch - Retreive documents from HTTP servers.
*
*/
2015-07-31 13:31:53 -07:00
#include <stdio.h>
2015-08-03 22:24:16 -07:00
#include <string.h>
#include <stdlib.h>
2015-08-06 15:19:51 -07:00
#include <getopt.h>
2015-08-03 22:24:16 -07:00
#include "lib/http_parser.h"
2015-08-03 22:24:16 -07:00
#define SIZE 512
struct http_req {
char domain[SIZE];
char path[SIZE];
};
2015-08-06 15:19:51 -07:00
struct {
int show_headers;
const char * output_file;
2015-08-07 16:33:57 -07:00
const char * cookie;
2015-08-06 15:19:51 -07:00
FILE * out;
} fetch_options = {0};
2015-08-03 22:24:16 -07:00
void parse_url(char * d, struct http_req * r) {
if (strstr(d, "http://") == d) {
d += strlen("http://");
char * s = strstr(d, "/");
if (!s) {
strcpy(r->domain, d);
strcpy(r->path, "");
} else {
*s = 0;
s++;
strcpy(r->domain, d);
strcpy(r->path, s);
}
} else {
fprintf(stderr, "sorry, can't parse %s\n", d);
exit(1);
}
}
int callback_header_field (http_parser *p, const char *buf, size_t len) {
2015-08-06 15:19:51 -07:00
if (fetch_options.show_headers) {
fprintf(stderr, "Header field: %.*s\n", len, buf);
}
return 0;
}
int callback_header_value (http_parser *p, const char *buf, size_t len) {
2015-08-06 15:19:51 -07:00
if (fetch_options.show_headers) {
fprintf(stderr, "Header value: %.*s\n", len, buf);
}
return 0;
}
int callback_body (http_parser *p, const char *buf, size_t len) {
2015-08-06 15:19:51 -07:00
fwrite(buf, 1, len, fetch_options.out);
return 0;
}
2015-08-06 15:19:51 -07:00
int usage(char * argv[]) {
2015-08-07 16:33:57 -07:00
fprintf(stderr, "Usage: %s [-h] [-c cookie] [-o file] url\n", argv[0]);
2015-08-06 15:19:51 -07:00
return 1;
}
2015-07-31 13:31:53 -07:00
int main(int argc, char * argv[]) {
2015-08-06 15:19:51 -07:00
int opt;
2015-08-07 16:33:57 -07:00
while ((opt = getopt(argc, argv, "?c:ho:")) != -1) {
2015-08-06 15:19:51 -07:00
switch (opt) {
case '?':
return usage(argv);
2015-08-07 16:33:57 -07:00
case 'c':
fetch_options.cookie = optarg;
break;
2015-08-06 15:19:51 -07:00
case 'h':
fetch_options.show_headers = 1;
break;
case 'o':
fetch_options.output_file = optarg;
break;
}
}
if (optind >= argc) {
return usage(argv);
}
2015-07-31 13:31:53 -07:00
2015-08-03 22:24:16 -07:00
struct http_req my_req;
2015-08-06 15:19:51 -07:00
parse_url(argv[optind], &my_req);
2015-08-03 22:24:16 -07:00
2015-07-31 13:31:53 -07:00
char file[100];
2015-08-03 22:24:16 -07:00
sprintf(file, "/dev/net/%s", my_req.domain);
2015-07-31 13:31:53 -07:00
2015-08-06 15:19:51 -07:00
fetch_options.out = stdout;
if (fetch_options.output_file) {
fetch_options.out = fopen(fetch_options.output_file, "w");
}
2015-07-31 13:31:53 -07:00
FILE * f = fopen(file,"r+");
if (!f) {
fprintf(stderr, "Nope.\n");
return 1;
}
2015-08-07 16:33:57 -07:00
if (fetch_options.cookie) {
fprintf(f,
"GET /%s HTTP/1.0\r\n"
"User-Agent: curl/7.35.0\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"Cookie: %s\r\n"
"\r\n", my_req.path, my_req.domain, fetch_options.cookie);
} else {
fprintf(f,
"GET /%s HTTP/1.0\r\n"
"User-Agent: curl/7.35.0\r\n"
"Host: %s\r\n"
"Accept: */*\r\n"
"\r\n", my_req.path, my_req.domain);
}
2015-07-31 13:31:53 -07:00
http_parser_settings settings;
memset(&settings, 0, sizeof(settings));
settings.on_header_field = callback_header_field;
settings.on_header_value = callback_header_value;
settings.on_body = callback_body;
http_parser parser;
http_parser_init(&parser, HTTP_RESPONSE);
2015-07-31 13:31:53 -07:00
while (!feof(f)) {
char buf[1024];
2015-08-03 22:24:16 -07:00
memset(buf, 0, sizeof(buf));
size_t r = fread(buf, 1, 1024, f);
http_parser_execute(&parser, &settings, buf, r);
2015-07-31 13:31:53 -07:00
}
2015-08-06 15:19:51 -07:00
fflush(fetch_options.out);
2015-08-05 20:03:44 -07:00
2015-07-31 13:31:53 -07:00
return 0;
}