?? htftp.c
字號:
*/PRIVATE BOOL HTFTPParseURL (HTRequest * request, char *url, ftp_ctrl *ctrl, ftp_data *data){ char *login = HTParse(url, "", PARSE_HOST); char *path = HTParse(url, "", PARSE_PATH+PARSE_PUNCTUATION); char *ptr = strchr(login, '@'); if (ptr) { /* Uid and/or passwd specified */ char *passwd; *ptr = '\0'; if ((passwd = strchr(login, ':'))) { /* Passwd specified */ *passwd++ = '\0'; HTUnEscape(passwd); StrAllocCopy(ctrl->passwd, passwd); } HTUnEscape(login); StrAllocCopy(ctrl->uid, login); } else if (g_FTPControlMode & FTP_ALWAYS_ASK_UID_PW) { ctrl->uid=NULL; ctrl->passwd=NULL; } else { /* Use anonymous */ HTUserProfile * up = HTRequest_userProfile(request); const char * mailaddress = HTUserProfile_email(up); StrAllocCopy(ctrl->uid, "anonymous"); if (mailaddress) StrAllocCopy(ctrl->passwd, mailaddress); else StrAllocCopy(ctrl->passwd, WWW_FTP_CLIENT); } HTTRACE(PROT_TRACE, "FTPParse.... uid `%s\' pw `%s\'\n" _ ctrl->uid ? ctrl->uid : "<null>" _ ctrl->passwd ? ctrl->passwd : "<null>"); /* ** Look for any type in the URI. If not 'type' parameter then look for ** trailing slash. */ if ((ptr = strchr(path, ';')) != NULL) { *ptr = '\0'; if (strncasecomp(ptr, ";type=", 6)) /* Look for type */ data->type = TOUPPER(*(ptr+6)); else if (*(ptr-1) == '/') data->type = 'D'; } else if (*(path+strlen(path)-1) == '/') { *(path+strlen(path)-1) = '\0'; data->type = 'D'; } HTTRACE(PROT_TRACE, "FTPParse.... Datatype %c\n" _ data->type ? data->type : '?'); StrAllocCopy(data->file, path); data->offset = data->file; HT_FREE(login); HT_FREE(path); return YES;}/* Use LIST or NLST** ----------------** This function sets the type field for what type of list we can use** Returns YES if OK, else NO*/PRIVATE BOOL FTPListType (ftp_data * data, FTPServerType type){ if (!data) return NO; switch (type) { case FTP_GENERIC: data->type='N'; break; case FTP_MACHTEN: data->type='L'; break; case FTP_UNIX: data->type='L'; break; case FTP_VMS: data->type='L'; break; case FTP_CMS: data->type='N'; break; case FTP_DCTS: data->type='N'; break; case FTP_TCPC: data->type='N'; break; case FTP_PETER_LEWIS: data->type='L'; break; case FTP_NCSA: data->type='N'; break; case FTP_WINNT: data->type='L'; break; default: data->type='N'; break; } return YES;}/* Open a Data socket for listening on** -----------------------------------** Set up a port to listen for data** Returns YES if OK, else NO*/PRIVATE BOOL AcceptDataSocket (HTNet *cnet, HTNet *dnet, ftp_data *data){ if (HTHost_listen(NULL, dnet, "ftp://localhost:0") == HT_ERROR) return NO; /* ** Now we must find out who we are to tell the other guy ** We have to get the local IP interface from the control connection as ** this is not yet set in the unaccepted data socket */ { SockA local_port, local_host; int addr_size = sizeof(local_port); memset((void *) &local_host, '\0', addr_size); memset((void *) &local_port, '\0', addr_size); if (getsockname(HTNet_socket(cnet), (struct sockaddr *) &local_host, &addr_size) < 0 || getsockname(HTNet_socket(dnet), (struct sockaddr *) &local_port, &addr_size) < 0) { HTRequest_addSystemError(HTNet_request(dnet), ERR_FATAL, socerrno, NO, "getsockname"); return NO; } HTTRACE(PROT_TRACE, "FTP......... This host is `%s\'\n" _ HTInetString(&local_host)); { u_long addr = local_host.sin_addr.s_addr; u_short port = local_port.sin_port; sprintf(data->host, "%d,%d,%d,%d,%d,%d", (int)*((unsigned char *)(&addr)+0), (int)*((unsigned char *)(&addr)+1), (int)*((unsigned char *)(&addr)+2), (int)*((unsigned char *)(&addr)+3), (int)*((unsigned char *)(&port)+0), (int)*((unsigned char *)(&port)+1)); } } return YES;}/* HTFTPLogin** -----------** This function makes a login to a ftp-server. It takes the user name** and passwd specified in ctrl->user and if that fails or an additional** account is needed, the user is prompted.** Returns HT_OK, HT_ERROR, or HT_WOULD_BLOCK*/PRIVATE int HTFTPLogin (HTRequest *request, HTNet *cnet, ftp_ctrl *ctrl){ int status; typedef enum _state { SUB_ERROR = -2, SUB_SUCCESS = -1, NEED_SELECT = 0, NEED_GREETING, NEED_REIN, NEED_UID, NEED_PASSWD, NEED_ACCOUNT, PROMPT_USER } state; /* Jump into a second level state machine */ while (1) { switch ((state) ctrl->substate) { case NEED_SELECT: { HTAlertCallback * cbf = HTAlert_find(HT_PROG_LOGIN); if (cbf) (*cbf)(request, HT_PROG_LOGIN, HT_MSG_NULL, NULL, NULL, NULL); HTTRACE(PROT_TRACE, "FTP Login... now in state NEED_SELECT\n"); ctrl->substate = ctrl->reset ? NEED_REIN : NEED_GREETING; } break; case NEED_GREETING: HTTRACE(PROT_TRACE, "FTP Login... now in state NEED_GREETING\n"); status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { if (ctrl->repcode/100 == 2) { ctrl->substate = (ctrl->uid && *ctrl->uid) ? NEED_UID : PROMPT_USER; } else { ctrl->substate = SUB_ERROR; } } else { ctrl->substate = SUB_ERROR; } break; case NEED_REIN: HTTRACE(PROT_TRACE, "FTP Login... now in state NEED_REIN\n"); if (!ctrl->sent) { status = SendCommand(request, ctrl, "REIN", NULL); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_ERROR) ctrl->substate = SUB_ERROR; ctrl->sent = YES; } else { status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { /* ** If the FTP server doesn't support the REIN command, then ** the return code will be 502 */ if ((ctrl->repcode/100 == 2) || (ctrl->repcode == 502)) { ctrl->substate = (ctrl->uid && *ctrl->uid) ? NEED_UID : PROMPT_USER; } else { ctrl->substate = SUB_SUCCESS; /* hope the best */ } } else { ctrl->substate = SUB_ERROR; } ctrl->sent = NO; } break; case NEED_UID: HTTRACE(PROT_TRACE, "FTP Login... now in state NEED_UID\n"); if (!ctrl->sent) { status = SendCommand(request, ctrl, "USER", ctrl->uid); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_ERROR) ctrl->substate = SUB_ERROR; ctrl->sent = YES; } else { status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { int code = ctrl->repcode/100; if (code == 2) /* Logged in w/o passwd! */ ctrl->substate = SUB_SUCCESS; else if (code == 3) { /* Password demanded */ ctrl->substate = (ctrl->passwd && *ctrl->passwd) ? NEED_PASSWD : PROMPT_USER;/* begin _GM_ *//* Note: libwww bug ID: GM3 */ /* } else if (ctrl->repcode == 530) */ /* ctrl->substate = PROMPT_USER;*/ /* User unknown */ } else if (ctrl->repcode == 530) { if (ctrl->alreadyLoggedIn == YES) { ctrl->substate = SUB_SUCCESS; HTTRACE(PROT_TRACE, "FTP Login... Already logged in\n"); } else { ctrl->substate = PROMPT_USER; HTTRACE(PROT_TRACE, "FTP Login... User Unknown\n"); } }/* end _GM_ */ else ctrl->substate = SUB_ERROR; } else ctrl->substate = SUB_ERROR; ctrl->sent = NO; } break; case NEED_PASSWD: HTTRACE(PROT_TRACE, "FTP Login... now in state NEED_PASSWD\n"); if (!ctrl->sent) { status = SendCommand(request, ctrl, "PASS", ctrl->passwd); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_ERROR) ctrl->substate = SUB_ERROR; ctrl->sent = YES; } else { status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { int code = ctrl->repcode/100; if (code == 2) /* Logged in with passwd */ ctrl->substate = SUB_SUCCESS; else if (code == 3) { /* Account required */ HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT); HTAlertPar * reply = HTAlert_newReply(); if (cbf && (*cbf)(request, HT_A_PROMPT, HT_MSG_ACCOUNT, NULL, NULL, reply)) { ctrl->account = HTAlert_replyMessage(reply); ctrl->substate = NEED_ACCOUNT; } else ctrl->substate = SUB_ERROR; HTAlert_deleteReply(reply); } else if (ctrl->repcode == 530) ctrl->substate = PROMPT_USER; else ctrl->substate = SUB_ERROR; } else ctrl->substate = SUB_ERROR; ctrl->sent = NO; } break; case NEED_ACCOUNT: HTTRACE(PROT_TRACE, "FTP Login... now in state NEED_ACCOUNT\n"); if (!ctrl->sent) { status = SendCommand(request, ctrl, "ACCT", ctrl->account); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_ERROR) ctrl->substate = SUB_ERROR; ctrl->sent = YES; } else { status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { int code = ctrl->repcode/100; if (code == 2) /* Logged in with account */ ctrl->substate = SUB_SUCCESS; else ctrl->substate = SUB_ERROR; /* hopeless */ } else ctrl->substate = SUB_ERROR; ctrl->sent = NO; } break; case PROMPT_USER: HTTRACE(PROT_TRACE, "FTP Login... now in state PROMPT_USER\n"); { HTAlertCallback *cbf = HTAlert_find(HT_A_USER_PW); HTAlertPar * reply = HTAlert_newReply(); HT_FREE(ctrl->uid); HT_FREE(ctrl->passwd); if (cbf && (*cbf)(request, HT_A_USER_PW, HT_MSG_FTP_UID, NULL, NULL, reply)){ ctrl->uid = HTAlert_replyMessage(reply); ctrl->passwd = HTAlert_replySecret(reply); } else { ctrl->uid = NULL; ctrl->passwd = NULL; } HTAlert_deleteReply(reply); if (ctrl->uid && *ctrl->uid && ctrl->passwd && *ctrl->passwd) ctrl->substate = NEED_UID; else ctrl->substate = SUB_ERROR; } break; case SUB_ERROR: HTTRACE(PROT_TRACE, "FTP Login... now in state SUB_ERROR\n"); HTRequest_addError(request, ERR_FATAL, NO, HTERR_FTP_LOGIN_FAILURE, NULL, 0, "HTFTPLogin"); HTTRACE(PROT_TRACE, "FTP......... Login failed\n"); ctrl->substate = 0; return HT_ERROR; break; case SUB_SUCCESS: HTTRACE(PROT_TRACE, "FTP Login... now in state SUB_SUCCESS\n"); HTTRACE(PROT_TRACE, "FTP......... Logged in as `%s\'\n" _ ctrl->uid); ctrl->substate = 0; return HT_OK; break; } }}/* HTFTPDataConnection** -------------------** Prepares a data connection to the server and initializes the** transfer mode.** Returns HT_OK, HT_ERROR, or HT_WOULD_BLOCK*/PRIVATE int HTFTPDataConnection (HTRequest * request, HTNet *cnet, ftp_ctrl *ctrl, ftp_data *data){ int status; HTNet *dnet = ctrl->dnet; typedef enum _state { SUB_ERROR = -2, SUB_SUCCESS = -1, NEED_TYPE = 0, NEED_SELECT, NEED_PASV, NEED_PORT } state; /* Jump into a second level state machine */ while (1) { switch ((state) ctrl->substate) { case NEED_TYPE: HTTRACE(PROT_TRACE, "FTP Data.... now in state NEED_TYPE\n"); if(!data->type|| data->pasv || data->type=='N' || data->type=='L'){ ctrl->substate = NEED_SELECT; break; } if (!ctrl->sent) { char type[2]; *type = data->type; *(type+1) = '\0'; status = SendCommand(request, ctrl, "TYPE", type); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_ERROR) ctrl->substate = SUB_ERROR; ctrl->sent = YES; } else { status = HTHost_read(HTNet_host(cnet), cnet); if (status == HT_WOULD_BLOCK) return HT_WOULD_BLOCK; else if (status == HT_LOADED) { if (ctrl->repcode/100 == 2) ctrl->substate = NEED_SELECT; else ctrl->substate = SUB_ERROR; } else ctrl->substate = SUB_ERROR; ctrl->sent = NO; }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -