Repair http queries.
authorjbj <devnull@localhost>
Tue, 16 Feb 1999 02:14:19 +0000 (02:14 +0000)
committerjbj <devnull@localhost>
Tue, 16 Feb 1999 02:14:19 +0000 (02:14 +0000)
New function urlStrerror to fish out URL open failure codes.

CVS patchset: 2795
CVS date: 1999/02/16 02:14:19

Makefile.am
ftp.c
ftp.h
po/rpm.pot
url.c
url.h

index 204b89c..9637ac9 100644 (file)
@@ -33,11 +33,9 @@ pkglib_SCRIPTS = find-provides find-requires mkinstalldirs \
 
 noinst_HEADERS = \
        acconfig.h      build.h         checksig.h      ftp.h   \
-       install.h       system.h        url.h           http.h\
-       verify.h
+       install.h       system.h        url.h           verify.h
 
-rpm_SOURCES =          build.c checksig.c ftp.c http.c install.c rpm.c url.c \
-                       verify.c
+rpm_SOURCES =          build.c checksig.c ftp.c install.c rpm.c url.c verify.c
 rpm_LDADD =            $(mylibs) @LIBMISC@
 
 $(PROGRAMS):           $(mylibs) @LIBMISC@
diff --git a/ftp.c b/ftp.c
index 90ed584..01a0c90 100644 (file)
--- a/ftp.c
+++ b/ftp.c
@@ -51,19 +51,13 @@ int inet_aton(const char *cp, struct in_addr *inp);
 
 static int ftpDebug = 0;
 static int ftpTimeoutSecs = TIMEOUT_SECS;
+static int httpTimeoutSecs = TIMEOUT_SECS;
 
-#ifdef DYING
-static int ftpCheckResponse(urlinfo *u, char ** str);
-static int ftpCommand(urlinfo *u, char * command, ...);
-static int copyData(FD_t sfd, FD_t tfd);
-static int getHostAddress(const char * host, struct in_addr * address);
-#endif
-
-static int ftpCheckResponse(urlinfo *u, char ** str) {
+static int checkResponse(int fd, int secs, int *ecp, char ** str) {
     static char buf[BUFFER_SIZE + 1];
     int bufLength = 0; 
     fd_set emptySet, readSet;
-    char * chptr, * start;
+    char *se, *s;
     struct timeval timeout;
     int bytesRead, rc = 0;
     int doesContinue = 1;
@@ -72,62 +66,86 @@ static int ftpCheckResponse(urlinfo *u, char ** str) {
     errorCode[0] = '\0';
     
     do {
-       FD_ZERO(&emptySet);
-       FD_ZERO(&readSet);
-       FD_SET(u->ftpControl, &readSet);
-
-       timeout.tv_sec = ftpTimeoutSecs;
-       timeout.tv_usec = 0;
-    
-       rc = select(u->ftpControl + 1, &readSet, &emptySet, &emptySet, &timeout);
-       if (rc < 1) {
-           if (rc==0) 
-               return FTPERR_BAD_SERVER_RESPONSE;
-           else
-               rc = FTPERR_UNKNOWN;
-       } else
-           rc = 0;
-
-       bytesRead = read(u->ftpControl, buf + bufLength, sizeof(buf) - 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;
-
+       /*
+        * XXX In order to preserve both getFile and getFd methods with
+        * XXX HTTP, the response is read 1 char at a time with breaks on
+        * XXX newlines.
+        */
        do {
-           while (*chptr != '\n' && *chptr) chptr++;
-
-           if (*chptr == '\n') {
-               *chptr = '\0';
-               if (*(chptr - 1) == '\r') *(chptr - 1) = '\0';
-               if (str) *str = start;
+           FD_ZERO(&emptySet);
+           FD_ZERO(&readSet);
+           FD_SET(fd, &readSet);
 
-               if (errorCode[0]) {
-                   if (!strncmp(start, errorCode, 3) && start[3] == ' ')
-                       doesContinue = 0;
-               } else {
-                   strncpy(errorCode, start, 3);
-                   errorCode[3] = '\0';
-                   if (start[3] != '-') {
+           timeout.tv_sec = secs;
+           timeout.tv_usec = 0;
+    
+           rc = select(fd + 1, &readSet, &emptySet, &emptySet, &timeout);
+           if (rc < 1) {
+               if (rc == 0) 
+                   return FTPERR_BAD_SERVER_RESPONSE;
+               else
+                   rc = FTPERR_UNKNOWN;
+           } else
+               rc = 0;
+
+           s = buf + bufLength;
+           bytesRead = read(fd, s, 1);
+           bufLength += bytesRead;
+           buf[bufLength] = '\0';
+       } while (bufLength < sizeof(buf) && *s != '\n');
+
+       /*
+        * Divide the response into lines. Skip continuation lines.
+        */
+       s = se = buf;
+       while (*se != '\0') {
+               while (*se && *se != '\n') se++;
+
+               if (se > s && se[-1] == '\r')
+                  se[-1] = '\0';
+               if (*se == '\0')
+                       break;
+
+               /* HTTP header termination on empty line */
+               if (*s == '\0') {
                        doesContinue = 0;
-                   } 
+                       break;
+               }
+               *se++ = '\0';
+
+               /* HTTP: look for "HTTP/1.1 123 ..." */
+               if (!strncmp(s, "HTTP", 4)) {
+                       char *e;
+                       if ((e = strchr(s, ' ')) != NULL) {
+                           e++;
+                           if (strchr("0123456789", *e))
+                               strncpy(errorCode, e, 3);
+                           errorCode[3] = '\0';
+                       }
+                       s = se;
+                       continue;
                }
 
-               start = chptr + 1;
-               chptr++;
-           } else {
-               chptr++;
-           }
-       } while (*chptr);
+               /* FTP: look for "123-" and/or "123 " */
+               if (strchr("0123456789", *s)) {
+                       if (errorCode[0]) {
+                           if (!strncmp(s, errorCode, 3) && s[3] == ' ')
+                               doesContinue = 0;
+                       } else {
+                           strncpy(errorCode, s, 3);
+                           errorCode[3] = '\0';
+                           if (s[3] != '-') {
+                               doesContinue = 0;
+                           } 
+                       }
+               }
+               s = se;
+       }
 
-       if (doesContinue && chptr > start) {
-           memcpy(buf, start, chptr - start - 1);
-           bufLength = chptr - start - 1;
+       if (doesContinue && se > s) {
+           bufLength = se - s - 1;
+           if (s != buf)
+               memcpy(buf, s, bufLength);
        } else {
            bufLength = 0;
        }
@@ -136,18 +154,29 @@ static int ftpCheckResponse(urlinfo *u, char ** str) {
 if (ftpDebug)
 fprintf(stderr, "<- %s\n", buf);
 
-    if (*errorCode == '4' || *errorCode == '5') {
-       if (!strncmp(errorCode, "550", 3))
-           return FTPERR_FILE_NOT_FOUND;
-       if (!strncmp(errorCode, "552", 3))
-           return FTPERR_NIC_ABORT_IN_PROGRESS;
+    if (str)   *str = buf;
+    if (ecp)   *ecp = atoi(errorCode);
 
-       return FTPERR_BAD_SERVER_RESPONSE;
-    }
+    return rc;
+}
 
-    if (rc) return rc;
+static int ftpCheckResponse(urlinfo *u, char ** str) {
+    int ec = 0;
+    int rc =  checkResponse(u->ftpControl, ftpTimeoutSecs, &ec, str);
 
-    return 0;
+    switch (ec) {
+    case 550:
+       return FTPERR_FILE_NOT_FOUND;
+       break;
+    case 552:
+       return FTPERR_NIC_ABORT_IN_PROGRESS;
+       break;
+    default:
+       if (ec >= 400 && ec <= 599)
+           return FTPERR_BAD_SERVER_RESPONSE;
+       break;
+    }
+    return rc;
 }
 
 static int ftpCommand(urlinfo *u, char * command, ...) {
@@ -218,7 +247,7 @@ static int getHostAddress(const char * host, struct in_addr * address) {
     return 0;
 }
 
-int tcpConnect(const char *host, int port)
+static int tcpConnect(const char *host, int port)
 {
     struct sockaddr_in sin;
     int sock = -1;
@@ -254,6 +283,59 @@ 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;
+    const char *path;
+    int port;
+    char *buf;
+    size_t len;
+
+    if (u == NULL || ((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
+       return FTPERR_BAD_HOSTNAME;
+
+    if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = 80;
+
+    path = (u->proxyh || u->proxyp > 0) ? u->url : u->path;
+    if ((sock = tcpConnect(host, port)) < 0)
+       return sock;
+
+    len = strlen(path) + sizeof("GET  HTTP 1.0\r\n\r\n");
+    buf = alloca(len);
+    strcpy(buf, "GET ");
+    strcat(buf, path);
+    strcat(buf, " HTTP 1.0\r\n");
+    strcat(buf, "\r\n");
+
+    if (write(sock, buf, len) != len) {
+       close(sock);
+       return FTPERR_SERVER_IO_ERROR;
+    }
+
+if (ftpDebug)
+fprintf(stderr, "-> %s", buf);
+
+  { int ec = 0;
+    int rc;
+    rc = checkResponse(sock, httpTimeoutSecs, &ec, NULL);
+
+    switch (ec) {
+    default:
+       if (rc == 0 && ec != 200)       /* not HTTP_OK */
+           rc = FTPERR_FILE_NOT_FOUND;
+       break;
+    }
+
+    if (rc < 0) {
+       close(sock);
+       return rc;
+    }
+  }
+
+    return sock;
+}
+
 int ftpOpen(urlinfo *u)
 {
     const char * host;
@@ -262,12 +344,12 @@ int ftpOpen(urlinfo *u)
     int port;
     int rc;
 
-    if (u == NULL || ((host = u->host) == NULL))
+    if (u == NULL || ((host = (u->proxyh ? u->proxyh : u->host)) == NULL))
        return FTPERR_BAD_HOSTNAME;
 
-    if ((port = u->port) < 0) port = IPPORT_FTP;
+    if ((port = (u->proxyp > 0 ? u->proxyp : u->port)) < 0) port = IPPORT_FTP;
 
-    if ((user = u->user) == NULL)
+    if ((user = (u->proxyu ? u->proxyu : u->user)) == NULL)
        user = "anonymous";
 
     if ((password = u->password) == NULL) {
@@ -497,6 +579,10 @@ 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;
@@ -568,4 +654,4 @@ const char *ftpStrerror(int errorNumber) {
       return _("Unknown or unexpected error");
   }
 }
-  
+
diff --git a/ftp.h b/ftp.h
index afc3e5b..54eefe8 100644 (file)
--- a/ftp.h
+++ b/ftp.h
@@ -24,6 +24,5 @@ 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
index fd7c5c2..0d8fbe4 100644 (file)
@@ -7,7 +7,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 1999-02-04 17:21-0500\n"
+"POT-Creation-Date: 1999-02-15 21:09-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -204,55 +204,55 @@ msgstr ""
 msgid "rpmconvert 1.0 - converting database in /var/lib/rpm\n"
 msgstr ""
 
-#: ../ftp.c:531
+#: ../ftp.c:617
 msgid "Success"
 msgstr ""
 
-#: ../ftp.c:534
+#: ../ftp.c:620
 msgid "Bad server response"
 msgstr ""
 
-#: ../ftp.c:537
+#: ../ftp.c:623
 msgid "Server IO error"
 msgstr ""
 
-#: ../ftp.c:540
+#: ../ftp.c:626
 msgid "Server timeout"
 msgstr ""
 
-#: ../ftp.c:543
+#: ../ftp.c:629
 msgid "Unable to lookup server host address"
 msgstr ""
 
-#: ../ftp.c:546
+#: ../ftp.c:632
 msgid "Unable to lookup server host name"
 msgstr ""
 
-#: ../ftp.c:549
+#: ../ftp.c:635
 msgid "Failed to connect to server"
 msgstr ""
 
-#: ../ftp.c:552
+#: ../ftp.c:638
 msgid "Failed to establish data connection to server"
 msgstr ""
 
-#: ../ftp.c:555
+#: ../ftp.c:641
 msgid "IO error to local file"
 msgstr ""
 
-#: ../ftp.c:558
+#: ../ftp.c:644
 msgid "Error setting remote server to passive mode"
 msgstr ""
 
-#: ../ftp.c:561
+#: ../ftp.c:647
 msgid "File not found on server"
 msgstr ""
 
-#: ../ftp.c:564
+#: ../ftp.c:650
 msgid "Abort in progress"
 msgstr ""
 
-#: ../ftp.c:568
+#: ../ftp.c:654
 msgid "Unknown or unexpected error"
 msgstr ""
 
@@ -1422,30 +1422,31 @@ msgstr ""
 msgid "error reading header from package\n"
 msgstr ""
 
-#: ../url.c:105
+#: ../url.c:118
 #, c-format
 msgid "Password for %s@%s: "
 msgstr ""
 
-#: ../url.c:169
+#: ../url.c:136 ../url.c:158
+#, c-format
+msgid "error: %sport must be a number\n"
+msgstr ""
+
+#: ../url.c:227
 msgid "url port must be a number\n"
 msgstr ""
 
-#: ../url.c:207
+#: ../url.c:263
 #, c-format
 msgid "logging into %s as %s, pw %s\n"
 msgstr ""
 
-#: ../url.c:230
-msgid "error: ftpport must be a number\n"
-msgstr ""
-
-#: ../lib/rpmdb.c:168 ../url.c:335
+#: ../lib/rpmdb.c:168 ../url.c:370
 #, c-format
 msgid "failed to open %s\n"
 msgstr ""
 
-#: ../url.c:350
+#: ../url.c:385
 #, c-format
 msgid "failed to create %s\n"
 msgstr ""
@@ -1568,7 +1569,7 @@ msgid "TIMECHECK failure: %s\n"
 msgstr ""
 
 #: ../build/files.c:291 ../build/files.c:303 ../build/files.c:372
-#: ../build/files.c:384 ../build/files.c:410
+#: ../build/files.c:384 ../build/files.c:415
 #, c-format
 msgid "Bad %s() syntax: %s"
 msgstr ""
@@ -1582,152 +1583,152 @@ msgstr ""
 msgid "No files after %%defattr(): %s"
 msgstr ""
 
-#: ../build/files.c:420
+#: ../build/files.c:425
 #, c-format
 msgid "Bad %s() mode spec: %s"
 msgstr ""
 
-#: ../build/files.c:432
+#: ../build/files.c:437
 #, c-format
 msgid "Bad %s() dirmode spec: %s"
 msgstr ""
 
-#: ../build/files.c:483
+#: ../build/files.c:488
 msgid "Bad %%config() syntax: %s"
 msgstr ""
 
-#: ../build/files.c:501
+#: ../build/files.c:506
 msgid "Invalid %%config token: %s"
 msgstr ""
 
-#: ../build/files.c:524 ../build/files.c:536 ../build/files.c:549
+#: ../build/files.c:529 ../build/files.c:541 ../build/files.c:554
 msgid "Bad %%lang() syntax: %s"
 msgstr ""
 
-#: ../build/files.c:555
+#: ../build/files.c:560
 msgid "%%lang() entries are 2 characters: %s"
 msgstr ""
 
-#: ../build/files.c:561
+#: ../build/files.c:566
 msgid "Only one entry in %%lang(): %s"
 msgstr ""
 
-#: ../build/files.c:643
+#: ../build/files.c:648
 msgid "Hit limit for %%docdir"
 msgstr ""
 
-#: ../build/files.c:649
+#: ../build/files.c:654
 msgid "Only one arg for %%docdir"
 msgstr ""
 
 #. We already got a file -- error
-#: ../build/files.c:674
+#: ../build/files.c:679
 #, c-format
 msgid "Two files on one line: %s"
 msgstr ""
 
-#: ../build/files.c:687
+#: ../build/files.c:692
 #, c-format
 msgid "File must begin with \"/\": %s"
 msgstr ""
 
-#: ../build/files.c:699
+#: ../build/files.c:704
 msgid "Can't mix special %%doc with other forms: %s"
 msgstr ""
 
-#: ../build/files.c:787
+#: ../build/files.c:792
 #, c-format
 msgid "File listed twice: %s"
 msgstr ""
 
-#: ../build/files.c:939
+#: ../build/files.c:944
 #, c-format
 msgid "File doesn't match prefix (%s): %s"
 msgstr ""
 
-#: ../build/files.c:949 ../build/files.c:1068
+#: ../build/files.c:954 ../build/files.c:1069
 #, c-format
 msgid "File not found: %s"
 msgstr ""
 
-#: ../build/files.c:996
+#: ../build/files.c:997
 #, c-format
 msgid "Bad owner/group: %s\n"
 msgstr ""
 
-#: ../build/files.c:1002
+#: ../build/files.c:1003
 #, c-format
 msgid "File %4d: 0%o %s.%s\t %s\n"
 msgstr ""
 
-#: ../build/files.c:1052
+#: ../build/files.c:1053
 #, c-format
 msgid "File needs leading \"/\": %s"
 msgstr ""
 
-#: ../build/files.c:1109
+#: ../build/files.c:1110
 msgid "Could not open %%files file: %s"
 msgstr ""
 
-#: ../build/files.c:1116 ../build/pack.c:448
+#: ../build/files.c:1117 ../build/pack.c:448
 #, c-format
 msgid "line: %s"
 msgstr ""
 
-#: ../build/files.c:1384 ../build/parsePrep.c:40
+#: ../build/files.c:1385 ../build/parsePrep.c:40
 #, c-format
 msgid "Bad owner/group: %s"
 msgstr ""
 
-#: ../build/files.c:1438
+#: ../build/files.c:1439
 #, c-format
 msgid "Couldn't exec %s"
 msgstr ""
 
-#: ../build/files.c:1442
+#: ../build/files.c:1443
 #, c-format
 msgid "Couldn't fork %s"
 msgstr ""
 
-#: ../build/files.c:1492
+#: ../build/files.c:1493
 #, c-format
 msgid "%s failed"
 msgstr ""
 
-#: ../build/files.c:1496
+#: ../build/files.c:1497
 #, c-format
 msgid "failed to write all data to %s"
 msgstr ""
 
-#: ../build/files.c:1530
+#: ../build/files.c:1531
 msgid "Finding provides...\n"
 msgstr ""
 
-#: ../build/files.c:1537
+#: ../build/files.c:1538
 msgid "Failed to find provides"
 msgstr ""
 
-#: ../build/files.c:1556
+#: ../build/files.c:1557
 msgid "Finding requires...\n"
 msgstr ""
 
-#: ../build/files.c:1563
+#: ../build/files.c:1564
 msgid "Failed to find requires"
 msgstr ""
 
-#: ../build/files.c:1597
+#: ../build/files.c:1598
 msgid "Provides:"
 msgstr ""
 
-#: ../build/files.c:1612
+#: ../build/files.c:1613
 msgid "Prereqs:"
 msgstr ""
 
-#: ../build/files.c:1624
+#: ../build/files.c:1625
 msgid "Requires:"
 msgstr ""
 
-#: ../build/files.c:1648
+#: ../build/files.c:1649
 #, c-format
 msgid "Processing files: %s\n"
 msgstr ""
@@ -1903,113 +1904,113 @@ msgstr ""
 msgid "line %d: Second %%files list"
 msgstr ""
 
-#: ../build/parsePreamble.c:156
+#: ../build/parsePreamble.c:157
 #, c-format
 msgid "Architecture is excluded: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:161
+#: ../build/parsePreamble.c:162
 #, c-format
 msgid "Architecture is not included: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:166
+#: ../build/parsePreamble.c:167
 #, c-format
 msgid "OS is excluded: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:171
+#: ../build/parsePreamble.c:172
 #, c-format
 msgid "OS is not included: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:207
+#: ../build/parsePreamble.c:208
 #, c-format
 msgid "%s field must be present in package: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:229
+#: ../build/parsePreamble.c:230
 #, c-format
 msgid "Duplicate %s entries in package: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:274
+#: ../build/parsePreamble.c:275
 #, c-format
 msgid "Unable to stat icon: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:285
+#: ../build/parsePreamble.c:286
 #, c-format
 msgid "Unable to read icon: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:295
+#: ../build/parsePreamble.c:296
 #, c-format
 msgid "Unknown icon type: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:330
+#: ../build/parsePreamble.c:331
 #, c-format
 msgid "line %d: Malformed tag: %s"
 msgstr ""
 
 #. Empty field
-#: ../build/parsePreamble.c:338
+#: ../build/parsePreamble.c:339
 #, c-format
 msgid "line %d: Empty tag: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:361 ../build/parsePreamble.c:368
+#: ../build/parsePreamble.c:362 ../build/parsePreamble.c:369
 #, c-format
 msgid "line %d: Illegal char '-' in %s: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:399
+#: ../build/parsePreamble.c:400
 #, c-format
 msgid "line %d: BuildRoot can not be \"/\": %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:412
+#: ../build/parsePreamble.c:413
 #, c-format
 msgid "line %d: Prefixes must not end with \"/\": %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:424
+#: ../build/parsePreamble.c:425
 #, c-format
 msgid "line %d: Docdir must begin with '/': %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:435
+#: ../build/parsePreamble.c:436
 #, c-format
 msgid "line %d: Epoch/Serial field must be a number: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:500
+#: ../build/parsePreamble.c:501
 #, c-format
 msgid "line %d: Bad BuildArchitecture format: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:510
+#: ../build/parsePreamble.c:511
 #, c-format
 msgid "Internal error: Bogus tag %d"
 msgstr ""
 
-#: ../build/parsePreamble.c:655
+#: ../build/parsePreamble.c:656
 #, c-format
 msgid "Bad package specification: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:661
+#: ../build/parsePreamble.c:662
 #, c-format
 msgid "Package already exists: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:688
+#: ../build/parsePreamble.c:689
 #, c-format
 msgid "line %d: Unknown tag: %s"
 msgstr ""
 
-#: ../build/parsePreamble.c:713
+#: ../build/parsePreamble.c:714
 msgid "Spec file can't use BuildRoot"
 msgstr ""
 
@@ -2233,31 +2234,31 @@ msgstr ""
 msgid "error removing record %s into %s"
 msgstr ""
 
-#: ../lib/depends.c:371 ../lib/depends.c:530
+#: ../lib/depends.c:372 ../lib/depends.c:531
 #, c-format
 msgid "cannot read header at %d for dependency check"
 msgstr ""
 
-#: ../lib/depends.c:436
+#: ../lib/depends.c:437
 #, c-format
 msgid "dependencies: looking for %s\n"
 msgstr ""
 
-#: ../lib/depends.c:623
+#: ../lib/depends.c:624
 #, c-format
 msgid "package %s require not satisfied: %s\n"
 msgstr ""
 
-#: ../lib/depends.c:666
+#: ../lib/depends.c:667
 #, c-format
 msgid "package %s conflicts: %s\n"
 msgstr ""
 
-#: ../lib/depends.c:766
+#: ../lib/depends.c:767
 msgid "dbrecMatchesDepFlags() failed to read header"
 msgstr ""
 
-#: ../lib/depends.c:818
+#: ../lib/depends.c:819
 #, c-format
 msgid "loop in prerequisite chain: %s"
 msgstr ""
@@ -3136,17 +3137,17 @@ msgstr ""
 msgid "Invalid signature spec in rc file"
 msgstr ""
 
-#: ../lib/transaction.c:570
+#: ../lib/transaction.c:576
 #, c-format
 msgid "relocating %s to %s\n"
 msgstr ""
 
-#: ../lib/transaction.c:576
+#: ../lib/transaction.c:582
 #, c-format
 msgid "excluding %s\n"
 msgstr ""
 
-#: ../lib/transaction.c:663
+#: ../lib/transaction.c:669
 #, c-format
 msgid "%s skipped due to missingok flag\n"
 msgstr ""
diff --git a/url.c b/url.c
index 92a6964..32d4089 100644 (file)
--- a/url.c
+++ b/url.c
@@ -6,7 +6,6 @@
 
 #include "url.h"
 #include "ftp.h"
-#include "http.h"
 
 static struct urlstring {
     const char *leadin;
@@ -23,12 +22,15 @@ void freeUrlinfo(urlinfo *u)
 {
     if (u->ftpControl >= 0)
        close(u->ftpControl);
+    FREE(u->url);
     FREE(u->service);
     FREE(u->user);
     FREE(u->password);
     FREE(u->host);
     FREE(u->portstr);
     FREE(u->path);
+    FREE(u->proxyu);
+    FREE(u->proxyh);
 
     FREE(u);
 }
@@ -39,8 +41,10 @@ urlinfo *newUrlinfo(void)
     if ((u = malloc(sizeof(*u))) == NULL)
        return NULL;
     memset(u, 0, sizeof(*u));
+    u->proxyp = -1;
     u->port = -1;
     u->ftpControl = -1;
+    u->ftpGetFileDoneNeeded = 0;
     return u;
 }
 
@@ -89,15 +93,24 @@ static void findUrlinfo(urlinfo **uret, int mustAsk)
        }
        *empty = u;
     } else {
+       /* Swap original url and path into the cached structure */
        const char *up = uCache[i]->path;
        uCache[i]->path = u->path;
        u->path = up;
+       up = uCache[i]->url;
+       uCache[i]->url = u->url;
+       u->url = up;
        freeUrlinfo(u);
     }
 
+    /* This URL is now cached. */
     *uret = u = uCache[i];
 
+    /* Perform one-time FTP initialization */
     if (!strcmp(u->service, "ftp")) {
+       char *proxy;
+       char *proxyport;
+
        if (mustAsk || (u->user != NULL && u->password == NULL)) {
            char * prompt;
            FREE(u->password);
@@ -105,7 +118,51 @@ static void findUrlinfo(urlinfo **uret, int mustAsk)
            sprintf(prompt, _("Password for %s@%s: "), u->user, u->host);
            u->password = strdup(getpass(prompt));
        }
+
+       if (u->proxyh == NULL && (proxy = rpmGetVar(RPMVAR_FTPPROXY)) != NULL) {
+           char *nu = malloc(strlen(u->user) + strlen(u->host) + sizeof("@"));
+           strcpy(nu, u->user);
+           strcat(nu, "@");
+           strcat(nu, u->host);
+           u->proxyu = nu;
+           u->proxyh = strdup(proxy);
+       }
+
+       if (u->proxyp < 0 && (proxyport = rpmGetVar(RPMVAR_FTPPORT)) != NULL) {
+           int port;
+           char *end;
+           port = strtol(proxyport, &end, 0);
+           if (*end) {
+               fprintf(stderr, _("error: %sport must be a number\n"),
+                       u->service);
+               return;
+           }
+           u->proxyp = port;
+       }
+    }
+
+    /* Perform one-time HTTP initialization */
+    if (!strcmp(u->service, "http")) {
+       char *proxy;
+       char *proxyport;
+
+       if (u->proxyh == NULL && (proxy = rpmGetVar(RPMVAR_HTTPPROXY)) != NULL) {
+           u->proxyh = strdup(proxy);
+       }
+
+       if (u->proxyp < 0 && (proxyport = rpmGetVar(RPMVAR_HTTPPORT)) != NULL) {
+           int port;
+           char *end;
+           port = strtol(proxyport, &end, 0);
+           if (*end) {
+               fprintf(stderr, _("error: %sport must be a number\n"),
+                       u->service);
+               return;
+           }
+           u->proxyp = port;
+       }
     }
+
     return;
 }
 
@@ -124,6 +181,7 @@ int urlSplit(const char * url, urlinfo **uret)
        freeUrlinfo(u);
        return -1;
     }
+    u->url = strdup(url);
     do {
        while (*se && *se != '/') se++;
        if (*se == '\0') {
@@ -201,42 +259,18 @@ static int urlConnect(const char * url, urlinfo ** uret)
        return -1;
 
     if (!strcmp(u->service, "ftp") && u->ftpControl < 0) {
-       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)");
 
-       /* XXX FIXME: this doesn't work with urlinfo caching */
-       if ((proxy = rpmGetVar(RPMVAR_FTPPROXY)) != NULL) {
-           char *nu = malloc(strlen(u->user) + strlen(u->host) + sizeof("@"));
-           strcpy(nu, u->user);
-           strcat(nu, "@");
-           strcat(nu, u->host);
-           free((void *)u->user);
-           u->user = nu;
-           free((void *)u->host);
-           u->host = strdup(proxy);
-       }
-
-       /* XXX FIXME: this doesn't work with urlinfo caching */
-       if ((proxyport = rpmGetVar(RPMVAR_FTPPORT)) != NULL) {
-           int port;
-           char *end;
-           port = strtol(proxyport, &end, 0);
-           if (*end) {
-               fprintf(stderr, _("error: ftpport must be a number\n"));
-               return -1;
-           }
-           u->port = port;
-       }
-
        u->ftpControl = ftpOpen(u);
 
-       if (u->ftpControl < 0)
+       if (u->ftpControl < 0) {        /* XXX save ftpOpen error */
+           u->openError = u->ftpControl;
            return u->ftpControl;
+       }
 
     }
 
@@ -300,10 +334,10 @@ FD_t ufdOpen(const char *url, int flags, mode_t mode)
            break;
        if ((fd = fdNew()) == NULL)
            break;
-        if (httpProxySetup(url,&u)) 
-           break;
        fd->fd_url = u;
        fd->fd_fd = httpOpen(u);
+       if (fd->fd_fd < 0)              /* XXX Save httpOpen error */
+           u->openError = fd->fd_fd;
        break;
     case URL_IS_PATH:
        if (urlSplit(url, &u))
@@ -381,3 +415,12 @@ int urlGetFile(const char * url, const char * dest) {
 
     return rc;
 }
+
+/* XXX This only works for httpOpen/ftpOpen failures */
+const char *urlStrerror(const char *url)
+{
+    urlinfo *u;
+    if (urlSplit(url, &u))
+       return "Malformed URL";
+    return ftpStrerror(u->openError);
+}
diff --git a/url.h b/url.h
index 9d5b6ad..07a803f 100644 (file)
--- a/url.h
+++ b/url.h
@@ -10,15 +10,20 @@ typedef enum {
 } urltype;
 
 typedef struct urlinfo {
+    const char *url;           /* copy of original url */
     const char *service;
     const char *user;
     const char *password;
     const char *host;
     const char *portstr;
     const char *path;
+    const char *proxyu;                /* FTP: proxy user */
+    const char *proxyh;                /* FTP/HTTP: proxy host */
+    int proxyp;                        /* FTP/HTTP: proxy port */
     int        port;
     int ftpControl;
     int ftpGetFileDoneNeeded;
+    int openError;             /* Type of open failure */
 } urlinfo;
 
 #ifndef        IPPORT_HTTP
@@ -36,6 +41,7 @@ void  freeUrlinfo(urlinfo *u);
 
 FD_t   ufdOpen(const char * pathname, int flags, mode_t mode);
 int    ufdClose(FD_t fd);
+const char *urlStrerror(const char *url);
 
 int    urlGetFile(const char * url, const char * dest);