📄 nanoftp.c.svn-base
字号:
} /* * Do the connect. */ if (connect(ctxt->controlFd, (struct sockaddr *) &ctxt->ftpAddr, addrlen) < 0) { __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a connection"); closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } /* * Wait for the HELLO from the server. */ res = xmlNanoFTPGetResponse(ctxt); if (res != 2) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } /* * State diagram for the login operation on the FTP server * * Reference: RFC 959 * * 1 * +---+ USER +---+------------->+---+ * | B |---------->| W | 2 ---->| E | * +---+ +---+------ | -->+---+ * | | | | | * 3 | | 4,5 | | | * -------------- ----- | | | * | | | | | * | | | | | * | --------- | * | 1| | | | * V | | | | * +---+ PASS +---+ 2 | ------>+---+ * | |---------->| W |------------->| S | * +---+ +---+ ---------->+---+ * | | | | | * 3 | |4,5| | | * -------------- -------- | * | | | | | * | | | | | * | ----------- * | 1,3| | | | * V | 2| | | * +---+ ACCT +---+-- | ----->+---+ * | |---------->| W | 4,5 -------->| F | * +---+ +---+------------->+---+ * * Of course in case of using a proxy this get really nasty and is not * standardized at all :-( */ if (proxy) { int len; char buf[400]; if (proxyUser != NULL) { /* * We need proxy auth */ snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->controlFd); ctxt->controlFd = -1; return(res); } res = xmlNanoFTPGetResponse(ctxt); switch (res) { case 2: if (proxyPasswd == NULL) break; case 3: if (proxyPasswd != NULL) snprintf(buf, sizeof(buf), "PASS %s\r\n", proxyPasswd); else snprintf(buf, sizeof(buf), "PASS anonymous@\r\n"); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->controlFd); ctxt->controlFd = -1; return(res); } res = xmlNanoFTPGetResponse(ctxt); if (res > 3) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; return(-1); } break; case 1: break; case 4: case 5: case -1: default: closesocket(ctxt->controlFd); ctxt->controlFd = -1; return(-1); } } /* * We assume we don't need more authentication to the proxy * and that it succeeded :-\ */ switch (proxyType) { case 0: /* we will try in sequence */ case 1: /* Using SITE command */ snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(res); } res = xmlNanoFTPGetResponse(ctxt); if (res == 2) { /* we assume it worked :-\ 1 is error for SITE command */ proxyType = 1; break; } if (proxyType == 1) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } case 2: /* USER user@host command */ if (ctxt->user == NULL) snprintf(buf, sizeof(buf), "USER anonymous@%s\r\n", ctxt->hostname); else snprintf(buf, sizeof(buf), "USER %s@%s\r\n", ctxt->user, ctxt->hostname); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(res); } res = xmlNanoFTPGetResponse(ctxt); if ((res == 1) || (res == 2)) { /* we assume it worked :-\ */ proxyType = 2; return(0); } if (ctxt->passwd == NULL) snprintf(buf, sizeof(buf), "PASS anonymous@\r\n"); else snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(res); } res = xmlNanoFTPGetResponse(ctxt); if ((res == 1) || (res == 2)) { /* we assume it worked :-\ */ proxyType = 2; return(0); } if (proxyType == 2) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } case 3: /* * If you need support for other Proxy authentication scheme * send the code or at least the sequence in use. */ default: closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } } /* * Non-proxy handling. */ res = xmlNanoFTPSendUser(ctxt); if (res < 0) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } res = xmlNanoFTPGetResponse(ctxt); switch (res) { case 2: return(0); case 3: break; case 1: case 4: case 5: case -1: default: closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } res = xmlNanoFTPSendPasswd(ctxt); if (res < 0) { closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } res = xmlNanoFTPGetResponse(ctxt); switch (res) { case 2: break; case 3: __xmlIOErr(XML_FROM_FTP, XML_FTP_ACCNT, "FTP server asking for ACCNT on anonymous\n"); case 1: case 4: case 5: case -1: default: closesocket(ctxt->controlFd); ctxt->controlFd = -1; ctxt->controlFd = -1; return(-1); } return(0);}/** * xmlNanoFTPConnectTo: * @server: an FTP server name * @port: the port (use 21 if 0) * * Tries to open a control connection to the given server/port * * Returns an fTP context or NULL if it failed */void*xmlNanoFTPConnectTo(const char *server, int port) { xmlNanoFTPCtxtPtr ctxt; int res; xmlNanoFTPInit(); if (server == NULL) return(NULL); ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(NULL); ctxt->hostname = xmlMemStrdup(server); if (port != 0) ctxt->port = port; res = xmlNanoFTPConnect(ctxt); if (res < 0) { xmlNanoFTPFreeCtxt(ctxt); return(NULL); } return(ctxt);}/** * xmlNanoFTPCwd: * @ctx: an FTP context * @directory: a directory on the server * * Tries to change the remote directory * * Returns -1 incase of error, 1 if CWD worked, 0 if it failed */intxmlNanoFTPCwd(void *ctx, char *directory) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; char buf[400]; int len; int res; /* * Expected response code for CWD: * * CWD * 250 * 500, 501, 502, 421, 530, 550 */ snprintf(buf, sizeof(buf), "CWD %s\r\n", directory); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); return(res); } res = xmlNanoFTPGetResponse(ctxt); if (res == 4) { return(-1); } if (res == 2) return(1); if (res == 5) { return(0); } return(0);}/** * xmlNanoFTPDele: * @ctx: an FTP context * @file: a file or directory on the server * * Tries to delete an item (file or directory) from server * * Returns -1 incase of error, 1 if DELE worked, 0 if it failed */intxmlNanoFTPDele(void *ctx, char *file) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; char buf[400]; int len; int res; /* * Expected response code for DELE: * * DELE * 250 * 450, 550 * 500, 501, 502, 421, 530 */ snprintf(buf, sizeof(buf), "DELE %s\r\n", file); buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); return(res); } res = xmlNanoFTPGetResponse(ctxt); if (res == 4) { return(-1); } if (res == 2) return(1); if (res == 5) { return(0); } return(0);}/** * xmlNanoFTPGetConnection: * @ctx: an FTP context * * Try to open a data connection to the server. Currently only * passive mode is supported. * * Returns -1 incase of error, 0 otherwise */intxmlNanoFTPGetConnection(void *ctx) { xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx; char buf[200], *cur; int len, i; int res; unsigned char ad[6], *adp, *portp; unsigned int temp[6];#ifdef SUPPORT_IP6 struct sockaddr_storage dataAddr;#else struct sockaddr_in dataAddr;#endif SOCKLEN_T dataAddrLen; memset (&dataAddr, 0, sizeof(dataAddr));#ifdef SUPPORT_IP6 if ((ctxt->ftpAddr).ss_family == AF_INET6) { ctxt->dataFd = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP); ((struct sockaddr_in6 *)&dataAddr)->sin6_family = AF_INET6; dataAddrLen = sizeof(struct sockaddr_in6); } else#endif { ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); ((struct sockaddr_in *)&dataAddr)->sin_family = AF_INET; dataAddrLen = sizeof (struct sockaddr_in); } if (ctxt->dataFd < 0) { __xmlIOErr(XML_FROM_FTP, 0, "socket failed"); return (-1); } if (ctxt->passive) {#ifdef SUPPORT_IP6 if ((ctxt->ftpAddr).ss_family == AF_INET6) snprintf (buf, sizeof(buf), "EPSV\r\n"); else#endif snprintf (buf, sizeof(buf), "PASV\r\n"); len = strlen (buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(res); } res = xmlNanoFTPReadResponse(ctx); if (res != 2) { if (res == 5) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-1); } else { /* * retry with an active connection */ closesocket(ctxt->dataFd); ctxt->dataFd = -1; ctxt->passive = 0; } } cur = &ctxt->controlBuf[ctxt->controlBufAnswer]; while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++;#ifdef SUPPORT_IP6 if ((ctxt->ftpAddr).ss_family == AF_INET6) { if (sscanf (cur, "%u", &temp[0]) != 1) { __xmlIOErr(XML_FROM_FTP, XML_FTP_EPSV_ANSWER, "Invalid answer to EPSV\n"); if (ctxt->dataFd != -1) { closesocket (ctxt->dataFd); ctxt->dataFd = -1; } return (-1); } memcpy (&((struct sockaddr_in6 *)&dataAddr)->sin6_addr, &((struct sockaddr_in6 *)&ctxt->ftpAddr)->sin6_addr, sizeof(struct in6_addr)); ((struct sockaddr_in6 *)&dataAddr)->sin6_port = htons (temp[0]); } else#endif { if (sscanf (cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5]) != 6) { __xmlIOErr(XML_FROM_FTP, XML_FTP_PASV_ANSWER, "Invalid answer to PASV\n"); if (ctxt->dataFd != -1) { closesocket (ctxt->dataFd); ctxt->dataFd = -1; } return (-1); } for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff); memcpy (&((struct sockaddr_in *)&dataAddr)->sin_addr, &ad[0], 4); memcpy (&((struct sockaddr_in *)&dataAddr)->sin_port, &ad[4], 2); } if (connect(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) { __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a data connection"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return (-1); } } else { getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);#ifdef SUPPORT_IP6 if ((ctxt->ftpAddr).ss_family == AF_INET6) ((struct sockaddr_in6 *)&dataAddr)->sin6_port = 0; else#endif ((struct sockaddr_in *)&dataAddr)->sin_port = 0; if (bind(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) { __xmlIOErr(XML_FROM_FTP, 0, "bind failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return (-1); } getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen); if (listen(ctxt->dataFd, 1) < 0) { __xmlIOErr(XML_FROM_FTP, 0, "listen failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return (-1); }#ifdef SUPPORT_IP6 if ((ctxt->ftpAddr).ss_family == AF_INET6) { char buf6[INET6_ADDRSTRLEN]; inet_ntop (AF_INET6, &((struct sockaddr_in6 *)&dataAddr)->sin6_addr, buf6, INET6_ADDRSTRLEN); adp = (unsigned char *) buf6; portp = (unsigned char *) &((struct sockaddr_in6 *)&dataAddr)->sin6_port; snprintf (buf, sizeof(buf), "EPRT |2|%s|%s|\r\n", adp, portp); } else#endif { adp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_addr; portp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_port; snprintf (buf, sizeof(buf), "PORT %d,%d,%d,%d,%d,%d\r\n", adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff, portp[0] & 0xff, portp[1] & 0xff); } buf[sizeof(buf) - 1] = 0; len = strlen(buf);#ifdef DEBUG_FTP xmlGenericError(xmlGenericErrorContext, "%s", buf);#endif res = send(ctxt->controlFd, buf, len, 0); if (res < 0) { __xmlIOErr(XML_FROM_FTP, 0, "send failed"); closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(res); } res = xmlNanoFTPGetResponse(ctxt); if (res != 2) { closesocket(ctxt->dataFd); ctxt->dataFd = -1; return(-1); } } return(ctxt->dataFd); }/** * xmlNanoFTPCloseConnection: * @ctx: an FTP context * * Close the data connection from the server * * Returns -1 incase of error, 0 otherwise */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -