Exemplo n.º 1
0
int ftp_get_filesize(int sock, const char * remotename)
{
	int size = 0;
	char buf[2000];
	char file[500];
	char * ptr;
	int fd, rc, tot;
	int i;

	strcpy(buf, remotename);
	ptr = strrchr(buf, '/');
	if (!*ptr)
		return -1;
	*ptr = '\0';

	strcpy(file, ptr+1);

	if ((rc = ftp_command(sock, "CWD", buf))) {
		return -1;
	}

	fd = ftp_data_command(sock, "LIST", file);
	if (fd <= 0) {
		close(sock);
		return -1;
	}

	ptr = buf;
	while ((tot = read(fd, ptr, sizeof(buf) - (ptr - buf) - 1)) != 0)
		ptr += tot;
	*ptr = '\0';
	close(fd);

	if (!(ptr = strstr(buf, file))) {
		log_message("FTP/get_filesize: Bad mood, directory does not contain searched file (%s)", file);
		if (ftp_end_data_command(sock))
			close(sock);
		return -1;
	}

	for (i=0; i<4; i++) {
		while (*ptr && *ptr != ' ')
			ptr--;
		while (*ptr && *ptr == ' ')
			ptr--;
	}
	while (*ptr && *ptr != ' ')
		ptr--;

	if (ptr)
		size = charstar_to_int(ptr+1);
	else
		size = 0;

	if (ftp_end_data_command(sock)) {
		close(sock);
		return -1;
	}

	return size;
}
Exemplo n.º 2
0
static int _http_download_file(const char * hostname, const char * remotename, int * size, const char * proxyprotocol, const char * proxyname, const char * proxyport, int recursion)
{
	char * buf;
	char headers[4096];
	char * nextChar = headers;
	int statusCode;
	struct in_addr serverAddress;
	struct pollfd polls;
	int sock;
	int rc;
	union {
		struct sockaddr_in in;
		struct sockaddr sa;
	} destPort;
	const char * header_content_length = "Content-Length: ";
	const char * header_location = "Location: http://";
	const char * http_server_name;
	int http_server_port;

	if (proxyprotocol) {
		http_server_name = proxyname;
		http_server_port = atoi(proxyport);
	} else {
		http_server_name = hostname;
		http_server_port = 80;
	}		

	log_message("HTTP: connecting to server %s:%i (%s)",
		    http_server_name, http_server_port,
		    proxyprotocol ? "proxy" : "no proxy");

	if ((rc = get_host_address(http_server_name, &serverAddress))) return rc;

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sock < 0) {
		return FTPERR_FAILED_CONNECT;
	}

	destPort.in.sin_family = AF_INET;
	destPort.in.sin_port = htons(http_server_port);
	destPort.in.sin_addr = serverAddress;

	if (connect(sock, &destPort.sa, sizeof(destPort.in))) {
		close(sock);
		return FTPERR_FAILED_CONNECT;
	}

        if (proxyprotocol)
		asprintf(&buf, "GET %s://%s%s HTTP/1.0\r\nHost: %s\r\n\r\n", proxyprotocol, hostname, remotename, hostname);
	else
		asprintf(&buf, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", remotename, hostname);

	write(sock, buf, strlen(buf));

	/* This is fun; read the response a character at a time until we:

	   1) Get our first \r\n; which lets us check the return code
	   2) Get a \r\n\r\n, which means we're done */

	*nextChar = '\0';
	statusCode = 0;
	while (!strstr(headers, "\r\n\r\n")) {
		polls.fd = sock;
		polls.events = POLLIN;
		rc = poll(&polls, 1, TIMEOUT_SECS*1000);

		if (rc == 0) {
			close(sock);
			return FTPERR_SERVER_TIMEOUT;
		} else if (rc < 0) {
			close(sock);
			return FTPERR_SERVER_IO_ERROR;
		}

		if (read(sock, nextChar, 1) != 1) {
			close(sock);
			return FTPERR_SERVER_IO_ERROR;
		}

		nextChar++;
		*nextChar = '\0';

		if (nextChar - headers == sizeof(headers)) {
			close(sock);
			return FTPERR_SERVER_IO_ERROR;
		}

		if (!statusCode && strstr(headers, "\r\n")) {
			char * start, * end;

			start = headers;
			while (!isspace(*start) && *start) start++;
			if (!*start) {
				close(sock);
				return FTPERR_SERVER_IO_ERROR;
			}
			start++;

			end = start;
			while (!isspace(*end) && *end) end++;
			if (!*end) {
				close(sock);
				return FTPERR_SERVER_IO_ERROR;
			}

			*end = '\0';
                        log_message("HTTP: server response '%s'", start);
			if (streq(start, "404")) {
				close(sock);
				return FTPERR_FILE_NOT_FOUND;
			} else if (streq(start, "302")) {
				log_message("HTTP: found, but document has moved");
				statusCode = 302;
			} else if (streq(start, "200")) {
				statusCode = 200;
			} else {
				close(sock);
				return FTPERR_BAD_SERVER_RESPONSE;
			}

			*end = ' ';
		}
	}

	if (statusCode == 302) {
		if (recursion >= HTTP_MAX_RECURSION) {
			log_message("HTTP: too many levels of recursion, aborting");
			close(sock);
			return FTPERR_UNKNOWN;
		}
		if ((buf = strstr(headers, header_location))) {
			char * found_host;
			char *found_file;
			found_host = buf + strlen(header_location);
			if ((found_file = index(found_host, '/'))) {
				if ((buf = index(found_file, '\r'))) {
					buf[0] = '\0';
					remotename = strdup(found_file);
					found_file[0] = '\0';
					hostname = strdup(found_host);
					log_message("HTTP: redirected to new host \"%s\" and file \"%s\"", hostname, remotename);
				}
			}
			
		}
		/*
		 * don't fail if new URL can't be parsed,
		 * asking the same URL may work if the DNS server are doing round-robin
		 */
		return _http_download_file(hostname, remotename, size, proxyprotocol, proxyname, proxyport, recursion + 1);
	}

	if ((buf = strstr(headers, header_content_length)))
		*size = charstar_to_int(buf + strlen(header_content_length));
	else
		*size = 0;

	return sock;
}
Exemplo n.º 3
0
/* true return value indicates that connection must be closed */
int process_msg(int fd, char* msg)
{
    int client_proto_major;
    int client_proto_minor;
    char * args;
    char * ptr, * ptr2;
    char * msg_orig;

    /* check for leading protocol tag */
    if (!str_begins_static_str(msg, "FB/")
            || strlen(msg) < 8) {  // 8 stands for "FB/M.m f"(oo)
        send_line_log(fd, fl_line_unrecognized, msg);
        return 1;
    }

    /* check if client protocol is compatible; for simplicity, we don't support client protocol more recent
     * than server protocol, we suppose that our servers are upgraded when a new release appears (but of
     * course client protocol older is supported within the major protocol) */
    client_proto_major = charstar_to_int(msg + 3);
    client_proto_minor = charstar_to_int(msg + 5);
    if (client_proto_major != proto_major
            || client_proto_minor > proto_minor) {
        send_line_log(fd, fl_proto_mismatch, msg);
        return 1;
    }

    if (remote_proto_minor[fd] == -1)
        remote_proto_minor[fd] = client_proto_minor;

    msg_orig = strdup(msg);

    /* after protocol, first word is command, then possible args */
    current_command = msg + 7; // 7 stands for "FB/M.m "
    if ((ptr = strchr(current_command, ' '))) {
        *ptr = '\0';
        args = current_command + strlen(current_command) + 1;
    } else
        args = NULL;

    if (streq(current_command, "PING")) {
        send_line_log(fd, ok_pong, msg_orig);
    } else if (streq(current_command, "NICK")) {
        if (!args) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else {
            if ((ptr = strchr(args, ' ')))
                *ptr = '\0';
            if (strlen(args) > 10)
                args[10] = '\0';
            if (!is_nick_ok(args)) {
                send_line_log(fd, wn_nick_invalid, msg_orig);
            } else {
                if (nick[fd] != NULL) {
                    free(nick[fd]);
                }
                nick[fd] = strdup(args);
                calculate_list_games();
                send_ok(fd, msg_orig);
            }
        }
    } else if (streq(current_command, "GEOLOC")) {
        if (!args) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else {
            if ((ptr = strchr(args, ' ')))
                *ptr = '\0';
            if (strlen(args) > 13)  // sign, 4 digits, dot, colon, sign, 4 digits, dot
                args[13] = '\0';
            if (geoloc[fd] != NULL) {
                free(geoloc[fd]);
            }
            geoloc[fd] = strdup(args);
            calculate_list_games();
            send_ok(fd, msg_orig);
        }
    } else if (streq(current_command, "CREATE")) {
        if (!args) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else {
            if ((ptr = strchr(args, ' ')))
                *ptr = '\0';
            if (strlen(args) > 10)
                args[10] = '\0';
            if (!is_nick_ok(args)) {
                send_line_log(fd, wn_nick_invalid, msg_orig);
            } else if (!nick_available(args)) {
                send_line_log(fd, wn_nick_in_use, msg_orig);
            } else if (already_in_game(fd)) {
                send_line_log(fd, wn_already_in_game, msg_orig);
            } else if (games_open == 16) {  // FB client can display 16 max
                send_line_log(fd, wn_max_open_games, msg_orig);
            } else {
                create_game(fd, strdup(args));
                send_ok(fd, msg_orig);
            }
        }
    } else if (streq(current_command, "JOIN")) {
        if (!args || !(ptr = strchr(args, ' '))) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else {
            struct game * g;
            char* nick = ptr + 1;
            *ptr = '\0';
            if ((ptr2 = strchr(ptr, ' ')))
                *ptr2 = '\0';
            if (strlen(nick) > 10)
                nick[10] = '\0';
            if (!is_nick_ok(nick)) {
                send_line_log(fd, wn_nick_invalid, msg_orig);
            } else if (!nick_available(nick)) {
                send_line_log(fd, wn_nick_in_use, msg_orig);
            } else if (already_in_game(fd)) {
                send_line_log(fd, wn_already_in_game, msg_orig);
            } else if (!(g = find_game_by_nick(args))) {
                send_line_log(fd, wn_no_such_game, msg_orig);
            } else {
                if (add_player(g, fd, strdup(nick)))
                    send_ok(fd, msg_orig);
                else
                    send_line_log(fd, wn_game_full, msg_orig);
            }
        }
    } else if (streq(current_command, "KICK")) {
        if (!args) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else {
            if ((ptr = strchr(args, ' ')))
                *ptr = '\0';
            if (strlen(args) > 10)
                args[10] = '\0';
            if (!already_in_game(fd)) {
                send_line_log(fd, wn_not_in_game, msg_orig);
            } else {
                struct game * g = find_game_by_fd(fd);
                if (g->players_conn[0] != fd) {
                    send_line_log(fd, wn_not_creator, msg_orig);
                } else {
                    kick_player(fd, g, args);
                }
            }
        }
    } else if (streq(current_command, "PART")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            player_part_game(fd);
            send_ok(fd, msg_orig);
        }
    } else if (streq(current_command, "LIST")) {
        send_line_log(fd, list_games_str, msg_orig);
    } else if (streq(current_command, "STATUS")) {  // 1.0 command
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            status(fd, msg_orig);
        }
    } else if (streq(current_command, "STATUSGEO")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            status_geo(fd, msg_orig);
        }
    } else if (streq(current_command, "PROTOCOL_LEVEL")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            protocol_level(fd, msg_orig);
        }
    } else if (streq(current_command, "TALK")) {
        if (!args) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else {
            talk(fd, args);
        }
    } else if (streq(current_command, "START")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            start_game(fd);
        }
    } else if (streq(current_command, "CLOSE")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            close_game(fd);
        }
    } else if (streq(current_command, "SETOPTIONS")) {
        if (!args) {
            send_line_log(fd, wn_missing_arguments, msg_orig);
        } else if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            setoptions(fd, args);
        }
    } else if (streq(current_command, "LEADER_CHECK_GAME_START")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            leader_check_game_start(fd);
        }
    } else if (streq(current_command, "OK_GAME_START")) {
        if (!already_in_game(fd)) {
            send_line_log(fd, wn_not_in_game, msg_orig);
        } else {
            ok_start_game(fd);
        }
    } else if (streq(current_command, "ADMIN_REREAD")) {
        if (!admin_authorized[fd]) {
            send_line_log(fd, wn_denied, msg_orig);
        } else {
            reread();
            send_ok(fd, "ADMIN_REREAD");
        }
    } else {
        send_line_log(fd, wn_unknown_command, msg);
    }

    free(msg_orig);
    current_command = NULL;

    return 0;
}