summaryrefslogtreecommitdiff
path: root/ftp.c
diff options
context:
space:
mode:
authorjbj <devnull@localhost>1999-02-16 02:14:19 +0000
committerjbj <devnull@localhost>1999-02-16 02:14:19 +0000
commit81f17dd94b4528af653c7bf76a10266c1e8d081e (patch)
tree1b3a8facc5b7abc582410476726ece3772e7b23d /ftp.c
parent6d0e3c455d9d8dd917429277d774c43bffd37c55 (diff)
downloadrpm-81f17dd94b4528af653c7bf76a10266c1e8d081e.tar.gz
rpm-81f17dd94b4528af653c7bf76a10266c1e8d081e.tar.bz2
rpm-81f17dd94b4528af653c7bf76a10266c1e8d081e.zip
Repair http queries.
New function urlStrerror to fish out URL open failure codes. CVS patchset: 2795 CVS date: 1999/02/16 02:14:19
Diffstat (limited to 'ftp.c')
-rw-r--r--ftp.c232
1 files changed, 159 insertions, 73 deletions
diff --git a/ftp.c b/ftp.c
index 90ed58402..01a0c909d 100644
--- 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");
}
}
-
+