111. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 10/2/2017 1:40:09 PM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

111.1 Files compared

# Location File Last Modified
1 chef-repo.zip\chef-repo\project_cookbooks\mocks\files\default\node-mocks\nodeMockServices-1.3.0.52.zip\node_modules\libxmljs\vendor\libxml nanoftp.c Fri Apr 11 14:19:04 2014 UTC
2 chef-repo.zip\chef-repo\project_cookbooks\mocks\files\default\node-mocks\nodeMockServices-1.3.0.52.zip\node_modules\libxmljs\vendor\libxml nanoftp.c Mon Oct 2 17:21:14 2017 UTC

111.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 4 4220
Changed 3 6
Inserted 0 0
Removed 0 0

111.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

111.4 Active regular expressions

No regular expressions were active.

111.5 Comparison detail

  1   /*
  2    * nanoftp .c: basic  FTP client  support
  3    *
  4    *  Refere nce: RFC 9 59
  5    */
  6  
  7   #ifdef TES TING
  8   #define ST ANDALONE
  9   #define HA VE_STDLIB_ H
  10   #define HA VE_UNISTD_ H
  11   #define HA VE_SYS_SOC KET_H
  12   #define HA VE_NETINET _IN_H
  13   #define HA VE_NETDB_H
  14   #define HA VE_SYS_TIM E_H
  15   #else /* T ESTING */
  16   #define NE ED_SOCKETS
  17   #endif /*  TESTING */
  18  
  19   #define IN _LIBXML
  20   #include " libxml.h"
  21  
  22   #ifdef LIB XML_FTP_EN ABLED
  23   #include < string.h>
  24  
  25   #ifdef HAV E_STDLIB_H
  26   #include < stdlib.h>
  27   #endif
  28   #ifdef HAV E_UNISTD_H
  29   #include < unistd.h>
  30   #endif
  31   #ifdef HAV E_SYS_SOCK ET_H
  32   #include < sys/socket .h>
  33   #endif
  34   #ifdef HAV E_NETINET_ IN_H
  35   #include < netinet/in .h>
  36   #endif
  37   #ifdef HAV E_ARPA_INE T_H
  38   #include < arpa/inet. h>
  39   #endif
  40   #ifdef HAV E_NETDB_H
  41   #include < netdb.h>
  42   #endif
  43   #ifdef HAV E_FCNTL_H
  44   #include < fcntl.h>
  45   #endif
  46   #ifdef HAV E_ERRNO_H
  47   #include < errno.h>
  48   #endif
  49   #ifdef HAV E_SYS_TIME _H
  50   #include < sys/time.h >
  51   #endif
  52   #ifdef HAV E_SYS_SELE CT_H
  53   #include < sys/select .h>
  54   #endif
  55   #ifdef HAV E_SYS_SOCK ET_H
  56   #include < sys/socket .h>
  57   #endif
  58   #ifdef HAV E_SYS_TYPE S_H
  59   #include < sys/types. h>
  60   #endif
  61   #ifdef HAV E_STRINGS_ H
  62   #include < strings.h>
  63   #endif
  64  
  65   #include < libxml/xml memory.h>
  66   #include < libxml/par ser.h>
  67   #include < libxml/xml error.h>
  68   #include < libxml/uri .h>
  69   #include < libxml/nan oftp.h>
  70   #include < libxml/glo bals.h>
  71  
  72   /* #define  DEBUG_FTP  1  */
  73   #ifdef STA NDALONE
  74   #ifndef DE BUG_FTP
  75   #define DE BUG_FTP 1
  76   #endif
  77   #endif
  78  
  79  
  80   #if define d(__MINGW3 2__) || de fined(_WIN 32_WCE)
  81   #ifndef _W INSOCKAPI_
  82   #define _W INSOCKAPI_
  83   #endif
  84   #include < wsockcompa t.h>
  85   #include < winsock2.h >
  86   #undef XML _SOCKLEN_T
  87   #define XM L_SOCKLEN_ T unsigned  int
  88   #endif
  89  
  90   /**
  91    * A coupl e portabil ity macros
  92    */
  93   #ifndef _W INSOCKAPI_
  94   #if !defin ed(__BEOS_ _) || defi ned(__HAIK U__)
  95   #define cl osesocket( s) close(s )
  96   #endif
  97   #endif
  98  
  99   #ifdef __B EOS__
  100   #ifndef PF _INET
  101   #define PF _INET AF_I NET
  102   #endif
  103   #endif
  104  
  105   #ifdef _AI X
  106   #ifdef HAV E_BROKEN_S S_FAMILY
  107   #define ss _family __ ss_family
  108   #endif
  109   #endif
  110  
  111   #ifndef XM L_SOCKLEN_ T
  112   #define XM L_SOCKLEN_ T unsigned  int
  113   #endif
  114  
  115   #define FT P_COMMAND_ OK           200
  116   #define FT P_SYNTAX_E RROR         500
  117   #define FT P_GET_PASS WD           331
  118   #define FT P_BUF_SIZE              1024
  119  
  120   #define XM L_NANO_MAX _URLBUF      4096
  121  
  122   typedef st ruct xmlNa noFTPCtxt  {
  123       char * protocol;      /* the  protocol  name */
  124       char * hostname;      /* the  host name  */
  125       int po rt;            /* the  port */
  126       char * path;          /* the  path with in the URL  */
  127       char * user;          /* use r string * /
  128       char * passwd;        /* pas swd string  */
  129   #ifdef SUP PORT_IP6
  130       struct  sockaddr_ storage ft pAddr; /*  this is la rge enough  to hold I Pv6 addres s*/
  131   #else
  132       struct  sockaddr_ in ftpAddr ; /* the s ocket addr ess struct  */
  133   #endif
  134       int pa ssive;         /* cur rently we  support on ly passive  !!! */
  135       SOCKET  controlFd ;   /* the  file desc riptor for  the contr ol socket  */
  136       SOCKET  dataFd;       /* the  file desc riptor for  the data  socket */
  137       int st ate;           /* WRI TE / READ  / CLOSED * /
  138       int re turnValue;     /* the  protocol  return val ue */
  139       /* buf fer for da ta receive d from the  control c onnection  */
  140       char c ontrolBuf[ FTP_BUF_SI ZE + 1];
  141       int co ntrolBufIn dex;
  142       int co ntrolBufUs ed;
  143       int co ntrolBufAn swer;
  144   } xmlNanoF TPCtxt, *x mlNanoFTPC txtPtr;
  145  
  146   static int  initializ ed = 0;
  147   static cha r *proxy =  NULL;       /* the p roxy name  if any */
  148   static int  proxyPort  = 0;        /* the p roxy port  if any */
  149   static cha r *proxyUs er = NULL;   /* user  for proxy  authentica tion */
  150   static cha r *proxyPa sswd = NUL L;/* passw d for prox y authenti cation */
  151   static int  proxyType  = 0;        /* uses  TYPE or a@ b ? */
  152  
  153   #ifdef SUP PORT_IP6
  154   static
  155   int have_i pv6(void)  {
  156       int s;
  157  
  158       s = so cket (AF_I NET6, SOCK _STREAM, 0 );
  159       if (s  != -1) {
  160           cl ose (s);
  161           re turn (1);
  162       }
  163       return  (0);
  164   }
  165   #endif
  166  
  167   /**
  168    * xmlFTPE rrMemory:
  169    * @extra:   extra in formations
  170    *
  171    * Handle  an out of  memory con dition
  172    */
  173   static voi d
  174   xmlFTPErrM emory(cons t char *ex tra)
  175   {
  176       __xmlS impleError (XML_FROM_ FTP, XML_E RR_NO_MEMO RY, NULL,  NULL, extr a);
  177   }
  178  
  179   /**
  180    * xmlNano FTPInit:
  181    *
  182    * Initial ize the FT P protocol  layer.
  183    * Current ly it just  checks fo r proxy in formations ,
  184    * and get  the hostn ame
  185    */
  186  
  187   void
  188   xmlNanoFTP Init(void)  {
  189       const  char *env;
  190   #ifdef _WI NSOCKAPI_
  191       WSADAT A wsaData;
  192   #endif
  193  
  194       if (in itialized)
  195           re turn;
  196  
  197   #ifdef _WI NSOCKAPI_
  198       if (WS AStartup(M AKEWORD(1,  1), &wsaD ata) != 0)
  199           re turn;
  200   #endif
  201  
  202         proxyPort  PORT ;
  203       env =  getenv("no _proxy");
  204       if (en v && ((env [0] == '*'  ) && (env [1] == 0)) )
  205           re turn;
  206       env =  getenv("ft p_proxy");
  207       if (en v != NULL)  {
  208           xm lNanoFTPSc anProxy(en v);
  209       } else  {
  210           en v = getenv ("FTP_PROX Y");
  211           if  (env != N ULL) {
  212                xmlNanoF TPScanProx y(env);
  213           }
  214       }
  215       env =  getenv("ft p_proxy_us er");
  216       if (en v != NULL)  {
  217           pr oxyUser =  xmlMemStrd up(env);
  218       }
  219       env =  getenv("ft p_proxy_pa ssword");
  220       if (en v != NULL)  {
  221           pr oxyPasswd  = xmlMemSt rdup(env);
  222       }
  223       initia lized = 1;
  224   }
  225  
  226   /**
  227    * xmlNano FTPCleanup :
  228    *
  229    * Cleanup  the FTP p rotocol la yer. This  cleanup pr oxy inform ations.
  230    */
  231  
  232   void
  233   xmlNanoFTP Cleanup(vo id) {
  234       if (pr oxy != NUL L) {
  235           xm lFree(prox y);
  236           pr oxy = NULL ;
  237       }
  238       if (pr oxyUser !=  NULL) {
  239           xm lFree(prox yUser);
  240           pr oxyUser =  NULL;
  241       }
  242       if (pr oxyPasswd  != NULL) {
  243           xm lFree(prox yPasswd);
  244           pr oxyPasswd  = NULL;
  245       }
  246   #ifdef _WI NSOCKAPI_
  247       if (in itialized)
  248           WS ACleanup() ;
  249   #endif
  250       initia lized = 0;
  251   }
  252  
  253   /**
  254    * xmlNano FTPProxy:
  255    * @host:   the proxy  host name
  256    * @port:   the proxy  port
  257    * @user:   the proxy  user name
  258    * @passwd :  the pro xy passwor d
  259    * @type:   the type  of proxy 1  for using  SITE, 2 f or USER a@ b
  260    *
  261    * Setup t he FTP pro xy informa tions.
  262    * This ca n also be  done by us ing ftp_pr oxy ftp_pr oxy_user a nd
  263    * ftp_pro xy_passwor d environm ent variab les.
  264    */
  265  
  266   void
  267   xmlNanoFTP Proxy(cons t char *ho st, int po rt, const  char *user ,
  268                    cons t char *pa sswd, int  type) {
  269       if (pr oxy != NUL L) {
  270           xm lFree(prox y);
  271           pr oxy = NULL ;
  272       }
  273       if (pr oxyUser !=  NULL) {
  274           xm lFree(prox yUser);
  275           pr oxyUser =  NULL;
  276       }
  277       if (pr oxyPasswd  != NULL) {
  278           xm lFree(prox yPasswd);
  279           pr oxyPasswd  = NULL;
  280       }
  281       if (ho st)
  282           pr oxy = xmlM emStrdup(h ost);
  283       if (us er)
  284           pr oxyUser =  xmlMemStrd up(user);
  285       if (pa sswd)
  286           pr oxyPasswd  = xmlMemSt rdup(passw d);
  287       proxyP ort = port ;
  288       proxyT ype = type ;
  289   }
  290  
  291   /**
  292    * xmlNano FTPScanURL :
  293    * @ctx:   an FTP con text
  294    * @URL:   The URL us ed to init ialize the  context
  295    *
  296    * (Re)Ini tialize an  FTP conte xt by pars ing the UR L and find ing
  297    * the pro tocol host  port and  path it in dicates.
  298    */
  299  
  300   static voi d
  301   xmlNanoFTP ScanURL(vo id *ctx, c onst char  *URL) {
  302       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  303       xmlURI Ptr uri;
  304  
  305       /*
  306        * Cle ar any exi sting data  from the  context
  307        */
  308       if (ct xt->protoc ol != NULL ) {
  309           xm lFree(ctxt ->protocol );
  310           ct xt->protoc ol = NULL;
  311       }
  312       if (ct xt->hostna me != NULL ) {
  313           xm lFree(ctxt ->hostname );
  314           ct xt->hostna me = NULL;
  315       }
  316       if (ct xt->path ! = NULL) {
  317           xm lFree(ctxt ->path);
  318           ct xt->path =  NULL;
  319       }
  320       if (UR L == NULL)  return;
  321  
  322       uri =  xmlParseUR IRaw(URL,  1);
  323       if (ur i == NULL)
  324           re turn;
  325  
  326       if ((u ri->scheme  == NULL)  || (uri->s erver == N ULL)) {
  327           xm lFreeURI(u ri);
  328           re turn;
  329       }
  330  
  331       ctxt-> protocol =  xmlMemStr dup(uri->s cheme);
  332       ctxt-> hostname =  xmlMemStr dup(uri->s erver);
  333       if (ur i->path !=  NULL)
  334           ct xt->path =  xmlMemStr dup(uri->p ath);
  335       else
  336           ct xt->path =  xmlMemStr dup("/");
  337       if (ur i->port !=  0)
  338           ct xt->port =  uri->port ;
  339  
  340       if (ur i->user !=  NULL) {
  341           ch ar *cptr;
  342           if  ((cptr=st rchr(uri-> user, ':') ) == NULL)
  343                ctxt->us er = xmlMe mStrdup(ur i->user);
  344           el se {
  345                ctxt->us er = (char  *)xmlStrn dup((xmlCh ar *)uri-> user,
  346                                 (c ptr - uri- >user));
  347                ctxt->pa sswd = xml MemStrdup( cptr+1);
  348           }
  349       }
  350  
  351       xmlFre eURI(uri);
  352  
  353   }
  354  
  355   /**
  356    * xmlNano FTPUpdateU RL:
  357    * @ctx:   an FTP con text
  358    * @URL:   The URL us ed to upda te the con text
  359    *
  360    * Update  an FTP con text by pa rsing the  URL and fi nding
  361    * new pat h it indic ates. If t here is an  error in  the
  362    * protoco l, hostnam e, port or  other inf ormation,  the
  363    * error i s raised.  It indicat es a new c onnection  has to
  364    * be esta blished.
  365    *
  366    * Returns  0 if Ok,  -1 in case  of error  (other hos t).
  367    */
  368  
  369   int
  370   xmlNanoFTP UpdateURL( void *ctx,  const cha r *URL) {
  371       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  372       xmlURI Ptr uri;
  373  
  374       if (UR L == NULL)
  375           re turn(-1);
  376       if (ct xt == NULL )
  377           re turn(-1);
  378       if (ct xt->protoc ol == NULL )
  379           re turn(-1);
  380       if (ct xt->hostna me == NULL )
  381           re turn(-1);
  382  
  383       uri =  xmlParseUR IRaw(URL,  1);
  384       if (ur i == NULL)
  385           re turn(-1);
  386  
  387       if ((u ri->scheme  == NULL)  || (uri->s erver == N ULL)) {
  388           xm lFreeURI(u ri);
  389           re turn(-1);
  390       }
  391       if ((s trcmp(ctxt ->protocol , uri->sch eme)) ||
  392           (s trcmp(ctxt ->hostname , uri->ser ver)) ||
  393           (( uri->port  != 0) && ( ctxt->port  != uri->p ort))) {
  394           xm lFreeURI(u ri);
  395           re turn(-1);
  396       }
  397  
  398       if (ur i->port !=  0)
  399           ct xt->port =  uri->port ;
  400  
  401       if (ct xt->path ! = NULL) {
  402           xm lFree(ctxt ->path);
  403           ct xt->path =  NULL;
  404       }
  405  
  406       if (ur i->path ==  NULL)
  407           ct xt->path =  xmlMemStr dup("/");
  408       else
  409           ct xt->path =  xmlMemStr dup(uri->p ath);
  410  
  411       xmlFre eURI(uri);
  412  
  413       return (0);
  414   }
  415  
  416   /**
  417    * xmlNano FTPScanPro xy:
  418    * @URL:   The proxy  URL used t o initiali ze the pro xy context
  419    *
  420    * (Re)Ini tialize th e FTP Prox y context  by parsing  the URL a nd finding
  421    * the pro tocol host  port it i ndicates.
  422    * Should  be like ft p://myprox y/ or ftp: //myproxy: 3128/
  423    * A NULL  URL cleans  up proxy  informatio ns.
  424    */
  425  
  426   void
  427   xmlNanoFTP ScanProxy( const char  *URL) {
  428       xmlURI Ptr uri;
  429  
  430       if (pr oxy != NUL L) {
  431           xm lFree(prox y);
  432           pr oxy = NULL ;
  433       }
  434       proxyP ort = 0;
  435  
  436   #ifdef DEB UG_FTP
  437       if (UR L == NULL)
  438           xm lGenericEr ror(xmlGen ericErrorC ontext,
  439                    "Rem oving FTP  proxy info \n");
  440       else
  441           xm lGenericEr ror(xmlGen ericErrorC ontext,
  442                    "Usi ng FTP pro xy %s\n",  URL);
  443   #endif
  444       if (UR L == NULL)  return;
  445  
  446       uri =  xmlParseUR IRaw(URL,  1);
  447       if ((u ri == NULL ) || (uri- >scheme ==  NULL) ||
  448           (s trcmp(uri- >scheme, " ftp")) ||  (uri->serv er == NULL )) {
  449           __ xmlIOErr(X ML_FROM_FT P, XML_FTP _URL_SYNTA X, "Syntax  Error\n") ;
  450           if  (uri != N ULL)
  451                xmlFreeU RI(uri);
  452           re turn;
  453       }
  454  
  455       proxy  = xmlMemSt rdup(uri-> server);
  456       if (ur i->port !=  0)
  457           pr oxyPort =  uri->port;
  458  
  459       xmlFre eURI(uri);
  460   }
  461  
  462   /**
  463    * xmlNano FTPNewCtxt :
  464    * @URL:   The URL us ed to init ialize the  context
  465    *
  466    * Allocat e and init ialize a n ew FTP con text.
  467    *
  468    * Returns  an FTP co ntext or N ULL in cas e of error .
  469    */
  470  
  471   void*
  472   xmlNanoFTP NewCtxt(co nst char * URL) {
  473       xmlNan oFTPCtxtPt r ret;
  474       char * unescaped;
  475  
  476       ret =  (xmlNanoFT PCtxtPtr)  xmlMalloc( sizeof(xml NanoFTPCtx t));
  477       if (re t == NULL)  {
  478           xm lFTPErrMem ory("alloc ating FTP  context");
  479           re turn(NULL) ;
  480       }
  481  
  482       memset (ret, 0, s izeof(xmlN anoFTPCtxt ));
  483         ret->port  PORT ;
  484       ret->p assive = 1 ;
  485       ret->r eturnValue  = 0;
  486       ret->c ontrolBufI ndex = 0;
  487       ret->c ontrolBufU sed = 0;
  488       ret->c ontrolFd =  INVALID_S OCKET;
  489  
  490       unesca ped = xmlU RIUnescape String(URL , 0, NULL) ;
  491       if (un escaped !=  NULL) {
  492           xm lNanoFTPSc anURL(ret,  unescaped );
  493           xm lFree(unes caped);
  494       } else  if (URL ! = NULL)
  495           xm lNanoFTPSc anURL(ret,  URL);
  496  
  497       return (ret);
  498   }
  499  
  500   /**
  501    * xmlNano FTPFreeCtx t:
  502    * @ctx:   an FTP con text
  503    *
  504    * Frees t he context  after clo sing the c onnection.
  505    */
  506  
  507   void
  508   xmlNanoFTP FreeCtxt(v oid * ctx)  {
  509       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  510       if (ct xt == NULL ) return;
  511       if (ct xt->hostna me != NULL ) xmlFree( ctxt->host name);
  512       if (ct xt->protoc ol != NULL ) xmlFree( ctxt->prot ocol);
  513       if (ct xt->path ! = NULL) xm lFree(ctxt ->path);
  514       ctxt-> passive =  1;
  515       if (ct xt->contro lFd != INV ALID_SOCKE T) closeso cket(ctxt- >controlFd );
  516       ctxt-> controlFd  = INVALID_ SOCKET;
  517       ctxt-> controlBuf Index = -1 ;
  518       ctxt-> controlBuf Used = -1;
  519       xmlFre e(ctxt);
  520   }
  521  
  522   /**
  523    * xmlNano FTPParseRe sponse:
  524    * @buf:   the buffer  containin g the resp onse
  525    * @len:   the buffer  length
  526    *
  527    * Parsing  of the se rver answe r, we just  extract t he code.
  528    *
  529    * returns  0 for err ors
  530    *     +XX X for last  line of r esponse
  531    *     -XX X for resp onse to be  continued
  532    */
  533   static int
  534   xmlNanoFTP ParseRespo nse(char * buf, int l en) {
  535       int va l = 0;
  536  
  537       if (le n < 3) ret urn(-1);
  538       if ((* buf >= '0' ) && (*buf  <= '9'))
  539           va l = val *  10 + (*buf  - '0');
  540       else
  541           re turn(0);
  542       buf++;
  543       if ((* buf >= '0' ) && (*buf  <= '9'))
  544           va l = val *  10 + (*buf  - '0');
  545       else
  546           re turn(0);
  547       buf++;
  548       if ((* buf >= '0' ) && (*buf  <= '9'))
  549           va l = val *  10 + (*buf  - '0');
  550       else
  551           re turn(0);
  552       buf++;
  553       if (*b uf == '-')
  554           re turn(-val) ;
  555       return (val);
  556   }
  557  
  558   /**
  559    * xmlNano FTPGetMore :
  560    * @ctx:   an FTP con text
  561    *
  562    * Read mo re informa tion from  the FTP co ntrol conn ection
  563    * Returns  the numbe r of bytes  read, < 0  indicates  an error
  564    */
  565   static int
  566   xmlNanoFTP GetMore(vo id *ctx) {
  567       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  568       int le n;
  569       int si ze;
  570  
  571       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET )) return( -1);
  572  
  573       if ((c txt->contr olBufIndex  < 0) || ( ctxt->cont rolBufInde x > FTP_BU F_SIZE)) {
  574   #ifdef DEB UG_FTP
  575           xm lGenericEr ror(xmlGen ericErrorC ontext,
  576                    "xml NanoFTPGet More : con trolBufInd ex = %d\n" ,
  577                    ctxt ->controlB ufIndex);
  578   #endif
  579           re turn(-1);
  580       }
  581  
  582       if ((c txt->contr olBufUsed  < 0) || (c txt->contr olBufUsed  > FTP_BUF_ SIZE)) {
  583   #ifdef DEB UG_FTP
  584           xm lGenericEr ror(xmlGen ericErrorC ontext,
  585                    "xml NanoFTPGet More : con trolBufUse d = %d\n",
  586                    ctxt ->controlB ufUsed);
  587   #endif
  588           re turn(-1);
  589       }
  590       if (ct xt->contro lBufIndex  > ctxt->co ntrolBufUs ed) {
  591   #ifdef DEB UG_FTP
  592           xm lGenericEr ror(xmlGen ericErrorC ontext,
  593                    "xml NanoFTPGet More : con trolBufInd ex > contr olBufUsed  %d > %d\n" ,
  594                   ctxt- >controlBu fIndex, ct xt->contro lBufUsed);
  595   #endif
  596           re turn(-1);
  597       }
  598  
  599       /*
  600        * Fir st pack th e control  buffer
  601        */
  602       if (ct xt->contro lBufIndex  > 0) {
  603           me mmove(&ctx t->control Buf[0], &c txt->contr olBuf[ctxt ->controlB ufIndex],
  604                    ctxt ->controlB ufUsed - c txt->contr olBufIndex );
  605           ct xt->contro lBufUsed - = ctxt->co ntrolBufIn dex;
  606           ct xt->contro lBufIndex  = 0;
  607       }
  608       size =  FTP_BUF_S IZE - ctxt ->controlB ufUsed;
  609       if (si ze == 0) {
  610   #ifdef DEB UG_FTP
  611           xm lGenericEr ror(xmlGen ericErrorC ontext,
  612                    "xml NanoFTPGet More : buf fer full % d \n", ctx t->control BufUsed);
  613   #endif
  614           re turn(0);
  615       }
  616  
  617       /*
  618        * Rea d the amou nt left on  the contr ol connect ion
  619        */
  620       if ((l en = recv( ctxt->cont rolFd, &ct xt->contro lBuf[ctxt- >controlBu fIndex],
  621                         size, 0))  < 0) {
  622           __ xmlIOErr(X ML_FROM_FT P, 0, "rec v failed") ;
  623           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  624           ct xt->contro lFd = INVA LID_SOCKET ;
  625           re turn(-1);
  626       }
  627   #ifdef DEB UG_FTP
  628       xmlGen ericError( xmlGeneric ErrorConte xt,
  629                "xmlNano FTPGetMore  : read %d  [%d - %d] \n", len,
  630               ctxt->con trolBufUse d, ctxt->c ontrolBufU sed + len) ;
  631   #endif
  632       ctxt-> controlBuf Used += le n;
  633       ctxt-> controlBuf [ctxt->con trolBufUse d] = 0;
  634  
  635       return (len);
  636   }
  637  
  638   /**
  639    * xmlNano FTPReadRes ponse:
  640    * @ctx:   an FTP con text
  641    *
  642    * Read th e response  from the  FTP server  after a c ommand.
  643    * Returns  the code  number
  644    */
  645   static int
  646   xmlNanoFTP ReadRespon se(void *c tx) {
  647       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  648       char * ptr, *end;
  649       int le n;
  650       int re s = -1, cu r = -1;
  651  
  652       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET )) return( -1);
  653  
  654   get_more:
  655       /*
  656        * Ass umes every thing up t o controlB uf[control BufIndex]  has been r ead
  657        * and  analyzed.
  658        */
  659       len =  xmlNanoFTP GetMore(ct x);
  660       if (le n < 0) {
  661           re turn(-1);
  662       }
  663       if ((c txt->contr olBufUsed  == 0) && ( len == 0))  {
  664           re turn(-1);
  665       }
  666       ptr =  &ctxt->con trolBuf[ct xt->contro lBufIndex] ;
  667       end =  &ctxt->con trolBuf[ct xt->contro lBufUsed];
  668  
  669   #ifdef DEB UG_FTP
  670       xmlGen ericError( xmlGeneric ErrorConte xt,
  671                "\n<<<\n %s\n--\n",  ptr);
  672   #endif
  673       while  (ptr < end ) {
  674           cu r = xmlNan oFTPParseR esponse(pt r, end - p tr);
  675           if  (cur > 0)  {
  676                /*
  677                 * Succe ssfully sc anned the  control co de, scratc h
  678                 * till  the end of  the line,  but keep  the index  to be
  679                 * able  to analyze  the resul t if neede d.
  680                 */
  681                res = cu r;
  682                ptr += 3 ;
  683                ctxt->co ntrolBufAn swer = ptr  - ctxt->c ontrolBuf;
  684                while (( ptr < end)  && (*ptr  != '\n'))  ptr++;
  685                if (*ptr  == '\n')  ptr++;
  686                if (*ptr  == '\r')  ptr++;
  687                break;
  688           }
  689           wh ile ((ptr  < end) &&  (*ptr != ' \n')) ptr+ +;
  690           if  (ptr >= e nd) {
  691                ctxt->co ntrolBufIn dex = ctxt ->controlB ufUsed;
  692                goto get _more;
  693           }
  694           if  (*ptr !=  '\r') ptr+ +;
  695       }
  696  
  697       if (re s < 0) got o get_more ;
  698       ctxt-> controlBuf Index = pt r - ctxt-> controlBuf ;
  699   #ifdef DEB UG_FTP
  700       ptr =  &ctxt->con trolBuf[ct xt->contro lBufIndex] ;
  701       xmlGen ericError( xmlGeneric ErrorConte xt, "\n--- \n%s\n--\n ", ptr);
  702   #endif
  703  
  704   #ifdef DEB UG_FTP
  705       xmlGen ericError( xmlGeneric ErrorConte xt, "Got % d\n", res) ;
  706   #endif
  707       return (res / 100 );
  708   }
  709  
  710   /**
  711    * xmlNano FTPGetResp onse:
  712    * @ctx:   an FTP con text
  713    *
  714    * Get the  response  from the F TP server  after a co mmand.
  715    * Returns  the code  number
  716    */
  717  
  718   int
  719   xmlNanoFTP GetRespons e(void *ct x) {
  720       int re s;
  721  
  722       res =  xmlNanoFTP ReadRespon se(ctx);
  723  
  724       return (res);
  725   }
  726  
  727   /**
  728    * xmlNano FTPCheckRe sponse:
  729    * @ctx:   an FTP con text
  730    *
  731    * Check i f there is  a respons e from the  FTP serve r after a  command.
  732    * Returns  the code  number, or  0
  733    */
  734  
  735   int
  736   xmlNanoFTP CheckRespo nse(void * ctx) {
  737       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  738       fd_set  rfd;
  739       struct  timeval t v;
  740  
  741       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET )) return( -1);
  742       tv.tv_ sec = 0;
  743       tv.tv_ usec = 0;
  744       FD_ZER O(&rfd);
  745       FD_SET (ctxt->con trolFd, &r fd);
  746       switch (select(ct xt->contro lFd + 1, & rfd, NULL,  NULL, &tv )) {
  747           ca se 0:
  748                return(0 );
  749           ca se -1:
  750                __xmlIOE rr(XML_FRO M_FTP, 0,  "select");
  751                return(- 1);
  752  
  753       }
  754  
  755       return (xmlNanoFT PReadRespo nse(ctx));
  756   }
  757  
  758   /**
  759    * Send th e user aut henticatio n
  760    */
  761  
  762   static int
  763   xmlNanoFTP SendUser(v oid *ctx)  {
  764       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  765       char b uf[200];
  766       int le n;
  767       int re s;
  768  
  769       if (ct xt->user = = NULL)
  770           sn printf(buf , sizeof(b uf), "USER  anonymous \r\n");
  771       else
  772           sn printf(buf , sizeof(b uf), "USER  %s\r\n",  ctxt->user );
  773       buf[si zeof(buf)  - 1] = 0;
  774       len =  strlen(buf );
  775   #ifdef DEB UG_FTP
  776       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  777   #endif
  778       res =  send(ctxt- >controlFd , buf, len , 0);
  779       if (re s < 0) {
  780           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  781           re turn(res);
  782       }
  783       return (0);
  784   }
  785  
  786   /**
  787    * Send th e password  authentic ation
  788    */
  789  
  790   static int
  791   xmlNanoFTP SendPasswd (void *ctx ) {
  792       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  793       char b uf[200];
  794       int le n;
  795       int re s;
  796  
  797       if (ct xt->passwd  == NULL)
  798           sn printf(buf , sizeof(b uf), "PASS  anonymous @\r\n");
  799       else
  800           sn printf(buf , sizeof(b uf), "PASS  %s\r\n",  ctxt->pass wd);
  801       buf[si zeof(buf)  - 1] = 0;
  802       len =  strlen(buf );
  803   #ifdef DEB UG_FTP
  804       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  805   #endif
  806       res =  send(ctxt- >controlFd , buf, len , 0);
  807       if (re s < 0) {
  808           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  809           re turn(res);
  810       }
  811       return (0);
  812   }
  813  
  814   /**
  815    * xmlNano FTPQuit:
  816    * @ctx:   an FTP con text
  817    *
  818    * Send a  QUIT comma nd to the  server
  819    *
  820    * Returns  -1 in cas e of error , 0 otherw ise
  821    */
  822  
  823  
  824   int
  825   xmlNanoFTP Quit(void  *ctx) {
  826       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  827       char b uf[200];
  828       int le n, res;
  829  
  830       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET )) return( -1);
  831  
  832       snprin tf(buf, si zeof(buf),  "QUIT\r\n ");
  833       len =  strlen(buf );
  834   #ifdef DEB UG_FTP
  835       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf); /* J ust to be  consistent , even tho ugh we kno w it can't  have a %  in it */
  836   #endif
  837       res =  send(ctxt- >controlFd , buf, len , 0);
  838       if (re s < 0) {
  839           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  840           re turn(res);
  841       }
  842       return (0);
  843   }
  844  
  845   /**
  846    * xmlNano FTPConnect :
  847    * @ctx:   an FTP con text
  848    *
  849    * Tries t o open a c ontrol con nection
  850    *
  851    * Returns  -1 in cas e of error , 0 otherw ise
  852    */
  853  
  854   int
  855   xmlNanoFTP Connect(vo id *ctx) {
  856       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  857       struct  hostent * hp;
  858       int po rt;
  859       int re s;
  860       int ad drlen = si zeof (stru ct sockadd r_in);
  861  
  862       if (ct xt == NULL )
  863           re turn(-1);
  864       if (ct xt->hostna me == NULL )
  865           re turn(-1);
  866  
  867       /*
  868        * do  the blocki ng DNS que ry.
  869        */
  870       if (pr oxy) {
  871           po rt = proxy Port;
  872       } else  {
  873           po rt = ctxt- >port;
  874       }
  875       if (po rt == 0)
  876           po rt =  PORT ;
  877  
  878       memset  (&ctxt->f tpAddr, 0,  sizeof(ct xt->ftpAdd r));
  879  
  880   #ifdef SUP PORT_IP6
  881       if (ha ve_ipv6 () ) {
  882           st ruct addri nfo hints,  *tmp, *re sult;
  883  
  884           re sult = NUL L;
  885           me mset (&hin ts, 0, siz eof(hints) );
  886           hi nts.ai_soc ktype = SO CK_STREAM;
  887  
  888           if  (proxy) {
  889                if (geta ddrinfo (p roxy, NULL , &hints,  &result) ! = 0) {
  890                    __xm lIOErr(XML _FROM_FTP,  0, "getad drinfo fai led");
  891                    retu rn (-1);
  892                }
  893           }
  894           el se
  895                if (geta ddrinfo (c txt->hostn ame, NULL,  &hints, & result) !=  0) {
  896                    __xm lIOErr(XML _FROM_FTP,  0, "getad drinfo fai led");
  897                    retu rn (-1);
  898                }
  899  
  900           fo r (tmp = r esult; tmp ; tmp = tm p->ai_next )
  901                if (tmp- >ai_family  == AF_INE T || tmp-> ai_family  == AF_INET 6)
  902                    brea k;
  903  
  904           if  (!tmp) {
  905                if (resu lt)
  906                    free addrinfo ( result);
  907                __xmlIOE rr(XML_FRO M_FTP, 0,  "getaddrin fo failed" );
  908                return ( -1);
  909           }
  910           if  (tmp->ai_ addrlen >  sizeof(ctx t->ftpAddr )) {
  911                __xmlIOE rr(XML_FRO M_FTP, 0,  "gethostby name addre ss mismatc h");
  912                return ( -1);
  913           }
  914           if  (tmp->ai_ family ==  AF_INET6)  {
  915                memcpy ( &ctxt->ftp Addr, tmp- >ai_addr,  tmp->ai_ad drlen);
  916                ((struct  sockaddr_ in6 *) &ct xt->ftpAdd r)->sin6_p ort = hton s (port);
  917                ctxt->co ntrolFd =  socket (AF _INET6, SO CK_STREAM,  0);
  918           }
  919           el se {
  920                memcpy ( &ctxt->ftp Addr, tmp- >ai_addr,  tmp->ai_ad drlen);
  921                ((struct  sockaddr_ in *) &ctx t->ftpAddr )->sin_por t = htons  (port);
  922                ctxt->co ntrolFd =  socket (AF _INET, SOC K_STREAM,  0);
  923           }
  924           ad drlen = tm p->ai_addr len;
  925           fr eeaddrinfo  (result);
  926       }
  927       else
  928   #endif
  929       {
  930           if  (proxy)
  931                hp = get hostbyname  (proxy);
  932           el se
  933                hp = get hostbyname  (ctxt->ho stname);
  934           if  (hp == NU LL) {
  935                __xmlIOE rr(XML_FRO M_FTP, 0,  "gethostby name faile d");
  936                return ( -1);
  937           }
  938           if  ((unsigne d int) hp- >h_length  >
  939                sizeof(( (struct so ckaddr_in  *)&ctxt->f tpAddr)->s in_addr))  {
  940                __xmlIOE rr(XML_FRO M_FTP, 0,  "gethostby name addre ss mismatc h");
  941                return ( -1);
  942           }
  943  
  944           /*
  945            *  Prepare t he socket
  946            * /
  947           (( struct soc kaddr_in * )&ctxt->ft pAddr)->si n_family =  AF_INET;
  948           me mcpy (&((s truct sock addr_in *) &ctxt->ftp Addr)->sin _addr,
  949                    hp-> h_addr_lis t[0], hp-> h_length);
  950           (( struct soc kaddr_in * )&ctxt->ft pAddr)->si n_port =
  951                 (unsign ed short)h tons ((uns igned shor t)port);
  952           ct xt->contro lFd = sock et (AF_INE T, SOCK_ST REAM, 0);
  953           ad drlen = si zeof (stru ct sockadd r_in);
  954       }
  955  
  956       if (ct xt->contro lFd == INV ALID_SOCKE T) {
  957           __ xmlIOErr(X ML_FROM_FT P, 0, "soc ket failed ");
  958           re turn(-1);
  959       }
  960  
  961       /*
  962        * Do  the connec t.
  963        */
  964       if (co nnect(ctxt ->controlF d, (struct  sockaddr  *) &ctxt-> ftpAddr,
  965                addrlen)  < 0) {
  966           __ xmlIOErr(X ML_FROM_FT P, 0, "Fai led to cre ate a conn ection");
  967           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  968           ct xt->contro lFd = INVA LID_SOCKET ;
  969           re turn(-1);
  970       }
  971  
  972       /*
  973        * Wai t for the  HELLO from  the serve r.
  974        */
  975       res =  xmlNanoFTP GetRespons e(ctxt);
  976       if (re s != 2) {
  977           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  978           ct xt->contro lFd = INVA LID_SOCKET ;
  979           re turn(-1);
  980       }
  981  
  982       /*
  983        * Sta te diagram  for the l ogin opera tion on th e FTP serv er
  984        *
  985        * Ref erence: RF C 959
  986        *
  987        *                         1
  988        * +-- -+   USER     +---+-- ---------- ->+---+
  989        * | B  |-------- -->| W | 2        --- ->| E |
  990        * +-- -+            +---+-- ----  |  - ->+---+
  991        *                    | |        | | |
  992        *                  3 | | 4, 5   | | |
  993        *     ---------- ----   --- --  | | |
  994        *   |                         | | | |
  995        *   |                         | | | |
  996        *   |                   --- ------  |
  997        *   |                 1|      | |   |
  998        *   V                  |      | |   |
  999        * +-- -+   PASS     +---+ 2   |  ----- ->+---+
  1000        * |    |-------- -->| W |-- ---------- ->| S |
  1001        * +-- -+            +---+    --------- ->+---+
  1002        *                    | |    | |     |
  1003        *                  3 | |4,5 | |     |
  1004        *     ---------- ----   --- -----   |
  1005        *   |                       | |  |  |
  1006        *   |                       | |  |  |
  1007        *   |                   --- --------
  1008        *   |               1,3|    | |  |
  1009        *   V                  |  2 | |  |
  1010        * +-- -+   ACCT     +---+--   |   ---- ->+---+
  1011        * |    |-------- -->| W | 4 ,5 ------- ->| F |
  1012        * +-- -+            +---+-- ---------- ->+---+
  1013        *
  1014        * Of  course in  case of us ing a prox y this get  really na sty and is  not
  1015        * sta ndardized  at all :-(
  1016        */
  1017       if (pr oxy) {
  1018           in t len;
  1019           ch ar buf[400 ];
  1020  
  1021           if  (proxyUse r != NULL)  {
  1022                /*
  1023                 * We ne ed proxy a uth
  1024                 */
  1025                snprintf (buf, size of(buf), " USER %s\r\ n", proxyU ser);
  1026                buf[size of(buf) -  1] = 0;
  1027                len = st rlen(buf);
  1028   #ifdef DEB UG_FTP
  1029                xmlGener icError(xm lGenericEr rorContext , "%s", bu f);
  1030   #endif
  1031                res = se nd(ctxt->c ontrolFd,  buf, len,  0);
  1032                if (res  < 0) {
  1033                    __xm lIOErr(XML _FROM_FTP,  0, "send  failed");
  1034                    clos esocket(ct xt->contro lFd);
  1035                    ctxt ->controlF d = INVALI D_SOCKET;
  1036                    retu rn(res);
  1037                }
  1038                res = xm lNanoFTPGe tResponse( ctxt);
  1039                switch ( res) {
  1040                    case  2:
  1041                         if (proxyP asswd == N ULL)
  1042                             break;
  1043                    case  3:
  1044                         if (proxyP asswd != N ULL)
  1045                             snprin tf(buf, si zeof(buf),  "PASS %s\ r\n", prox yPasswd);
  1046                         else
  1047                             snprin tf(buf, si zeof(buf),  "PASS ano nymous@\r\ n");
  1048                         buf[sizeof (buf) - 1]  = 0;
  1049                         len = strl en(buf);
  1050   #ifdef DEB UG_FTP
  1051                         xmlGeneric Error(xmlG enericErro rContext,  "%s", buf) ;
  1052   #endif
  1053                         res = send (ctxt->con trolFd, bu f, len, 0) ;
  1054                         if (res <  0) {
  1055                             __xmlI OErr(XML_F ROM_FTP, 0 , "send fa iled");
  1056                             closes ocket(ctxt ->controlF d);
  1057                             ctxt-> controlFd  = INVALID_ SOCKET;
  1058                             return (res);
  1059                         }
  1060                         res = xmlN anoFTPGetR esponse(ct xt);
  1061                         if (res >  3) {
  1062                             closes ocket(ctxt ->controlF d);
  1063                             ctxt-> controlFd  = INVALID_ SOCKET;
  1064                             return (-1);
  1065                         }
  1066                         break;
  1067                    case  1:
  1068                         break;
  1069                    case  4:
  1070                    case  5:
  1071                    case  -1:
  1072                    defa ult:
  1073                         closesocke t(ctxt->co ntrolFd);
  1074                         ctxt->cont rolFd = IN VALID_SOCK ET;
  1075                         return(-1) ;
  1076                }
  1077           }
  1078  
  1079           /*
  1080            *  We assume  we don't  need more  authentica tion to th e proxy
  1081            *  and that  it succeed ed :-\
  1082            * /
  1083           sw itch (prox yType) {
  1084                case 0:
  1085                    /* w e will try  in sequen ce */
  1086                case 1:
  1087                    /* U sing SITE  command */
  1088                    snpr intf(buf,  sizeof(buf ), "SITE % s\r\n", ct xt->hostna me);
  1089                    buf[ sizeof(buf ) - 1] = 0 ;
  1090                    len  = strlen(b uf);
  1091   #ifdef DEB UG_FTP
  1092                    xmlG enericErro r(xmlGener icErrorCon text, "%s" , buf);
  1093   #endif
  1094                    res  = send(ctx t->control Fd, buf, l en, 0);
  1095                    if ( res < 0) {
  1096                         __xmlIOErr (XML_FROM_ FTP, 0, "s end failed ");
  1097                         closesocke t(ctxt->co ntrolFd);  ctxt->cont rolFd = IN VALID_SOCK ET;
  1098                         ctxt->cont rolFd = IN VALID_SOCK ET;
  1099                         return(res );
  1100                    }
  1101                    res  = xmlNanoF TPGetRespo nse(ctxt);
  1102                    if ( res == 2)  {
  1103                         /* we assu me it work ed :-\ 1 i s error fo r SITE com mand */
  1104                         proxyType  = 1;
  1105                         break;
  1106                    }
  1107                    if ( proxyType  == 1) {
  1108                         closesocke t(ctxt->co ntrolFd);  ctxt->cont rolFd = IN VALID_SOCK ET;
  1109                         ctxt->cont rolFd = IN VALID_SOCK ET;
  1110                         return(-1) ;
  1111                    }
  1112                case 2:
  1113                    /* U SER user@h ost comman d */
  1114                    if ( ctxt->user  == NULL)
  1115                         snprintf(b uf, sizeof (buf), "US ER anonymo us@%s\r\n" ,
  1116                                         ctxt- >hostname) ;
  1117                    else
  1118                         snprintf(b uf, sizeof (buf), "US ER %s@%s\r \n",
  1119                                         ctxt- >user, ctx t->hostnam e);
  1120                    buf[ sizeof(buf ) - 1] = 0 ;
  1121                    len  = strlen(b uf);
  1122   #ifdef DEB UG_FTP
  1123                    xmlG enericErro r(xmlGener icErrorCon text, "%s" , buf);
  1124   #endif
  1125                    res  = send(ctx t->control Fd, buf, l en, 0);
  1126                    if ( res < 0) {
  1127                         __xmlIOErr (XML_FROM_ FTP, 0, "s end failed ");
  1128                         closesocke t(ctxt->co ntrolFd);  ctxt->cont rolFd = IN VALID_SOCK ET;
  1129                         ctxt->cont rolFd = IN VALID_SOCK ET;
  1130                         return(res );
  1131                    }
  1132                    res  = xmlNanoF TPGetRespo nse(ctxt);
  1133                    if ( (res == 1)  || (res = = 2)) {
  1134                         /* we assu me it work ed :-\ */
  1135                         proxyType  = 2;
  1136                         return(0);
  1137                    }
  1138                    if ( ctxt->pass wd == NULL )
  1139                         snprintf(b uf, sizeof (buf), "PA SS anonymo us@\r\n");
  1140                    else
  1141                         snprintf(b uf, sizeof (buf), "PA SS %s\r\n" , ctxt->pa sswd);
  1142                    buf[ sizeof(buf ) - 1] = 0 ;
  1143                    len  = strlen(b uf);
  1144   #ifdef DEB UG_FTP
  1145                    xmlG enericErro r(xmlGener icErrorCon text, "%s" , buf);
  1146   #endif
  1147                    res  = send(ctx t->control Fd, buf, l en, 0);
  1148                    if ( res < 0) {
  1149                         __xmlIOErr (XML_FROM_ FTP, 0, "s end failed ");
  1150                         closesocke t(ctxt->co ntrolFd);  ctxt->cont rolFd = IN VALID_SOCK ET;
  1151                         ctxt->cont rolFd = IN VALID_SOCK ET;
  1152                         return(res );
  1153                    }
  1154                    res  = xmlNanoF TPGetRespo nse(ctxt);
  1155                    if ( (res == 1)  || (res = = 2)) {
  1156                         /* we assu me it work ed :-\ */
  1157                         proxyType  = 2;
  1158                         return(0);
  1159                    }
  1160                    if ( proxyType  == 2) {
  1161                         closesocke t(ctxt->co ntrolFd);  ctxt->cont rolFd = IN VALID_SOCK ET;
  1162                         ctxt->cont rolFd = IN VALID_SOCK ET;
  1163                         return(-1) ;
  1164                    }
  1165                case 3:
  1166                    /*
  1167                     * I f you need  support f or other P roxy authe ntication  scheme
  1168                     * s end the co de or at l east the s equence in  use.
  1169                     */
  1170                default:
  1171                    clos esocket(ct xt->contro lFd); ctxt ->controlF d = INVALI D_SOCKET;
  1172                    ctxt ->controlF d = INVALI D_SOCKET;
  1173                    retu rn(-1);
  1174           }
  1175       }
  1176       /*
  1177        * Non -proxy han dling.
  1178        */
  1179       res =  xmlNanoFTP SendUser(c txt);
  1180       if (re s < 0) {
  1181           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  1182           ct xt->contro lFd = INVA LID_SOCKET ;
  1183           re turn(-1);
  1184       }
  1185       res =  xmlNanoFTP GetRespons e(ctxt);
  1186       switch  (res) {
  1187           ca se 2:
  1188                return(0 );
  1189           ca se 3:
  1190                break;
  1191           ca se 1:
  1192           ca se 4:
  1193           ca se 5:
  1194           ca se -1:
  1195           de fault:
  1196                closesoc ket(ctxt-> controlFd) ; ctxt->co ntrolFd =  INVALID_SO CKET;
  1197                ctxt->co ntrolFd =  INVALID_SO CKET;
  1198                return(- 1);
  1199       }
  1200       res =  xmlNanoFTP SendPasswd (ctxt);
  1201       if (re s < 0) {
  1202           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  1203           ct xt->contro lFd = INVA LID_SOCKET ;
  1204           re turn(-1);
  1205       }
  1206       res =  xmlNanoFTP GetRespons e(ctxt);
  1207       switch  (res) {
  1208           ca se 2:
  1209                break;
  1210           ca se 3:
  1211                __xmlIOE rr(XML_FRO M_FTP, XML _FTP_ACCNT ,
  1212                            "FTP se rver askin g for ACCN T on anony mous\n");
  1213           ca se 1:
  1214           ca se 4:
  1215           ca se 5:
  1216           ca se -1:
  1217           de fault:
  1218                closesoc ket(ctxt-> controlFd) ; ctxt->co ntrolFd =  INVALID_SO CKET;
  1219                ctxt->co ntrolFd =  INVALID_SO CKET;
  1220                return(- 1);
  1221       }
  1222  
  1223       return (0);
  1224   }
  1225  
  1226   /**
  1227    * xmlNano FTPConnect To:
  1228    * @server :  an FTP  server nam e
  1229    * @port:   the port  (use 21 if  0)
  1230    *
  1231    * Tries t o open a c ontrol con nection to  the given  server/po rt
  1232    *
  1233    * Returns  an fTP co ntext or N ULL if it  failed
  1234    */
  1235  
  1236   void*
  1237   xmlNanoFTP ConnectTo( const char  *server,  int port)  {
  1238       xmlNan oFTPCtxtPt r ctxt;
  1239       int re s;
  1240  
  1241       xmlNan oFTPInit() ;
  1242       if (se rver == NU LL)
  1243           re turn(NULL) ;
  1244       if (po rt <= 0)
  1245           re turn(NULL) ;
  1246       ctxt =  (xmlNanoF TPCtxtPtr)  xmlNanoFT PNewCtxt(N ULL);
  1247       ctxt-> hostname =  xmlMemStr dup(server );
  1248       if (po rt != 0)
  1249           ct xt->port =  port;
  1250       res =  xmlNanoFTP Connect(ct xt);
  1251       if (re s < 0) {
  1252           xm lNanoFTPFr eeCtxt(ctx t);
  1253           re turn(NULL) ;
  1254       }
  1255       return (ctxt);
  1256   }
  1257  
  1258   /**
  1259    * xmlNano FTPCwd:
  1260    * @ctx:   an FTP con text
  1261    * @direct ory:  a di rectory on  the serve r
  1262    *
  1263    * Tries t o change t he remote  directory
  1264    *
  1265    * Returns  -1 incase  of error,  1 if CWD  worked, 0  if it fail ed
  1266    */
  1267  
  1268   int
  1269   xmlNanoFTP Cwd(void * ctx, const  char *dir ectory) {
  1270       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1271       char b uf[400];
  1272       int le n;
  1273       int re s;
  1274  
  1275       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET )) return( -1);
  1276       if (di rectory ==  NULL) ret urn 0;
  1277  
  1278       /*
  1279        * Exp ected resp onse code  for CWD:
  1280        *
  1281        * CWD
  1282        *      250
  1283        *      500, 501,  502, 421,  530, 550
  1284        */
  1285       snprin tf(buf, si zeof(buf),  "CWD %s\r \n", direc tory);
  1286       buf[si zeof(buf)  - 1] = 0;
  1287       len =  strlen(buf );
  1288   #ifdef DEB UG_FTP
  1289       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  1290   #endif
  1291       res =  send(ctxt- >controlFd , buf, len , 0);
  1292       if (re s < 0) {
  1293           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  1294           re turn(res);
  1295       }
  1296       res =  xmlNanoFTP GetRespons e(ctxt);
  1297       if (re s == 4) {
  1298           re turn(-1);
  1299       }
  1300       if (re s == 2) re turn(1);
  1301       if (re s == 5) {
  1302           re turn(0);
  1303       }
  1304       return (0);
  1305   }
  1306  
  1307   /**
  1308    * xmlNano FTPDele:
  1309    * @ctx:   an FTP con text
  1310    * @file:   a file or  directory  on the se rver
  1311    *
  1312    * Tries t o delete a n item (fi le or dire ctory) fro m server
  1313    *
  1314    * Returns  -1 incase  of error,  1 if DELE  worked, 0  if it fai led
  1315    */
  1316  
  1317   int
  1318   xmlNanoFTP Dele(void  *ctx, cons t char *fi le) {
  1319       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1320       char b uf[400];
  1321       int le n;
  1322       int re s;
  1323  
  1324       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET ) || (file  == NULL))  return(-1 );
  1325       if (fi le == NULL ) return ( 0);
  1326  
  1327       /*
  1328        * Exp ected resp onse code  for DELE:
  1329        *
  1330        * DEL E
  1331        *        250
  1332        *        450, 55 0
  1333        *        500, 50 1, 502, 42 1, 530
  1334        */
  1335  
  1336       snprin tf(buf, si zeof(buf),  "DELE %s\ r\n", file );
  1337       buf[si zeof(buf)  - 1] = 0;
  1338       len =  strlen(buf );
  1339   #ifdef DEB UG_FTP
  1340       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  1341   #endif
  1342       res =  send(ctxt- >controlFd , buf, len , 0);
  1343       if (re s < 0) {
  1344           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  1345           re turn(res);
  1346       }
  1347       res =  xmlNanoFTP GetRespons e(ctxt);
  1348       if (re s == 4) {
  1349           re turn(-1);
  1350       }
  1351       if (re s == 2) re turn(1);
  1352       if (re s == 5) {
  1353           re turn(0);
  1354       }
  1355       return (0);
  1356   }
  1357   /**
  1358    * xmlNano FTPGetConn ection:
  1359    * @ctx:   an FTP con text
  1360    *
  1361    * Try to  open a dat a connecti on to the  server. Cu rrently on ly
  1362    * passive  mode is s upported.
  1363    *
  1364    * Returns  -1 incase  of error,  0 otherwi se
  1365    */
  1366  
  1367   SOCKET
  1368   xmlNanoFTP GetConnect ion(void * ctx) {
  1369       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1370       char b uf[200], * cur;
  1371       int le n, i;
  1372       int re s;
  1373       unsign ed char ad [6], *adp,  *portp;
  1374       unsign ed int tem p[6];
  1375   #ifdef SUP PORT_IP6
  1376       struct  sockaddr_ storage da taAddr;
  1377   #else
  1378       struct  sockaddr_ in dataAdd r;
  1379   #endif
  1380       XML_SO CKLEN_T da taAddrLen;
  1381  
  1382       if (ct xt == NULL ) return I NVALID_SOC KET;
  1383  
  1384       memset  (&dataAdd r, 0, size of(dataAdd r));
  1385   #ifdef SUP PORT_IP6
  1386       if ((c txt->ftpAd dr).ss_fam ily == AF_ INET6) {
  1387           ct xt->dataFd  = socket  (AF_INET6,  SOCK_STRE AM, IPPROT O_TCP);
  1388           (( struct soc kaddr_in6  *)&dataAdd r)->sin6_f amily = AF _INET6;
  1389           da taAddrLen  = sizeof(s truct sock addr_in6);
  1390       } else
  1391   #endif
  1392       {
  1393           ct xt->dataFd  = socket  (AF_INET,  SOCK_STREA M, IPPROTO _TCP);
  1394           (( struct soc kaddr_in * )&dataAddr )->sin_fam ily = AF_I NET;
  1395           da taAddrLen  = sizeof ( struct soc kaddr_in);
  1396       }
  1397  
  1398       if (ct xt->dataFd  == INVALI D_SOCKET)  {
  1399           __ xmlIOErr(X ML_FROM_FT P, 0, "soc ket failed ");
  1400           re turn INVAL ID_SOCKET;
  1401       }
  1402  
  1403       if (ct xt->passiv e) {
  1404   #ifdef SUP PORT_IP6
  1405           if  ((ctxt->f tpAddr).ss _family ==  AF_INET6)
  1406                snprintf  (buf, siz eof(buf),  "EPSV\r\n" );
  1407           el se
  1408   #endif
  1409                snprintf  (buf, siz eof(buf),  "PASV\r\n" );
  1410           le n = strlen  (buf);
  1411   #ifdef DEB UG_FTP
  1412           xm lGenericEr ror(xmlGen ericErrorC ontext, "% s", buf);
  1413   #endif
  1414           re s = send(c txt->contr olFd, buf,  len, 0);
  1415           if  (res < 0)  {
  1416                __xmlIOE rr(XML_FRO M_FTP, 0,  "send fail ed");
  1417                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1418                return I NVALID_SOC KET;
  1419           }
  1420           re s = xmlNan oFTPReadRe sponse(ctx );
  1421           if  (res != 2 ) {
  1422                if (res  == 5) {
  1423                    clos esocket(ct xt->dataFd ); ctxt->d ataFd = IN VALID_SOCK ET;
  1424                    retu rn INVALID _SOCKET;
  1425                } else {
  1426                    /*
  1427                     * r etry with  an active  connection
  1428                     */
  1429                    clos esocket(ct xt->dataFd ); ctxt->d ataFd = IN VALID_SOCK ET;
  1430                    ctxt ->passive  = 0;
  1431                }
  1432           }
  1433           cu r = &ctxt- >controlBu f[ctxt->co ntrolBufAn swer];
  1434           wh ile (((*cu r < '0') | | (*cur >  '9')) && * cur != '\0 ') cur++;
  1435   #ifdef SUP PORT_IP6
  1436           if  ((ctxt->f tpAddr).ss _family ==  AF_INET6)  {
  1437                if (ssca nf (cur, " %u", &temp [0]) != 1)  {
  1438                    __xm lIOErr(XML _FROM_FTP,  XML_FTP_E PSV_ANSWER ,
  1439                             "Inval id answer  to EPSV\n" );
  1440                    if ( ctxt->data Fd != INVA LID_SOCKET ) {
  1441                         closesocke t (ctxt->d ataFd); ct xt->dataFd  = INVALID _SOCKET;
  1442                    }
  1443                    retu rn INVALID _SOCKET;
  1444                }
  1445                memcpy ( &((struct  sockaddr_i n6 *)&data Addr)->sin 6_addr, &( (struct so ckaddr_in6  *)&ctxt-> ftpAddr)-> sin6_addr,  sizeof(st ruct in6_a ddr));
  1446                ((struct  sockaddr_ in6 *)&dat aAddr)->si n6_port =  htons (tem p[0]);
  1447           }
  1448           el se
  1449   #endif
  1450           {
  1451                if (ssca nf (cur, " %u,%u,%u,% u,%u,%u",  &temp[0],  &temp[1],  &temp[2],
  1452                    &tem p[3], &tem p[4], &tem p[5]) != 6 ) {
  1453                    __xm lIOErr(XML _FROM_FTP,  XML_FTP_P ASV_ANSWER ,
  1454                             "Inval id answer  to PASV\n" );
  1455                    if ( ctxt->data Fd != INVA LID_SOCKET ) {
  1456                         closesocke t (ctxt->d ataFd); ct xt->dataFd  = INVALID _SOCKET;
  1457                    }
  1458                    retu rn INVALID _SOCKET;
  1459                }
  1460                for (i=0 ; i<6; i++ ) ad[i] =  (unsigned  char) (tem p[i] & 0xf f);
  1461                memcpy ( &((struct  sockaddr_i n *)&dataA ddr)->sin_ addr, &ad[ 0], 4);
  1462                memcpy ( &((struct  sockaddr_i n *)&dataA ddr)->sin_ port, &ad[ 4], 2);
  1463           }
  1464  
  1465           if  (connect( ctxt->data Fd, (struc t sockaddr  *) &dataA ddr, dataA ddrLen) <  0) {
  1466                __xmlIOE rr(XML_FRO M_FTP, 0,  "Failed to  create a  data conne ction");
  1467                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1468                return I NVALID_SOC KET;
  1469           }
  1470       } else  {
  1471           ge tsockname( ctxt->data Fd, (struc t sockaddr  *) &dataA ddr, &data AddrLen);
  1472   #ifdef SUP PORT_IP6
  1473           if  ((ctxt->f tpAddr).ss _family ==  AF_INET6)
  1474                ((struct  sockaddr_ in6 *)&dat aAddr)->si n6_port =  0;
  1475           el se
  1476   #endif
  1477                ((struct  sockaddr_ in *)&data Addr)->sin _port = 0;
  1478  
  1479           if  (bind(ctx t->dataFd,  (struct s ockaddr *)  &dataAddr , dataAddr Len) < 0)  {
  1480                __xmlIOE rr(XML_FRO M_FTP, 0,  "bind fail ed");
  1481                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1482                return I NVALID_SOC KET;
  1483           }
  1484           ge tsockname( ctxt->data Fd, (struc t sockaddr  *) &dataA ddr, &data AddrLen);
  1485  
  1486           if  (listen(c txt->dataF d, 1) < 0)  {
  1487                __xmlIOE rr(XML_FRO M_FTP, 0,  "listen fa iled");
  1488                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1489                return I NVALID_SOC KET;
  1490           }
  1491   #ifdef SUP PORT_IP6
  1492           if  ((ctxt->f tpAddr).ss _family ==  AF_INET6)  {
  1493                char buf 6[INET6_AD DRSTRLEN];
  1494                inet_nto p (AF_INET 6, &((stru ct sockadd r_in6 *)&d ataAddr)-> sin6_addr,
  1495                         buf6, INET 6_ADDRSTRL EN);
  1496                adp = (u nsigned ch ar *) buf6 ;
  1497                portp =  (unsigned  char *) &( (struct so ckaddr_in6  *)&dataAd dr)->sin6_ port;
  1498                snprintf  (buf, siz eof(buf),  "EPRT |2|% s|%s|\r\n" , adp, por tp);
  1499           }  else
  1500   #endif
  1501           {
  1502                adp = (u nsigned ch ar *) &((s truct sock addr_in *) &dataAddr) ->sin_addr ;
  1503                portp =  (unsigned  char *) &( (struct so ckaddr_in  *)&dataAdd r)->sin_po rt;
  1504                snprintf  (buf, siz eof(buf),  "PORT %d,% d,%d,%d,%d ,%d\r\n",
  1505                adp[0] &  0xff, adp [1] & 0xff , adp[2] &  0xff, adp [3] & 0xff ,
  1506                portp[0]  & 0xff, p ortp[1] &  0xff);
  1507           }
  1508  
  1509           bu f[sizeof(b uf) - 1] =  0;
  1510           le n = strlen (buf);
  1511   #ifdef DEB UG_FTP
  1512           xm lGenericEr ror(xmlGen ericErrorC ontext, "% s", buf);
  1513   #endif
  1514  
  1515           re s = send(c txt->contr olFd, buf,  len, 0);
  1516           if  (res < 0)  {
  1517                __xmlIOE rr(XML_FRO M_FTP, 0,  "send fail ed");
  1518                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1519                return I NVALID_SOC KET;
  1520           }
  1521           re s = xmlNan oFTPGetRes ponse(ctxt );
  1522           if  (res != 2 ) {
  1523                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1524                return I NVALID_SOC KET;
  1525           }
  1526       }
  1527       return (ctxt->dat aFd);
  1528  
  1529   }
  1530  
  1531   /**
  1532    * xmlNano FTPCloseCo nnection:
  1533    * @ctx:   an FTP con text
  1534    *
  1535    * Close t he data co nnection f rom the se rver
  1536    *
  1537    * Returns  -1 incase  of error,  0 otherwi se
  1538    */
  1539  
  1540   int
  1541   xmlNanoFTP CloseConne ction(void  *ctx) {
  1542       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1543       int re s;
  1544       fd_set  rfd, efd;
  1545       struct  timeval t v;
  1546  
  1547       if ((c txt == NUL L) || (ctx t->control Fd == INVA LID_SOCKET )) return( -1);
  1548  
  1549       closes ocket(ctxt ->dataFd);  ctxt->dat aFd = INVA LID_SOCKET ;
  1550       tv.tv_ sec = 15;
  1551       tv.tv_ usec = 0;
  1552       FD_ZER O(&rfd);
  1553       FD_SET (ctxt->con trolFd, &r fd);
  1554       FD_ZER O(&efd);
  1555       FD_SET (ctxt->con trolFd, &e fd);
  1556       res =  select(ctx t->control Fd + 1, &r fd, NULL,  &efd, &tv) ;
  1557       if (re s < 0) {
  1558   #ifdef DEB UG_FTP
  1559           pe rror("sele ct");
  1560   #endif
  1561           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  1562           re turn(-1);
  1563       }
  1564       if (re s == 0) {
  1565   #ifdef DEB UG_FTP
  1566           xm lGenericEr ror(xmlGen ericErrorC ontext,
  1567                    "xml NanoFTPClo seConnecti on: timeou t\n");
  1568   #endif
  1569           cl osesocket( ctxt->cont rolFd); ct xt->contro lFd = INVA LID_SOCKET ;
  1570       } else  {
  1571           re s = xmlNan oFTPGetRes ponse(ctxt );
  1572           if  (res != 2 ) {
  1573                closesoc ket(ctxt-> controlFd) ; ctxt->co ntrolFd =  INVALID_SO CKET;
  1574                return(- 1);
  1575           }
  1576       }
  1577       return (0);
  1578   }
  1579  
  1580   /**
  1581    * xmlNano FTPParseLi st:
  1582    * @list:   some data  listing r eceived fr om the ser ver
  1583    * @callba ck:  the u ser callba ck
  1584    * @userDa ta:  the u ser callba ck data
  1585    *
  1586    * Parse a t most one  entry fro m the list ing.
  1587    *
  1588    * Returns  -1 incase  of error,  the lengt h of data  parsed oth erwise
  1589    */
  1590  
  1591   static int
  1592   xmlNanoFTP ParseList( const char  *list, ft pListCallb ack callba ck, void * userData)  {
  1593       const  char *cur  = list;
  1594       char f ilename[15 1];
  1595       char a ttrib[11];
  1596       char o wner[11];
  1597       char g roup[11];
  1598       char m onth[4];
  1599       int ye ar = 0;
  1600       int mi nute = 0;
  1601       int ho ur = 0;
  1602       int da y = 0;
  1603       unsign ed long si ze = 0;
  1604       int li nks = 0;
  1605       int i;
  1606  
  1607       if (!s trncmp(cur , "total",  5)) {
  1608           cu r += 5;
  1609           wh ile (*cur  == ' ') cu r++;
  1610           wh ile ((*cur  >= '0') & & (*cur <=  '9'))
  1611                links =  (links * 1 0) + (*cur ++ - '0');
  1612           wh ile ((*cur  == ' ') | | (*cur ==  '\n')  ||  (*cur ==  '\r'))
  1613                cur++;
  1614           re turn(cur -  list);
  1615       } else  if (*list  == '+') {
  1616           re turn(0);
  1617       } else  {
  1618           wh ile ((*cur  == ' ') | | (*cur ==  '\n')  ||  (*cur ==  '\r'))
  1619                cur++;
  1620           if  (*cur ==  0) return( 0);
  1621           i  = 0;
  1622           wh ile (*cur  != ' ') {
  1623                if (i <  10)
  1624                    attr ib[i++] =  *cur;
  1625                cur++;
  1626                if (*cur  == 0) ret urn(0);
  1627           }
  1628           at trib[10] =  0;
  1629           wh ile (*cur  == ' ') cu r++;
  1630           if  (*cur ==  0) return( 0);
  1631           wh ile ((*cur  >= '0') & & (*cur <=  '9'))
  1632                links =  (links * 1 0) + (*cur ++ - '0');
  1633           wh ile (*cur  == ' ') cu r++;
  1634           if  (*cur ==  0) return( 0);
  1635           i  = 0;
  1636           wh ile (*cur  != ' ') {
  1637                if (i <  10)
  1638                    owne r[i++] = * cur;
  1639                cur++;
  1640                if (*cur  == 0) ret urn(0);
  1641           }
  1642           ow ner[i] = 0 ;
  1643           wh ile (*cur  == ' ') cu r++;
  1644           if  (*cur ==  0) return( 0);
  1645           i  = 0;
  1646           wh ile (*cur  != ' ') {
  1647                if (i <  10)
  1648                    grou p[i++] = * cur;
  1649                cur++;
  1650                if (*cur  == 0) ret urn(0);
  1651           }
  1652           gr oup[i] = 0 ;
  1653           wh ile (*cur  == ' ') cu r++;
  1654           if  (*cur ==  0) return( 0);
  1655           wh ile ((*cur  >= '0') & & (*cur <=  '9'))
  1656                size = ( size * 10)  + (*cur++  - '0');
  1657           wh ile (*cur  == ' ') cu r++;
  1658           if  (*cur ==  0) return( 0);
  1659           i  = 0;
  1660           wh ile (*cur  != ' ') {
  1661                if (i <  3)
  1662                    mont h[i++] = * cur;
  1663                cur++;
  1664                if (*cur  == 0) ret urn(0);
  1665           }
  1666           mo nth[i] = 0 ;
  1667           wh ile (*cur  == ' ') cu r++;
  1668           if  (*cur ==  0) return( 0);
  1669           wh ile ((*cur  >= '0') & & (*cur <=  '9'))
  1670                day = (d ay * 10) +  (*cur++ -  '0');
  1671           wh ile (*cur  == ' ') cu r++;
  1672           if  (*cur ==  0) return( 0);
  1673           if  ((cur[1]  == 0) || ( cur[2] ==  0)) return (0);
  1674           if  ((cur[1]  == ':') ||  (cur[2] = = ':')) {
  1675                while (( *cur >= '0 ') && (*cu r <= '9'))
  1676                    hour  = (hour *  10) + (*c ur++ - '0' );
  1677                if (*cur  == ':') c ur++;
  1678                while (( *cur >= '0 ') && (*cu r <= '9'))
  1679                    minu te = (minu te * 10) +  (*cur++ -  '0');
  1680           }  else {
  1681                while (( *cur >= '0 ') && (*cu r <= '9'))
  1682                    year  = (year *  10) + (*c ur++ - '0' );
  1683           }
  1684           wh ile (*cur  == ' ') cu r++;
  1685           if  (*cur ==  0) return( 0);
  1686           i  = 0;
  1687           wh ile ((*cur  != '\n')   && (*cur  != '\r'))  {
  1688                if (i <  150)
  1689                    file name[i++]  = *cur;
  1690                cur++;
  1691                if (*cur  == 0) ret urn(0);
  1692           }
  1693           fi lename[i]  = 0;
  1694           if  ((*cur !=  '\n') &&  (*cur != ' \r'))
  1695                return(0 );
  1696           wh ile ((*cur  == '\n')   || (*cur  == '\r'))
  1697                cur++;
  1698       }
  1699       if (ca llback !=  NULL) {
  1700           ca llback(use rData, fil ename, att rib, owner , group, s ize, links ,
  1701                     yea r, month,  day, hour,  minute);
  1702       }
  1703       return (cur - lis t);
  1704   }
  1705  
  1706   /**
  1707    * xmlNano FTPList:
  1708    * @ctx:   an FTP con text
  1709    * @callba ck:  the u ser callba ck
  1710    * @userDa ta:  the u ser callba ck data
  1711    * @filena me:  optio nal files  to list
  1712    *
  1713    * Do a li sting on t he server.  All files  info are  passed bac k
  1714    * in the  callbacks.
  1715    *
  1716    * Returns  -1 incase  of error,  0 otherwi se
  1717    */
  1718  
  1719   int
  1720   xmlNanoFTP List(void  *ctx, ftpL istCallbac k callback , void *us erData,
  1721                   const  char *fil ename) {
  1722       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1723       char b uf[4096 +  1];
  1724       int le n, res;
  1725       int in dx = 0, ba se;
  1726       fd_set  rfd, efd;
  1727       struct  timeval t v;
  1728  
  1729       if (ct xt == NULL ) return ( -1);
  1730       if (fi lename ==  NULL) {
  1731           if  (xmlNanoF TPCwd(ctxt , ctxt->pa th) < 1)
  1732                return(- 1);
  1733           ct xt->dataFd  = xmlNano FTPGetConn ection(ctx t);
  1734           if  (ctxt->da taFd == IN VALID_SOCK ET)
  1735                return(- 1);
  1736           sn printf(buf , sizeof(b uf), "LIST  -L\r\n");
  1737       } else  {
  1738           if  (filename [0] != '/' ) {
  1739                if (xmlN anoFTPCwd( ctxt, ctxt ->path) <  1)
  1740                    retu rn(-1);
  1741           }
  1742           ct xt->dataFd  = xmlNano FTPGetConn ection(ctx t);
  1743           if  (ctxt->da taFd == IN VALID_SOCK ET)
  1744                return(- 1);
  1745           sn printf(buf , sizeof(b uf), "LIST  -L %s\r\n ", filenam e);
  1746       }
  1747       buf[si zeof(buf)  - 1] = 0;
  1748       len =  strlen(buf );
  1749   #ifdef DEB UG_FTP
  1750       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  1751   #endif
  1752       res =  send(ctxt- >controlFd , buf, len , 0);
  1753       if (re s < 0) {
  1754           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  1755           cl osesocket( ctxt->data Fd); ctxt- >dataFd =  INVALID_SO CKET;
  1756           re turn(res);
  1757       }
  1758       res =  xmlNanoFTP ReadRespon se(ctxt);
  1759       if (re s != 1) {
  1760           cl osesocket( ctxt->data Fd); ctxt- >dataFd =  INVALID_SO CKET;
  1761           re turn(-res) ;
  1762       }
  1763  
  1764       do {
  1765           tv .tv_sec =  1;
  1766           tv .tv_usec =  0;
  1767           FD _ZERO(&rfd );
  1768           FD _SET(ctxt- >dataFd, & rfd);
  1769           FD _ZERO(&efd );
  1770           FD _SET(ctxt- >dataFd, & efd);
  1771           re s = select (ctxt->dat aFd + 1, & rfd, NULL,  &efd, &tv );
  1772           if  (res < 0)  {
  1773   #ifdef DEB UG_FTP
  1774                perror(" select");
  1775   #endif
  1776                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1777                return(- 1);
  1778           }
  1779           if  (res == 0 ) {
  1780                res = xm lNanoFTPCh eckRespons e(ctxt);
  1781                if (res  < 0) {
  1782                    clos esocket(ct xt->dataFd ); ctxt->d ataFd = IN VALID_SOCK ET;
  1783                    ctxt ->dataFd =  INVALID_S OCKET;
  1784                    retu rn(-1);
  1785                }
  1786                if (res  == 2) {
  1787                    clos esocket(ct xt->dataFd ); ctxt->d ataFd = IN VALID_SOCK ET;
  1788                    retu rn(0);
  1789                }
  1790  
  1791                continue ;
  1792           }
  1793  
  1794           if  ((len = r ecv(ctxt-> dataFd, &b uf[indx],  sizeof(buf ) - (indx  + 1), 0))  < 0) {
  1795                __xmlIOE rr(XML_FRO M_FTP, 0,  "recv");
  1796                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1797                ctxt->da taFd = INV ALID_SOCKE T;
  1798                return(- 1);
  1799           }
  1800   #ifdef DEB UG_FTP
  1801           wr ite(1, &bu f[indx], l en);
  1802   #endif
  1803           in dx += len;
  1804           bu f[indx] =  0;
  1805           ba se = 0;
  1806           do  {
  1807                res = xm lNanoFTPPa rseList(&b uf[base],  callback,  userData);
  1808                base +=  res;
  1809           }  while (res  > 0);
  1810  
  1811           me mmove(&buf [0], &buf[ base], ind x - base);
  1812           in dx -= base ;
  1813       } whil e (len !=  0);
  1814       xmlNan oFTPCloseC onnection( ctxt);
  1815       return (0);
  1816   }
  1817  
  1818   /**
  1819    * xmlNano FTPGetSock et:
  1820    * @ctx:   an FTP con text
  1821    * @filena me:  the f ile to ret rieve (or  NULL if pa th is in c ontext).
  1822    *
  1823    * Initiat e fetch of  the given  file from  the serve r.
  1824    *
  1825    * Returns  the socke t for the  data conne ction, or  <0 in case  of error
  1826    */
  1827  
  1828  
  1829   SOCKET
  1830   xmlNanoFTP GetSocket( void *ctx,  const cha r *filenam e) {
  1831       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1832       char b uf[300];
  1833       int re s, len;
  1834       if (ct x == NULL)
  1835           re turn INVAL ID_SOCKET;
  1836       if ((f ilename ==  NULL) &&  (ctxt->pat h == NULL) )
  1837           re turn INVAL ID_SOCKET;
  1838       ctxt-> dataFd = x mlNanoFTPG etConnecti on(ctxt);
  1839       if (ct xt->dataFd  == INVALI D_SOCKET)
  1840           re turn INVAL ID_SOCKET;
  1841  
  1842       snprin tf(buf, si zeof(buf),  "TYPE I\r \n");
  1843       len =  strlen(buf );
  1844   #ifdef DEB UG_FTP
  1845       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  1846   #endif
  1847       res =  send(ctxt- >controlFd , buf, len , 0);
  1848       if (re s < 0) {
  1849           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  1850           cl osesocket( ctxt->data Fd); ctxt- >dataFd =  INVALID_SO CKET;
  1851           re turn INVAL ID_SOCKET;
  1852       }
  1853       res =  xmlNanoFTP ReadRespon se(ctxt);
  1854       if (re s != 2) {
  1855           cl osesocket( ctxt->data Fd); ctxt- >dataFd =  INVALID_SO CKET;
  1856           re turn INVAL ID_SOCKET;
  1857       }
  1858       if (fi lename ==  NULL)
  1859           sn printf(buf , sizeof(b uf), "RETR  %s\r\n",  ctxt->path );
  1860       else
  1861           sn printf(buf , sizeof(b uf), "RETR  %s\r\n",  filename);
  1862       buf[si zeof(buf)  - 1] = 0;
  1863       len =  strlen(buf );
  1864   #ifdef DEB UG_FTP
  1865       xmlGen ericError( xmlGeneric ErrorConte xt, "%s",  buf);
  1866   #endif
  1867       res =  send(ctxt- >controlFd , buf, len , 0);
  1868       if (re s < 0) {
  1869           __ xmlIOErr(X ML_FROM_FT P, 0, "sen d failed") ;
  1870           cl osesocket( ctxt->data Fd); ctxt- >dataFd =  INVALID_SO CKET;
  1871           re turn INVAL ID_SOCKET;
  1872       }
  1873       res =  xmlNanoFTP ReadRespon se(ctxt);
  1874       if (re s != 1) {
  1875           cl osesocket( ctxt->data Fd); ctxt- >dataFd =  INVALID_SO CKET;
  1876           re turn INVAL ID_SOCKET;
  1877       }
  1878       return (ctxt->dat aFd);
  1879   }
  1880  
  1881   /**
  1882    * xmlNano FTPGet:
  1883    * @ctx:   an FTP con text
  1884    * @callba ck:  the u ser callba ck
  1885    * @userDa ta:  the u ser callba ck data
  1886    * @filena me:  the f ile to ret rieve
  1887    *
  1888    * Fetch t he given f ile from t he server.  All data  are passed  back
  1889    * in the  callbacks.  The last  callback h as a size  of 0 block .
  1890    *
  1891    * Returns  -1 incase  of error,  0 otherwi se
  1892    */
  1893  
  1894   int
  1895   xmlNanoFTP Get(void * ctx, ftpDa taCallback  callback,  void *use rData,
  1896                  const  char *file name) {
  1897       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1898       char b uf[4096];
  1899       int le n = 0, res ;
  1900       fd_set  rfd;
  1901       struct  timeval t v;
  1902  
  1903       if (ct xt == NULL ) return(- 1);
  1904       if ((f ilename ==  NULL) &&  (ctxt->pat h == NULL) )
  1905           re turn(-1);
  1906       if (ca llback ==  NULL)
  1907           re turn(-1);
  1908       if (xm lNanoFTPGe tSocket(ct xt, filena me) == INV ALID_SOCKE T)
  1909           re turn(-1);
  1910  
  1911       do {
  1912           tv .tv_sec =  1;
  1913           tv .tv_usec =  0;
  1914           FD _ZERO(&rfd );
  1915           FD _SET(ctxt- >dataFd, & rfd);
  1916           re s = select (ctxt->dat aFd + 1, & rfd, NULL,  NULL, &tv );
  1917           if  (res < 0)  {
  1918   #ifdef DEB UG_FTP
  1919                perror(" select");
  1920   #endif
  1921                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1922                return(- 1);
  1923           }
  1924           if  (res == 0 ) {
  1925                res = xm lNanoFTPCh eckRespons e(ctxt);
  1926                if (res  < 0) {
  1927                    clos esocket(ct xt->dataFd ); ctxt->d ataFd = IN VALID_SOCK ET;
  1928                    ctxt ->dataFd =  INVALID_S OCKET;
  1929                    retu rn(-1);
  1930                }
  1931                if (res  == 2) {
  1932                    clos esocket(ct xt->dataFd ); ctxt->d ataFd = IN VALID_SOCK ET;
  1933                    retu rn(0);
  1934                }
  1935  
  1936                continue ;
  1937           }
  1938           if  ((len = r ecv(ctxt-> dataFd, bu f, sizeof( buf), 0))  < 0) {
  1939                __xmlIOE rr(XML_FRO M_FTP, 0,  "recv fail ed");
  1940                callback (userData,  buf, len) ;
  1941                closesoc ket(ctxt-> dataFd); c txt->dataF d = INVALI D_SOCKET;
  1942                return(- 1);
  1943           }
  1944           ca llback(use rData, buf , len);
  1945       } whil e (len !=  0);
  1946  
  1947       return (xmlNanoFT PCloseConn ection(ctx t));
  1948   }
  1949  
  1950   /**
  1951    * xmlNano FTPRead:
  1952    * @ctx:   the FTP co ntext
  1953    * @dest:   a buffer
  1954    * @len:   the buffer  length
  1955    *
  1956    * This fu nction tri es to read  @len byte s from the  existing  FTP connec tion
  1957    * and sav es them in  @dest. Th is is a bl ocking cal l.
  1958    *
  1959    * Returns  the numbe r of byte  read. 0 is  an indica tion of an  end of co nnection.
  1960    *          -1 indica tes a para meter erro r.
  1961    */
  1962   int
  1963   xmlNanoFTP Read(void  *ctx, void  *dest, in t len) {
  1964       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  1965  
  1966       if (ct x == NULL)  return(-1 );
  1967       if (ct xt->dataFd  == INVALI D_SOCKET)  return(0);
  1968       if (de st == NULL ) return(- 1);
  1969       if (le n <= 0) re turn(0);
  1970  
  1971       len =  recv(ctxt- >dataFd, d est, len,  0);
  1972       if (le n <= 0) {
  1973           if  (len < 0)
  1974                __xmlIOE rr(XML_FRO M_FTP, 0,  "recv fail ed");
  1975           xm lNanoFTPCl oseConnect ion(ctxt);
  1976       }
  1977   #ifdef DEB UG_FTP
  1978       xmlGen ericError( xmlGeneric ErrorConte xt, "Recvd  %d bytes\ n", len);
  1979   #endif
  1980       return (len);
  1981   }
  1982  
  1983   /**
  1984    * xmlNano FTPOpen:
  1985    * @URL: t he URL to  the resour ce
  1986    *
  1987    * Start t o fetch th e given ft p:// resou rce
  1988    *
  1989    * Returns  an FTP co ntext, or  NULL
  1990    */
  1991  
  1992   void*
  1993   xmlNanoFTP Open(const  char *URL ) {
  1994       xmlNan oFTPCtxtPt r ctxt;
  1995       SOCKET  sock;
  1996  
  1997       xmlNan oFTPInit() ;
  1998       if (UR L == NULL)  return(NU LL);
  1999       if (st rncmp("ftp ://", URL,  6)) retur n(NULL);
  2000  
  2001       ctxt =  (xmlNanoF TPCtxtPtr)  xmlNanoFT PNewCtxt(U RL);
  2002       if (ct xt == NULL ) return(N ULL);
  2003       if (xm lNanoFTPCo nnect(ctxt ) < 0) {
  2004           xm lNanoFTPFr eeCtxt(ctx t);
  2005           re turn(NULL) ;
  2006       }
  2007       sock =  xmlNanoFT PGetSocket (ctxt, ctx t->path);
  2008       if (so ck == INVA LID_SOCKET ) {
  2009           xm lNanoFTPFr eeCtxt(ctx t);
  2010           re turn(NULL) ;
  2011       }
  2012       return (ctxt);
  2013   }
  2014  
  2015   /**
  2016    * xmlNano FTPClose:
  2017    * @ctx: a n FTP cont ext
  2018    *
  2019    * Close t he connect ion and bo th control  and trans port
  2020    *
  2021    * Returns  -1 incase  of error,  0 otherwi se
  2022    */
  2023  
  2024   int
  2025   xmlNanoFTP Close(void  *ctx) {
  2026       xmlNan oFTPCtxtPt r ctxt = ( xmlNanoFTP CtxtPtr) c tx;
  2027  
  2028       if (ct xt == NULL )
  2029           re turn(-1);
  2030  
  2031       if (ct xt->dataFd  != INVALI D_SOCKET)  {
  2032           cl osesocket( ctxt->data Fd);
  2033           ct xt->dataFd  = INVALID _SOCKET;
  2034       }
  2035       if (ct xt->contro lFd != INV ALID_SOCKE T) {
  2036           xm lNanoFTPQu it(ctxt);
  2037           cl osesocket( ctxt->cont rolFd);
  2038           ct xt->contro lFd = INVA LID_SOCKET ;
  2039       }
  2040       xmlNan oFTPFreeCt xt(ctxt);
  2041       return (0);
  2042   }
  2043  
  2044   #ifdef STA NDALONE
  2045   /********* ********** ********** ********** ********** ********** ********** ***
  2046    *                                                                             *
  2047    *                        Basic  test in St andalone m ode                     *
  2048    *                                                                             *
  2049    ********* ********** ********** ********** ********** ********** ********** ***/
  2050   static
  2051   void ftpLi st(void *u serData, c onst char  *filename,  const cha r* attrib,
  2052                 const c har *owner , const ch ar *group,  unsigned  long size,  int links ,
  2053                 int yea r, const c har *month , int day,  int hour,  int minut e) {
  2054       xmlGen ericError( xmlGeneric ErrorConte xt,
  2055                "%s %s % s %ld %s\n ", attrib,  owner, gr oup, size,  filename) ;
  2056   }
  2057   static
  2058   void ftpDa ta(void *u serData, c onst char  *data, int  len) {
  2059       if (us erData ==  NULL) retu rn;
  2060       if (le n <= 0) {
  2061           fc lose((FILE *)userData );
  2062           re turn;
  2063       }
  2064       fwrite (data, len , 1, (FILE *)userData );
  2065   }
  2066  
  2067   int main(i nt argc, c har **argv ) {
  2068       void * ctxt;
  2069       FILE * output;
  2070       char * tstfile =  NULL;
  2071  
  2072       xmlNan oFTPInit() ;
  2073       if (ar gc > 1) {
  2074           ct xt = xmlNa noFTPNewCt xt(argv[1] );
  2075           if  (xmlNanoF TPConnect( ctxt) < 0)  {
  2076                xmlGener icError(xm lGenericEr rorContext ,
  2077                         "Couldn't  connect to  %s\n", ar gv[1]);
  2078                exit(1);
  2079           }
  2080           if  (argc > 2 )
  2081                tstfile  = argv[2];
  2082       } else
  2083           ct xt = xmlNa noFTPConne ctTo("loca lhost", 0) ;
  2084       if (ct xt == NULL ) {
  2085           xm lGenericEr ror(xmlGen ericErrorC ontext,
  2086                    "Cou ldn't conn ect to loc alhost\n") ;
  2087           ex it(1);
  2088       }
  2089       xmlNan oFTPList(c txt, ftpLi st, NULL,  tstfile);
  2090       output  = fopen(" /tmp/tstda ta", "w");
  2091       if (ou tput != NU LL) {
  2092           if  (xmlNanoF TPGet(ctxt , ftpData,  (void *)  output, ts tfile) < 0 )
  2093                xmlGener icError(xm lGenericEr rorContext ,
  2094                         "Failed to  get file\ n");
  2095  
  2096       }
  2097       xmlNan oFTPClose( ctxt);
  2098       xmlMem oryDump();
  2099       exit(0 );
  2100   }
  2101   #endif /*  STANDALONE  */
  2102   #else /* ! LIBXML_FTP _ENABLED * /
  2103   #ifdef STA NDALONE
  2104   #include < stdio.h>
  2105   int main(i nt argc, c har **argv ) {
  2106       xmlGen ericError( xmlGeneric ErrorConte xt,
  2107                "%s : FT P support  not compil ed in\n",  argv[0]);
  2108       return (0);
  2109   }
  2110   #endif /*  STANDALONE  */
  2111   #endif /*  LIBXML_FTP _ENABLED * /
  2112   #define bo ttom_nanof tp
  2113   #include " elfgcchack .h"