4 * Author: Teemu Rantanen <tvr@cs.hut.fi>
5 * Copyright (c) 1992 Teemu Rantanen
8 * Created: Sun Apr 19 22:42:51 1992 tvr
9 * Last modified: Mon May 11 23:30:15 1992 tvr
14 #include <sys/types.h>
27 * Erwise's own ftp load function. Setup all things to be done
30 PUBLIC int HTFTP_open_file_read
33 HTParentAnchor *, anchor
39 * Set up a list of things to do
43 static void (*functions[]) () =
47 WWWErwiseFtpGetCommand, /* get junk */
50 WWWErwiseFtpUser, /* Send user */
53 WWWErwiseFtpGetCommand,
56 WWWErwiseFtpPass, /* send pass */
59 WWWErwiseFtpGetCommand,
62 WWWErwiseFtpBinary, /* set binary mode */
65 WWWErwiseFtpGetCommand,
68 WWWErwiseFtpPassive, /* set passive mode */
72 WWWErwiseFtpGetPassive, /* Get reply and request a file */
76 WWWErwiseFtpDataChannel, /* make connection */
79 WWWErwiseFtpCheckForError,/* check for file not found etc ... */
81 WWWErwiseSetSelect, /* read data */
84 WWWErwiseSetPoll, /* parse stuff */
85 WWWErwiseTerminateIfLoadToFile,
89 WWWErwiseConnection->function = functions;
93 * Set up information needed later
96 WWWErwiseConnection->ftphost = HTParse (name, "", PARSE_HOST);
98 WWWErwiseConnection->anAnchor = anchor;
101 * Start connecting to data port
104 status = cl_start_connection (WWWErwiseConnection->ftphost,
109 * FTP mode on formatting is PLAINTEXT
112 WWWErwiseConnection->diag = 1;
119 * Send misc commands to data flow
125 CL_DEBUG (("FTP: send user\n"));
127 WWWErwiseConnection->command = strdup ("USER ftp\r\n");
129 WWWErwiseConnection->function++;
135 char tmp[8192], hostname[1024];
137 CL_DEBUG (("FTP: send pass\n"));
139 if (!gethostname (hostname, 1024))
141 strcpy (hostname, "noname.rupu");
144 sprintf (tmp, "PASS erwise@%s\r\n", hostname);
146 WWWErwiseConnection->command = strdup (tmp);
148 WWWErwiseConnection->function++;
152 WWWErwiseFtpPassive ()
154 CL_DEBUG (("FTP: send pasv\n"));
156 WWWErwiseConnection->command = strdup ("PASV\r\n");
158 WWWErwiseConnection->function++;
162 WWWErwiseFtpBinary ()
164 CL_DEBUG (("FTP: set binary\n"));
166 WWWErwiseConnection->command = strdup ("TYPE I\r\n");
168 WWWErwiseConnection->function++;
173 * Get junk commands return when the are accomplished
176 #define ERWISE_BL_SIZE 8192
179 WWWErwiseFtpGetCommand ()
181 char tmp[ERWISE_BL_SIZE];
185 i = NETREAD (WWWErwiseConnection->fd, tmp, ERWISE_BL_SIZE);
187 if ((i == -1) && (errno == EWOULDBLOCK))
192 CL_DEBUG (("FTP: got %s\n", tmp));
194 if ((tmp[0] < '2') || (tmp[0] > '3'))
197 WWWErwiseStatus = CL_FAILED;
203 WWWErwiseConnection->function++;
207 * Get return code from passive command
211 WWWErwiseFtpGetPassive ()
219 i = NETREAD (WWWErwiseConnection->fd, tmp, 1024);
221 if ((i == -1) && (errno == EWOULDBLOCK))
228 CL_DEBUG (("FTP: got passive %s\n", tmp));
231 * Get to the line which is reply from PASV command.
232 * Check for errors on the way.
241 if ((*p >= '0') && (*p <= '9'))
243 if (!strncmp ("227", p, 3))
249 if ((p[0] < '2') || (tmp[0] > '3'))
251 WWWErwiseStatus = CL_FAILED;
259 while (*p && (*p != '\n'))
267 * no line but no errors yet
274 * Correct line, get port
277 while (*p && (*p != '('))
283 * 227 but no address / port ??
286 WWWErwiseStatus = CL_FAILED;
291 sscanf (p, "(%d,%d,%d,%d,%d,%d)", &a1, &a2, &a3, &a4, &p1, &p2);
293 port = p1 * 256 + p2;
295 printf ("ErwiseFTP: got connection to %d.%d.%d.%d on port %d\n",
296 a1, a2, a3, a4, port);
299 * send receive command too
303 char *filename = HTParse (WWWErwiseConnection->address, "",
304 PARSE_PATH + PARSE_PUNCTUATION);
306 sprintf (tmp, "RETR %s\r\n", filename);
308 WWWErwiseConnection->command = strdup (tmp);
311 WWWErwiseConnection->port = port;
313 WWWErwiseConnection->function++;
318 * Make data channel connection
321 WWWErwiseFtpDataChannel ()
324 * Set data flow port to secondary so that it can be closed properly
327 WWWErwiseConnection->secondary_fd = WWWErwiseConnection->fd;
329 cl_start_connection (WWWErwiseConnection->ftphost,
331 WWWErwiseConnection->port);
333 WWWErwiseConnection->function++;
339 * Start connection. Make sure it is nonblocking one.
343 cl_start_connection (host, connection, port)
345 ClConnection_t *connection;
349 * Code partly from get_connection()
354 struct hostent *phost; /* Pointer to host -- See netdb.h */
355 struct sockaddr_in soc_address; /* Binary network address */
356 struct sockaddr_in *sin = &soc_address;
360 sin->sin_family = AF_INET; /* Family, host order */
361 sin->sin_port = htons (port);
366 if (*host >= '0' && *host <= '9')
367 { /* Numeric node address: */
368 sin->sin_addr.s_addr = inet_addr (host); /* See arpa/inet.h */
372 { /* Alphanumeric node name: */
373 phost = gethostbyname (host); /* See netdb.h */
378 "FTP: Can't find internet node name `%s'.\n",
381 WWWErwiseStatus = CL_FAILED;
385 memcpy (&sin->sin_addr, phost->h_addr, phost->h_length);
390 "FTP: Parsed remote address as port %d, inet %d.%d.%d.%d\n",
391 (unsigned int) ntohs (sin->sin_port),
392 (int) *((unsigned char *) (&sin->sin_addr) + 0),
393 (int) *((unsigned char *) (&sin->sin_addr) + 1),
394 (int) *((unsigned char *) (&sin->sin_addr) + 2),
395 (int) *((unsigned char *) (&sin->sin_addr) + 3));
402 s = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
406 WWWErwiseStatus = CL_FAILED;
414 * Must NOT select connection now. Must poll.
416 connection->select_fd = 0;
418 (void) fcntl (s, F_SETFL, O_NONBLOCK);
419 (void) fcntl (s, F_SETFL, FNDELAY);
421 status = erwise_connect (s,
422 (struct sockaddr *) & soc_address,
423 sizeof (soc_address));
436 * Check for errors when retr is sent
440 WWWErwiseFtpCheckForError ()
449 fd = WWWErwiseConnection->fd;
450 fd2 = WWWErwiseConnection->secondary_fd;
452 tv.tv_sec = tv.tv_usec = 0;
455 FD_SET (fd, &readfds);
456 FD_SET (fd2, &readfds);
458 FD_ZERO (&exceptionfds);
459 FD_SET (fd, &exceptionfds);
460 FD_SET (fd2, &exceptionfds);
462 select ((fd > fd2 ? fd : fd2) + 1, &readfds, NULL, &exceptionfds, &tv);
465 * Error on either data or command channel
467 if (FD_ISSET (fd, &exceptionfds) || FD_ISSET (fd2, &exceptionfds))
470 WWWErwiseStatus = CL_FAILED;
476 * Data is flowing (OK)
478 if (FD_ISSET (fd, &readfds))
481 WWWErwiseConnection->function++;
487 * Anything here is considered an error
489 if (FD_ISSET (fd2, &readfds))
492 WWWErwiseStatus = CL_FAILED;