Finally, preliminary http support.
authoradevries <devnull@localhost>
Thu, 4 Feb 1999 18:48:03 +0000 (18:48 +0000)
committeradevries <devnull@localhost>
Thu, 4 Feb 1999 18:48:03 +0000 (18:48 +0000)
- Alex

CVS patchset: 2773
CVS date: 1999/02/04 18:48:03

CREDITS
Makefile.am
ftp.c
ftp.h
http.c [new file with mode: 0644]
http.h [new file with mode: 0644]
install.c
lib/rpmlib.h
rpm.c
url.c

diff --git a/CREDITS b/CREDITS
index b79312e..97779b3 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -12,6 +12,7 @@ Significant code, ideas, or porting help have been contributed by:
        Till Bubeck
        Kit Cosper
        Kristof Depraetere
+        Alex deVries
        Karl Eichwalder
        Fred Fish
        David Fox
index 548d527..204b89c 100644 (file)
@@ -33,10 +33,10 @@ pkglib_SCRIPTS = find-provides find-requires mkinstalldirs \
 
 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@
 
diff --git a/ftp.c b/ftp.c
index 41185bb..90ed584 100644 (file)
--- a/ftp.c
+++ b/ftp.c
@@ -218,7 +218,7 @@ static int getHostAddress(const char * host, struct in_addr * address) {
     return 0;
 }
 
-static int tcpConnect(const char *host, int port)
+int tcpConnect(const char *host, int port)
 {
     struct sockaddr_in sin;
     int sock = -1;
@@ -254,38 +254,6 @@ fprintf(stderr,"++ connect %s:%d on fd %d\n", inet_ntoa(sin.sin_addr), ntohs(sin
     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;
@@ -529,10 +497,6 @@ fprintf(stderr, "-> %s", retrCommand);
     return 0;
 }
 
-int httpGetFile(FD_t sfd, FD_t tfd) {
-    return copyData(sfd, tfd);
-}
-
 int ftpGetFile(FD_t sfd, FD_t tfd)
 {
     urlinfo *u;
diff --git a/ftp.h b/ftp.h
index 54eefe8..afc3e5b 100644 (file)
--- a/ftp.h
+++ b/ftp.h
@@ -24,5 +24,6 @@ int   ftpGetFile(FD_t sfd, FD_t tfd);
 int    ftpGetFileDesc(FD_t);
 int    ftpAbort(FD_t fd);
 int    ftpClose(FD_t fd);
+int tcpConnect(const char *host, int port);
 
 #endif
diff --git a/http.c b/http.c
new file mode 100644 (file)
index 0000000..6b5c9ef
--- /dev/null
+++ b/http.c
@@ -0,0 +1,205 @@
+/* 
+ * 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;
+}
+
diff --git a/http.h b/http.h
new file mode 100644 (file)
index 0000000..bfe3b63
--- /dev/null
+++ b/http.h
@@ -0,0 +1,25 @@
+#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
index 0081ddb..0266133 100644 (file)
--- a/install.c
+++ b/install.c
@@ -141,7 +141,7 @@ int doInstall(const char * rootdir, const char ** argv, int installFlags,
                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);
index 5cba1f1..6f29582 100644 (file)
@@ -251,8 +251,10 @@ extern const struct headerSprintfExtension rpmHeaderFormats[];
 #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, ...);
diff --git a/rpm.c b/rpm.c
index 3e64c83..bff389c 100755 (executable)
--- a/rpm.c
+++ b/rpm.c
@@ -36,6 +36,8 @@ static int excldocs;
 static int force;
 static char * ftpPort;
 static char * ftpProxy;
+static char * httpPort;
+static char * httpProxy;
 static int showHash;
 static int help;
 static int ignoreArch;
@@ -89,6 +91,8 @@ static struct poptOption optionsTable[] = {
  { "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},
@@ -179,6 +183,7 @@ static void printUsage(void) {
     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"));
@@ -187,6 +192,7 @@ static void printUsage(void) {
     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 ..."));
@@ -195,6 +201,7 @@ static void printUsage(void) {
     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>]"));
@@ -277,6 +284,10 @@ static void printHelp(void) {
                  _("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"));
@@ -517,6 +528,8 @@ int main(int argc, char ** argv) {
     force = 0;
     ftpProxy = NULL;
     ftpPort = NULL;
+    httpProxy = NULL;
+    httpPort = NULL;
     showHash = 0;
     help = 0;
     ignoreArch = 0;
@@ -1042,6 +1055,12 @@ int main(int argc, char ** argv) {
        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;
 
@@ -1063,6 +1082,14 @@ int main(int argc, char ** argv) {
        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 ||
diff --git a/url.c b/url.c
index ed28c3e..817bbe3 100644 (file)
--- a/url.c
+++ b/url.c
@@ -6,6 +6,7 @@
 
 #include "url.h"
 #include "ftp.h"
+#include "http.h"
 
 static struct urlstring {
     const char *leadin;
@@ -299,6 +300,7 @@ FD_t ufdOpen(const char *url, int flags, mode_t mode)
            break;
        if ((fd = fdNew()) == NULL)
            break;
+        httpProxySetup(url,&u);
        fd->fd_url = u;
        fd->fd_fd = httpOpen(u);
        break;