| #include "a.h" |
| |
| typedef struct DEntry DEntry; |
| struct DEntry |
| { |
| CEntry ce; |
| HTTPHeader hdr; |
| char *tmpfile; |
| int fd; |
| }; |
| |
| static void |
| dfree(CEntry *ce) |
| { |
| DEntry *d; |
| |
| d = (DEntry*)ce; |
| if(d->tmpfile){ |
| remove(d->tmpfile); |
| free(d->tmpfile); |
| close(d->fd); |
| } |
| } |
| |
| static Cache *downloadcache; |
| |
| static char* |
| parseurl(char *url, char **path) |
| { |
| char *host, *p; |
| int len; |
| |
| if(memcmp(url, "http://", 7) != 0) |
| return nil; |
| p = strchr(url+7, '/'); |
| if(p == nil) |
| p = url+strlen(url); |
| len = p - (url+7); |
| host = emalloc(len+1); |
| memmove(host, url+7, len); |
| host[len] = 0; |
| if(*p == 0) |
| p = "/"; |
| *path = p; |
| return host; |
| } |
| |
| int |
| download(char *url, HTTPHeader *hdr) |
| { |
| DEntry *d; |
| char *host, *path; |
| char buf[] = "/var/tmp/smugfs.XXXXXX"; |
| char *req; |
| int fd; |
| Fmt fmt; |
| |
| if(downloadcache == nil) |
| downloadcache = newcache(sizeof(DEntry), 128, dfree); |
| |
| host = parseurl(url, &path); |
| if(host == nil) |
| return -1; |
| |
| d = (DEntry*)cachelookup(downloadcache, url, 1); |
| if(d->tmpfile){ |
| free(host); |
| *hdr = d->hdr; |
| return dup(d->fd, -1); |
| } |
| d->fd = -1; // paranoia |
| |
| if((fd = opentemp(buf, ORDWR|ORCLOSE)) < 0){ |
| free(host); |
| return -1; |
| } |
| |
| fmtstrinit(&fmt); |
| fmtprint(&fmt, "GET %s HTTP/1.0\r\n", path); |
| fmtprint(&fmt, "Host: %s\r\n", host); |
| fmtprint(&fmt, "User-Agent: " USER_AGENT "\r\n"); |
| fmtprint(&fmt, "\r\n"); |
| req = fmtstrflush(&fmt); |
| |
| fprint(2, "Get %s\n", url); |
| |
| if(httptofile(&http, host, req, hdr, fd) < 0){ |
| free(host); |
| free(req); |
| return -1; |
| } |
| free(host); |
| free(req); |
| d->tmpfile = estrdup(buf); |
| d->fd = dup(fd, -1); |
| d->hdr = *hdr; |
| return fd; |
| } |
| |
| void |
| downloadflush(char *substr) |
| { |
| if(downloadcache) |
| cacheflush(downloadcache, substr); |
| } |