Till Bubeck
Kit Cosper
Kristof Depraetere
+ Alex deVries
Karl Eichwalder
Fred Fish
David Fox
noinst_HEADERS = \
acconfig.h build.h checksig.h ftp.h \
- install.h system.h url.h \
+ install.h system.h url.h http.h\
verify.h
-rpm_SOURCES = build.c checksig.c ftp.c install.c rpm.c url.c \
+rpm_SOURCES = build.c checksig.c ftp.c http.c install.c rpm.c url.c \
verify.c
rpm_LDADD = $(mylibs) @LIBMISC@
return 0;
}
-static int tcpConnect(const char *host, int port)
+int tcpConnect(const char *host, int port)
{
struct sockaddr_in sin;
int sock = -1;
return sock;
}
-int httpOpen(urlinfo *u)
-{
- int sock;
- const char *host;
- int port;
- char *buf;
- size_t len;
-
- if (u == NULL || ((host = u->host) == NULL))
- return FTPERR_BAD_HOSTNAME;
-
- if ((port = u->port) < 0) port = 80;
-
- if ((sock = tcpConnect(host, port)) < 0)
- return sock;
-
- len = strlen(u->path) + sizeof("GET \r\n");
- buf = alloca(len);
- strcpy(buf, "GET ");
- strcat(buf, u->path);
- strcat(buf, "\r\n");
-
- if (write(sock, buf, len) != len) {
- close(sock);
- return FTPERR_SERVER_IO_ERROR;
- }
-
-if (ftpDebug)
-fprintf(stderr, "-> %s", buf);
- return sock;
-}
-
int ftpOpen(urlinfo *u)
{
const char * host;
return 0;
}
-int httpGetFile(FD_t sfd, FD_t tfd) {
- return copyData(sfd, tfd);
-}
-
int ftpGetFile(FD_t sfd, FD_t tfd)
{
urlinfo *u;
int ftpGetFileDesc(FD_t);
int ftpAbort(FD_t fd);
int ftpClose(FD_t fd);
+int tcpConnect(const char *host, int port);
#endif
--- /dev/null
+/*
+ * This handles all HTTP transfers.
+ *
+ * Written by Alex deVries <puffin@redhat.com>
+ *
+ * To do:
+ * - better HTTP response code handling
+ * - HTTP proxy authentication
+ * - non-peek parsing of the header so that querying works
+ */
+
+
+#include <netinet/in.h>
+
+#include "system.h"
+#include "build/rpmbuild.h"
+#include "url.h"
+#include "ftp.h"
+#include "http.h"
+
+static int httpDebug = 0;
+
+int httpProxySetup(const char * url, urlinfo ** uret)
+{
+ urlinfo *u;
+
+ if (urlSplit(url, &u) < 0)
+ return -1;
+
+ if (!strcmp(u->service, "http")) {
+ char *newpath;
+ char *proxy;
+ char *proxyport;
+
+ rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"),
+ u->host,
+ u->user ? u->user : "ftp",
+ u->password ? u->password : "(username)");
+
+ if ((proxy = rpmGetVar(RPMVAR_HTTPPROXY)) != NULL) {
+ newpath = malloc(strlen((*uret)->host)+
+ strlen((*uret)->path) + 7 + 6 + 1 );
+
+ sprintf(newpath,"http://%s:%i%s",
+ (*uret)->host,(*uret)->port,(*uret)->path);
+ u->host = strdup(proxy);
+ free(u->path);
+ u->path = newpath;
+ }
+
+ if ((proxyport = rpmGetVar(RPMVAR_HTTPPORT)) != NULL) {
+ int port;
+ char *end;
+ port = strtol(proxyport, &end, 0);
+ if (*end) {
+ fprintf(stderr, _("error: httport must be a number\n"));
+ return -1;
+ }
+ u->port=port;
+ }
+ }
+
+ if (uret != NULL)
+ *uret = u;
+ return 0;
+}
+
+int httpOpen(urlinfo *u)
+{
+ int sock;
+ FILE * sockfile;
+ const char *host;
+ int port;
+ char *buf;
+ size_t len;
+
+ if (u == NULL || ((host = u->host) == NULL))
+ return HTTPERR_BAD_HOSTNAME;
+
+ if ((port = u->port) < 0) port = 80;
+
+ if ((sock = tcpConnect(host, port)) < 0)
+ return sock;
+
+ len = strlen(u->path) + sizeof("GET HTTP 1.0\r\n\r\n");
+ buf = alloca(len);
+ strcpy(buf, "GET ");
+ strcat(buf, u->path);
+ strcat(buf, " HTTP 1.0\r\n");
+ strcat(buf,"\r\n");
+
+ sockfile = fdopen(sock,"r+");
+
+ if (write(sock, buf, len) != len) {
+ close(sock);
+ return HTTPERR_SERVER_IO_ERROR;
+ }
+
+ if (httpDebug) fprintf(stderr, "-> %s", buf);
+
+ return sock;
+}
+
+#define httpTimeoutSecs 15
+#define BUFFER_SIZE 2048
+
+int httpSkipHeader(FD_t sfd, char *buf,int * bytesRead, char ** start) {
+
+ int doesContinue = 1;
+ int dataHere = 0;
+ char errorCode[4];
+ fd_set emptySet, readSet;
+ char * chptr ;
+ struct timeval timeout;
+ int rc = 0;
+ int bufLength = 0;
+
+ errorCode[0] = '\0';
+
+
+ do {
+ FD_ZERO(&emptySet);
+ FD_ZERO(&readSet);
+ FD_SET(sfd->fd_fd, &readSet);
+
+ timeout.tv_sec = httpTimeoutSecs;
+ timeout.tv_usec = 0;
+
+ rc = select(sfd->fd_fd+1, &readSet, &emptySet, &emptySet, &timeout);
+ if (rc < 1) {
+ if (rc==0)
+ return HTTPERR_BAD_SERVER_RESPONSE;
+ else
+ rc = HTTPERR_UNKNOWN;
+ } else
+ rc = 0;
+
+ *bytesRead = read(sfd->fd_fd, buf + bufLength,
+ *bytesRead - bufLength - 1);
+
+ bufLength += (*bytesRead);
+
+ buf[bufLength] = '\0';
+
+ /* divide the response into lines, checking each one to see if
+ we are finished or need to continue */
+
+ *start = chptr =buf;
+
+ if (!dataHere) {
+ do {
+ while (*chptr != '\n' && *chptr) chptr++;
+
+ if (*chptr == '\n') {
+ *chptr = '\0';
+ if (*(chptr - 1) == '\r') *(chptr - 1) = '\0';
+
+ if ((!strncmp(*start,"HTTP",4)) &&
+ (strchr(*start,' '))) {
+ *start = strchr(*start,' ')+1;
+ if (!strncmp(*start,"200",3)) {
+ doesContinue = 1;
+ }
+ } else {
+ if (**start == '\0') {
+ dataHere = 1;
+ }
+ }
+ *start = chptr + 1;
+ chptr++;
+ } else {
+ chptr++;
+ }
+ } while (chptr && !dataHere);
+ }
+ } while (doesContinue && !rc && !dataHere);
+ return 0;
+}
+
+int httpGetFile(FD_t sfd, FD_t tfd) {
+
+ static char buf[BUFFER_SIZE + 1];
+ int bufLength = 0;
+ int bytesRead = BUFFER_SIZE, rc = 0;
+ char * start;
+
+ httpSkipHeader(sfd,buf,&bytesRead,&start);
+
+ /* Write the buffer out to tfd */
+
+ if (write (tfd->fd_fd,start,bytesRead-(start-buf))<0) {
+ return HTTPERR_SERVER_IO_ERROR;
+ }
+
+ while (1) {
+ bytesRead = read(sfd->fd_fd, buf,
+ sizeof(buf)-1);
+ if (!bytesRead) return 0;
+ if (write (tfd->fd_fd,buf,bytesRead)<0) {
+ return HTTPERR_SERVER_IO_ERROR;
+ }
+ }
+ return 0;
+}
+
--- /dev/null
+#ifndef H_HTTP
+#define H_HTTP
+
+int httpProxySetup(const char * url, urlinfo ** uret);
+int httpCheckResponse(int fd, char ** str);
+int httpSkipHeader(FD_t sfd, char *buf,int * bytesRead, char ** start);
+
+
+
+#define HTTPERR_BAD_SERVER_RESPONSE -1
+#define HTTPERR_SERVER_IO_ERROR -2
+#define HTTPERR_SERVER_TIMEOUT -3
+#define HTTPERR_BAD_HOSTNAME -5
+/*
+#define FTPERR_BAD_HOST_ADDR -4
+#define FTPERR_FAILED_CONNECT -6
+#define FTPERR_FILE_IO_ERROR -7
+#define FTPERR_PASSIVE_ERROR -8
+#define FTPERR_FAILED_DATA_CONNECT -9
+#define FTPERR_FILE_NOT_FOUND -10
+#define FTPERR_NIC_ABORT_IN_PROGRESS -11
+*/
+#define HTTPERR_UNKNOWN -100
+
+#endif
strcpy(tfnbuf, "rpm-xfer.XXXXXX");
/* XXX watchout for rootdir = NULL */
tfn = rpmGetPath( (rootdir ? rootdir : ""),
- "%{_tmppath}", mktemp(tfnbuf), NULL);
+ "%{_tmppath}/", mktemp(tfnbuf), NULL);
}
rpmMessage(RPMMESS_DEBUG, _(" ... as %s\n"), tfn);
#define RPMVAR_MACROFILES 49
#define RPMVAR_GPG_PATH 51
#define RPMVAR_GPG_NAME 52
+#define RPMVAR_HTTPPROXY 53
+#define RPMVAR_HTTPPORT 54
-#define RPMVAR_NUM 53 /* number of RPMVAR entries */
+#define RPMVAR_NUM 55 /* number of RPMVAR entries */
#define xfree(_p) free((void *)_p)
const char *rpmGetPath(const char *path, ...);
static int force;
static char * ftpPort;
static char * ftpProxy;
+static char * httpPort;
+static char * httpProxy;
static int showHash;
static int help;
static int ignoreArch;
{ "ftpproxy", '\0', POPT_ARG_STRING, &ftpProxy, 0, NULL, NULL},
{ "hash", 'h', 0, &showHash, 0, NULL, NULL},
{ "help", '\0', 0, &help, 0, NULL, NULL},
+ { "httpport", '\0', POPT_ARG_STRING, &httpPort, 0, NULL, NULL},
+ { "httpproxy", '\0', POPT_ARG_STRING, &httpProxy, 0, NULL, NULL},
{ NULL, 'i', 0, 0, 'i', NULL, NULL},
{ "ignorearch", '\0', 0, &ignoreArch, 0, NULL, NULL},
{ "ignoreos", '\0', 0, &ignoreOs, 0, NULL, NULL},
puts(_(" [--rcfile <file>] [--ignorearch] [--dbpath <dir>]"));
puts(_(" [--prefix <dir>] [--ignoreos] [--nodeps] [--allfiles]"));
puts(_(" [--ftpproxy <host>] [--ftpport <port>] [--justdb]"));
+ puts(_(" [--httpproxy <host>] [--httpport <port>] "));
puts(_(" [--noorder] [--relocate oldpath=newpath]"));
puts(_(" [--badreloc] [--notriggers] [--excludepath <path>]"));
puts(_(" file1.rpm ... fileN.rpm"));
puts(_(" [--excludedocs] [--includedocs] [--rcfile <file>]"));
puts(_(" [--ignorearch] [--dbpath <dir>] [--prefix <dir>] "));
puts(_(" [--ftpproxy <host>] [--ftpport <port>]"));
+ puts(_(" [--httpproxy <host>] [--httpport <port>] "));
puts(_(" [--ignoreos] [--nodeps] [--allfiles] [--justdb]"));
puts(_(" [--noorder] [--relocate oldpath=newpath]"));
puts(_(" [--badreloc] [--excludepath <path>] file1.rpm ..."));
puts(_(" [--scripts] [--root <dir>] [--rcfile <file>]"));
puts(_(" [--whatprovides] [--whatrequires] [--requires]"));
puts(_(" [--triggeredby] [--ftpuseport] [--ftpproxy <host>]"));
+ puts(_(" [--httpproxy <host>] [--httpport <port>] "));
puts(_(" [--ftpport <port>] [--provides] [--triggers] [--dump]"));
puts(_(" [--changelog] [--dbpath <dir>] [targets]"));
puts(_(" rpm {--verify -V -y} [-afpg] [--root <dir>] [--rcfile <file>]"));
_("hostname or IP of ftp proxy"));
printHelpLine(_(" --ftpport <port> "),
_("port number of ftp server (or proxy)"));
+ printHelpLine(_(" --httpproxy <host> "),
+ _("hostname or IP of http proxy"));
+ printHelpLine(_(" --httpport <port> "),
+ _("port number of http server (or proxy)"));
puts( _(" Package specification options:"));
printHelpLine( " -a ",
_("query all packages"));
force = 0;
ftpProxy = NULL;
ftpPort = NULL;
+ httpProxy = NULL;
+ httpPort = NULL;
showHash = 0;
help = 0;
ignoreArch = 0;
argerror(_("ftp options can only be used during package queries, "
"installs, and upgrades"));
+ if ((httpProxy || httpPort) && !(bigMode == MODE_INSTALL ||
+ ((bigMode == MODE_QUERY && querySource == QUERY_RPM)) ||
+ ((bigMode == MODE_VERIFY && querySource == VERIFY_RPM))))
+ argerror(_("http options can only be used during package queries, "
+ "installs, and upgrades"));
+
if (oldPackage || (force && upgrade))
installFlags |= RPMINSTALL_UPGRADETOOLD;
rpmSetVar(RPMVAR_FTPPORT, ftpPort);
addMacro(&globalMacroContext, "_ftpport", NULL, ftpPort, RMIL_CMDLINE);
}
+ if (httpProxy) {
+ rpmSetVar(RPMVAR_HTTPPROXY, httpProxy);
+ addMacro(&globalMacroContext, "_httpproxy", NULL, httpProxy, RMIL_CMDLINE);
+ }
+ if (httpPort) {
+ rpmSetVar(RPMVAR_HTTPPORT, httpPort);
+ addMacro(&globalMacroContext, "_httpport", NULL, httpPort, RMIL_CMDLINE);
+ }
if (signIt) {
if (bigMode == MODE_REBUILD || bigMode == MODE_BUILD ||
#include "url.h"
#include "ftp.h"
+#include "http.h"
static struct urlstring {
const char *leadin;
break;
if ((fd = fdNew()) == NULL)
break;
+ httpProxySetup(url,&u);
fd->fd_url = u;
fd->fd_fd = httpOpen(u);
break;