@helm2/poc_jenki_rce 0.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of @helm2/poc_jenki_rce might be problematic. Click here for more details.

Files changed (160) hide show
  1. package/LICENSE +19 -0
  2. package/Makefile +18 -0
  3. package/README.md +52 -0
  4. package/binding.gyp +81 -0
  5. package/index.d.ts +273 -0
  6. package/index.js +45 -0
  7. package/lib/bindings.js +1 -0
  8. package/lib/document.js +118 -0
  9. package/lib/element.js +82 -0
  10. package/lib/sax_parser.js +38 -0
  11. package/package.json +70 -0
  12. package/src/html_document.cc +7 -0
  13. package/src/html_document.h +18 -0
  14. package/src/libxmljs.cc +252 -0
  15. package/src/libxmljs.h +53 -0
  16. package/src/xml_attribute.cc +173 -0
  17. package/src/xml_attribute.h +40 -0
  18. package/src/xml_comment.cc +117 -0
  19. package/src/xml_comment.h +30 -0
  20. package/src/xml_document.cc +810 -0
  21. package/src/xml_document.h +67 -0
  22. package/src/xml_element.cc +565 -0
  23. package/src/xml_element.h +61 -0
  24. package/src/xml_namespace.cc +158 -0
  25. package/src/xml_namespace.h +39 -0
  26. package/src/xml_node.cc +761 -0
  27. package/src/xml_node.h +73 -0
  28. package/src/xml_pi.cc +161 -0
  29. package/src/xml_pi.h +34 -0
  30. package/src/xml_sax_parser.cc +424 -0
  31. package/src/xml_sax_parser.h +73 -0
  32. package/src/xml_syntax_error.cc +66 -0
  33. package/src/xml_syntax_error.h +25 -0
  34. package/src/xml_text.cc +320 -0
  35. package/src/xml_text.h +48 -0
  36. package/src/xml_textwriter.cc +315 -0
  37. package/src/xml_textwriter.h +62 -0
  38. package/src/xml_xpath_context.cc +70 -0
  39. package/src/xml_xpath_context.h +23 -0
  40. package/vendor/libxml/Copyright +23 -0
  41. package/vendor/libxml/DOCBparser.c +305 -0
  42. package/vendor/libxml/HTMLparser.c +7287 -0
  43. package/vendor/libxml/HTMLtree.c +1200 -0
  44. package/vendor/libxml/Makefile +2983 -0
  45. package/vendor/libxml/SAX.c +180 -0
  46. package/vendor/libxml/SAX2.c +3036 -0
  47. package/vendor/libxml/buf.c +1351 -0
  48. package/vendor/libxml/buf.h +72 -0
  49. package/vendor/libxml/c14n.c +2234 -0
  50. package/vendor/libxml/catalog.c +3828 -0
  51. package/vendor/libxml/chvalid.c +336 -0
  52. package/vendor/libxml/config.h +294 -0
  53. package/vendor/libxml/config.h.gch +0 -0
  54. package/vendor/libxml/debugXML.c +3423 -0
  55. package/vendor/libxml/dict.c +1298 -0
  56. package/vendor/libxml/elfgcchack.h +17818 -0
  57. package/vendor/libxml/enc.h +32 -0
  58. package/vendor/libxml/encoding.c +3975 -0
  59. package/vendor/libxml/entities.c +1163 -0
  60. package/vendor/libxml/error.c +998 -0
  61. package/vendor/libxml/globals.c +1126 -0
  62. package/vendor/libxml/hash.c +1146 -0
  63. package/vendor/libxml/include/libxml/DOCBparser.h +96 -0
  64. package/vendor/libxml/include/libxml/HTMLparser.h +306 -0
  65. package/vendor/libxml/include/libxml/HTMLtree.h +147 -0
  66. package/vendor/libxml/include/libxml/Makefile +725 -0
  67. package/vendor/libxml/include/libxml/Makefile.am +54 -0
  68. package/vendor/libxml/include/libxml/Makefile.in +725 -0
  69. package/vendor/libxml/include/libxml/SAX.h +173 -0
  70. package/vendor/libxml/include/libxml/SAX2.h +178 -0
  71. package/vendor/libxml/include/libxml/c14n.h +128 -0
  72. package/vendor/libxml/include/libxml/catalog.h +182 -0
  73. package/vendor/libxml/include/libxml/chvalid.h +230 -0
  74. package/vendor/libxml/include/libxml/debugXML.h +217 -0
  75. package/vendor/libxml/include/libxml/dict.h +79 -0
  76. package/vendor/libxml/include/libxml/encoding.h +245 -0
  77. package/vendor/libxml/include/libxml/entities.h +151 -0
  78. package/vendor/libxml/include/libxml/globals.h +508 -0
  79. package/vendor/libxml/include/libxml/hash.h +236 -0
  80. package/vendor/libxml/include/libxml/list.h +137 -0
  81. package/vendor/libxml/include/libxml/nanoftp.h +163 -0
  82. package/vendor/libxml/include/libxml/nanohttp.h +81 -0
  83. package/vendor/libxml/include/libxml/parser.h +1243 -0
  84. package/vendor/libxml/include/libxml/parserInternals.h +644 -0
  85. package/vendor/libxml/include/libxml/pattern.h +100 -0
  86. package/vendor/libxml/include/libxml/relaxng.h +217 -0
  87. package/vendor/libxml/include/libxml/schemasInternals.h +958 -0
  88. package/vendor/libxml/include/libxml/schematron.h +142 -0
  89. package/vendor/libxml/include/libxml/threads.h +89 -0
  90. package/vendor/libxml/include/libxml/tree.h +1311 -0
  91. package/vendor/libxml/include/libxml/uri.h +94 -0
  92. package/vendor/libxml/include/libxml/valid.h +458 -0
  93. package/vendor/libxml/include/libxml/xinclude.h +129 -0
  94. package/vendor/libxml/include/libxml/xlink.h +189 -0
  95. package/vendor/libxml/include/libxml/xmlIO.h +368 -0
  96. package/vendor/libxml/include/libxml/xmlautomata.h +146 -0
  97. package/vendor/libxml/include/libxml/xmlerror.h +945 -0
  98. package/vendor/libxml/include/libxml/xmlexports.h +77 -0
  99. package/vendor/libxml/include/libxml/xmlmemory.h +224 -0
  100. package/vendor/libxml/include/libxml/xmlmodule.h +57 -0
  101. package/vendor/libxml/include/libxml/xmlreader.h +428 -0
  102. package/vendor/libxml/include/libxml/xmlregexp.h +222 -0
  103. package/vendor/libxml/include/libxml/xmlsave.h +88 -0
  104. package/vendor/libxml/include/libxml/xmlschemas.h +246 -0
  105. package/vendor/libxml/include/libxml/xmlschemastypes.h +151 -0
  106. package/vendor/libxml/include/libxml/xmlstring.h +140 -0
  107. package/vendor/libxml/include/libxml/xmlunicode.h +202 -0
  108. package/vendor/libxml/include/libxml/xmlversion.h +484 -0
  109. package/vendor/libxml/include/libxml/xmlwin32version.h +239 -0
  110. package/vendor/libxml/include/libxml/xmlwriter.h +488 -0
  111. package/vendor/libxml/include/libxml/xpath.h +564 -0
  112. package/vendor/libxml/include/libxml/xpathInternals.h +632 -0
  113. package/vendor/libxml/include/libxml/xpointer.h +114 -0
  114. package/vendor/libxml/include/win32config.h +122 -0
  115. package/vendor/libxml/include/wsockcompat.h +54 -0
  116. package/vendor/libxml/legacy.c +1343 -0
  117. package/vendor/libxml/libxml.h +134 -0
  118. package/vendor/libxml/list.c +779 -0
  119. package/vendor/libxml/nanoftp.c +2118 -0
  120. package/vendor/libxml/nanohttp.c +1899 -0
  121. package/vendor/libxml/parser.c +15553 -0
  122. package/vendor/libxml/parserInternals.c +2164 -0
  123. package/vendor/libxml/pattern.c +2621 -0
  124. package/vendor/libxml/relaxng.c +11101 -0
  125. package/vendor/libxml/rngparser.c +1595 -0
  126. package/vendor/libxml/runsuite.c +1157 -0
  127. package/vendor/libxml/save.h +36 -0
  128. package/vendor/libxml/schematron.c +1787 -0
  129. package/vendor/libxml/threads.c +1049 -0
  130. package/vendor/libxml/timsort.h +601 -0
  131. package/vendor/libxml/tree.c +10183 -0
  132. package/vendor/libxml/trio.c +6895 -0
  133. package/vendor/libxml/trio.h +230 -0
  134. package/vendor/libxml/triodef.h +228 -0
  135. package/vendor/libxml/trionan.c +914 -0
  136. package/vendor/libxml/trionan.h +84 -0
  137. package/vendor/libxml/triop.h +150 -0
  138. package/vendor/libxml/triostr.c +2112 -0
  139. package/vendor/libxml/triostr.h +144 -0
  140. package/vendor/libxml/uri.c +2561 -0
  141. package/vendor/libxml/valid.c +7138 -0
  142. package/vendor/libxml/xinclude.c +2657 -0
  143. package/vendor/libxml/xlink.c +183 -0
  144. package/vendor/libxml/xmlIO.c +4135 -0
  145. package/vendor/libxml/xmlcatalog.c +624 -0
  146. package/vendor/libxml/xmllint.c +3796 -0
  147. package/vendor/libxml/xmlmemory.c +1163 -0
  148. package/vendor/libxml/xmlmodule.c +468 -0
  149. package/vendor/libxml/xmlreader.c +6033 -0
  150. package/vendor/libxml/xmlregexp.c +8271 -0
  151. package/vendor/libxml/xmlsave.c +2735 -0
  152. package/vendor/libxml/xmlschemas.c +29173 -0
  153. package/vendor/libxml/xmlschemastypes.c +6276 -0
  154. package/vendor/libxml/xmlstring.c +1050 -0
  155. package/vendor/libxml/xmlunicode.c +3179 -0
  156. package/vendor/libxml/xmlwriter.c +4738 -0
  157. package/vendor/libxml/xpath.c +14734 -0
  158. package/vendor/libxml/xpointer.c +2969 -0
  159. package/vendor/libxml/xzlib.c +815 -0
  160. package/vendor/libxml/xzlib.h +19 -0
@@ -0,0 +1,2118 @@
1
+ /*
2
+ * nanoftp.c: basic FTP client support
3
+ *
4
+ * Reference: RFC 959
5
+ */
6
+
7
+ #ifdef TESTING
8
+ #define STANDALONE
9
+ #define HAVE_STDLIB_H
10
+ #define HAVE_UNISTD_H
11
+ #define HAVE_SYS_SOCKET_H
12
+ #define HAVE_NETINET_IN_H
13
+ #define HAVE_NETDB_H
14
+ #define HAVE_SYS_TIME_H
15
+ #endif /* TESTING */
16
+
17
+ #define IN_LIBXML
18
+ #include "libxml.h"
19
+
20
+ #ifdef LIBXML_FTP_ENABLED
21
+ #include <string.h>
22
+
23
+ #ifdef HAVE_STDLIB_H
24
+ #include <stdlib.h>
25
+ #endif
26
+ #ifdef HAVE_UNISTD_H
27
+ #include <unistd.h>
28
+ #endif
29
+ #ifdef HAVE_SYS_SOCKET_H
30
+ #include <sys/socket.h>
31
+ #endif
32
+ #ifdef HAVE_NETINET_IN_H
33
+ #include <netinet/in.h>
34
+ #endif
35
+ #ifdef HAVE_ARPA_INET_H
36
+ #include <arpa/inet.h>
37
+ #endif
38
+ #ifdef HAVE_NETDB_H
39
+ #include <netdb.h>
40
+ #endif
41
+ #ifdef HAVE_FCNTL_H
42
+ #include <fcntl.h>
43
+ #endif
44
+ #ifdef HAVE_ERRNO_H
45
+ #include <errno.h>
46
+ #endif
47
+ #ifdef HAVE_SYS_TIME_H
48
+ #include <sys/time.h>
49
+ #endif
50
+ #ifdef HAVE_SYS_SELECT_H
51
+ #include <sys/select.h>
52
+ #endif
53
+ #ifdef HAVE_SYS_SOCKET_H
54
+ #include <sys/socket.h>
55
+ #endif
56
+ #ifdef HAVE_SYS_TYPES_H
57
+ #include <sys/types.h>
58
+ #endif
59
+ #ifdef HAVE_STRINGS_H
60
+ #include <strings.h>
61
+ #endif
62
+
63
+ #include <libxml/xmlmemory.h>
64
+ #include <libxml/parser.h>
65
+ #include <libxml/xmlerror.h>
66
+ #include <libxml/uri.h>
67
+ #include <libxml/nanoftp.h>
68
+ #include <libxml/globals.h>
69
+
70
+ /* #define DEBUG_FTP 1 */
71
+ #ifdef STANDALONE
72
+ #ifndef DEBUG_FTP
73
+ #define DEBUG_FTP 1
74
+ #endif
75
+ #endif
76
+
77
+
78
+ #if defined(_WIN32) && !defined(__CYGWIN__)
79
+ #include <wsockcompat.h>
80
+ #endif
81
+
82
+ /**
83
+ * A couple portability macros
84
+ */
85
+ #ifndef _WINSOCKAPI_
86
+ #if !defined(__BEOS__) || defined(__HAIKU__)
87
+ #define closesocket(s) close(s)
88
+ #endif
89
+ #endif
90
+
91
+ #ifdef __BEOS__
92
+ #ifndef PF_INET
93
+ #define PF_INET AF_INET
94
+ #endif
95
+ #endif
96
+
97
+ #ifdef _AIX
98
+ #ifdef HAVE_BROKEN_SS_FAMILY
99
+ #define ss_family __ss_family
100
+ #endif
101
+ #endif
102
+
103
+ #ifndef XML_SOCKLEN_T
104
+ #define XML_SOCKLEN_T unsigned int
105
+ #endif
106
+
107
+ #define FTP_COMMAND_OK 200
108
+ #define FTP_SYNTAX_ERROR 500
109
+ #define FTP_GET_PASSWD 331
110
+ #define FTP_BUF_SIZE 1024
111
+
112
+ #define XML_NANO_MAX_URLBUF 4096
113
+
114
+ typedef struct xmlNanoFTPCtxt {
115
+ char *protocol; /* the protocol name */
116
+ char *hostname; /* the host name */
117
+ int port; /* the port */
118
+ char *path; /* the path within the URL */
119
+ char *user; /* user string */
120
+ char *passwd; /* passwd string */
121
+ #ifdef SUPPORT_IP6
122
+ struct sockaddr_storage ftpAddr; /* this is large enough to hold IPv6 address*/
123
+ #else
124
+ struct sockaddr_in ftpAddr; /* the socket address struct */
125
+ #endif
126
+ int passive; /* currently we support only passive !!! */
127
+ SOCKET controlFd; /* the file descriptor for the control socket */
128
+ SOCKET dataFd; /* the file descriptor for the data socket */
129
+ int state; /* WRITE / READ / CLOSED */
130
+ int returnValue; /* the protocol return value */
131
+ /* buffer for data received from the control connection */
132
+ char controlBuf[FTP_BUF_SIZE + 1];
133
+ int controlBufIndex;
134
+ int controlBufUsed;
135
+ int controlBufAnswer;
136
+ } xmlNanoFTPCtxt, *xmlNanoFTPCtxtPtr;
137
+
138
+ static int initialized = 0;
139
+ static char *proxy = NULL; /* the proxy name if any */
140
+ static int proxyPort = 0; /* the proxy port if any */
141
+ static char *proxyUser = NULL; /* user for proxy authentication */
142
+ static char *proxyPasswd = NULL;/* passwd for proxy authentication */
143
+ static int proxyType = 0; /* uses TYPE or a@b ? */
144
+
145
+ #ifdef SUPPORT_IP6
146
+ static
147
+ int have_ipv6(void) {
148
+ int s;
149
+
150
+ s = socket (AF_INET6, SOCK_STREAM, 0);
151
+ if (s != -1) {
152
+ close (s);
153
+ return (1);
154
+ }
155
+ return (0);
156
+ }
157
+ #endif
158
+
159
+ /**
160
+ * xmlFTPErrMemory:
161
+ * @extra: extra information
162
+ *
163
+ * Handle an out of memory condition
164
+ */
165
+ static void
166
+ xmlFTPErrMemory(const char *extra)
167
+ {
168
+ __xmlSimpleError(XML_FROM_FTP, XML_ERR_NO_MEMORY, NULL, NULL, extra);
169
+ }
170
+
171
+ /**
172
+ * xmlNanoFTPInit:
173
+ *
174
+ * Initialize the FTP protocol layer.
175
+ * Currently it just checks for proxy information,
176
+ * and get the hostname
177
+ */
178
+
179
+ void
180
+ xmlNanoFTPInit(void) {
181
+ const char *env;
182
+ #ifdef _WINSOCKAPI_
183
+ WSADATA wsaData;
184
+ #endif
185
+
186
+ if (initialized)
187
+ return;
188
+
189
+ #ifdef _WINSOCKAPI_
190
+ if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
191
+ return;
192
+ #endif
193
+
194
+ proxyPort = 21;
195
+ env = getenv("no_proxy");
196
+ if (env && ((env[0] == '*' ) && (env[1] == 0)))
197
+ return;
198
+ env = getenv("ftp_proxy");
199
+ if (env != NULL) {
200
+ xmlNanoFTPScanProxy(env);
201
+ } else {
202
+ env = getenv("FTP_PROXY");
203
+ if (env != NULL) {
204
+ xmlNanoFTPScanProxy(env);
205
+ }
206
+ }
207
+ env = getenv("ftp_proxy_user");
208
+ if (env != NULL) {
209
+ proxyUser = xmlMemStrdup(env);
210
+ }
211
+ env = getenv("ftp_proxy_password");
212
+ if (env != NULL) {
213
+ proxyPasswd = xmlMemStrdup(env);
214
+ }
215
+ initialized = 1;
216
+ }
217
+
218
+ /**
219
+ * xmlNanoFTPCleanup:
220
+ *
221
+ * Cleanup the FTP protocol layer. This cleanup proxy information.
222
+ */
223
+
224
+ void
225
+ xmlNanoFTPCleanup(void) {
226
+ if (proxy != NULL) {
227
+ xmlFree(proxy);
228
+ proxy = NULL;
229
+ }
230
+ if (proxyUser != NULL) {
231
+ xmlFree(proxyUser);
232
+ proxyUser = NULL;
233
+ }
234
+ if (proxyPasswd != NULL) {
235
+ xmlFree(proxyPasswd);
236
+ proxyPasswd = NULL;
237
+ }
238
+ #ifdef _WINSOCKAPI_
239
+ if (initialized)
240
+ WSACleanup();
241
+ #endif
242
+ initialized = 0;
243
+ }
244
+
245
+ /**
246
+ * xmlNanoFTPProxy:
247
+ * @host: the proxy host name
248
+ * @port: the proxy port
249
+ * @user: the proxy user name
250
+ * @passwd: the proxy password
251
+ * @type: the type of proxy 1 for using SITE, 2 for USER a@b
252
+ *
253
+ * Setup the FTP proxy information.
254
+ * This can also be done by using ftp_proxy ftp_proxy_user and
255
+ * ftp_proxy_password environment variables.
256
+ */
257
+
258
+ void
259
+ xmlNanoFTPProxy(const char *host, int port, const char *user,
260
+ const char *passwd, int type) {
261
+ if (proxy != NULL) {
262
+ xmlFree(proxy);
263
+ proxy = NULL;
264
+ }
265
+ if (proxyUser != NULL) {
266
+ xmlFree(proxyUser);
267
+ proxyUser = NULL;
268
+ }
269
+ if (proxyPasswd != NULL) {
270
+ xmlFree(proxyPasswd);
271
+ proxyPasswd = NULL;
272
+ }
273
+ if (host)
274
+ proxy = xmlMemStrdup(host);
275
+ if (user)
276
+ proxyUser = xmlMemStrdup(user);
277
+ if (passwd)
278
+ proxyPasswd = xmlMemStrdup(passwd);
279
+ proxyPort = port;
280
+ proxyType = type;
281
+ }
282
+
283
+ /**
284
+ * xmlNanoFTPScanURL:
285
+ * @ctx: an FTP context
286
+ * @URL: The URL used to initialize the context
287
+ *
288
+ * (Re)Initialize an FTP context by parsing the URL and finding
289
+ * the protocol host port and path it indicates.
290
+ */
291
+
292
+ static void
293
+ xmlNanoFTPScanURL(void *ctx, const char *URL) {
294
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
295
+ xmlURIPtr uri;
296
+
297
+ /*
298
+ * Clear any existing data from the context
299
+ */
300
+ if (ctxt->protocol != NULL) {
301
+ xmlFree(ctxt->protocol);
302
+ ctxt->protocol = NULL;
303
+ }
304
+ if (ctxt->hostname != NULL) {
305
+ xmlFree(ctxt->hostname);
306
+ ctxt->hostname = NULL;
307
+ }
308
+ if (ctxt->path != NULL) {
309
+ xmlFree(ctxt->path);
310
+ ctxt->path = NULL;
311
+ }
312
+ if (URL == NULL) return;
313
+
314
+ uri = xmlParseURIRaw(URL, 1);
315
+ if (uri == NULL)
316
+ return;
317
+
318
+ if ((uri->scheme == NULL) || (uri->server == NULL)) {
319
+ xmlFreeURI(uri);
320
+ return;
321
+ }
322
+
323
+ ctxt->protocol = xmlMemStrdup(uri->scheme);
324
+ ctxt->hostname = xmlMemStrdup(uri->server);
325
+ if (uri->path != NULL)
326
+ ctxt->path = xmlMemStrdup(uri->path);
327
+ else
328
+ ctxt->path = xmlMemStrdup("/");
329
+ if (uri->port != 0)
330
+ ctxt->port = uri->port;
331
+
332
+ if (uri->user != NULL) {
333
+ char *cptr;
334
+ if ((cptr=strchr(uri->user, ':')) == NULL)
335
+ ctxt->user = xmlMemStrdup(uri->user);
336
+ else {
337
+ ctxt->user = (char *)xmlStrndup((xmlChar *)uri->user,
338
+ (cptr - uri->user));
339
+ ctxt->passwd = xmlMemStrdup(cptr+1);
340
+ }
341
+ }
342
+
343
+ xmlFreeURI(uri);
344
+
345
+ }
346
+
347
+ /**
348
+ * xmlNanoFTPUpdateURL:
349
+ * @ctx: an FTP context
350
+ * @URL: The URL used to update the context
351
+ *
352
+ * Update an FTP context by parsing the URL and finding
353
+ * new path it indicates. If there is an error in the
354
+ * protocol, hostname, port or other information, the
355
+ * error is raised. It indicates a new connection has to
356
+ * be established.
357
+ *
358
+ * Returns 0 if Ok, -1 in case of error (other host).
359
+ */
360
+
361
+ int
362
+ xmlNanoFTPUpdateURL(void *ctx, const char *URL) {
363
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
364
+ xmlURIPtr uri;
365
+
366
+ if (URL == NULL)
367
+ return(-1);
368
+ if (ctxt == NULL)
369
+ return(-1);
370
+ if (ctxt->protocol == NULL)
371
+ return(-1);
372
+ if (ctxt->hostname == NULL)
373
+ return(-1);
374
+
375
+ uri = xmlParseURIRaw(URL, 1);
376
+ if (uri == NULL)
377
+ return(-1);
378
+
379
+ if ((uri->scheme == NULL) || (uri->server == NULL)) {
380
+ xmlFreeURI(uri);
381
+ return(-1);
382
+ }
383
+ if ((strcmp(ctxt->protocol, uri->scheme)) ||
384
+ (strcmp(ctxt->hostname, uri->server)) ||
385
+ ((uri->port != 0) && (ctxt->port != uri->port))) {
386
+ xmlFreeURI(uri);
387
+ return(-1);
388
+ }
389
+
390
+ if (uri->port != 0)
391
+ ctxt->port = uri->port;
392
+
393
+ if (ctxt->path != NULL) {
394
+ xmlFree(ctxt->path);
395
+ ctxt->path = NULL;
396
+ }
397
+
398
+ if (uri->path == NULL)
399
+ ctxt->path = xmlMemStrdup("/");
400
+ else
401
+ ctxt->path = xmlMemStrdup(uri->path);
402
+
403
+ xmlFreeURI(uri);
404
+
405
+ return(0);
406
+ }
407
+
408
+ /**
409
+ * xmlNanoFTPScanProxy:
410
+ * @URL: The proxy URL used to initialize the proxy context
411
+ *
412
+ * (Re)Initialize the FTP Proxy context by parsing the URL and finding
413
+ * the protocol host port it indicates.
414
+ * Should be like ftp://myproxy/ or ftp://myproxy:3128/
415
+ * A NULL URL cleans up proxy information.
416
+ */
417
+
418
+ void
419
+ xmlNanoFTPScanProxy(const char *URL) {
420
+ xmlURIPtr uri;
421
+
422
+ if (proxy != NULL) {
423
+ xmlFree(proxy);
424
+ proxy = NULL;
425
+ }
426
+ proxyPort = 0;
427
+
428
+ #ifdef DEBUG_FTP
429
+ if (URL == NULL)
430
+ xmlGenericError(xmlGenericErrorContext,
431
+ "Removing FTP proxy info\n");
432
+ else
433
+ xmlGenericError(xmlGenericErrorContext,
434
+ "Using FTP proxy %s\n", URL);
435
+ #endif
436
+ if (URL == NULL) return;
437
+
438
+ uri = xmlParseURIRaw(URL, 1);
439
+ if ((uri == NULL) || (uri->scheme == NULL) ||
440
+ (strcmp(uri->scheme, "ftp")) || (uri->server == NULL)) {
441
+ __xmlIOErr(XML_FROM_FTP, XML_FTP_URL_SYNTAX, "Syntax Error\n");
442
+ if (uri != NULL)
443
+ xmlFreeURI(uri);
444
+ return;
445
+ }
446
+
447
+ proxy = xmlMemStrdup(uri->server);
448
+ if (uri->port != 0)
449
+ proxyPort = uri->port;
450
+
451
+ xmlFreeURI(uri);
452
+ }
453
+
454
+ /**
455
+ * xmlNanoFTPNewCtxt:
456
+ * @URL: The URL used to initialize the context
457
+ *
458
+ * Allocate and initialize a new FTP context.
459
+ *
460
+ * Returns an FTP context or NULL in case of error.
461
+ */
462
+
463
+ void*
464
+ xmlNanoFTPNewCtxt(const char *URL) {
465
+ xmlNanoFTPCtxtPtr ret;
466
+ char *unescaped;
467
+
468
+ ret = (xmlNanoFTPCtxtPtr) xmlMalloc(sizeof(xmlNanoFTPCtxt));
469
+ if (ret == NULL) {
470
+ xmlFTPErrMemory("allocating FTP context");
471
+ return(NULL);
472
+ }
473
+
474
+ memset(ret, 0, sizeof(xmlNanoFTPCtxt));
475
+ ret->port = 21;
476
+ ret->passive = 1;
477
+ ret->returnValue = 0;
478
+ ret->controlBufIndex = 0;
479
+ ret->controlBufUsed = 0;
480
+ ret->controlFd = INVALID_SOCKET;
481
+
482
+ unescaped = xmlURIUnescapeString(URL, 0, NULL);
483
+ if (unescaped != NULL) {
484
+ xmlNanoFTPScanURL(ret, unescaped);
485
+ xmlFree(unescaped);
486
+ } else if (URL != NULL)
487
+ xmlNanoFTPScanURL(ret, URL);
488
+
489
+ return(ret);
490
+ }
491
+
492
+ /**
493
+ * xmlNanoFTPFreeCtxt:
494
+ * @ctx: an FTP context
495
+ *
496
+ * Frees the context after closing the connection.
497
+ */
498
+
499
+ void
500
+ xmlNanoFTPFreeCtxt(void * ctx) {
501
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
502
+ if (ctxt == NULL) return;
503
+ if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);
504
+ if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);
505
+ if (ctxt->path != NULL) xmlFree(ctxt->path);
506
+ if (ctxt->user != NULL) xmlFree(ctxt->user);
507
+ if (ctxt->passwd != NULL) xmlFree(ctxt->passwd);
508
+ ctxt->passive = 1;
509
+ if (ctxt->controlFd != INVALID_SOCKET) closesocket(ctxt->controlFd);
510
+ ctxt->controlFd = INVALID_SOCKET;
511
+ ctxt->controlBufIndex = -1;
512
+ ctxt->controlBufUsed = -1;
513
+ xmlFree(ctxt);
514
+ }
515
+
516
+ /**
517
+ * xmlNanoFTPParseResponse:
518
+ * @buf: the buffer containing the response
519
+ * @len: the buffer length
520
+ *
521
+ * Parsing of the server answer, we just extract the code.
522
+ *
523
+ * returns 0 for errors
524
+ * +XXX for last line of response
525
+ * -XXX for response to be continued
526
+ */
527
+ static int
528
+ xmlNanoFTPParseResponse(char *buf, int len) {
529
+ int val = 0;
530
+
531
+ if (len < 3) return(-1);
532
+ if ((*buf >= '0') && (*buf <= '9'))
533
+ val = val * 10 + (*buf - '0');
534
+ else
535
+ return(0);
536
+ buf++;
537
+ if ((*buf >= '0') && (*buf <= '9'))
538
+ val = val * 10 + (*buf - '0');
539
+ else
540
+ return(0);
541
+ buf++;
542
+ if ((*buf >= '0') && (*buf <= '9'))
543
+ val = val * 10 + (*buf - '0');
544
+ else
545
+ return(0);
546
+ buf++;
547
+ if (*buf == '-')
548
+ return(-val);
549
+ return(val);
550
+ }
551
+
552
+ /**
553
+ * xmlNanoFTPGetMore:
554
+ * @ctx: an FTP context
555
+ *
556
+ * Read more information from the FTP control connection
557
+ * Returns the number of bytes read, < 0 indicates an error
558
+ */
559
+ static int
560
+ xmlNanoFTPGetMore(void *ctx) {
561
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
562
+ int len;
563
+ int size;
564
+
565
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
566
+
567
+ if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) {
568
+ #ifdef DEBUG_FTP
569
+ xmlGenericError(xmlGenericErrorContext,
570
+ "xmlNanoFTPGetMore : controlBufIndex = %d\n",
571
+ ctxt->controlBufIndex);
572
+ #endif
573
+ return(-1);
574
+ }
575
+
576
+ if ((ctxt->controlBufUsed < 0) || (ctxt->controlBufUsed > FTP_BUF_SIZE)) {
577
+ #ifdef DEBUG_FTP
578
+ xmlGenericError(xmlGenericErrorContext,
579
+ "xmlNanoFTPGetMore : controlBufUsed = %d\n",
580
+ ctxt->controlBufUsed);
581
+ #endif
582
+ return(-1);
583
+ }
584
+ if (ctxt->controlBufIndex > ctxt->controlBufUsed) {
585
+ #ifdef DEBUG_FTP
586
+ xmlGenericError(xmlGenericErrorContext,
587
+ "xmlNanoFTPGetMore : controlBufIndex > controlBufUsed %d > %d\n",
588
+ ctxt->controlBufIndex, ctxt->controlBufUsed);
589
+ #endif
590
+ return(-1);
591
+ }
592
+
593
+ /*
594
+ * First pack the control buffer
595
+ */
596
+ if (ctxt->controlBufIndex > 0) {
597
+ memmove(&ctxt->controlBuf[0], &ctxt->controlBuf[ctxt->controlBufIndex],
598
+ ctxt->controlBufUsed - ctxt->controlBufIndex);
599
+ ctxt->controlBufUsed -= ctxt->controlBufIndex;
600
+ ctxt->controlBufIndex = 0;
601
+ }
602
+ size = FTP_BUF_SIZE - ctxt->controlBufUsed;
603
+ if (size == 0) {
604
+ #ifdef DEBUG_FTP
605
+ xmlGenericError(xmlGenericErrorContext,
606
+ "xmlNanoFTPGetMore : buffer full %d \n", ctxt->controlBufUsed);
607
+ #endif
608
+ return(0);
609
+ }
610
+
611
+ /*
612
+ * Read the amount left on the control connection
613
+ */
614
+ if ((len = recv(ctxt->controlFd, &ctxt->controlBuf[ctxt->controlBufIndex],
615
+ size, 0)) < 0) {
616
+ __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
617
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
618
+ ctxt->controlFd = INVALID_SOCKET;
619
+ return(-1);
620
+ }
621
+ #ifdef DEBUG_FTP
622
+ xmlGenericError(xmlGenericErrorContext,
623
+ "xmlNanoFTPGetMore : read %d [%d - %d]\n", len,
624
+ ctxt->controlBufUsed, ctxt->controlBufUsed + len);
625
+ #endif
626
+ ctxt->controlBufUsed += len;
627
+ ctxt->controlBuf[ctxt->controlBufUsed] = 0;
628
+
629
+ return(len);
630
+ }
631
+
632
+ /**
633
+ * xmlNanoFTPReadResponse:
634
+ * @ctx: an FTP context
635
+ *
636
+ * Read the response from the FTP server after a command.
637
+ * Returns the code number
638
+ */
639
+ static int
640
+ xmlNanoFTPReadResponse(void *ctx) {
641
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
642
+ char *ptr, *end;
643
+ int len;
644
+ int res = -1, cur = -1;
645
+
646
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
647
+
648
+ get_more:
649
+ /*
650
+ * Assumes everything up to controlBuf[controlBufIndex] has been read
651
+ * and analyzed.
652
+ */
653
+ len = xmlNanoFTPGetMore(ctx);
654
+ if (len < 0) {
655
+ return(-1);
656
+ }
657
+ if ((ctxt->controlBufUsed == 0) && (len == 0)) {
658
+ return(-1);
659
+ }
660
+ ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
661
+ end = &ctxt->controlBuf[ctxt->controlBufUsed];
662
+
663
+ #ifdef DEBUG_FTP
664
+ xmlGenericError(xmlGenericErrorContext,
665
+ "\n<<<\n%s\n--\n", ptr);
666
+ #endif
667
+ while (ptr < end) {
668
+ cur = xmlNanoFTPParseResponse(ptr, end - ptr);
669
+ if (cur > 0) {
670
+ /*
671
+ * Successfully scanned the control code, scratch
672
+ * till the end of the line, but keep the index to be
673
+ * able to analyze the result if needed.
674
+ */
675
+ res = cur;
676
+ ptr += 3;
677
+ ctxt->controlBufAnswer = ptr - ctxt->controlBuf;
678
+ while ((ptr < end) && (*ptr != '\n')) ptr++;
679
+ if (*ptr == '\n') ptr++;
680
+ if (*ptr == '\r') ptr++;
681
+ break;
682
+ }
683
+ while ((ptr < end) && (*ptr != '\n')) ptr++;
684
+ if (ptr >= end) {
685
+ ctxt->controlBufIndex = ctxt->controlBufUsed;
686
+ goto get_more;
687
+ }
688
+ if (*ptr != '\r') ptr++;
689
+ }
690
+
691
+ if (res < 0) goto get_more;
692
+ ctxt->controlBufIndex = ptr - ctxt->controlBuf;
693
+ #ifdef DEBUG_FTP
694
+ ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
695
+ xmlGenericError(xmlGenericErrorContext, "\n---\n%s\n--\n", ptr);
696
+ #endif
697
+
698
+ #ifdef DEBUG_FTP
699
+ xmlGenericError(xmlGenericErrorContext, "Got %d\n", res);
700
+ #endif
701
+ return(res / 100);
702
+ }
703
+
704
+ /**
705
+ * xmlNanoFTPGetResponse:
706
+ * @ctx: an FTP context
707
+ *
708
+ * Get the response from the FTP server after a command.
709
+ * Returns the code number
710
+ */
711
+
712
+ int
713
+ xmlNanoFTPGetResponse(void *ctx) {
714
+ int res;
715
+
716
+ res = xmlNanoFTPReadResponse(ctx);
717
+
718
+ return(res);
719
+ }
720
+
721
+ /**
722
+ * xmlNanoFTPCheckResponse:
723
+ * @ctx: an FTP context
724
+ *
725
+ * Check if there is a response from the FTP server after a command.
726
+ * Returns the code number, or 0
727
+ */
728
+
729
+ int
730
+ xmlNanoFTPCheckResponse(void *ctx) {
731
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
732
+ fd_set rfd;
733
+ struct timeval tv;
734
+
735
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
736
+ tv.tv_sec = 0;
737
+ tv.tv_usec = 0;
738
+ FD_ZERO(&rfd);
739
+ FD_SET(ctxt->controlFd, &rfd);
740
+ switch(select(ctxt->controlFd + 1, &rfd, NULL, NULL, &tv)) {
741
+ case 0:
742
+ return(0);
743
+ case -1:
744
+ __xmlIOErr(XML_FROM_FTP, 0, "select");
745
+ return(-1);
746
+
747
+ }
748
+
749
+ return(xmlNanoFTPReadResponse(ctx));
750
+ }
751
+
752
+ /**
753
+ * Send the user authentication
754
+ */
755
+
756
+ static int
757
+ xmlNanoFTPSendUser(void *ctx) {
758
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
759
+ char buf[200];
760
+ int len;
761
+ int res;
762
+
763
+ if (ctxt->user == NULL)
764
+ snprintf(buf, sizeof(buf), "USER anonymous\r\n");
765
+ else
766
+ snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user);
767
+ buf[sizeof(buf) - 1] = 0;
768
+ len = strlen(buf);
769
+ #ifdef DEBUG_FTP
770
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
771
+ #endif
772
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
773
+ if (res < 0) {
774
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
775
+ return(res);
776
+ }
777
+ return(0);
778
+ }
779
+
780
+ /**
781
+ * Send the password authentication
782
+ */
783
+
784
+ static int
785
+ xmlNanoFTPSendPasswd(void *ctx) {
786
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
787
+ char buf[200];
788
+ int len;
789
+ int res;
790
+
791
+ if (ctxt->passwd == NULL)
792
+ snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
793
+ else
794
+ snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
795
+ buf[sizeof(buf) - 1] = 0;
796
+ len = strlen(buf);
797
+ #ifdef DEBUG_FTP
798
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
799
+ #endif
800
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
801
+ if (res < 0) {
802
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
803
+ return(res);
804
+ }
805
+ return(0);
806
+ }
807
+
808
+ /**
809
+ * xmlNanoFTPQuit:
810
+ * @ctx: an FTP context
811
+ *
812
+ * Send a QUIT command to the server
813
+ *
814
+ * Returns -1 in case of error, 0 otherwise
815
+ */
816
+
817
+
818
+ int
819
+ xmlNanoFTPQuit(void *ctx) {
820
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
821
+ char buf[200];
822
+ int len, res;
823
+
824
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
825
+
826
+ snprintf(buf, sizeof(buf), "QUIT\r\n");
827
+ len = strlen(buf);
828
+ #ifdef DEBUG_FTP
829
+ xmlGenericError(xmlGenericErrorContext, "%s", buf); /* Just to be consistent, even though we know it can't have a % in it */
830
+ #endif
831
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
832
+ if (res < 0) {
833
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
834
+ return(res);
835
+ }
836
+ return(0);
837
+ }
838
+
839
+ /**
840
+ * xmlNanoFTPConnect:
841
+ * @ctx: an FTP context
842
+ *
843
+ * Tries to open a control connection
844
+ *
845
+ * Returns -1 in case of error, 0 otherwise
846
+ */
847
+
848
+ int
849
+ xmlNanoFTPConnect(void *ctx) {
850
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
851
+ struct hostent *hp;
852
+ int port;
853
+ int res;
854
+ int addrlen = sizeof (struct sockaddr_in);
855
+
856
+ if (ctxt == NULL)
857
+ return(-1);
858
+ if (ctxt->hostname == NULL)
859
+ return(-1);
860
+
861
+ /*
862
+ * do the blocking DNS query.
863
+ */
864
+ if (proxy) {
865
+ port = proxyPort;
866
+ } else {
867
+ port = ctxt->port;
868
+ }
869
+ if (port == 0)
870
+ port = 21;
871
+
872
+ memset (&ctxt->ftpAddr, 0, sizeof(ctxt->ftpAddr));
873
+
874
+ #ifdef SUPPORT_IP6
875
+ if (have_ipv6 ()) {
876
+ struct addrinfo hints, *tmp, *result;
877
+
878
+ result = NULL;
879
+ memset (&hints, 0, sizeof(hints));
880
+ hints.ai_socktype = SOCK_STREAM;
881
+
882
+ if (proxy) {
883
+ if (getaddrinfo (proxy, NULL, &hints, &result) != 0) {
884
+ __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
885
+ return (-1);
886
+ }
887
+ }
888
+ else
889
+ if (getaddrinfo (ctxt->hostname, NULL, &hints, &result) != 0) {
890
+ __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
891
+ return (-1);
892
+ }
893
+
894
+ for (tmp = result; tmp; tmp = tmp->ai_next)
895
+ if (tmp->ai_family == AF_INET || tmp->ai_family == AF_INET6)
896
+ break;
897
+
898
+ if (!tmp) {
899
+ if (result)
900
+ freeaddrinfo (result);
901
+ __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
902
+ return (-1);
903
+ }
904
+ if ((size_t)tmp->ai_addrlen > sizeof(ctxt->ftpAddr)) {
905
+ if (result)
906
+ freeaddrinfo (result);
907
+ __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch");
908
+ return (-1);
909
+ }
910
+ if (tmp->ai_family == AF_INET6) {
911
+ memcpy (&ctxt->ftpAddr, tmp->ai_addr, tmp->ai_addrlen);
912
+ ((struct sockaddr_in6 *) &ctxt->ftpAddr)->sin6_port = htons (port);
913
+ ctxt->controlFd = socket (AF_INET6, SOCK_STREAM, 0);
914
+ }
915
+ else {
916
+ memcpy (&ctxt->ftpAddr, tmp->ai_addr, tmp->ai_addrlen);
917
+ ((struct sockaddr_in *) &ctxt->ftpAddr)->sin_port = htons (port);
918
+ ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0);
919
+ }
920
+ addrlen = tmp->ai_addrlen;
921
+ freeaddrinfo (result);
922
+ }
923
+ else
924
+ #endif
925
+ {
926
+ if (proxy)
927
+ hp = gethostbyname (GETHOSTBYNAME_ARG_CAST proxy);
928
+ else
929
+ hp = gethostbyname (GETHOSTBYNAME_ARG_CAST ctxt->hostname);
930
+ if (hp == NULL) {
931
+ __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname failed");
932
+ return (-1);
933
+ }
934
+ if ((unsigned int) hp->h_length >
935
+ sizeof(((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr)) {
936
+ __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch");
937
+ return (-1);
938
+ }
939
+
940
+ /*
941
+ * Prepare the socket
942
+ */
943
+ ((struct sockaddr_in *)&ctxt->ftpAddr)->sin_family = AF_INET;
944
+ memcpy (&((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr,
945
+ hp->h_addr_list[0], hp->h_length);
946
+ ((struct sockaddr_in *)&ctxt->ftpAddr)->sin_port =
947
+ (unsigned short)htons ((unsigned short)port);
948
+ ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0);
949
+ addrlen = sizeof (struct sockaddr_in);
950
+ }
951
+
952
+ if (ctxt->controlFd == INVALID_SOCKET) {
953
+ __xmlIOErr(XML_FROM_FTP, 0, "socket failed");
954
+ return(-1);
955
+ }
956
+
957
+ /*
958
+ * Do the connect.
959
+ */
960
+ if (connect(ctxt->controlFd, (struct sockaddr *) &ctxt->ftpAddr,
961
+ addrlen) < 0) {
962
+ __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a connection");
963
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
964
+ ctxt->controlFd = INVALID_SOCKET;
965
+ return(-1);
966
+ }
967
+
968
+ /*
969
+ * Wait for the HELLO from the server.
970
+ */
971
+ res = xmlNanoFTPGetResponse(ctxt);
972
+ if (res != 2) {
973
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
974
+ ctxt->controlFd = INVALID_SOCKET;
975
+ return(-1);
976
+ }
977
+
978
+ /*
979
+ * State diagram for the login operation on the FTP server
980
+ *
981
+ * Reference: RFC 959
982
+ *
983
+ * 1
984
+ * +---+ USER +---+------------->+---+
985
+ * | B |---------->| W | 2 ---->| E |
986
+ * +---+ +---+------ | -->+---+
987
+ * | | | | |
988
+ * 3 | | 4,5 | | |
989
+ * -------------- ----- | | |
990
+ * | | | | |
991
+ * | | | | |
992
+ * | --------- |
993
+ * | 1| | | |
994
+ * V | | | |
995
+ * +---+ PASS +---+ 2 | ------>+---+
996
+ * | |---------->| W |------------->| S |
997
+ * +---+ +---+ ---------->+---+
998
+ * | | | | |
999
+ * 3 | |4,5| | |
1000
+ * -------------- -------- |
1001
+ * | | | | |
1002
+ * | | | | |
1003
+ * | -----------
1004
+ * | 1,3| | | |
1005
+ * V | 2| | |
1006
+ * +---+ ACCT +---+-- | ----->+---+
1007
+ * | |---------->| W | 4,5 -------->| F |
1008
+ * +---+ +---+------------->+---+
1009
+ *
1010
+ * Of course in case of using a proxy this get really nasty and is not
1011
+ * standardized at all :-(
1012
+ */
1013
+ if (proxy) {
1014
+ int len;
1015
+ char buf[400];
1016
+
1017
+ if (proxyUser != NULL) {
1018
+ /*
1019
+ * We need proxy auth
1020
+ */
1021
+ snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser);
1022
+ buf[sizeof(buf) - 1] = 0;
1023
+ len = strlen(buf);
1024
+ #ifdef DEBUG_FTP
1025
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1026
+ #endif
1027
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1028
+ if (res < 0) {
1029
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1030
+ closesocket(ctxt->controlFd);
1031
+ ctxt->controlFd = INVALID_SOCKET;
1032
+ return(res);
1033
+ }
1034
+ res = xmlNanoFTPGetResponse(ctxt);
1035
+ switch (res) {
1036
+ case 2:
1037
+ if (proxyPasswd == NULL)
1038
+ break;
1039
+ /* Falls through. */
1040
+ case 3:
1041
+ if (proxyPasswd != NULL)
1042
+ snprintf(buf, sizeof(buf), "PASS %s\r\n", proxyPasswd);
1043
+ else
1044
+ snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
1045
+ buf[sizeof(buf) - 1] = 0;
1046
+ len = strlen(buf);
1047
+ #ifdef DEBUG_FTP
1048
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1049
+ #endif
1050
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1051
+ if (res < 0) {
1052
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1053
+ closesocket(ctxt->controlFd);
1054
+ ctxt->controlFd = INVALID_SOCKET;
1055
+ return(res);
1056
+ }
1057
+ res = xmlNanoFTPGetResponse(ctxt);
1058
+ if (res > 3) {
1059
+ closesocket(ctxt->controlFd);
1060
+ ctxt->controlFd = INVALID_SOCKET;
1061
+ return(-1);
1062
+ }
1063
+ break;
1064
+ case 1:
1065
+ break;
1066
+ case 4:
1067
+ case 5:
1068
+ case -1:
1069
+ default:
1070
+ closesocket(ctxt->controlFd);
1071
+ ctxt->controlFd = INVALID_SOCKET;
1072
+ return(-1);
1073
+ }
1074
+ }
1075
+
1076
+ /*
1077
+ * We assume we don't need more authentication to the proxy
1078
+ * and that it succeeded :-\
1079
+ */
1080
+ switch (proxyType) {
1081
+ case 0:
1082
+ /* we will try in sequence */
1083
+ case 1:
1084
+ /* Using SITE command */
1085
+ snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname);
1086
+ buf[sizeof(buf) - 1] = 0;
1087
+ len = strlen(buf);
1088
+ #ifdef DEBUG_FTP
1089
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1090
+ #endif
1091
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1092
+ if (res < 0) {
1093
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1094
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1095
+ ctxt->controlFd = INVALID_SOCKET;
1096
+ return(res);
1097
+ }
1098
+ res = xmlNanoFTPGetResponse(ctxt);
1099
+ if (res == 2) {
1100
+ /* we assume it worked :-\ 1 is error for SITE command */
1101
+ proxyType = 1;
1102
+ break;
1103
+ }
1104
+ if (proxyType == 1) {
1105
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1106
+ ctxt->controlFd = INVALID_SOCKET;
1107
+ return(-1);
1108
+ }
1109
+ /* Falls through. */
1110
+ case 2:
1111
+ /* USER user@host command */
1112
+ if (ctxt->user == NULL)
1113
+ snprintf(buf, sizeof(buf), "USER anonymous@%s\r\n",
1114
+ ctxt->hostname);
1115
+ else
1116
+ snprintf(buf, sizeof(buf), "USER %s@%s\r\n",
1117
+ ctxt->user, ctxt->hostname);
1118
+ buf[sizeof(buf) - 1] = 0;
1119
+ len = strlen(buf);
1120
+ #ifdef DEBUG_FTP
1121
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1122
+ #endif
1123
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1124
+ if (res < 0) {
1125
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1126
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1127
+ ctxt->controlFd = INVALID_SOCKET;
1128
+ return(res);
1129
+ }
1130
+ res = xmlNanoFTPGetResponse(ctxt);
1131
+ if ((res == 1) || (res == 2)) {
1132
+ /* we assume it worked :-\ */
1133
+ proxyType = 2;
1134
+ return(0);
1135
+ }
1136
+ if (ctxt->passwd == NULL)
1137
+ snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
1138
+ else
1139
+ snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
1140
+ buf[sizeof(buf) - 1] = 0;
1141
+ len = strlen(buf);
1142
+ #ifdef DEBUG_FTP
1143
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1144
+ #endif
1145
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1146
+ if (res < 0) {
1147
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1148
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1149
+ ctxt->controlFd = INVALID_SOCKET;
1150
+ return(res);
1151
+ }
1152
+ res = xmlNanoFTPGetResponse(ctxt);
1153
+ if ((res == 1) || (res == 2)) {
1154
+ /* we assume it worked :-\ */
1155
+ proxyType = 2;
1156
+ return(0);
1157
+ }
1158
+ if (proxyType == 2) {
1159
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1160
+ ctxt->controlFd = INVALID_SOCKET;
1161
+ return(-1);
1162
+ }
1163
+ /* Falls through. */
1164
+ case 3:
1165
+ /*
1166
+ * If you need support for other Proxy authentication scheme
1167
+ * send the code or at least the sequence in use.
1168
+ */
1169
+ default:
1170
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1171
+ ctxt->controlFd = INVALID_SOCKET;
1172
+ return(-1);
1173
+ }
1174
+ }
1175
+ /*
1176
+ * Non-proxy handling.
1177
+ */
1178
+ res = xmlNanoFTPSendUser(ctxt);
1179
+ if (res < 0) {
1180
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1181
+ ctxt->controlFd = INVALID_SOCKET;
1182
+ return(-1);
1183
+ }
1184
+ res = xmlNanoFTPGetResponse(ctxt);
1185
+ switch (res) {
1186
+ case 2:
1187
+ return(0);
1188
+ case 3:
1189
+ break;
1190
+ case 1:
1191
+ case 4:
1192
+ case 5:
1193
+ case -1:
1194
+ default:
1195
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1196
+ ctxt->controlFd = INVALID_SOCKET;
1197
+ return(-1);
1198
+ }
1199
+ res = xmlNanoFTPSendPasswd(ctxt);
1200
+ if (res < 0) {
1201
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1202
+ ctxt->controlFd = INVALID_SOCKET;
1203
+ return(-1);
1204
+ }
1205
+ res = xmlNanoFTPGetResponse(ctxt);
1206
+ switch (res) {
1207
+ case 2:
1208
+ break;
1209
+ case 3:
1210
+ __xmlIOErr(XML_FROM_FTP, XML_FTP_ACCNT,
1211
+ "FTP server asking for ACCNT on anonymous\n");
1212
+ /* Falls through. */
1213
+ case 1:
1214
+ case 4:
1215
+ case 5:
1216
+ case -1:
1217
+ default:
1218
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1219
+ ctxt->controlFd = INVALID_SOCKET;
1220
+ return(-1);
1221
+ }
1222
+
1223
+ return(0);
1224
+ }
1225
+
1226
+ /**
1227
+ * xmlNanoFTPConnectTo:
1228
+ * @server: an FTP server name
1229
+ * @port: the port (use 21 if 0)
1230
+ *
1231
+ * Tries to open a control connection to the given server/port
1232
+ *
1233
+ * Returns an fTP context or NULL if it failed
1234
+ */
1235
+
1236
+ void*
1237
+ xmlNanoFTPConnectTo(const char *server, int port) {
1238
+ xmlNanoFTPCtxtPtr ctxt;
1239
+ int res;
1240
+
1241
+ xmlNanoFTPInit();
1242
+ if (server == NULL)
1243
+ return(NULL);
1244
+ if (port <= 0)
1245
+ return(NULL);
1246
+ ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(NULL);
1247
+ if (ctxt == NULL)
1248
+ return(NULL);
1249
+ ctxt->hostname = xmlMemStrdup(server);
1250
+ if (ctxt->hostname == NULL) {
1251
+ xmlNanoFTPFreeCtxt(ctxt);
1252
+ return(NULL);
1253
+ }
1254
+ ctxt->port = port;
1255
+ res = xmlNanoFTPConnect(ctxt);
1256
+ if (res < 0) {
1257
+ xmlNanoFTPFreeCtxt(ctxt);
1258
+ return(NULL);
1259
+ }
1260
+ return(ctxt);
1261
+ }
1262
+
1263
+ /**
1264
+ * xmlNanoFTPCwd:
1265
+ * @ctx: an FTP context
1266
+ * @directory: a directory on the server
1267
+ *
1268
+ * Tries to change the remote directory
1269
+ *
1270
+ * Returns -1 in case of error, 1 if CWD worked, 0 if it failed
1271
+ */
1272
+
1273
+ int
1274
+ xmlNanoFTPCwd(void *ctx, const char *directory) {
1275
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1276
+ char buf[400];
1277
+ int len;
1278
+ int res;
1279
+
1280
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
1281
+ if (directory == NULL) return 0;
1282
+
1283
+ /*
1284
+ * Expected response code for CWD:
1285
+ *
1286
+ * CWD
1287
+ * 250
1288
+ * 500, 501, 502, 421, 530, 550
1289
+ */
1290
+ snprintf(buf, sizeof(buf), "CWD %s\r\n", directory);
1291
+ buf[sizeof(buf) - 1] = 0;
1292
+ len = strlen(buf);
1293
+ #ifdef DEBUG_FTP
1294
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1295
+ #endif
1296
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1297
+ if (res < 0) {
1298
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1299
+ return(res);
1300
+ }
1301
+ res = xmlNanoFTPGetResponse(ctxt);
1302
+ if (res == 4) {
1303
+ return(-1);
1304
+ }
1305
+ if (res == 2) return(1);
1306
+ if (res == 5) {
1307
+ return(0);
1308
+ }
1309
+ return(0);
1310
+ }
1311
+
1312
+ /**
1313
+ * xmlNanoFTPDele:
1314
+ * @ctx: an FTP context
1315
+ * @file: a file or directory on the server
1316
+ *
1317
+ * Tries to delete an item (file or directory) from server
1318
+ *
1319
+ * Returns -1 in case of error, 1 if DELE worked, 0 if it failed
1320
+ */
1321
+
1322
+ int
1323
+ xmlNanoFTPDele(void *ctx, const char *file) {
1324
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1325
+ char buf[400];
1326
+ int len;
1327
+ int res;
1328
+
1329
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET) ||
1330
+ (file == NULL)) return(-1);
1331
+
1332
+ /*
1333
+ * Expected response code for DELE:
1334
+ *
1335
+ * DELE
1336
+ * 250
1337
+ * 450, 550
1338
+ * 500, 501, 502, 421, 530
1339
+ */
1340
+
1341
+ snprintf(buf, sizeof(buf), "DELE %s\r\n", file);
1342
+ buf[sizeof(buf) - 1] = 0;
1343
+ len = strlen(buf);
1344
+ #ifdef DEBUG_FTP
1345
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1346
+ #endif
1347
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1348
+ if (res < 0) {
1349
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1350
+ return(res);
1351
+ }
1352
+ res = xmlNanoFTPGetResponse(ctxt);
1353
+ if (res == 4) {
1354
+ return(-1);
1355
+ }
1356
+ if (res == 2) return(1);
1357
+ if (res == 5) {
1358
+ return(0);
1359
+ }
1360
+ return(0);
1361
+ }
1362
+ /**
1363
+ * xmlNanoFTPGetConnection:
1364
+ * @ctx: an FTP context
1365
+ *
1366
+ * Try to open a data connection to the server. Currently only
1367
+ * passive mode is supported.
1368
+ *
1369
+ * Returns -1 in case of error, 0 otherwise
1370
+ */
1371
+
1372
+ SOCKET
1373
+ xmlNanoFTPGetConnection(void *ctx) {
1374
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1375
+ char buf[200], *cur;
1376
+ int len, i;
1377
+ int res;
1378
+ unsigned char ad[6], *adp, *portp;
1379
+ unsigned int temp[6];
1380
+ #ifdef SUPPORT_IP6
1381
+ struct sockaddr_storage dataAddr;
1382
+ #else
1383
+ struct sockaddr_in dataAddr;
1384
+ #endif
1385
+ XML_SOCKLEN_T dataAddrLen;
1386
+
1387
+ if (ctxt == NULL) return INVALID_SOCKET;
1388
+
1389
+ memset (&dataAddr, 0, sizeof(dataAddr));
1390
+ #ifdef SUPPORT_IP6
1391
+ if ((ctxt->ftpAddr).ss_family == AF_INET6) {
1392
+ ctxt->dataFd = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
1393
+ ((struct sockaddr_in6 *)&dataAddr)->sin6_family = AF_INET6;
1394
+ dataAddrLen = sizeof(struct sockaddr_in6);
1395
+ } else
1396
+ #endif
1397
+ {
1398
+ ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1399
+ ((struct sockaddr_in *)&dataAddr)->sin_family = AF_INET;
1400
+ dataAddrLen = sizeof (struct sockaddr_in);
1401
+ }
1402
+
1403
+ if (ctxt->dataFd == INVALID_SOCKET) {
1404
+ __xmlIOErr(XML_FROM_FTP, 0, "socket failed");
1405
+ return INVALID_SOCKET;
1406
+ }
1407
+
1408
+ if (ctxt->passive) {
1409
+ #ifdef SUPPORT_IP6
1410
+ if ((ctxt->ftpAddr).ss_family == AF_INET6)
1411
+ snprintf (buf, sizeof(buf), "EPSV\r\n");
1412
+ else
1413
+ #endif
1414
+ snprintf (buf, sizeof(buf), "PASV\r\n");
1415
+ len = strlen (buf);
1416
+ #ifdef DEBUG_FTP
1417
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1418
+ #endif
1419
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1420
+ if (res < 0) {
1421
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1422
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1423
+ return INVALID_SOCKET;
1424
+ }
1425
+ res = xmlNanoFTPReadResponse(ctx);
1426
+ if (res != 2) {
1427
+ if (res == 5) {
1428
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1429
+ return INVALID_SOCKET;
1430
+ } else {
1431
+ /*
1432
+ * retry with an active connection
1433
+ */
1434
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1435
+ ctxt->passive = 0;
1436
+ }
1437
+ }
1438
+ cur = &ctxt->controlBuf[ctxt->controlBufAnswer];
1439
+ while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++;
1440
+ #ifdef SUPPORT_IP6
1441
+ if ((ctxt->ftpAddr).ss_family == AF_INET6) {
1442
+ if (sscanf (cur, "%u", &temp[0]) != 1) {
1443
+ __xmlIOErr(XML_FROM_FTP, XML_FTP_EPSV_ANSWER,
1444
+ "Invalid answer to EPSV\n");
1445
+ if (ctxt->dataFd != INVALID_SOCKET) {
1446
+ closesocket (ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1447
+ }
1448
+ return INVALID_SOCKET;
1449
+ }
1450
+ memcpy (&((struct sockaddr_in6 *)&dataAddr)->sin6_addr, &((struct sockaddr_in6 *)&ctxt->ftpAddr)->sin6_addr, sizeof(struct in6_addr));
1451
+ ((struct sockaddr_in6 *)&dataAddr)->sin6_port = htons (temp[0]);
1452
+ }
1453
+ else
1454
+ #endif
1455
+ {
1456
+ if (sscanf (cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
1457
+ &temp[3], &temp[4], &temp[5]) != 6) {
1458
+ __xmlIOErr(XML_FROM_FTP, XML_FTP_PASV_ANSWER,
1459
+ "Invalid answer to PASV\n");
1460
+ if (ctxt->dataFd != INVALID_SOCKET) {
1461
+ closesocket (ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1462
+ }
1463
+ return INVALID_SOCKET;
1464
+ }
1465
+ for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff);
1466
+ memcpy (&((struct sockaddr_in *)&dataAddr)->sin_addr, &ad[0], 4);
1467
+ memcpy (&((struct sockaddr_in *)&dataAddr)->sin_port, &ad[4], 2);
1468
+ }
1469
+
1470
+ if (connect(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {
1471
+ __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a data connection");
1472
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1473
+ return INVALID_SOCKET;
1474
+ }
1475
+ } else {
1476
+ getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);
1477
+ #ifdef SUPPORT_IP6
1478
+ if ((ctxt->ftpAddr).ss_family == AF_INET6)
1479
+ ((struct sockaddr_in6 *)&dataAddr)->sin6_port = 0;
1480
+ else
1481
+ #endif
1482
+ ((struct sockaddr_in *)&dataAddr)->sin_port = 0;
1483
+
1484
+ if (bind(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {
1485
+ __xmlIOErr(XML_FROM_FTP, 0, "bind failed");
1486
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1487
+ return INVALID_SOCKET;
1488
+ }
1489
+ getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);
1490
+
1491
+ if (listen(ctxt->dataFd, 1) < 0) {
1492
+ __xmlIOErr(XML_FROM_FTP, 0, "listen failed");
1493
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1494
+ return INVALID_SOCKET;
1495
+ }
1496
+ #ifdef SUPPORT_IP6
1497
+ if ((ctxt->ftpAddr).ss_family == AF_INET6) {
1498
+ char buf6[INET6_ADDRSTRLEN];
1499
+ inet_ntop (AF_INET6, &((struct sockaddr_in6 *)&dataAddr)->sin6_addr,
1500
+ buf6, INET6_ADDRSTRLEN);
1501
+ adp = (unsigned char *) buf6;
1502
+ portp = (unsigned char *) &((struct sockaddr_in6 *)&dataAddr)->sin6_port;
1503
+ snprintf (buf, sizeof(buf), "EPRT |2|%s|%s|\r\n", adp, portp);
1504
+ } else
1505
+ #endif
1506
+ {
1507
+ adp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_addr;
1508
+ portp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_port;
1509
+ snprintf (buf, sizeof(buf), "PORT %d,%d,%d,%d,%d,%d\r\n",
1510
+ adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff,
1511
+ portp[0] & 0xff, portp[1] & 0xff);
1512
+ }
1513
+
1514
+ buf[sizeof(buf) - 1] = 0;
1515
+ len = strlen(buf);
1516
+ #ifdef DEBUG_FTP
1517
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1518
+ #endif
1519
+
1520
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1521
+ if (res < 0) {
1522
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1523
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1524
+ return INVALID_SOCKET;
1525
+ }
1526
+ res = xmlNanoFTPGetResponse(ctxt);
1527
+ if (res != 2) {
1528
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1529
+ return INVALID_SOCKET;
1530
+ }
1531
+ }
1532
+ return(ctxt->dataFd);
1533
+
1534
+ }
1535
+
1536
+ /**
1537
+ * xmlNanoFTPCloseConnection:
1538
+ * @ctx: an FTP context
1539
+ *
1540
+ * Close the data connection from the server
1541
+ *
1542
+ * Returns -1 in case of error, 0 otherwise
1543
+ */
1544
+
1545
+ int
1546
+ xmlNanoFTPCloseConnection(void *ctx) {
1547
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1548
+ int res;
1549
+ fd_set rfd, efd;
1550
+ struct timeval tv;
1551
+
1552
+ if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
1553
+
1554
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1555
+ tv.tv_sec = 15;
1556
+ tv.tv_usec = 0;
1557
+ FD_ZERO(&rfd);
1558
+ FD_SET(ctxt->controlFd, &rfd);
1559
+ FD_ZERO(&efd);
1560
+ FD_SET(ctxt->controlFd, &efd);
1561
+ res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv);
1562
+ if (res < 0) {
1563
+ #ifdef DEBUG_FTP
1564
+ perror("select");
1565
+ #endif
1566
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1567
+ return(-1);
1568
+ }
1569
+ if (res == 0) {
1570
+ #ifdef DEBUG_FTP
1571
+ xmlGenericError(xmlGenericErrorContext,
1572
+ "xmlNanoFTPCloseConnection: timeout\n");
1573
+ #endif
1574
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1575
+ } else {
1576
+ res = xmlNanoFTPGetResponse(ctxt);
1577
+ if (res != 2) {
1578
+ closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1579
+ return(-1);
1580
+ }
1581
+ }
1582
+ return(0);
1583
+ }
1584
+
1585
+ /**
1586
+ * xmlNanoFTPParseList:
1587
+ * @list: some data listing received from the server
1588
+ * @callback: the user callback
1589
+ * @userData: the user callback data
1590
+ *
1591
+ * Parse at most one entry from the listing.
1592
+ *
1593
+ * Returns -1 in case of error, the length of data parsed otherwise
1594
+ */
1595
+
1596
+ static int
1597
+ xmlNanoFTPParseList(const char *list, ftpListCallback callback, void *userData) {
1598
+ const char *cur = list;
1599
+ char filename[151];
1600
+ char attrib[11];
1601
+ char owner[11];
1602
+ char group[11];
1603
+ char month[4];
1604
+ int year = 0;
1605
+ int minute = 0;
1606
+ int hour = 0;
1607
+ int day = 0;
1608
+ unsigned long size = 0;
1609
+ int links = 0;
1610
+ int i;
1611
+
1612
+ if (!strncmp(cur, "total", 5)) {
1613
+ cur += 5;
1614
+ while (*cur == ' ') cur++;
1615
+ while ((*cur >= '0') && (*cur <= '9'))
1616
+ links = (links * 10) + (*cur++ - '0');
1617
+ while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r'))
1618
+ cur++;
1619
+ return(cur - list);
1620
+ } else if (*list == '+') {
1621
+ return(0);
1622
+ } else {
1623
+ while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r'))
1624
+ cur++;
1625
+ if (*cur == 0) return(0);
1626
+ i = 0;
1627
+ while (*cur != ' ') {
1628
+ if (i < 10)
1629
+ attrib[i++] = *cur;
1630
+ cur++;
1631
+ if (*cur == 0) return(0);
1632
+ }
1633
+ attrib[10] = 0;
1634
+ while (*cur == ' ') cur++;
1635
+ if (*cur == 0) return(0);
1636
+ while ((*cur >= '0') && (*cur <= '9'))
1637
+ links = (links * 10) + (*cur++ - '0');
1638
+ while (*cur == ' ') cur++;
1639
+ if (*cur == 0) return(0);
1640
+ i = 0;
1641
+ while (*cur != ' ') {
1642
+ if (i < 10)
1643
+ owner[i++] = *cur;
1644
+ cur++;
1645
+ if (*cur == 0) return(0);
1646
+ }
1647
+ owner[i] = 0;
1648
+ while (*cur == ' ') cur++;
1649
+ if (*cur == 0) return(0);
1650
+ i = 0;
1651
+ while (*cur != ' ') {
1652
+ if (i < 10)
1653
+ group[i++] = *cur;
1654
+ cur++;
1655
+ if (*cur == 0) return(0);
1656
+ }
1657
+ group[i] = 0;
1658
+ while (*cur == ' ') cur++;
1659
+ if (*cur == 0) return(0);
1660
+ while ((*cur >= '0') && (*cur <= '9'))
1661
+ size = (size * 10) + (*cur++ - '0');
1662
+ while (*cur == ' ') cur++;
1663
+ if (*cur == 0) return(0);
1664
+ i = 0;
1665
+ while (*cur != ' ') {
1666
+ if (i < 3)
1667
+ month[i++] = *cur;
1668
+ cur++;
1669
+ if (*cur == 0) return(0);
1670
+ }
1671
+ month[i] = 0;
1672
+ while (*cur == ' ') cur++;
1673
+ if (*cur == 0) return(0);
1674
+ while ((*cur >= '0') && (*cur <= '9'))
1675
+ day = (day * 10) + (*cur++ - '0');
1676
+ while (*cur == ' ') cur++;
1677
+ if (*cur == 0) return(0);
1678
+ if ((cur[1] == 0) || (cur[2] == 0)) return(0);
1679
+ if ((cur[1] == ':') || (cur[2] == ':')) {
1680
+ while ((*cur >= '0') && (*cur <= '9'))
1681
+ hour = (hour * 10) + (*cur++ - '0');
1682
+ if (*cur == ':') cur++;
1683
+ while ((*cur >= '0') && (*cur <= '9'))
1684
+ minute = (minute * 10) + (*cur++ - '0');
1685
+ } else {
1686
+ while ((*cur >= '0') && (*cur <= '9'))
1687
+ year = (year * 10) + (*cur++ - '0');
1688
+ }
1689
+ while (*cur == ' ') cur++;
1690
+ if (*cur == 0) return(0);
1691
+ i = 0;
1692
+ while ((*cur != '\n') && (*cur != '\r')) {
1693
+ if (i < 150)
1694
+ filename[i++] = *cur;
1695
+ cur++;
1696
+ if (*cur == 0) return(0);
1697
+ }
1698
+ filename[i] = 0;
1699
+ if ((*cur != '\n') && (*cur != '\r'))
1700
+ return(0);
1701
+ while ((*cur == '\n') || (*cur == '\r'))
1702
+ cur++;
1703
+ }
1704
+ if (callback != NULL) {
1705
+ callback(userData, filename, attrib, owner, group, size, links,
1706
+ year, month, day, hour, minute);
1707
+ }
1708
+ return(cur - list);
1709
+ }
1710
+
1711
+ /**
1712
+ * xmlNanoFTPList:
1713
+ * @ctx: an FTP context
1714
+ * @callback: the user callback
1715
+ * @userData: the user callback data
1716
+ * @filename: optional files to list
1717
+ *
1718
+ * Do a listing on the server. All files info are passed back
1719
+ * in the callbacks.
1720
+ *
1721
+ * Returns -1 in case of error, 0 otherwise
1722
+ */
1723
+
1724
+ int
1725
+ xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
1726
+ const char *filename) {
1727
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1728
+ char buf[4096 + 1];
1729
+ int len, res;
1730
+ int indx = 0, base;
1731
+ fd_set rfd, efd;
1732
+ struct timeval tv;
1733
+
1734
+ if (ctxt == NULL) return (-1);
1735
+ if (filename == NULL) {
1736
+ if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1)
1737
+ return(-1);
1738
+ ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
1739
+ if (ctxt->dataFd == INVALID_SOCKET)
1740
+ return(-1);
1741
+ snprintf(buf, sizeof(buf), "LIST -L\r\n");
1742
+ } else {
1743
+ if (filename[0] != '/') {
1744
+ if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1)
1745
+ return(-1);
1746
+ }
1747
+ ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
1748
+ if (ctxt->dataFd == INVALID_SOCKET)
1749
+ return(-1);
1750
+ snprintf(buf, sizeof(buf), "LIST -L %s\r\n", filename);
1751
+ }
1752
+ buf[sizeof(buf) - 1] = 0;
1753
+ len = strlen(buf);
1754
+ #ifdef DEBUG_FTP
1755
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1756
+ #endif
1757
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1758
+ if (res < 0) {
1759
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1760
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1761
+ return(res);
1762
+ }
1763
+ res = xmlNanoFTPReadResponse(ctxt);
1764
+ if (res != 1) {
1765
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1766
+ return(-res);
1767
+ }
1768
+
1769
+ do {
1770
+ tv.tv_sec = 1;
1771
+ tv.tv_usec = 0;
1772
+ FD_ZERO(&rfd);
1773
+ FD_SET(ctxt->dataFd, &rfd);
1774
+ FD_ZERO(&efd);
1775
+ FD_SET(ctxt->dataFd, &efd);
1776
+ res = select(ctxt->dataFd + 1, &rfd, NULL, &efd, &tv);
1777
+ if (res < 0) {
1778
+ #ifdef DEBUG_FTP
1779
+ perror("select");
1780
+ #endif
1781
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1782
+ return(-1);
1783
+ }
1784
+ if (res == 0) {
1785
+ res = xmlNanoFTPCheckResponse(ctxt);
1786
+ if (res < 0) {
1787
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1788
+ ctxt->dataFd = INVALID_SOCKET;
1789
+ return(-1);
1790
+ }
1791
+ if (res == 2) {
1792
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1793
+ return(0);
1794
+ }
1795
+
1796
+ continue;
1797
+ }
1798
+
1799
+ if ((len = recv(ctxt->dataFd, &buf[indx], sizeof(buf) - (indx + 1), 0)) < 0) {
1800
+ __xmlIOErr(XML_FROM_FTP, 0, "recv");
1801
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1802
+ ctxt->dataFd = INVALID_SOCKET;
1803
+ return(-1);
1804
+ }
1805
+ #ifdef DEBUG_FTP
1806
+ write(1, &buf[indx], len);
1807
+ #endif
1808
+ indx += len;
1809
+ buf[indx] = 0;
1810
+ base = 0;
1811
+ do {
1812
+ res = xmlNanoFTPParseList(&buf[base], callback, userData);
1813
+ base += res;
1814
+ } while (res > 0);
1815
+
1816
+ memmove(&buf[0], &buf[base], indx - base);
1817
+ indx -= base;
1818
+ } while (len != 0);
1819
+ xmlNanoFTPCloseConnection(ctxt);
1820
+ return(0);
1821
+ }
1822
+
1823
+ /**
1824
+ * xmlNanoFTPGetSocket:
1825
+ * @ctx: an FTP context
1826
+ * @filename: the file to retrieve (or NULL if path is in context).
1827
+ *
1828
+ * Initiate fetch of the given file from the server.
1829
+ *
1830
+ * Returns the socket for the data connection, or <0 in case of error
1831
+ */
1832
+
1833
+
1834
+ SOCKET
1835
+ xmlNanoFTPGetSocket(void *ctx, const char *filename) {
1836
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1837
+ char buf[300];
1838
+ int res, len;
1839
+ if (ctx == NULL)
1840
+ return INVALID_SOCKET;
1841
+ if ((filename == NULL) && (ctxt->path == NULL))
1842
+ return INVALID_SOCKET;
1843
+ ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
1844
+ if (ctxt->dataFd == INVALID_SOCKET)
1845
+ return INVALID_SOCKET;
1846
+
1847
+ snprintf(buf, sizeof(buf), "TYPE I\r\n");
1848
+ len = strlen(buf);
1849
+ #ifdef DEBUG_FTP
1850
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1851
+ #endif
1852
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1853
+ if (res < 0) {
1854
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1855
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1856
+ return INVALID_SOCKET;
1857
+ }
1858
+ res = xmlNanoFTPReadResponse(ctxt);
1859
+ if (res != 2) {
1860
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1861
+ return INVALID_SOCKET;
1862
+ }
1863
+ if (filename == NULL)
1864
+ snprintf(buf, sizeof(buf), "RETR %s\r\n", ctxt->path);
1865
+ else
1866
+ snprintf(buf, sizeof(buf), "RETR %s\r\n", filename);
1867
+ buf[sizeof(buf) - 1] = 0;
1868
+ len = strlen(buf);
1869
+ #ifdef DEBUG_FTP
1870
+ xmlGenericError(xmlGenericErrorContext, "%s", buf);
1871
+ #endif
1872
+ res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1873
+ if (res < 0) {
1874
+ __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1875
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1876
+ return INVALID_SOCKET;
1877
+ }
1878
+ res = xmlNanoFTPReadResponse(ctxt);
1879
+ if (res != 1) {
1880
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1881
+ return INVALID_SOCKET;
1882
+ }
1883
+ return(ctxt->dataFd);
1884
+ }
1885
+
1886
+ /**
1887
+ * xmlNanoFTPGet:
1888
+ * @ctx: an FTP context
1889
+ * @callback: the user callback
1890
+ * @userData: the user callback data
1891
+ * @filename: the file to retrieve
1892
+ *
1893
+ * Fetch the given file from the server. All data are passed back
1894
+ * in the callbacks. The last callback has a size of 0 block.
1895
+ *
1896
+ * Returns -1 in case of error, 0 otherwise
1897
+ */
1898
+
1899
+ int
1900
+ xmlNanoFTPGet(void *ctx, ftpDataCallback callback, void *userData,
1901
+ const char *filename) {
1902
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1903
+ char buf[4096];
1904
+ int len = 0, res;
1905
+ fd_set rfd;
1906
+ struct timeval tv;
1907
+
1908
+ if (ctxt == NULL) return(-1);
1909
+ if ((filename == NULL) && (ctxt->path == NULL))
1910
+ return(-1);
1911
+ if (callback == NULL)
1912
+ return(-1);
1913
+ if (xmlNanoFTPGetSocket(ctxt, filename) == INVALID_SOCKET)
1914
+ return(-1);
1915
+
1916
+ do {
1917
+ tv.tv_sec = 1;
1918
+ tv.tv_usec = 0;
1919
+ FD_ZERO(&rfd);
1920
+ FD_SET(ctxt->dataFd, &rfd);
1921
+ res = select(ctxt->dataFd + 1, &rfd, NULL, NULL, &tv);
1922
+ if (res < 0) {
1923
+ #ifdef DEBUG_FTP
1924
+ perror("select");
1925
+ #endif
1926
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1927
+ return(-1);
1928
+ }
1929
+ if (res == 0) {
1930
+ res = xmlNanoFTPCheckResponse(ctxt);
1931
+ if (res < 0) {
1932
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1933
+ ctxt->dataFd = INVALID_SOCKET;
1934
+ return(-1);
1935
+ }
1936
+ if (res == 2) {
1937
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1938
+ return(0);
1939
+ }
1940
+
1941
+ continue;
1942
+ }
1943
+ if ((len = recv(ctxt->dataFd, buf, sizeof(buf), 0)) < 0) {
1944
+ __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
1945
+ callback(userData, buf, len);
1946
+ closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1947
+ return(-1);
1948
+ }
1949
+ callback(userData, buf, len);
1950
+ } while (len != 0);
1951
+
1952
+ return(xmlNanoFTPCloseConnection(ctxt));
1953
+ }
1954
+
1955
+ /**
1956
+ * xmlNanoFTPRead:
1957
+ * @ctx: the FTP context
1958
+ * @dest: a buffer
1959
+ * @len: the buffer length
1960
+ *
1961
+ * This function tries to read @len bytes from the existing FTP connection
1962
+ * and saves them in @dest. This is a blocking call.
1963
+ *
1964
+ * Returns the number of byte read. 0 is an indication of an end of connection.
1965
+ * -1 indicates a parameter error.
1966
+ */
1967
+ int
1968
+ xmlNanoFTPRead(void *ctx, void *dest, int len) {
1969
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1970
+
1971
+ if (ctx == NULL) return(-1);
1972
+ if (ctxt->dataFd == INVALID_SOCKET) return(0);
1973
+ if (dest == NULL) return(-1);
1974
+ if (len <= 0) return(0);
1975
+
1976
+ len = recv(ctxt->dataFd, dest, len, 0);
1977
+ if (len <= 0) {
1978
+ if (len < 0)
1979
+ __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
1980
+ xmlNanoFTPCloseConnection(ctxt);
1981
+ }
1982
+ #ifdef DEBUG_FTP
1983
+ xmlGenericError(xmlGenericErrorContext, "Recvd %d bytes\n", len);
1984
+ #endif
1985
+ return(len);
1986
+ }
1987
+
1988
+ /**
1989
+ * xmlNanoFTPOpen:
1990
+ * @URL: the URL to the resource
1991
+ *
1992
+ * Start to fetch the given ftp:// resource
1993
+ *
1994
+ * Returns an FTP context, or NULL
1995
+ */
1996
+
1997
+ void*
1998
+ xmlNanoFTPOpen(const char *URL) {
1999
+ xmlNanoFTPCtxtPtr ctxt;
2000
+ SOCKET sock;
2001
+
2002
+ xmlNanoFTPInit();
2003
+ if (URL == NULL) return(NULL);
2004
+ if (strncmp("ftp://", URL, 6)) return(NULL);
2005
+
2006
+ ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(URL);
2007
+ if (ctxt == NULL) return(NULL);
2008
+ if (xmlNanoFTPConnect(ctxt) < 0) {
2009
+ xmlNanoFTPFreeCtxt(ctxt);
2010
+ return(NULL);
2011
+ }
2012
+ sock = xmlNanoFTPGetSocket(ctxt, ctxt->path);
2013
+ if (sock == INVALID_SOCKET) {
2014
+ xmlNanoFTPFreeCtxt(ctxt);
2015
+ return(NULL);
2016
+ }
2017
+ return(ctxt);
2018
+ }
2019
+
2020
+ /**
2021
+ * xmlNanoFTPClose:
2022
+ * @ctx: an FTP context
2023
+ *
2024
+ * Close the connection and both control and transport
2025
+ *
2026
+ * Returns -1 in case of error, 0 otherwise
2027
+ */
2028
+
2029
+ int
2030
+ xmlNanoFTPClose(void *ctx) {
2031
+ xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
2032
+
2033
+ if (ctxt == NULL)
2034
+ return(-1);
2035
+
2036
+ if (ctxt->dataFd != INVALID_SOCKET) {
2037
+ closesocket(ctxt->dataFd);
2038
+ ctxt->dataFd = INVALID_SOCKET;
2039
+ }
2040
+ if (ctxt->controlFd != INVALID_SOCKET) {
2041
+ xmlNanoFTPQuit(ctxt);
2042
+ closesocket(ctxt->controlFd);
2043
+ ctxt->controlFd = INVALID_SOCKET;
2044
+ }
2045
+ xmlNanoFTPFreeCtxt(ctxt);
2046
+ return(0);
2047
+ }
2048
+
2049
+ #ifdef STANDALONE
2050
+ /************************************************************************
2051
+ * *
2052
+ * Basic test in Standalone mode *
2053
+ * *
2054
+ ************************************************************************/
2055
+ static
2056
+ void ftpList(void *userData, const char *filename, const char* attrib,
2057
+ const char *owner, const char *group, unsigned long size, int links,
2058
+ int year, const char *month, int day, int hour, int minute) {
2059
+ xmlGenericError(xmlGenericErrorContext,
2060
+ "%s %s %s %ld %s\n", attrib, owner, group, size, filename);
2061
+ }
2062
+ static
2063
+ void ftpData(void *userData, const char *data, int len) {
2064
+ if (userData == NULL) return;
2065
+ if (len <= 0) {
2066
+ fclose((FILE*)userData);
2067
+ return;
2068
+ }
2069
+ fwrite(data, len, 1, (FILE*)userData);
2070
+ }
2071
+
2072
+ int main(int argc, char **argv) {
2073
+ void *ctxt;
2074
+ FILE *output;
2075
+ char *tstfile = NULL;
2076
+
2077
+ xmlNanoFTPInit();
2078
+ if (argc > 1) {
2079
+ ctxt = xmlNanoFTPNewCtxt(argv[1]);
2080
+ if (xmlNanoFTPConnect(ctxt) < 0) {
2081
+ xmlGenericError(xmlGenericErrorContext,
2082
+ "Couldn't connect to %s\n", argv[1]);
2083
+ exit(1);
2084
+ }
2085
+ if (argc > 2)
2086
+ tstfile = argv[2];
2087
+ } else
2088
+ ctxt = xmlNanoFTPConnectTo("localhost", 0);
2089
+ if (ctxt == NULL) {
2090
+ xmlGenericError(xmlGenericErrorContext,
2091
+ "Couldn't connect to localhost\n");
2092
+ exit(1);
2093
+ }
2094
+ xmlNanoFTPList(ctxt, ftpList, NULL, tstfile);
2095
+ output = fopen("/tmp/tstdata", "w");
2096
+ if (output != NULL) {
2097
+ if (xmlNanoFTPGet(ctxt, ftpData, (void *) output, tstfile) < 0)
2098
+ xmlGenericError(xmlGenericErrorContext,
2099
+ "Failed to get file\n");
2100
+
2101
+ }
2102
+ xmlNanoFTPClose(ctxt);
2103
+ xmlMemoryDump();
2104
+ exit(0);
2105
+ }
2106
+ #endif /* STANDALONE */
2107
+ #else /* !LIBXML_FTP_ENABLED */
2108
+ #ifdef STANDALONE
2109
+ #include <stdio.h>
2110
+ int main(int argc, char **argv) {
2111
+ xmlGenericError(xmlGenericErrorContext,
2112
+ "%s : FTP support not compiled in\n", argv[0]);
2113
+ return(0);
2114
+ }
2115
+ #endif /* STANDALONE */
2116
+ #endif /* LIBXML_FTP_ENABLED */
2117
+ #define bottom_nanoftp
2118
+ #include "elfgcchack.h"