📄 htftp.c
字号:
} else if (strncmp(response_text+4, "Windows_NT", 10) == 0) { server_type = WINDOWS_NT_SERVER; CTRACE((tfp, "HTFTP: Treating as Window_NT server.\n")); set_unix_dirstyle(&server_type, &use_list); } else if (strncmp(response_text+4, "Windows2000", 11) == 0) { server_type = WINDOWS_2K_SERVER; CTRACE((tfp, "HTFTP: Treating as Window_2K server.\n")); set_unix_dirstyle(&server_type, &use_list); } else if (strncmp(response_text+4, "MS Windows", 10) == 0) { server_type = MS_WINDOWS_SERVER; use_list = TRUE; CTRACE((tfp, "HTFTP: Treating as MS Windows server.\n")); } else if (strncmp(response_text+4, "MACOS AppleShare IP FTP Server", 30) == 0) { server_type = APPLESHARE_SERVER; use_list = TRUE; set_mac_binary(server_type); CTRACE((tfp, "HTFTP: Treating as AppleShare server.\n")); } else { server_type = GENERIC_SERVER; CTRACE((tfp, "HTFTP: Ugh! A Generic server.\n")); get_ftp_pwd(&server_type, &use_list); unsure_type = TRUE; } } else { /* SYST fails :( try to get the type from the PWD command */ get_ftp_pwd(&server_type, &use_list); }/* Now we inform the server of the port number we will listen on*/#ifdef NOTREPEAT_PORT { int status = response(port_command); if (status != 2) { if (control->socket) close_connection(control->socket); return -status; /* Bad return */ } CTRACE((tfp, "HTFTP: Port defined.\n")); }#endif /* NOTREPEAT_PORT */ return con->socket; /* Good return */}/* Close Master (listening) socket** -------------------------------*****/PRIVATE int close_master_socket NOARGS{ int status; if (master_socket != -1) FD_CLR(master_socket, &open_sockets); status = NETCLOSE(master_socket); CTRACE((tfp, "HTFTP: Closed master socket %d\n", master_socket)); master_socket = -1; if (status < 0) return HTInetStatus(gettext("close master socket")); else return status;}/* Open a master socket for listening on** -------------------------------------**** When data is transferred, we open a port, and wait for the server to** connect with the data.**** On entry,** master_socket Must be negative if not set up already.** On exit,** Returns socket number if good** less than zero if error.** master_socket is socket number if good, else negative.** port_number is valid if good.*/PRIVATE int get_listen_socket NOARGS{#ifdef INET6 struct sockaddr_storage soc_address; /* Binary network address */ struct sockaddr_in* soc_in = (struct sockaddr_in *)&soc_address; int af; int slen;#else struct sockaddr_in soc_address; /* Binary network address */ struct sockaddr_in* soc_in = &soc_address;#endif /* INET6 */ int new_socket; /* Will be master_socket */ FD_ZERO(&open_sockets); /* Clear our record of open sockets */ num_sockets = 0;#ifndef REPEAT_LISTEN if (master_socket >= 0) return master_socket; /* Done already */#endif /* !REPEAT_LISTEN */#ifdef INET6 /* query address family of control connection */ slen = sizeof(soc_address); if (getsockname(control->socket, (struct sockaddr *)&soc_address, &slen) < 0) { return HTInetStatus("getsockname failed"); } af = ((struct sockaddr *)&soc_address)->sa_family; memset(&soc_address, 0, sizeof(soc_address));#endif /* INET6 *//* Create internet socket*/#ifdef INET6 new_socket = socket(af, SOCK_STREAM, IPPROTO_TCP);#else new_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);#endif /* INET6 */ if (new_socket < 0) return HTInetStatus(gettext("socket for master socket")); CTRACE((tfp, "HTFTP: Opened master socket number %d\n", new_socket));/* Search for a free port.*/#ifdef INET6 memset(&soc_address, 0, sizeof(soc_address)); ((struct sockaddr *)&soc_address)->sa_family = af; switch (af) { case AF_INET:#ifdef SIN6_LEN ((struct sockaddr *)&soc_address)->sa_len = sizeof(struct sockaddr_in);#endif /* SIN6_LEN */ break; case AF_INET6:#ifdef SIN6_LEN ((struct sockaddr *)&soc_address)->sa_len = sizeof(struct sockaddr_in6);#endif /* SIN6_LEN */ break; default: HTInetStatus("AF"); }#else soc_in->sin_family = AF_INET; /* Family = internet, host order */ soc_in->sin_addr.s_addr = INADDR_ANY; /* Any peer address */#endif /* INET6 */#ifdef POLL_PORTS { PortNumber old_port_number = port_number; for (port_number = (old_port_number+1); ; port_number++) { int status; if (port_number > LAST_TCP_PORT) port_number = FIRST_TCP_PORT; if (port_number == old_port_number) { return HTInetStatus("bind"); }#ifdef INET6 soc_in->sin_port = htons(port_number);#else soc_address.sin_port = htons(port_number);#endif /* INET6 */#ifdef SOCKS if (socks_flag) if ((status=Rbind(new_socket, (struct sockaddr*)&soc_address, /* Cast to generic sockaddr */ SOCKADDR_LEN(soc_address)#ifndef SHORTENED_RBIND ,socks_bind_remoteAddr#endif /* !SHORTENED_RBIND */ )) == 0) { break; } else#endif /* SOCKS */ if ((status=bind(new_socket, (struct sockaddr*)&soc_address, /* Cast to generic sockaddr */ SOCKADDR_LEN(soc_address) )) == 0) { break; } CTRACE((tfp, "TCP bind attempt to port %d yields %d, errno=%d\n", port_number, status, SOCKET_ERRNO)); } /* for */ }#else { int status; int address_length = sizeof(soc_address);#ifdef SOCKS if (socks_flag) status = Rgetsockname(control->socket, (struct sockaddr *)&soc_address, (void *)&address_length); else#endif /* SOCKS */ status = getsockname(control->socket, (struct sockaddr *)&soc_address, (void *)&address_length); if (status<0) return HTInetStatus("getsockname");#ifdef INET6 CTRACE((tfp, "HTFTP: This host is %s\n", HTInetString((SockA *)soc_in))); soc_in->sin_port = 0; /* Unspecified: please allocate */#else CTRACE((tfp, "HTFTP: This host is %s\n", HTInetString(soc_in))); soc_address.sin_port = 0; /* Unspecified: please allocate */#endif /* INET6 */#ifdef SOCKS if (socks_flag) status=Rbind(new_socket, (struct sockaddr*)&soc_address, /* Cast to generic sockaddr */ sizeof(soc_address)#ifndef SHORTENED_RBIND#ifdef INET6 socks_bind_remoteAddr#else ,socks_bind_remoteAddr#endif /* INET6 */#endif /* !SHORTENED_RBIND */ ); else#endif /* SOCKS */ status=bind(new_socket, (struct sockaddr*)&soc_address, /* Cast to generic sockaddr */ SOCKADDR_LEN(soc_address) ); if (status<0) return HTInetStatus("bind"); address_length = sizeof(soc_address);#ifdef SOCKS if (socks_flag) status = Rgetsockname(new_socket, (struct sockaddr*)&soc_address, (void *)&address_length); else#endif /* SOCKS */ status = getsockname(new_socket, (struct sockaddr*)&soc_address, (void *)&address_length); if (status<0) return HTInetStatus("getsockname"); }#endif /* POLL_PORTS */#ifdef INET6 CTRACE((tfp, "HTFTP: bound to port %d on %s\n", (int)ntohs(soc_in->sin_port), HTInetString((SockA *)soc_in)));#else CTRACE((tfp, "HTFTP: bound to port %d on %s\n", (int)ntohs(soc_in->sin_port), HTInetString(soc_in)));#endif /* INET6 */#ifdef REPEAT_LISTEN if (master_socket >= 0) (void) close_master_socket();#endif /* REPEAT_LISTEN */ master_socket = new_socket;/* Now we must find out who we are to tell the other guy*/ (void)HTHostName(); /* Make address valid - doesn't work*/#ifdef INET6 switch (((struct sockaddr *)&soc_address)->sa_family) { case AF_INET:#endif /* INET6 */ sprintf(port_command, "PORT %d,%d,%d,%d,%d,%d%c%c", (int)*((unsigned char *)(&soc_in->sin_addr)+0), (int)*((unsigned char *)(&soc_in->sin_addr)+1), (int)*((unsigned char *)(&soc_in->sin_addr)+2), (int)*((unsigned char *)(&soc_in->sin_addr)+3), (int)*((unsigned char *)(&soc_in->sin_port)+0), (int)*((unsigned char *)(&soc_in->sin_port)+1), CR, LF);#ifdef INET6 break; case AF_INET6: { char hostbuf[MAXHOSTNAMELEN]; char portbuf[MAXHOSTNAMELEN]; getnameinfo((struct sockaddr *)&soc_address, SOCKADDR_LEN(soc_address), hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); sprintf(port_command, "EPRT |%d|%s|%s|%c%c", 2, hostbuf, portbuf, CR, LF); break; } default: sprintf(port_command, "JUNK%c%c", CR, LF); break; }#endif /* INET6 */ /* Inform TCP that we will accept connections */ { int status;#ifdef SOCKS if (socks_flag) status = Rlisten(master_socket, 1); else#endif /* SOCKS */ status = listen(master_socket, 1); if (status < 0) { master_socket = -1; return HTInetStatus("listen"); } } CTRACE((tfp, "TCP: Master socket(), bind() and listen() all OK\n")); FD_SET(master_socket, &open_sockets); if ((master_socket+1) > num_sockets) num_sockets = master_socket+1; return master_socket; /* Good */} /* get_listen_socket */PRIVATE char * months[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};/* Procedure: Set the current and last year strings and date integer** -----------------------------------------------------------------**** Bug:** This code is for sorting listings by date, if that option** is selected in Lynx, and doesn't take into account time** zones or ensure resetting at midnight, so the sort may not** be perfect, but the actual date isn't changed in the display,** i.e., the date is still correct. - FM*/PRIVATE void set_years_and_date NOARGS{ char day[8], month[8], date[12]; time_t NowTime; int i; NowTime = time(NULL); strncpy(day, (char *)ctime(&NowTime)+8, 2); day[2] = '\0'; if (day[0] == ' ') { day[0] = '0'; } strncpy(month, (char *)ctime(&NowTime)+4, 3); month[3] = '\0'; for (i = 0; i < 12; i++) { if (!strcasecomp(month, months[i])) { break; } } i++; sprintf(date, "9999%02d%.2s", i, day); TheDate = atoi(date); strcpy(ThisYear, (char *)ctime(&NowTime)+20); ThisYear[4] = '\0'; sprintf(LastYear, "%d", (atoi(ThisYear) - 1)); HaveYears = TRUE;}typedef struct _EntryInfo { char * filename; char * type; char * date; unsigned int size; BOOLEAN display; /* show this entry? */} EntryInfo;PRIVATE void free_entryinfo_struct_contents ARGS1( EntryInfo *, entry_info){ if (entry_info) { FREE(entry_info->filename); FREE(entry_info->type); FREE(entry_info->date); } /* dont free the struct */}/* * is_ls_date() -- * Return TRUE if s points to a string of the form: * "Sep 1 1990 " or * "Sep 11 11:59 " or * "Dec 12 1989 " or * "FCv 23 1990 " ... */PRIVATE BOOLEAN is_ls_date ARGS1( char *, s){ /* must start with three alpha characters */ if (!isalpha(UCH(*s++)) || !isalpha(UCH(*s++)) || !isalpha(UCH(*s++))) return FALSE; /* space or HT_NON_BREAK_SPACE */ if (!(*s == ' ' || *s == HT_NON_BREAK_SPACE)) { s++; return FALSE; } s++; /* space or digit */ if (!(*s == ' ' || isdigit(UCH(*s)))) { s++; return FALSE; } s++; /* digit */ if (!isdigit(UCH(*s++))) return FALSE; /* space */ if (*s++ != ' ') return FALSE; /* space or digit */ if (!(*s == ' ' || isdigit(UCH(*s)))) { s++; return FALSE; } s++; /* digit */ if (!isdigit(UCH(*s++))) return FALSE; /* colon or digit */ if (!(*s == ':' || isdigit(UCH(*s)))) { s++; return FALSE; } s++; /* digit */ if (!isdigit(UCH(*s++))) return FALSE; /* space or digit */ if (!(*s == ' ' || isdigit(UCH(*s)))) { s++; return FALSE; } s++; /* space */ if (*s++ != ' ') return FALSE; return TRUE;} /* is_ls_date() *//* * parse_eplf_line() -- * Extract the name, size, and date from an EPLF line. - 08-06-96 DJB */PRIVATE void parse_eplf_line ARGS2( char *, line, EntryInfo *, info){ char *cp = line; char ct[26]; unsigned long size; time_t secs; static time_t base; /* time() value on this OS in 1970 */ static int flagbase = 0; if (!flagbase) { struct tm t; t.tm_year = 70; t.tm_mon = 0; t.tm_mday = 0; t.tm_hour = 0; t.tm_min = 0; t.tm_sec = 0; t.tm_isdst = -1; base = mktime(&t); /* could return -1 */ flagbase = 1; } while (*cp) { switch(*cp) { case '\t': StrAllocCopy(info->filename, cp + 1); return; case 's':
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -