ReactOS  0.4.14-dev-608-gd495a4f
open.c
Go to the documentation of this file.
1 /* open.c
2  *
3  * Copyright (c) 1996-2001 Mike Gleason, NCEMRSoft.
4  * All rights reserved.
5  *
6  */
7 
8 #include "syshdrs.h"
9 
10 static void
12 {
13  /* Requires the cip->bufSize field set,
14  * and the cip->buf set if the
15  * buffer is allocated.
16  */
17  if (cip->buf != NULL) {
18  (void) memset(cip->buf, 0, cip->bufSize);
19  free(cip->buf);
20  cip->buf = NULL;
21  }
22 
23  if (cip->startingWorkingDirectory != NULL) {
26  }
27 
28 #if USE_SIO
30 #endif
32 } /* FTPDeallocateHost */
33 
34 
35 
36 
37 
38 static int
40 {
41  char *buf;
42 
43  /* Requires the cip->bufSize field set,
44  * and the cip->buf cleared if the
45  * buffer is not allocated.
46  */
47  if (cip->buf == NULL) {
48  buf = (char *) calloc((size_t) 1, cip->bufSize);
49  if (buf == NULL) {
50  Error(cip, kDontPerror, "Malloc failed.\n");
51  cip->errNo = kErrMallocFailed;
52  return (kErrMallocFailed);
53  }
54  cip->buf = buf;
55  }
56  return (kNoErr);
57 } /* FTPAllocateHost */
58 
59 
60 
61 
62 void
64 {
65  if (lip == NULL)
66  return;
67  if (strcmp(lip->magic, kLibraryMagic))
68  return;
69 
70  if (lip->htried == 0) {
71  (void) memset(lip->ourHostName, 0, sizeof(lip->ourHostName));
72  lip->hresult = GetOurHostName(lip->ourHostName, sizeof(lip->ourHostName));
73  }
74  lip->htried++;
75 } /* FTPInitializeOurHostName */
76 
77 
78 
79 
80 void
82 {
83  if (lip == NULL)
84  return;
85  if (strcmp(lip->magic, kLibraryMagic))
86  return;
87 
89 
90  if (lip->defaultAnonPassword[0] == '\0') {
91 #ifdef SPAM_PROBLEM_HAS_BEEN_SOLVED_FOREVER
93  (void) STRNCAT(lip->defaultAnonPassword, "@");
94 
95  /* Default to the "user@" notation
96  * supported by NcFTPd and wu-ftpd.
97  */
98  if (lip->htried > 0)
100 #else
101  (void) STRNCPY(lip->defaultAnonPassword, "NcFTP@");
102 #endif
103  }
104 } /* FTPInitializeAnonPassword */
105 
106 
107 
108 
109 int
111 {
112  ResponsePtr rp;
113  int result = kErrLoginFailed;
114  int anonLogin;
115  int sentpass = 0;
116  int fwloggedin;
117  int firstTime;
118  char cwd[512];
119 
120  if (cip == NULL)
121  return (kErrBadParameter);
123  return (kErrBadParameter);
124 
125  if (strcmp(cip->magic, kLibraryMagic))
126  return (kErrBadMagic);
127 
128  anonLogin = 0;
129  if (cip->user[0] == '\0')
130  (void) STRNCPY(cip->user, "anonymous");
131  if ((strcmp(cip->user, "anonymous") == 0) || (strcmp(cip->user, "ftp") == 0)) {
132  anonLogin = 1;
133  /* Try to get the email address if you didn't specify
134  * a password when the user is anonymous.
135  */
136  if (cip->pass[0] == '\0') {
138  (void) STRNCPY(cip->pass, cip->lip->defaultAnonPassword);
139  }
140  }
141 
142  rp = InitResponse();
143  if (rp == NULL) {
145  cip->errNo = kErrMallocFailed;
146  goto done2;
147  }
148 
149  for (firstTime = 1, fwloggedin = 0; ; ) {
150  /* Here's a mini finite-automaton for the login process.
151  *
152  * Originally, the FTP protocol was designed to be entirely
153  * implementable from a FA. It could be done, but I don't think
154  * it's something an interactive process could be the most
155  * effective with.
156  */
157 
158  if (firstTime != 0) {
159  rp->code = 220;
160  firstTime = 0;
161  } else if (result < 0) {
162  goto done;
163  }
164 
165  switch (rp->code) {
166  case 220: /* Welcome, ready for new user. */
167  if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) {
168  ReInitResponse(cip, rp);
169  result = RCmd(cip, rp, "USER %s", cip->user);
170  } else if (cip->firewallType == kFirewallUserAtSite) {
171  ReInitResponse(cip, rp);
172  result = RCmd(cip, rp, "USER %s@%s", cip->user, cip->host);
173  } else if (cip->firewallType == kFirewallUserAtUserPassAtPass) {
174  ReInitResponse(cip, rp);
175  result = RCmd(cip, rp, "USER %s@%s@%s", cip->user, cip->firewallUser, cip->host);
176  } else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) {
177  ReInitResponse(cip, rp);
178  result = RCmd(cip, rp, "USER %s@%s %s", cip->user, cip->host, cip->firewallUser);
179  } else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) {
180  /* only reached when !fwloggedin */
181  ReInitResponse(cip, rp);
182  result = RCmd(cip, rp, "USER %s@%s", cip->firewallUser, cip->host);
183  } else if (cip->firewallType > kFirewallNotInUse) {
184  ReInitResponse(cip, rp);
185  result = RCmd(cip, rp, "USER %s", cip->firewallUser);
186  } else {
187  goto unknown;
188  }
189  break;
190 
191  case 230: /* 230 User logged in, proceed. */
192  case 231: /* User name accepted. */
193  case 202: /* Command not implemented, superfluous at this site. */
194  if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0))
195  goto okay;
196 
197  /* Now logged in to the firewall. */
198  fwloggedin++;
199 
201  ReInitResponse(cip, rp);
202  result = RCmd(cip, rp, "USER %s@%s", cip->user, cip->host);
203  } else if (cip->firewallType == kFirewallUserAtUserPassAtPass) {
204  goto okay;
205  } else if (cip->firewallType == kFirewallOpenSite) {
206  ReInitResponse(cip, rp);
207  result = RCmd(cip, rp, "OPEN %s", cip->host);
208  } else if (cip->firewallType == kFirewallSiteSite) {
209  ReInitResponse(cip, rp);
210  result = RCmd(cip, rp, "SITE %s", cip->host);
211  } else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) {
212  /* only reached when !fwloggedin */
213  ReInitResponse(cip, rp);
214  result = RCmd(cip, rp, "USER %s", cip->user);
215  } else /* kFirewallUserAtSite */ {
216  goto okay;
217  }
218  break;
219 
220  case 421: /* 421 Service not available, closing control connection. */
222  goto done;
223 
224  case 331: /* 331 User name okay, need password. */
225  if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) {
226  if ((cip->pass[0] == '\0') && (cip->passphraseProc != NoGetPassphraseProc))
227  (*cip->passphraseProc)(cip, &rp->msg, cip->pass, sizeof(cip->pass));
228  ReInitResponse(cip, rp);
229  result = RCmd(cip, rp, "PASS %s", cip->pass);
230  } else if (cip->firewallType == kFirewallUserAtSite) {
231  ReInitResponse(cip, rp);
232  result = RCmd(cip, rp, "PASS %s", cip->pass);
233  } else if (cip->firewallType == kFirewallUserAtUserPassAtPass) {
234  ReInitResponse(cip, rp);
235  result = RCmd(cip, rp, "PASS %s@%s", cip->pass, cip->firewallPass);
236  } else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) {
237  ReInitResponse(cip, rp);
238  result = RCmd(cip, rp, "PASS %s", cip->pass);
239  } else if (cip->firewallType == kFirewallFwuAtSiteFwpUserPass) {
240  /* only reached when !fwloggedin */
241  ReInitResponse(cip, rp);
242  result = RCmd(cip, rp, "PASS %s", cip->firewallPass);
243  } else if (cip->firewallType > kFirewallNotInUse) {
244  ReInitResponse(cip, rp);
245  result = RCmd(cip, rp, "PASS %s", cip->firewallPass);
246  } else {
247  goto unknown;
248  }
249  sentpass++;
250  break;
251 
252  case 332: /* 332 Need account for login. */
253  case 532: /* 532 Need account for storing files. */
254  if ((cip->firewallType == kFirewallNotInUse) || (fwloggedin != 0)) {
255  ReInitResponse(cip, rp);
256  result = RCmd(cip, rp, "ACCT %s", cip->acct);
257  } else if (cip->firewallType == kFirewallUserAtSiteFwuPassFwp) {
258  ReInitResponse(cip, rp);
259  result = RCmd(cip, rp, "ACCT %s", cip->firewallPass);
260  } else {
261  /* ACCT not supported on firewall. */
262  goto unknown;
263  }
264  break;
265 
266  case 530: /* Not logged in. */
268  goto done;
269 
270  case 501: /* Syntax error in parameters or arguments. */
271  case 503: /* Bad sequence of commands. */
272  case 550: /* Can't set guest privileges. */
273  goto done;
274 
275  default:
276  unknown:
277  if (rp->msg.first == NULL) {
278  Error(cip, kDontPerror, "Lost connection during login.\n");
279  } else {
280  Error(cip, kDontPerror, "Unexpected response: %s\n",
281  rp->msg.first->line
282  );
283  }
284  goto done;
285  }
286  }
287 
288 okay:
289  /* Do the application's connect message callback, if present. */
290  if (cip->onLoginMsgProc != 0)
291  (*cip->onLoginMsgProc)(cip, rp);
292  DoneWithResponse(cip, rp);
293  result = 0;
294  cip->loggedIn = 1;
295 
296  /* Make a note of what our root directory is.
297  * This is often different from "/" when not
298  * logged in anonymously.
299  */
300  if (cip->startingWorkingDirectory != NULL) {
303  }
304  if ((cip->doNotGetStartingWorkingDirectory == 0) &&
305  (FTPGetCWD(cip, cwd, sizeof(cwd)) == kNoErr))
306  {
307  cip->startingWorkingDirectory = StrDup(cwd);
308  }
309 
310  /* When a new site is opened, ASCII mode is assumed (by protocol). */
311  cip->curTransferType = 'A';
312  PrintF(cip, "Logged in to %s as %s.\n", cip->host, cip->user);
313 
314  /* Don't leave cleartext password in memory. */
315  if ((anonLogin == 0) && (cip->leavePass == 0))
316  (void) memset(cip->pass, '*', strlen(cip->pass));
317 
318  if (result < 0)
319  cip->errNo = result;
320  return result;
321 
322 done:
323  DoneWithResponse(cip, rp);
324 
325 done2:
326  /* Don't leave cleartext password in memory. */
327  if ((anonLogin == 0) && (cip->leavePass == 0))
328  (void) memset(cip->pass, '*', strlen(cip->pass));
329  if (result < 0)
330  cip->errNo = result;
331  return result;
332 } /* FTPLoginHost */
333 
334 
335 
336 
337 static void
338 FTPExamineMlstFeatures(const FTPCIPtr cip, const char *features)
339 {
340  char buf[256], *feat;
341  int flags;
342 
343  flags = 0;
344  STRNCPY(buf, features);
345  feat = strtok(buf, ";*");
346  while (feat != NULL) {
347  if (ISTRNEQ(feat, "OS.", 3))
348  feat += 3;
349  if (ISTREQ(feat, "type")) {
350  flags |= kMlsOptType;
351  } else if (ISTREQ(feat, "size")) {
352  flags |= kMlsOptSize;
353  } else if (ISTREQ(feat, "modify")) {
354  flags |= kMlsOptModify;
355  } else if (ISTREQ(feat, "UNIX.mode")) {
357  } else if (ISTREQ(feat, "UNIX.owner")) {
359  } else if (ISTREQ(feat, "UNIX.group")) {
361  } else if (ISTREQ(feat, "perm")) {
362  flags |= kMlsOptPerm;
363  } else if (ISTREQ(feat, "UNIX.uid")) {
365  } else if (ISTREQ(feat, "UNIX.gid")) {
367  } else if (ISTREQ(feat, "UNIX.gid")) {
368  flags |= kMlsOptUnique;
369  }
370  feat = strtok(NULL, ";*");
371  }
372 
373  cip->mlsFeatures = flags;
374 } /* FTPExamineMlstFeatures */
375 
376 
377 
378 
379 int
381 {
382  ResponsePtr rp;
383  int result;
384  LinePtr lp;
385  char *cp, *p;
386 
387  if (cip == NULL)
388  return (kErrBadParameter);
389  if (strcmp(cip->magic, kLibraryMagic))
390  return (kErrBadMagic);
391 
392  if (cip->serverType == kServerTypeNetWareFTP) {
393  /* NetWare 5.00 server freaks out when
394  * you give it a command it doesn't
395  * recognize, so cheat here and return.
396  */
397  cip->hasPASV = kCommandAvailable;
406  return (kNoErr);
407  }
408 
409  rp = InitResponse();
410  if (rp == NULL) {
411  cip->errNo = kErrMallocFailed;
412  result = cip->errNo;
413  } else {
415  result = RCmd(cip, rp, "FEAT");
416  if (result < kNoErr) {
417  DoneWithResponse(cip, rp);
418  return (result);
419  } else if (result != 2) {
420  /* We cheat here and pre-populate some
421  * fields when the server is wu-ftpd.
422  * This server is very common and we
423  * know it has always had these.
424  */
425  if (cip->serverType == kServerTypeWuFTPd) {
426  cip->hasPASV = kCommandAvailable;
427  cip->hasSIZE = kCommandAvailable;
428  cip->hasMDTM = kCommandAvailable;
429  cip->hasREST = kCommandAvailable;
431  } else if (cip->serverType == kServerTypeNcFTPd) {
432  cip->hasPASV = kCommandAvailable;
433  cip->hasSIZE = kCommandAvailable;
434  cip->hasMDTM = kCommandAvailable;
435  cip->hasREST = kCommandAvailable;
437  }
438 
439  /* Newer commands are only shown in FEAT,
440  * so we don't have to do the "try it,
441  * then save that it didn't work" thing.
442  */
445  } else {
446  cip->hasFEAT = kCommandAvailable;
447 
448  for (lp = rp->msg.first; lp != NULL; lp = lp->next) {
449  /* If first character was not a space it is
450  * either:
451  *
452  * (a) The header line in the response;
453  * (b) The trailer line in the response;
454  * (c) A protocol violation.
455  */
456  cp = lp->line;
457  if (*cp++ != ' ')
458  continue;
459  if (ISTRNCMP(cp, "PASV", 4) == 0) {
460  cip->hasPASV = kCommandAvailable;
461  } else if (ISTRNCMP(cp, "SIZE", 4) == 0) {
462  cip->hasSIZE = kCommandAvailable;
463  } else if (ISTRNCMP(cp, "MDTM", 4) == 0) {
464  cip->hasMDTM = kCommandAvailable;
465  } else if (ISTRNCMP(cp, "REST", 4) == 0) {
466  cip->hasREST = kCommandAvailable;
467  } else if (ISTRNCMP(cp, "UTIME", 5) == 0) {
469  } else if (ISTRNCMP(cp, "MLST", 4) == 0) {
470  cip->hasMLST = kCommandAvailable;
471  cip->hasMLSD = kCommandAvailable;
472  FTPExamineMlstFeatures(cip, cp + 5);
473  } else if (ISTRNCMP(cp, "CLNT", 4) == 0) {
474  cip->hasCLNT = kCommandAvailable;
475  } else if (ISTRNCMP(cp, "Compliance Level: ", 18) == 0) {
476  /* Probably only NcFTPd will ever implement this.
477  * But we use it internally to differentiate
478  * between different NcFTPd implementations of
479  * IETF extensions.
480  */
481  cip->ietfCompatLevel = atoi(cp + 18);
482  }
483  }
484  }
485 
486  ReInitResponse(cip, rp);
487  result = RCmd(cip, rp, "HELP SITE");
488  if (result == 2) {
489  for (lp = rp->msg.first; lp != NULL; lp = lp->next) {
490  cp = lp->line;
491  if (strstr(cp, "RETRBUFSIZE") != NULL)
493  if (strstr(cp, "RBUFSZ") != NULL)
495  /* See if RBUFSIZ matches (but not STORBUFSIZE) */
496  if (
497  ((p = strstr(cp, "RBUFSIZ")) != NULL) &&
498  (
499  (p == cp) ||
500  ((p > cp) && (!isupper(p[-1])))
501  )
502  )
504  if (strstr(cp, "STORBUFSIZE") != NULL)
506  if (strstr(cp, "SBUFSIZ") != NULL)
508  if (strstr(cp, "SBUFSZ") != NULL)
510  if (strstr(cp, "BUFSIZE") != NULL)
512  }
513  }
514  DoneWithResponse(cip, rp);
515  }
516 
517  return (kNoErr);
518 } /* FTPQueryFeatures */
519 
520 
521 
522 int
524 {
525  ResponsePtr rp;
526  int result;
527 
528  if (cip == NULL)
529  return (kErrBadParameter);
530  if (strcmp(cip->magic, kLibraryMagic))
531  return (kErrBadMagic);
532 
533  /* Data connection shouldn't be open normally. */
534  if (cip->dataSocket != kClosedFileDescriptor)
536 
537  result = kNoErr;
538  if (cip->connected != 0) {
539  rp = InitResponse();
540  if (rp == NULL) {
541  cip->errNo = kErrMallocFailed;
542  result = cip->errNo;
543  } else {
544  rp->eofOkay = 1; /* We are expecting EOF after this cmd. */
545  cip->eofOkay = 1;
546  (void) RCmd(cip, rp, "QUIT");
547  DoneWithResponse(cip, rp);
548  }
549  }
550 
552 
553  /* Dispose dynamic data structures, so you won't leak
554  * if you OpenHost with this again.
555  */
556  FTPDeallocateHost(cip);
557  return (result);
558 } /* FTPCloseHost */
559 
560 
561 
562 
563 void
565 {
566 #ifdef SIGPIPE
567  FTPSigProc osigpipe;
568 #endif
569 
570  if (cip == NULL)
571  return;
572  if (strcmp(cip->magic, kLibraryMagic))
573  return;
574 
575 #ifdef SIGPIPE
576  osigpipe = signal(SIGPIPE, (FTPSigProc) SIG_IGN);
577 #endif
578 
579  /* Linger could cause close to block, so unset it. */
580  if (cip->dataSocket != kClosedFileDescriptor)
581  (void) SetLinger(cip, cip->dataSocket, 0);
582  CloseDataConnection(cip); /* Shouldn't be open normally. */
583 
584  /* Linger should already be turned off for this. */
586 
587  FTPDeallocateHost(cip);
588 
589 #ifdef SIGPIPE
590  (void) signal(SIGPIPE, (FTPSigProc) osigpipe);
591 #endif
592 } /* FTPShutdownHost */
593 
594 
595 
596 
597 void
598 URLCopyToken(char *dst, size_t dsize, const char *src, size_t howmuch)
599 {
600  char *dlim;
601  const char *slim;
602  unsigned int hc;
603  int c;
604  char h[4];
605 
606  dlim = dst + dsize - 1; /* leave room for \0 */
607  slim = src + howmuch;
608  while (src < slim) {
609  c = *src++;
610  if (c == '\0')
611  break;
612  if (c == '%') {
613  /* hex representation */
614  if (src < slim + 2) {
615  h[0] = *src++;
616  h[1] = *src++;
617  h[2] = '\0';
618  hc = 0xeeff;
619  if ((sscanf(h, "%x", &hc) >= 0) && (hc != 0xeeff)) {
620  if (dst < dlim) {
621  *(unsigned char *)dst = (unsigned char) hc;
622  dst++;
623  }
624  }
625  } else {
626  break;
627  }
628  } else {
629  *dst++ = (char) c;
630  }
631  }
632  *dst = '\0';
633 } /* URLCopyToken */
634 
635 
636 
637 
638 int
640  const FTPCIPtr cip, /* area pointed to may be modified */
641  char *const url, /* always modified */
642  LineListPtr cdlist, /* always modified */
643  char *const fn, /* always modified */
644  const size_t fnsize,
645  int *const xtype, /* optional; may be modified */
646  int *const wantnlst /* optional; always modified */
647 )
648 {
649  char *cp;
650  char *hstart, *hend;
651  char *h2start;
652  char *at1;
653  char portstr[32];
654  int port;
655  int sc;
656  char *lastslash;
657  char *parsestr;
658  char *tok;
659  char subdir[128];
660  char *semi;
661 
662  InitLineList(cdlist);
663  *fn = '\0';
664  if (wantnlst != NULL)
665  *wantnlst = 0;
666  if (xtype != NULL)
667  *xtype = kTypeBinary;
668 
669  cp = NULL; /* shut up warnings */
670 #ifdef HAVE_STRCASECMP
671  if (strncasecmp(url, "<URL:ftp://", 11) == 0) {
672  cp = url + strlen(url) - 1;
673  if (*cp != '>')
674  return (kMalformedURL); /* missing closing > */
675  *cp = '\0';
676  cp = url + 11;
677  } else if (strncasecmp(url, "ftp://", 6) == 0) {
678  cp = url + 6;
679  } else {
680  return (-1); /* not a RFC 1738 URL */
681  }
682 #else /* HAVE_STRCASECMP */
683  if (strncmp(url, "<URL:ftp://", 11) == 0) {
684  cp = url + strlen(url) - 1;
685  if (*cp != '>')
686  return (kMalformedURL); /* missing closing > */
687  *cp = '\0';
688  cp = url + 11;
689  } else if (strncmp(url, "ftp://", 6) == 0) {
690  cp = url + 6;
691  } else {
692  return (-1); /* not a RFC 1738 URL */
693  }
694 #endif /* HAVE_STRCASECMP */
695 
696  /* //<user>:<password>@<host>:<port>/<url-path> */
697 
698  at1 = NULL;
699  for (hstart = cp; ; cp++) {
700  if (*cp == '@') {
701  if (at1 == NULL)
702  at1 = cp;
703  else
704  return (kMalformedURL);
705  } else if ((*cp == '\0') || (*cp == '/')) {
706  hend = cp;
707  break;
708  }
709  }
710 
711  sc = *hend;
712  *hend = '\0';
713  if (at1 == NULL) {
714  /* no user or password */
715  h2start = hstart;
716  } else {
717  *at1 = '\0';
718  cp = strchr(hstart, ':');
719  if (cp == NULL) {
720  /* whole thing is the user name then */
721  URLCopyToken(cip->user, sizeof(cip->user), hstart, (size_t) (at1 - hstart));
722  } else if (strchr(cp + 1, ':') != NULL) {
723  /* Too many colons */
724  return (kMalformedURL);
725  } else {
726  URLCopyToken(cip->user, sizeof(cip->user), hstart, (size_t) (cp - hstart));
727  URLCopyToken(cip->pass, sizeof(cip->pass), cp + 1, (size_t) (at1 - (cp + 1)));
728  }
729  *at1 = '@';
730  h2start = at1 + 1;
731  }
732 
733  cp = strchr(h2start, ':');
734  if (cp == NULL) {
735  /* whole thing is the host then */
736  URLCopyToken(cip->host, sizeof(cip->host), h2start, (size_t) (hend - h2start));
737  } else if (strchr(cp + 1, ':') != NULL) {
738  /* Too many colons */
739  return (kMalformedURL);
740  } else {
741  URLCopyToken(cip->host, sizeof(cip->host), h2start, (size_t) (cp - h2start));
742  URLCopyToken(portstr, sizeof(portstr), cp + 1, (size_t) (hend - (cp + 1)));
743  port = atoi(portstr);
744  if (port > 0)
745  cip->port = port;
746  }
747 
748  *hend = (char) sc;
749  if ((*hend == '\0') || ((*hend == '/') && (hend[1] == '\0'))) {
750  /* no path, okay */
751  return (0);
752  }
753 
754  lastslash = strrchr(hend, '/');
755  if (lastslash == NULL) {
756  /* no path, okay */
757  return (0);
758  }
759  *lastslash = '\0';
760 
761  if ((semi = strchr(lastslash + 1, ';')) != NULL) {
762  *semi++ = '\0';
763 #ifdef HAVE_STRCASECMP
764  if (strcasecmp(semi, "type=i") == 0) {
765  if (xtype != NULL)
766  *xtype = kTypeBinary;
767  } else if (strcasecmp(semi, "type=a") == 0) {
768  if (xtype != NULL)
769  *xtype = kTypeAscii;
770  } else if (strcasecmp(semi, "type=b") == 0) {
771  if (xtype != NULL)
772  *xtype = kTypeBinary;
773  } else if (strcasecmp(semi, "type=d") == 0) {
774  if (wantnlst != NULL) {
775  *wantnlst = 1;
776  if (xtype != NULL)
777  *xtype = kTypeAscii;
778  } else {
779  /* You didn't want these. */
780  return (kMalformedURL);
781  }
782  }
783 #else /* HAVE_STRCASECMP */
784  if (strcmp(semi, "type=i") == 0) {
785  if (xtype != NULL)
786  *xtype = kTypeBinary;
787  } else if (strcmp(semi, "type=a") == 0) {
788  if (xtype != NULL)
789  *xtype = kTypeAscii;
790  } else if (strcmp(semi, "type=b") == 0) {
791  if (xtype != NULL)
792  *xtype = kTypeBinary;
793  } else if (strcmp(semi, "type=d") == 0) {
794  if (wantnlst != NULL) {
795  *wantnlst = 1;
796  if (xtype != NULL)
797  *xtype = kTypeAscii;
798  } else {
799  /* You didn't want these. */
800  return (kMalformedURL);
801  }
802  }
803 #endif /* HAVE_STRCASECMP */
804  }
805  URLCopyToken(fn, fnsize, lastslash + 1, strlen(lastslash + 1));
806  for (parsestr = hend; (tok = strtok(parsestr, "/")) != NULL; parsestr = NULL) {
807  URLCopyToken(subdir, sizeof(subdir), tok, strlen(tok));
808  (void) AddLine(cdlist, subdir);
809  }
810  *lastslash = '/';
811  return (kNoErr);
812 } /* FTPDecodeURL */
813 
814 
815 
816 
817 int
819 {
820  int result;
821  time_t t0, t1;
822  int elapsed;
823  int dials;
824 
825  if (cip == NULL)
826  return (kErrBadParameter);
827  if (strcmp(cip->magic, kLibraryMagic))
828  return (kErrBadMagic);
829 
830  if (cip->host[0] == '\0') {
831  cip->errNo = kErrBadParameter;
832  return (kErrBadParameter);
833  }
834 
835  for ( result = kErrConnectMiscErr, dials = 0;
836  cip->maxDials < 0 || dials < cip->maxDials;
837  dials++)
838  {
839  /* Allocate (or if the host was closed, reallocate)
840  * the transfer data buffer.
841  */
842  result = FTPAllocateHost(cip);
843  if (result < 0)
844  return (result);
845 
846  if (dials > 0)
847  PrintF(cip, "Retry Number: %d\n", dials);
848  if (cip->redialStatusProc != 0)
849  (*cip->redialStatusProc)(cip, kRedialStatusDialing, dials);
850  (void) time(&t0);
851  result = OpenControlConnection(cip, cip->host, cip->port);
852  (void) time(&t1);
853  if (result == kNoErr) {
854  /* We were hooked up successfully. */
855  PrintF(cip, "Connected to %s.\n", cip->host);
856 
857  result = FTPLoginHost(cip);
858  if (result == kNoErr) {
859  (void) FTPQueryFeatures(cip);
860  break;
861  }
862 
863  /* Close and try again. */
864  (void) FTPCloseHost(cip);
865 
866  /* Originally we also stopped retyring if
867  * we got kErrBadRemoteUser and non-anonymous,
868  * but some FTP servers apparently do their
869  * max user check after the username is sent.
870  */
871  if (result == kErrBadRemoteUserOrPassword /* || (result == kErrBadRemoteUser) */) {
872  if (strcmp(cip->user, "anonymous") != 0) {
873  /* Non-anonymous login was denied, and
874  * retrying is not going to help.
875  */
876  break;
877  }
878  }
880  /* Irrecoverable error, so don't bother redialing.
881  * The error message should have already been printed
882  * from OpenControlConnection().
883  */
884  PrintF(cip, "Cannot recover from miscellaneous open error %d.\n", result);
885  return result;
886  }
887 
888  /* Retryable error, wait and then redial. */
889  if (cip->redialDelay > 0) {
890  /* But don't sleep if this is the last loop. */
891  if ((cip->maxDials < 0) || (dials < (cip->maxDials - 1))) {
892  elapsed = (int) (t1 - t0);
893  if (elapsed < cip->redialDelay) {
894  PrintF(cip, "Sleeping %u seconds.\n",
895  (unsigned) cip->redialDelay - elapsed);
896  if (cip->redialStatusProc != 0)
897  (*cip->redialStatusProc)(cip, kRedialStatusSleeping, cip->redialDelay - elapsed);
898  (void) sleep((unsigned) cip->redialDelay - elapsed);
899  }
900  }
901  }
902  }
903  return (result);
904 } /* FTPOpenHost */
905 
906 
907 
908 
909 int
911 {
912  int result;
913  time_t t0, t1;
914  int elapsed;
915  int dials;
916 
917  if (cip == NULL)
918  return (kErrBadParameter);
919  if (strcmp(cip->magic, kLibraryMagic))
920  return (kErrBadMagic);
921 
922  if (cip->host[0] == '\0') {
923  cip->errNo = kErrBadParameter;
924  return (kErrBadParameter);
925  }
926 
927  for ( result = kErrConnectMiscErr, dials = 0;
928  cip->maxDials < 0 || dials < cip->maxDials;
929  dials++)
930  {
931 
932  /* Allocate (or if the host was closed, reallocate)
933  * the transfer data buffer.
934  */
935  result = FTPAllocateHost(cip);
936  if (result < 0)
937  return (result);
938 
939  if (dials > 0)
940  PrintF(cip, "Retry Number: %d\n", dials);
941  if (cip->redialStatusProc != 0)
942  (*cip->redialStatusProc)(cip, kRedialStatusDialing, dials);
943  (void) time(&t0);
944  result = OpenControlConnection(cip, cip->host, cip->port);
945  (void) time(&t1);
946  if (result == kNoErr) {
947  /* We were hooked up successfully. */
948  PrintF(cip, "Connected to %s.\n", cip->host);
949 
950  /* Not logging in... */
951  if (result == kNoErr)
952  break;
954  /* Irrecoverable error, so don't bother redialing.
955  * The error message should have already been printed
956  * from OpenControlConnection().
957  */
958  PrintF(cip, "Cannot recover from miscellaneous open error %d.\n", result);
959  return result;
960  }
961 
962  /* Retryable error, wait and then redial. */
963  if (cip->redialDelay > 0) {
964  /* But don't sleep if this is the last loop. */
965  if ((cip->maxDials < 0) || (dials < (cip->maxDials - 1))) {
966  elapsed = (int) (t1 - t0);
967  if (elapsed < cip->redialDelay) {
968  PrintF(cip, "Sleeping %u seconds.\n",
969  (unsigned) cip->redialDelay - elapsed);
970  if (cip->redialStatusProc != 0)
971  (*cip->redialStatusProc)(cip, kRedialStatusSleeping, cip->redialDelay - elapsed);
972  (void) sleep((unsigned) cip->redialDelay - elapsed);
973  }
974  }
975  }
976  }
977  return (result);
978 } /* FTPOpenHostNoLogin */
979 
980 
981 
982 
983 int
984 FTPInitConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip, size_t bufSize)
985 {
986  size_t siz;
987 
988  if ((lip == NULL) || (cip == NULL) || (bufSize == 0))
989  return (kErrBadParameter);
990 
991  siz = sizeof(FTPConnectionInfo);
992  (void) memset(cip, 0, siz);
993 
994  if (strcmp(lip->magic, kLibraryMagic))
995  return (kErrBadMagic);
996 
997  cip->buf = NULL; /* denote that it needs to be allocated. */
998  cip->bufSize = bufSize;
999  cip->port = lip->defaultPort;
1000  cip->firewallPort = lip->defaultPort;
1001  cip->maxDials = kDefaultMaxDials;
1009  cip->dataPortMode = kSendPortMode;
1011  cip->lip = lip;
1032  (void) STRNCPY(cip->magic, kLibraryMagic);
1033  (void) STRNCPY(cip->user, "anonymous");
1034  return (kNoErr);
1035 } /* FTPInitConnectionInfo */
1036 
1037 
1038 
1039 
1040 int
1042 {
1043  char *buf;
1044 
1045  cip->lip = lip;
1046  cip->debugLog = NULL;
1047  cip->errLog = NULL;
1048  cip->debugLogProc = NULL;
1049  cip->errLogProc = NULL;
1050  cip->buf = NULL;
1051  cip->cin = NULL;
1052  cip->cout = NULL;
1053  cip->errNo = 0;
1054  cip->progress = NULL;
1055  cip->rname = NULL;
1056  cip->lname = NULL;
1057  cip->onConnectMsgProc = NULL;
1058  cip->redialStatusProc = NULL;
1059  cip->printResponseProc = NULL;
1060  cip->onLoginMsgProc = NULL;
1061  cip->passphraseProc = NULL;
1064 
1065  (void) memset(&cip->lastFTPCmdResultLL, 0, sizeof(LineList));
1066 
1067  /* Allocate a new buffer. */
1068  buf = (char *) calloc((size_t) 1, cip->bufSize);
1069  if (buf == NULL) {
1070  cip->errNo = kErrMallocFailed;
1071  return (kErrMallocFailed);
1072  }
1073  cip->buf = buf;
1074 
1075  /* Reattach the FILE pointers for use with the Std I/O library
1076  * routines.
1077  */
1078  if ((cip->cin = _fdopen(cip->ctrlSocketR, "r")) == NULL) {
1079  cip->errNo = kErrFdopenR;
1082  return (kErrFdopenR);
1083  }
1084 
1085  if ((cip->cout = _fdopen(cip->ctrlSocketW, "w")) == NULL) {
1086  CloseFile(&cip->cin);
1087  cip->errNo = kErrFdopenW;
1090  return (kErrFdopenW);
1091  }
1092 
1093 #if USE_SIO
1094  if (InitSReadlineInfo(&cip->ctrlSrl, cip->ctrlSocketR, cip->srlBuf, sizeof(cip->srlBuf), (int) cip->ctrlTimeout, 1) < 0) {
1095  cip->errNo = kErrFdopenW;
1096  CloseFile(&cip->cin);
1097  cip->errNo = kErrFdopenW;
1100  return (kErrFdopenW);
1101  }
1102 #endif
1103  return (kNoErr);
1104 } /* FTPRebuildConnectionInfo */
1105 
1106 
1107 
1108 
1109 int
1111 {
1112  struct servent *ftp;
1113 
1114  if (lip == NULL)
1115  return (kErrBadParameter);
1116 
1117  (void) memset(lip, 0, sizeof(FTPLibraryInfo));
1118  if ((ftp = getservbyname("ftp", "tcp")) == NULL)
1119  lip->defaultPort = (unsigned int) kDefaultFTPPort;
1120  else
1121  lip->defaultPort = (unsigned int) ntohs(ftp->s_port);
1122 
1123  lip->init = 1;
1124  (void) STRNCPY(lip->magic, kLibraryMagic);
1125 
1126  /* We'll initialize the defaultAnonPassword field
1127  * later when we try the first anon ftp connection.
1128  */
1129 
1130 #ifdef HAVE_LIBSOCKS
1131  SOCKSinit("libncftp");
1132  lip->socksInit = 1;
1133 #endif
1134  return (kNoErr);
1135 } /* FTPInitLibrary */
1136 
1137 /* Open.c */
void DisposeSReadlineInfo(SReadlineInfo *)
Definition: SReadline.c:57
#define kFirewallSiteSite
Definition: ncftp.h:391
#define kServerTypeWuFTPd
Definition: ncftp.h:462
LineList lastFTPCmdResultLL
Definition: ncftp.h:215
static void FTPExamineMlstFeatures(const FTPCIPtr cip, const char *features)
Definition: open.c:338
#define kFirewallLastType
Definition: ncftp.h:396
int printMode
Definition: ncftp.h:93
int ietfCompatLevel
Definition: ncftp.h:233
FILE * cin
Definition: ncftp.h:188
void ReInitResponse(const FTPCIPtr, ResponsePtr)
Definition: rcmd.c:142
unsigned int ctrlTimeout
Definition: ncftp.h:143
void FTPAbortDataTransfer(const FTPCIPtr cip)
Definition: rcmd.c:870
#define sleep
Definition: syshdrs.h:37
unsigned int port
Definition: ncftp.h:140
#define kErrBadParameter
Definition: ncftp_errno.h:56
int socksInit
Definition: ncftp.h:116
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
const char * asciiFilenameExtensions
Definition: ncftp.h:246
#define kCommandAvailable
Definition: ncftp.h:380
int hasSTORBUFSIZE
Definition: ncftp.h:174
#define kDefaultFTPPort
Definition: ncftp.h:312
int STATfileParamWorks
Definition: ncftp.h:179
#define strcasecmp
Definition: fake.h:9
int RCmd(const FTPCIPtr, ResponsePtr, const char *,...)
Definition: rcmd.c:718
#define kResponseNoSave
Definition: ncftp.h:309
#define kServerTypeNcFTPd
Definition: ncftp.h:463
_Check_return_ _CRTIMP FILE *__cdecl _fdopen(_In_ int _FileHandle, _In_z_ const char *_Mode)
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
int InitSReadlineInfo(SReadlineInfo *, int, char *, size_t, int, int)
Definition: SReadline.c:24
char pass[64]
Definition: ncftp.h:138
#define kMlsOptModify
Definition: ncftp.h:403
void CloseDataConnection(const FTPCIPtr cip)
Definition: ftp.c:831
#define kFirewallUserAtSite
Definition: ncftp.h:389
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
#define kErrLoginFailed
Definition: ncftp_errno.h:73
#define free
Definition: debug_ros.c:5
#define NoGetPassphraseProc
Definition: ncftp.h:453
void CloseControlConnection(const FTPCIPtr cip)
Definition: ftp.c:197
char * buf
Definition: ncftp.h:186
#define kDefaultMaxDials
Definition: ncftp.h:341
FTPLoginMessageProc onLoginMsgProc
Definition: ncftp.h:227
int FTPOpenHost(const FTPCIPtr cip)
Definition: open.c:818
#define kCommandAvailabilityUnknown
Definition: ncftp.h:379
char magic[16]
Definition: ncftp.h:114
void DoneWithResponse(const FTPCIPtr, ResponsePtr)
Definition: rcmd.c:114
char ourHostName[64]
Definition: ncftp.h:118
char user[64]
Definition: ncftp.h:137
#define kDefaultCtrlTimeout
Definition: ncftp.h:322
LinePtr next
Definition: ncftp.h:80
#define ISTRNEQ(a, b, s)
Definition: util.h:34
#define STRNCPY(dst, src, n)
Definition: rdesktop.h:168
int doNotGetStartingWorkingDirectory
Definition: ncftp.h:237
#define kErrMallocFailed
Definition: ncftp_errno.h:40
FTPProgressMeterProc progress
Definition: ncftp.h:198
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
__u16 time
Definition: mkdosfs.c:366
#define kFirewallNotInUse
Definition: ncftp.h:388
int NLSTfileParamWorks
Definition: ncftp.h:180
char magic[16]
Definition: ncftp.h:135
#define kMlsOptUNIXuid
Definition: ncftp.h:408
#define ntohs(x)
Definition: module.h:208
#define kDefaultRedialDelay
Definition: ncftp.h:342
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
FTPLogProc errLogProc
Definition: ncftp.h:148
#define ISTREQ(a, b)
Definition: util.h:33
#define StrDup
Definition: shlwapi.h:1533
GLuint GLsizei bufSize
Definition: glext.h:6040
#define kServerTypeNetWareFTP
Definition: ncftp.h:472
char host[64]
Definition: ncftp.h:136
FTPLIPtr lip
Definition: ncftp.h:149
FTPRedialStatusProc redialStatusProc
Definition: ncftp.h:225
#define kSendPortMode
Definition: ncftp.h:295
int GetOurHostName(char *host, size_t siz)
Definition: ftp.c:81
#define kFirewallUserAtSiteFwuPassFwp
Definition: ncftp.h:395
int hasRETRBUFSIZE
Definition: ncftp.h:171
#define kMlsOptType
Definition: ncftp.h:401
FILE * errLog
Definition: ncftp.h:146
int FTPInitLibrary(const FTPLIPtr lip)
Definition: open.c:1110
#define kMalformedURL
Definition: ncftp.h:385
FTPConnectMessageProc onConnectMsgProc
Definition: ncftp.h:224
#define strncasecmp
Definition: fake.h:10
smooth NULL
Definition: ftsmooth.c:416
unsigned char
Definition: typeof.h:29
void FTPInitializeOurHostName(const FTPLIPtr lip)
Definition: open.c:63
int firewallType
Definition: ncftp.h:221
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define kErrConnectRefused
Definition: ncftp_errno.h:37
struct FTPConnectionInfo FTPConnectionInfo
const char * rname
Definition: ncftp.h:208
char firewallPass[64]
Definition: ncftp.h:219
#define STRNCAT(d, s)
Definition: Strn.h:48
char * startingWorkingDirectory
Definition: ncftp.h:158
int code
Definition: ncftp.h:92
#define kFirewallLoginThenUserAtSite
Definition: ncftp.h:390
static int FTPAllocateHost(const FTPCIPtr cip)
Definition: open.c:39
PSERVENT WSAAPI getservbyname(IN const char FAR *name, IN const char FAR *proto)
Definition: getxbyxx.c:500
char acct[64]
Definition: ncftp.h:139
int FTPDecodeURL(const FTPCIPtr cip, char *const url, LineListPtr cdlist, char *const fn, const size_t fnsize, int *const xtype, int *const wantnlst)
Definition: open.c:639
int htried
Definition: ncftp.h:120
#define isupper(c)
Definition: acclib.h:71
static const WCHAR url[]
Definition: encode.c:1432
#define kErrHostDisconnectedDuringLogin
Definition: ncftp_errno.h:70
#define kErrBadMagic
Definition: ncftp_errno.h:55
char defaultAnonPassword[80]
Definition: ncftp.h:121
const GLubyte * c
Definition: glext.h:8905
int strncmp(const char *String1, const char *String2, ACPI_SIZE Count)
Definition: utclib.c:534
LinePtr AddLine(LineListPtr list, const char *buf1)
Definition: linelist.c:94
#define kTypeBinary
Definition: ncftp.h:354
unsigned int defaultPort
Definition: ncftp.h:117
int FTPLoginHost(const FTPCIPtr cip)
Definition: open.c:110
BOOL Error
Definition: chkdsk.c:66
#define kErrBadRemoteUser
Definition: ncftp_errno.h:71
#define kFirewallFwuAtSiteFwpUserPass
Definition: ncftp.h:394
Definition: id3.c:18
void(* FTPSigProc)(int)
Definition: ncftp.h:76
#define kErrFdopenR
Definition: ncftp_errno.h:25
Definition: ncftp.h:89
GLbitfield flags
Definition: glext.h:7161
Definition: ncftp.h:79
#define kDefaultAbortTimeout
Definition: ncftp.h:323
char firewallUser[64]
Definition: ncftp.h:218
#define kTypeAscii
Definition: ncftp.h:353
#define SIGPIPE
Definition: signal.h:35
int signal
Definition: xcptfil.c:12
Definition: ncftp.h:84
unsigned int xferTimeout
Definition: ncftp.h:141
void FTPInitializeAnonPassword(const FTPLIPtr lip)
Definition: open.c:81
#define kRedialStatusSleeping
Definition: ncftp.h:347
FTPLogProc debugLogProc
Definition: ncftp.h:147
#define kClosedFileDescriptor
Definition: util.h:47
#define kDontPerror
Definition: util.h:45
#define kMlsOptUNIXgid
Definition: ncftp.h:409
FILE * cout
Definition: ncftp.h:189
LinePtr first
Definition: ncftp.h:85
FILE * debugLog
Definition: ncftp.h:145
GLenum src
Definition: glext.h:6340
void FTPShutdownHost(const FTPCIPtr cip)
Definition: open.c:564
int FTPRebuildConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip)
Definition: open.c:1041
#define kCommandNotAvailable
Definition: ncftp.h:381
int OpenControlConnection(const FTPCIPtr cip, char *host, unsigned int port)
Definition: ftp.c:347
#define kMlsOptUNIXgroup
Definition: ncftp.h:406
#define kDefaultConnTimeout
Definition: ncftp.h:321
#define kErrConnectMiscErr
Definition: ncftp_errno.h:35
int FTPOpenHostNoLogin(const FTPCIPtr cip)
Definition: open.c:910
LineList msg
Definition: ncftp.h:90
void PrintF(const FTPCIPtr cip, const char *const fmt,...)
Definition: util.c:340
#define kResponseNoPrint
Definition: ncftp.h:308
#define kFirewallOpenSite
Definition: ncftp.h:392
FTPPrintResponseProc printResponseProc
Definition: ncftp.h:226
int hresult
Definition: ncftp.h:119
#define kMlsOptPerm
Definition: ncftp.h:407
static void FTPDeallocateHost(const FTPCIPtr cip)
Definition: open.c:11
__kernel_time_t time_t
Definition: linux.h:252
#define ISTRNCMP
Definition: util.h:29
int curTransferType
Definition: ncftp.h:157
GLenum GLenum dst
Definition: glext.h:6340
void InitLineList(LineListPtr list)
Definition: linelist.c:54
int FTPGetCWD(const FTPCIPtr cip, char *const newCwd, const size_t newCwdSize)
Definition: cmds.c:254
const char * lname
Definition: ncftp.h:209
unsigned int firewallPort
Definition: ncftp.h:220
int FTPQueryFeatures(const FTPCIPtr cip)
Definition: open.c:380
void GetUsrName(char *, size_t)
Definition: util.c:290
char * strtok(char *String, const char *Delimiters)
Definition: utclib.c:338
char srlBuf[768]
Definition: ncftp.h:239
#define kFirewallUserAtUserPassAtPass
Definition: ncftp.h:393
int SetLinger(const FTPCIPtr cip, int sockfd, int onoff)
Definition: ftp.c:262
char * strchr(const char *String, int ch)
Definition: utclib.c:501
_Check_return_ int __cdecl atoi(_In_z_ const char *_Str)
#define kDefaultXferTimeout
Definition: ncftp.h:320
size_t bufSize
Definition: ncftp.h:187
void CloseFile(FILE **f)
Definition: util.c:327
#define kMlsOptUNIXowner
Definition: ncftp.h:405
POINT cp
Definition: magnifier.c:59
#define calloc
Definition: rosglue.h:14
int FTPInitConnectionInfo(const FTPLIPtr lip, const FTPCIPtr cip, size_t bufSize)
Definition: open.c:984
void URLCopyToken(char *dst, size_t dsize, const char *src, size_t howmuch)
Definition: open.c:598
#define kLibraryMagic
Definition: ncftp.h:65
#define kErrRemoteHostClosedConnection
Definition: ncftp_errno.h:75
#define c
Definition: ke_i.h:80
#define kMlsOptUNIXmode
Definition: ncftp.h:404
#define kNoErr
Definition: ncftp_errno.h:9
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
unsigned int abortTimeout
Definition: ncftp.h:144
#define kErrConnectRetryableErr
Definition: ncftp_errno.h:36
void DisposeLineListContents(LineListPtr list)
Definition: linelist.c:33
int FTPCloseHost(const FTPCIPtr cip)
Definition: open.c:523
GLfloat GLfloat p
Definition: glext.h:8902
SReadlineInfo ctrlSrl
Definition: ncftp.h:240
#define SIG_IGN
Definition: signal.h:48
ResponsePtr InitResponse(void)
Definition: rcmd.c:38
USHORT port
Definition: uri.c:228
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
unsigned int connTimeout
Definition: ncftp.h:142
char * line
Definition: ncftp.h:81
#define kErrBadRemoteUserOrPassword
Definition: ncftp_errno.h:72
#define kRedialStatusDialing
Definition: ncftp.h:346
int eofOkay
Definition: ncftp.h:94
#define kMlsOptSize
Definition: ncftp.h:402
#define kMlsOptUnique
Definition: ncftp.h:410
int dataPortMode
Definition: ncftp.h:152
FTPGetPassphraseProc passphraseProc
Definition: ncftp.h:242
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
static WCHAR ftp[]
Definition: url.c:29
#define kErrFdopenW
Definition: ncftp_errno.h:26