Index: lib/libfetch/fetch.h =================================================================== --- lib/libfetch/fetch.h (revision 187089) +++ lib/libfetch/fetch.h (working copy) @@ -44,6 +44,7 @@ char host[MAXHOSTNAMELEN+1]; int port; char *doc; + char *postdata; off_t offset; size_t length; time_t ims_time; @@ -100,6 +101,7 @@ FILE *fetchXGetHTTP(struct url *, struct url_stat *, const char *); FILE *fetchGetHTTP(struct url *, const char *); FILE *fetchPutHTTP(struct url *, const char *); +FILE *fetchPostHTTP(struct url *, const char *); int fetchStatHTTP(struct url *, struct url_stat *, const char *); struct url_ent *fetchListHTTP(struct url *, const char *); @@ -113,11 +115,13 @@ /* Generic functions */ FILE *fetchXGetURL(const char *, struct url_stat *, const char *); FILE *fetchGetURL(const char *, const char *); +FILE *fetchPostURL(const char *, const char *); FILE *fetchPutURL(const char *, const char *); int fetchStatURL(const char *, struct url_stat *, const char *); struct url_ent *fetchListURL(const char *, const char *); FILE *fetchXGet(struct url *, struct url_stat *, const char *); FILE *fetchGet(struct url *, const char *); +FILE *fetchPost(struct url *, const char *); FILE *fetchPut(struct url *, const char *); int fetchStat(struct url *, struct url_stat *, const char *); struct url_ent *fetchList(struct url *, const char *); Index: lib/libfetch/http.c =================================================================== --- lib/libfetch/http.c (revision 187089) +++ lib/libfetch/http.c (working copy) @@ -803,7 +803,7 @@ char hbuf[MAXHOSTNAMELEN + 7], *host; conn_t *conn; struct url *url, *new; - int chunked, direct, ims, need_auth, noredirect, verbose; + int chunked, direct, ims, need_auth, noredirect, postdata, verbose; int e, i, n, val; off_t offset, clength, length, size; time_t mtime; @@ -816,6 +816,7 @@ noredirect = CHECK_FLAG('A'); verbose = CHECK_FLAG('v'); ims = CHECK_FLAG('i'); + postdata = CHECK_FLAG('x'); if (direct && purl) { fetchFreeURL(purl); @@ -932,9 +933,16 @@ http_cmd(conn, "User-Agent: %s " _LIBFETCH_VER, getprogname()); if (url->offset > 0) http_cmd(conn, "Range: bytes=%lld-", (long long)url->offset); + /* If it is POST */ + if (postdata && url->postdata != NULL) { + http_cmd(conn, "Content-Length: %d", strlen(url->postdata)); + http_cmd(conn, "Content-Type: application/x-www-form-urlencoded"); + } http_cmd(conn, "Connection: close"); http_cmd(conn, ""); - + if (postdata && url->postdata != NULL) { + http_cmd(conn, url->postdata); + } /* * Force the queued request to be dispatched. Normally, one * would do this with shutdown(2) but squid proxies can be @@ -1219,6 +1227,15 @@ } /* + * Send an HTTP POST request + */ +FILE * +fetchPostHTTP(struct url *URL __unused, const char *flags __unused) +{ + return (http_request(URL, "POST", NULL, http_get_proxy(URL, flags), flags)); +} + +/* * Get an HTTP document's metadata */ int Index: lib/libfetch/fetch.c =================================================================== --- lib/libfetch/fetch.c (revision 187089) +++ lib/libfetch/fetch.c (working copy) @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -121,7 +122,25 @@ return (NULL); } + /* + * Select the appropriate protocol for the URL scheme, and return a + * write-only stream connected to the document referenced by the URL. + */ +FILE * +fetchPost(struct url *URL, const char *flags) +{ + + if (strcasecmp(URL->scheme, SCHEME_HTTP) == 0) + return (fetchPostHTTP(URL, flags)); + else if (strcasecmp(URL->scheme, SCHEME_HTTPS) == 0) + return (fetchPostHTTP(URL, flags)); + warnx("fetchPost(): only implemented for http and https"); + url_seterr(URL_BAD_SCHEME); + return (NULL); +} + +/* * Select the appropriate protocol for the URL scheme, and return the * size of the document referenced by the URL if it exists. */ @@ -211,6 +230,24 @@ } /* + * Attempt to parse the given URL; if successful, call fetchPost(). + */ +FILE * +fetchPostURL(const char *URL, const char *flags) +{ + struct url *u; + FILE *f; + + if ((u = fetchParseURL(URL)) == NULL) + return (NULL); + + f = fetchPost(u, flags); + + fetchFreeURL(u); + return (f); +} + +/* * Attempt to parse the given URL; if successful, call fetchStat(). */ int Index: usr.bin/fetch/fetch.c =================================================================== --- usr.bin/fetch/fetch.c (revision 187089) +++ usr.bin/fetch/fetch.c (working copy) @@ -80,6 +80,9 @@ int U_flag; /* -U: do not use high ports */ int v_level = 1; /* -v: verbosity level */ int v_tty; /* stdout is a tty */ +int x_flag; /* -x: data to send via HTTP POST */ +char *x_data; /* data to send via HTTP POST */ + pid_t pgrp; /* our process group */ long w_secs; /* -w: retry delay */ int family = PF_UNSPEC; /* -[46]: address family to use */ @@ -382,6 +385,11 @@ strcat(flags, "d"); if (A_flag) strcat(flags, "A"); + if (x_flag) { + url->postdata = x_data; + strcat(flags, "x"); + } + timeout = T_secs ? T_secs : http_timeout; if (i_flag) { if (stat(i_filename, &sb)) { @@ -451,7 +459,11 @@ /* start the transfer */ if (timeout) alarm(timeout); - f = fetchXGet(url, &us, flags); + if (x_flag) { + f = fetchPost(url, flags); + } else { + f = fetchXGet(url, &us, flags); + } if (timeout) alarm(0); if (sigalrm || sigint) @@ -748,7 +760,7 @@ int c, e, r; while ((c = getopt(argc, argv, - "146AaB:bc:dFf:Hh:i:lMmN:nPpo:qRrS:sT:tUvw:")) != -1) + "146AaB:bc:dFf:Hh:i:lMmN:nPpo:qRrS:sT:tUvw:x:")) != -1) switch (c) { case '1': once_flag = 1; @@ -862,6 +874,10 @@ if (*optarg == '\0' || *end != '\0') errx(1, "invalid delay (%s)", optarg); break; + case 'x': + x_flag = 1; + x_data = optarg; + break; default: usage(); exit(1);