static struct ftp_connection_info *add_file_cmd_to_str(struct connection *c) { unsigned char *d = get_url_data(c->url); unsigned char *de; int del; unsigned char port_string[50]; struct ftp_connection_info *inf, *inf2; unsigned char *s; int l; if (!d) { internal("get_url_data failed"); setcstate(c, S_INTERNAL); abort_connection(c); return NULL; } de = init_str(), del = 0; add_conv_str(&de, &del, d, strlen(cast_const_char d), -2); d = de; inf = mem_alloc(sizeof(struct ftp_connection_info)); memset(inf, 0, sizeof(struct ftp_connection_info)); l = 0; s = init_str(); inf->pasv = ftp_options.passive_ftp; #ifdef LINKS_2 if (*c->socks_proxy) inf->pasv = 1; if (ftp_options.eprt_epsv || is_ipv6(c->sock1)) inf->eprt_epsv = 1; #endif c->info = inf; if (!inf->pasv) { int ps; #ifdef SUPPORT_IPV6 if (is_ipv6(c->sock1)) { ps = get_pasv_socket_ipv6(c, c->sock1, &c->sock2, port_string); if (ps) { mem_free(d); mem_free(s); return NULL; } } else #endif { unsigned char pc[6]; ps = get_pasv_socket(c, c->sock1, &c->sock2, pc); if (ps) { mem_free(d); mem_free(s); return NULL; } if (inf->eprt_epsv) sprintf(cast_char port_string, "|1|%d.%d.%d.%d|%d|", pc[0], pc[1], pc[2], pc[3], (pc[4] << 8) | pc[5]); else sprintf(cast_char port_string, "%d,%d,%d,%d,%d,%d", pc[0], pc[1], pc[2], pc[3], pc[4], pc[5]); } if (strlen(cast_const_char port_string) >= sizeof(port_string)) internal("buffer overflow in get_pasv_socket_ipv6: %d > %d", (int)strlen(cast_const_char port_string), (int)sizeof(port_string)); } #ifdef HAVE_IPTOS if (ftp_options.set_tos) { int rx; int on = IPTOS_THROUGHPUT; EINTRLOOP(rx, setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int))); } #endif if (!(de = cast_uchar strchr(cast_const_char d, POST_CHAR))) de = d + strlen(cast_const_char d); if (d == de || de[-1] == '/') { inf->dir = 1; inf->pending_commands = 4; add_to_str(&s, &l, cast_uchar "TYPE A\r\n"); add_port_pasv(&s, &l, inf, port_string); add_to_str(&s, &l, cast_uchar "CWD /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, cast_uchar "\r\nLIST\r\n"); c->from = 0; } else { inf->dir = 0; inf->pending_commands = 3; add_to_str(&s, &l, cast_uchar "TYPE I\r\n"); add_port_pasv(&s, &l, inf, port_string); if (c->from && c->no_cache < NC_IF_MOD) { add_to_str(&s, &l, cast_uchar "REST "); add_num_to_str(&s, &l, c->from); add_to_str(&s, &l, cast_uchar "\r\n"); inf->rest_sent = 1; inf->pending_commands++; } else c->from = 0; add_to_str(&s, &l, cast_uchar "RETR /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, cast_uchar "\r\n"); } inf->opc = inf->pending_commands; if ((unsigned)l > MAXINT - sizeof(struct ftp_connection_info) - 1) overalloc(); inf2 = mem_realloc(inf, sizeof(struct ftp_connection_info) + l + 1); strcpy(cast_char (inf = inf2)->cmdbuf, cast_const_char s); mem_free(s); c->info = inf; mem_free(d); return inf; }
struct ftp_connection_info *add_file_cmd_to_str(struct connection *c) { unsigned char *d = get_url_data(c->url); unsigned char *de; int del; unsigned char pc[6]; int ps; struct ftp_connection_info *inf, *inf2; unsigned char *s; int l; if (!d) { internal("get_url_data failed"); setcstate(c, S_INTERNAL); abort_connection(c); return NULL; } de = init_str(), del = 0; add_conv_str(&de, &del, d, strlen(d), -2); d = de; inf = mem_alloc(sizeof(struct ftp_connection_info)); memset(inf, 0, sizeof(struct ftp_connection_info)); l = 0; s = init_str(); inf->pasv = ftp_options.passive_ftp; if (*c->socks_proxy) inf->pasv = 1; c->info = inf; if (!inf->pasv) if ((ps = get_pasv_socket(c, c->sock1, &c->sock2, pc))) { mem_free(d); return NULL; } #ifdef HAVE_IPTOS if (ftp_options.set_tos) { int on = IPTOS_THROUGHPUT; setsockopt(c->sock2, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)); } #endif if (!(de = strchr(d, POST_CHAR))) de = d + strlen(d); if (d == de || de[-1] == '/') { inf->dir = 1; inf->pending_commands = 4; add_to_str(&s, &l, "TYPE A\r\n"); if (!inf->pasv) { add_to_str(&s, &l, "PORT "); add_num_to_str(&s, &l, pc[0]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[1]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[2]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[3]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[4]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[5]); add_to_str(&s, &l, "\r\n"); } else { add_to_str(&s, &l, "PASV\r\n"); } add_to_str(&s, &l, "CWD /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, "\r\nLIST\r\n"); c->from = 0; } else { inf->dir = 0; inf->pending_commands = 3; add_to_str(&s, &l, "TYPE I\r\n"); if (!inf->pasv) { add_to_str(&s, &l, "PORT "); add_num_to_str(&s, &l, pc[0]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[1]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[2]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[3]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[4]); add_chr_to_str(&s, &l, ','); add_num_to_str(&s, &l, pc[5]); add_to_str(&s, &l, "\r\n"); } else { add_to_str(&s, &l, "PASV\r\n"); } if (c->from && c->no_cache < NC_IF_MOD) { add_to_str(&s, &l, "REST "); add_num_to_str(&s, &l, c->from); add_to_str(&s, &l, "\r\n"); inf->rest_sent = 1; inf->pending_commands++; } else c->from = 0; add_to_str(&s, &l, "RETR /"); add_bytes_to_str(&s, &l, d, de - d); add_to_str(&s, &l, "\r\n"); } inf->opc = inf->pending_commands; if ((unsigned)l > MAXINT - sizeof(struct ftp_connection_info) - 1) overalloc(); inf2 = mem_realloc(inf, sizeof(struct ftp_connection_info) + l + 1); strcpy((inf = inf2)->cmdbuf, s); mem_free(s); c->info = inf; mem_free(d); return inf; }