裴国兴
unread,Nov 8, 2009, 7:00:20 AM11/8/09Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to btload
----------------------urifetch.h----------------
struct uristat{
size_t st_size;
time_t st_mtime;
};
int uriopen(const char *url, struct uristat *sb);
int urifetch(int fd, size_t size, const char *path);
----------------------urifetch.c----------------
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <winsock.h>
#include "urifetch.h"
#define close(a) closesocket(a)
static int leapMonth(size_t year, size_t month)
{
return (year%100)&&!(year&0x3)&&(month==2);
}
static int urlsplit(const char **inp, char *outp, int splitch)
{
char *output = outp;
const char *url = *inp;
while (*url && *url!=splitch)
*output++ = *url++;
*output = 0;
*inp = url;
return output - outp;
}
static int urlskip(const char **inp, const char *skips)
{
const char *url = *inp;
const char *oldinp = *inp;
while (*url == *skips++)
url++;
*inp = url;
return url-oldinp;
}
static size_t Month2Date(size_t year, int month)
{
int i;
size_t date = 0;
const int MONTHS[]={31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30,
31, 29};
for (i=0; i<month; i++)
date += MONTHS[i]+leapMonth(year, i);
return date;
}
static time_t uritime(const char *uritime)
{
char format[1024];
const char *month_names[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
size_t month = 0;
size_t date, year, hour, minus, second;
for (month=0; month<12; month++) {
snprintf(format, sizeof(format), "%s %s %s",
"%*s %d", month_names[month], "%d %d:%d:%d GMT");
if (sscanf(uritime, format, &date, &year,
&hour, &minus, &second) == 5)
break;
}
size_t total = 0;
assert(month < 12);
size_t y = 1970;
for (y=1970; y<year; y++) {
size_t day = Month2Date(y, 12);
total += day;
}
total += Month2Date(year, month)+date;
total = total*24+hour;
total = total*60+minus;
total = total*60+second;
return (time_t)(total);
}
static int statparse(const char *header, size_t count, struct uristat
*sb)
{
size_t length = 0;
const char *optname = NULL;
assert(sb != NULL);
optname="Content-Length: ";
if (!strncmp(optname, header, strlen(optname))) {
sscanf(header+strlen(optname), "%d", &length);
sb->st_size = length;
return 0;
}
optname="Last-Modified: ";
if (!strncmp(optname, header, strlen(optname))) {
/* Sat, 15 Aug 2009 05:46:42 GMT */
sb->st_mtime = uritime(header+strlen(optname));
return 0;
}
printf("%s", header);
return 0;
}
static int urigets(int fd, char *header, size_t count)
{
int hdrsz = 0;
int error = 0;
while (hdrsz < count) {
error = recv(fd, &header[hdrsz], 1, 0);
if (error != 1)
break;
hdrsz++;
if (hdrsz < 2)
continue;
if (!strncmp(&header[hdrsz-2], "\r\n", 2))
break;
}
if (hdrsz < count)
header[hdrsz] = 0;
return hdrsz;
}
int uriopen(const char *url, struct uristat *sb)
{
char schema[32];
char domain[256];
char location[512];
char urlrequest[4096];
char header[8192];
const char *oldurl = url;
urlsplit(&url, schema, ':');
urlskip(&url, "://");
urlsplit(&url, domain, '/');
strcpy(location, url);
int fd = -1;
int hdrsz = 0;
int error = 0;
struct hostent *phost;
phost = gethostbyname(domain);
if (phost == NULL)
return -1;
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET;
srvaddr.sin_port = htons(80);
srvaddr.sin_addr = *(struct in_addr*)phost->h_addr;
struct sockaddr *caddr = (struct sockaddr*)&srvaddr;
fd = socket(AF_INET, SOCK_STREAM, 0);
if (fd == -1)
return -1;
error = connect(fd, caddr, sizeof(srvaddr));
if (error != 0)
goto fail;
snprintf(urlrequest, sizeof urlrequest,
"GET %s HTTP/1.0\r\n"
"Accept: */*\r\n"
"Host: %s\r\n"
"Referer: %s\r\n"
"Connection: Close\r\n"
/*"User-Agent: MiniDownload\r\n"*/
"\r\n", location, domain, oldurl);
error = send(fd, urlrequest, strlen(urlrequest), 0);
if (error < strlen(urlrequest))
goto fail;
hdrsz = urigets(fd, header, sizeof(header));
assert(hdrsz < sizeof(header));
printf("%s\n", header);
hdrsz = urigets(fd, header, sizeof(header));
assert(hdrsz < sizeof(header));
while (hdrsz > 2) {
statparse(header, hdrsz, sb);
hdrsz = urigets(fd, header, sizeof(header));
}
assert(!strcmp("\r\n", header));
return fd;
fail:
close(fd);
return -1;
}
int urifetch(int fd, size_t size, const char *path)
{
int iocnt;
int error = -1;
char buffer[8192];
FILE *fpo = fopen(path, "wb");
size_t total = 0;
assert(fpo != NULL);
while (total < size){
iocnt = recv(fd, buffer, sizeof(buffer), 0);
if (iocnt == -1)
goto fail;
if (iocnt == 0)
goto fail;
fwrite(buffer, iocnt, 1, fpo);
total += iocnt;
}
#if 1
assert (total == size);
iocnt = recv(fd, buffer, sizeof(buffer), 0);
assert (iocnt == 0);
#endif
error = 0;
fail:
fclose(fpo);
return error;
}
-----------------简单HTTP下载实现