Example #1
0
void wr_transfer_download_add_file(wr_transfer_t *transfer, wr_file_t *file, wi_boolean_t recursive) {
    
	wi_string_t		*remote_path, *local_path, *parent_path;
	
	remote_path = wr_file_path(file);
	
	if(recursive) {
		local_path = wi_string_by_appending_path_component(transfer->name,
                                                           wi_string_substring_from_index(remote_path, wi_string_length(transfer->master_path)));
	} else {
		local_path = wi_string_last_path_component(remote_path);
	}
	
	local_path = wi_string_by_appending_path_component(wi_string_by_normalizing_path(wr_download_path), local_path);
	parent_path = wi_string_by_deleting_last_path_component(local_path);
	
	wi_fs_create_directory(parent_path, 0755);
    
	if(wr_file_type(file) == WR_FILE_FILE) {
		wi_mutable_array_add_data(transfer->remote_paths, remote_path);
		wi_mutable_array_add_data(transfer->local_paths, local_path);
		wi_mutable_array_add_data(transfer->files, file);
		
		transfer->total_size += wr_file_size(file);
	} else {
		if(!wi_fs_path_exists(local_path, NULL)) {
			if(!wi_fs_create_directory(local_path, 0755)) {
				wr_printf_prefix(WI_STR("get: Unable to create directory at %@: %m"),
                                 local_path);
			}
		}
	}
     
}
void wi_test_directory_enumerator(void) {
    wi_directory_enumerator_t           *enumerator;
    wi_mutable_array_t                  *contents;
    wi_string_t                         *path, *subpath;
    wi_boolean_t                        result;
    wi_directory_enumerator_status_t    status;
    
    path = wi_filesystem_temporary_path_with_template(WI_STR("/tmp/libwired-test-directory-enumerator.XXXXXXX"));
    path = wi_string_by_resolving_symbolic_links_in_path(path);
    result = wi_filesystem_create_directory_at_path(path);
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    enumerator = wi_filesystem_directory_enumerator_at_path(path);
    
    WI_TEST_ASSERT_NOT_NULL(enumerator, "");
    
    contents = wi_mutable_array();
    
    while((status = wi_directory_enumerator_get_next_path(enumerator, &subpath)) == WI_DIRECTORY_ENUMERATOR_PATH)
        wi_mutable_array_add_data(contents, subpath);
    
    WI_TEST_ASSERT_EQUALS(status, WI_DIRECTORY_ENUMERATOR_EOF, "");
    WI_TEST_ASSERT_EQUALS(wi_array_count(contents), 0U, "");
    
    result = wi_filesystem_change_current_directory_to_path(path);
    
    WI_TEST_ASSERT_TRUE(result, "");

    result = wi_filesystem_create_directory_at_path(WI_STR("foo"));
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    result = wi_filesystem_create_directory_at_path(WI_STR("foo/bar"));
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    result = wi_filesystem_create_directory_at_path(WI_STR("foo/bar/baz"));
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    enumerator = wi_filesystem_directory_enumerator_at_path(path);
    
    WI_TEST_ASSERT_NOT_NULL(enumerator, "");
    
    while((status = wi_directory_enumerator_get_next_path(enumerator, &subpath)) == WI_DIRECTORY_ENUMERATOR_PATH)
        wi_mutable_array_add_data(contents, subpath);
    
    WI_TEST_ASSERT_EQUALS(status, WI_DIRECTORY_ENUMERATOR_EOF, "");
    WI_TEST_ASSERT_EQUALS(wi_array_count(contents), 3U, "");
    WI_TEST_ASSERT_EQUAL_INSTANCES(wi_array_data_at_index(contents, 0), wi_string_by_appending_path_component(path, WI_STR("foo")), "");
    WI_TEST_ASSERT_EQUAL_INSTANCES(wi_array_data_at_index(contents, 1), wi_string_by_appending_path_component(path, WI_STR("foo/bar")), "");
    WI_TEST_ASSERT_EQUAL_INSTANCES(wi_array_data_at_index(contents, 2), wi_string_by_appending_path_component(path, WI_STR("foo/bar/baz")), "");
    
    wi_filesystem_delete_path(path);
}
Example #3
0
static void wr_command_load(wi_array_t *arguments) {
	wi_mutable_string_t		*path;
	wi_file_t				*file;
	
	path = wi_user_home();
	path = wi_string_by_appending_path_component(path, WI_STR(WB_WIREBOT_USER_PATH));
	path = wi_string_by_appending_path_component(path, WI_ARRAY(arguments, 0));
	
	file = wi_file_for_reading(path);
	
	if(file)
		wr_commands_parse_file(file);
	else
		wr_printf_prefix(WI_STR("load: %@: %m"), path);
}
Example #4
0
static void wr_command_save(wi_array_t *arguments) {
	wi_file_t		*file;
	wi_string_t		*path, *login, *password, *port;
	
	path = wi_user_home();
	path = wi_string_by_appending_path_component(path, WI_STR(WB_WIREBOT_USER_PATH));
	path = wi_string_by_appending_path_component(path, WI_ARRAY(arguments, 0));
	
	file = wi_file_for_writing(path);
	
	if(!file) {
		wr_printf_prefix(WI_STR("save: %@: %m"), path);
		
		return;
	}
	
	wi_file_write_format(file, WI_STR("charset %@\n"), wi_string_encoding_charset(wr_client_string_encoding));
	wi_file_write_format(file, WI_STR("timestamp %@\n"), wr_timestamp_format);
	wi_file_write_format(file, WI_STR("nick %@\n"), wr_nick);
	
	if(wi_string_length(wr_status) > 0)
		wi_file_write_format(file, WI_STR("status %@\n"), wr_status);
	
	if(wr_icon_path)
		wi_file_write_format(file, WI_STR("icon %@\n"), wr_icon_path);
	
	if(wr_connected) {
		if(wi_string_length(wi_p7_socket_user_name(wr_p7_socket)) > 0)
			login = wi_string_with_format(WI_STR("-l %@"), wi_p7_socket_user_name(wr_p7_socket));
		else
			login = NULL;
		
		if(wi_string_length(wr_password) > 0)
			password = wi_string_with_format(WI_STR("-p %@"), wr_password);
		else
			password = NULL;
		
		if(wi_address_port(wi_socket_address(wr_socket)) != WR_PORT)
			port = wi_string_with_format(WI_STR("-P %u"), wi_address_port(wi_socket_address(wr_socket)));
		else
			port = NULL;
		
		wi_file_write_format(file, WI_STR("open %#@ %#@ %#@ %@\n"),
			login, password, port, wi_address_string(wi_socket_address(wr_socket)));
	}
	
	wr_printf_prefix(WI_STR("save: \"%@\" saved"), path);
}
Example #5
0
void wi_test_string_paths(void) {
	WI_TEST_ASSERT_EQUAL_INSTANCES(
		wi_string_path_components(WI_STR("/usr/local/wired")),
		wi_autorelease(wi_array_init_with_data(wi_array_alloc(),
			WI_STR("/"), WI_STR("usr"), WI_STR("local"), WI_STR("wired"), NULL)),
		"");
	
	WI_TEST_ASSERT_EQUAL_INSTANCES(
		wi_string_by_normalizing_path(WI_STR("////usr/././local/../local/../local/wired///")),
		WI_STR("/usr/local/wired"),
		"");
	
	WI_TEST_ASSERT_EQUAL_INSTANCES(
		wi_string_by_appending_path_component(WI_STR("/usr/local/"), WI_STR("/wired")),
		WI_STR("/usr/local/wired"),
		"");
	
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_last_path_component(WI_STR("/usr/local/wired/")), WI_STR("wired"), "");
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_last_path_component(WI_STR("/")), WI_STR("/"), "");
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_last_path_component(WI_STR("/wired/")), WI_STR("wired"), "");
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_by_deleting_last_path_component(WI_STR("/usr/local/wired")), WI_STR("/usr/local"), "");
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_path_extension(WI_STR("wired.c")), WI_STR("c"), "");
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_path_extension(WI_STR("wired")), WI_STR(""), "");
	WI_TEST_ASSERT_EQUAL_INSTANCES(wi_string_by_deleting_path_extension(WI_STR("wired")), WI_STR("wired"), "");
}
Example #6
0
void wi_test_dsa_creation(void) {
#ifdef WI_DSA
    wi_dsa_t    *dsa;
    
    dsa = wi_autorelease(wi_dsa_init_with_bits(wi_dsa_alloc(), 512));
    
    WI_TEST_ASSERT_NOT_NULL(dsa, "");
    WI_TEST_ASSERT_EQUALS(wi_dsa_bits(dsa), 384U, "");
    
    dsa = wi_autorelease(wi_dsa_init_with_pem_file(wi_dsa_alloc(), WI_STR("/non/existing/file.pem")));
    
    WI_TEST_ASSERT_NULL(dsa, "");
    
    dsa = wi_autorelease(wi_dsa_init_with_pem_file(wi_dsa_alloc(), wi_string_by_appending_path_component(wi_test_fixture_path, WI_STR("wi-dsa-tests-1.pem"))));
    
    WI_TEST_ASSERT_NULL(dsa, "");
    
    dsa = wi_autorelease(wi_dsa_init_with_pem_file(wi_dsa_alloc(), wi_string_by_appending_path_component(wi_test_fixture_path, WI_STR("wi-dsa-tests-2.pem"))));
    
    WI_TEST_ASSERT_NOT_NULL(dsa, "");
    WI_TEST_ASSERT_EQUALS(wi_dsa_bits(dsa), 384U, "");
    
    dsa = wi_autorelease(wi_dsa_init_with_private_key(wi_dsa_alloc(), wi_data()));
    
    WI_TEST_ASSERT_NULL(dsa, "");
    
    dsa = wi_autorelease(wi_dsa_init_with_private_key(wi_dsa_alloc(), wi_data_with_base64_string(WI_STR("MIH3AgEAAkEA0c36Uaj1S/cKjYAokEUtWQHmFHLqd8mbnY9J9wyNS0mlXvklnko2NlflL1qg9p58uRjkGBtCinI0mxeEIxwckwIVAPpF85s7Iv1o7z4UUAs9KRamjULXAkBFchKBXr+D+lGgnBFtb//EBThgSD9t3WBxyKGvNLBDWGJu2+av/fR9uBxBm1cUUldzGvqBjr/lcBmTIUe4rmAcAkBBN2fEFvs6uuIX+/8EqM1T2yBmwt3KHMVuCD+opZga29WJPNZgNXIj8yNFGFIxJeTndvhcndNrlcztYx3e/GSCAhRDUGb+CUPkNuBbsSHbdYtEQ+/2Gg=="))));
    
    WI_TEST_ASSERT_NOT_NULL(dsa, "");
    WI_TEST_ASSERT_EQUALS(wi_dsa_bits(dsa), 384U, "");
    
    dsa = wi_autorelease(wi_dsa_init_with_public_key(wi_dsa_alloc(), wi_data()));
    
    WI_TEST_ASSERT_NULL(dsa, "");
#endif
}
Example #7
0
void wr_client_reload_icon(void) {
    wi_data_t 		*data;
    wi_string_t 	*icon_path;

    if(wr_icon)
        wi_release(wr_icon), wr_icon = NULL;

    if(wr_icon_path)
        wi_release(wr_icon_path), wr_icon_path = NULL;

    icon_path = wi_config_path_for_name(wd_config, WI_STR("icon path"));

    if(!wi_string_has_prefix(icon_path, WI_STR("/")))
        wr_icon_path = wi_retain(wi_string_by_appending_path_component(wi_string_by_appending_path_component(wi_user_home(), WI_STR(".wirebot")), icon_path));
    else {
        wr_icon_path = wi_retain(icon_path);
    }

    if(wi_fs_path_exists(wr_icon_path, false))	{
        wr_icon = wi_data_init_with_contents_of_file(wi_data_alloc(), wr_icon_path);
    } else {
        wr_icon = wi_data_init_with_base64(wi_data_alloc(), wi_string_with_cstring(wr_default_icon));
    }
}
Example #8
0
void wi_test_fsevents(void) {
#ifdef WI_PTHREADS
	wi_string_t			*directory;
	
	wi_test_fsevents_fsevents = wi_fsevents_init(wi_fsevents_alloc());
	
	if(!wi_test_fsevents_fsevents) {
		if(wi_error_domain() != WI_ERROR_DOMAIN_LIBWIRED && wi_error_code() != WI_ERROR_FSEVENTS_NOTSUPP)
			WI_TEST_ASSERT_NOT_NULL(wi_test_fsevents_fsevents, "%m");
		
		return;
	}
	
	directory = wi_fs_temporary_path_with_template(WI_STR("/tmp/libwired-fsevents.XXXXXXXX"));
	
	wi_fs_create_directory(directory, 0700);
	
	wi_fsevents_add_path(wi_test_fsevents_fsevents, directory);
	wi_fsevents_set_callback(wi_test_fsevents_fsevents, wi_test_fsevents_callback);
	
	wi_test_fsevents_lock = wi_condition_lock_init_with_condition(wi_condition_lock_alloc(), 0);
	
	if(!wi_thread_create_thread(wi_test_fsevents_thread, NULL))
		WI_TEST_FAIL("%m");
	
	wi_thread_sleep(0.1);
	
	wi_string_write_to_file(WI_STR("foo"), wi_string_by_appending_path_component(directory, WI_STR("file")));
	
	wi_condition_lock_lock_when_condition(wi_test_fsevents_lock, 1, 0.0);
	
	if(!wi_test_fsevents_path)
		WI_TEST_FAIL("No fsevents callback received");
	else
		WI_TEST_ASSERT_EQUAL_INSTANCES(wi_test_fsevents_path, directory, "");
	
	wi_condition_lock_unlock(wi_test_fsevents_lock);

	wi_fs_delete_path(directory);
	
	wi_release(wi_test_fsevents_lock);
	wi_release(wi_test_fsevents_fsevents);
	wi_release(wi_test_fsevents_path);
#endif
}
Example #9
0
static void wr_command_log(wi_array_t *arguments) {
	wi_mutable_string_t		*string;
	wi_string_t				*path;
	
	path = wi_user_home();
	path = wi_string_by_appending_path_component(path, WI_ARRAY(arguments, 0));

	string = wi_mutable_copy(wi_terminal_buffer_string(wr_window_buffer(wr_current_window)));

	wi_mutable_string_append_string(string, WI_STR("\n"));
	
	if(!wi_string_write_to_file(string, path))
		wr_printf_prefix(WI_STR("log: %@: %m"), path);
	else
		wr_printf_prefix(WI_STR("log: \"%@\" saved"), path);
	
	wi_release(string);
}
void wi_test_string_encoding_conversion(void) {
#ifdef WI_STRING_ENCODING
    wi_string_t             *string, *path;
    wi_data_t               *data;
    wi_string_encoding_t    *encoding;
    
    encoding = wi_string_encoding_with_charset(WI_STR("ISO-8859-1"), 0);
    string = wi_string_with_c_string("hello world", encoding);
    
    WI_TEST_ASSERT_EQUAL_INSTANCES(string, WI_STR("hello world"), "");
    
    data = wi_data_with_base64_string(WI_STR("aGVsbG8gd29ybGQ="));
    string = wi_string_with_data(data, encoding);
    
    WI_TEST_ASSERT_EQUAL_INSTANCES(string, WI_STR("hello world"), "");
    
    string = wi_string_with_bytes(wi_data_bytes(data), wi_data_length(data), encoding);
    
    WI_TEST_ASSERT_EQUAL_INSTANCES(string, WI_STR("hello world"), "");
    
    path = wi_string_by_appending_path_component(wi_test_fixture_path, WI_STR("wi-string-encoding-tests-1.txt"));
    string = wi_string_with_contents_of_file(path, encoding);
    
    WI_TEST_ASSERT_NOT_NULL(string, "");
    WI_TEST_ASSERT_EQUALS(wi_string_character_at_index(string, 0), 'h', "");
    WI_TEST_ASSERT_EQUALS(wi_string_length(string), 14, "");
    
    data = wi_string_data(WI_STR("hello world"), encoding);

    WI_TEST_ASSERT_EQUAL_INSTANCES(data, wi_data_with_base64_string(WI_STR("aGVsbG8gd29ybGQ=")), "");

    encoding = wi_string_encoding_with_charset(WI_STR("ASCII"), 0);
    string = wi_string_with_contents_of_file(path, encoding);
    
    WI_TEST_ASSERT_NULL(string, "");
    
    encoding = wi_string_encoding_with_charset(WI_STR("hello world"), 0);
    string = wi_string_with_contents_of_file(path, encoding);
    
    WI_TEST_ASSERT_NULL(string, "");
#endif
}
Example #11
0
void wd_user_unsubscribe_path(wd_user_t *user, wi_string_t *realpath) {
	wi_string_t		*metapath;
	
	wi_recursive_lock_lock(user->user_lock);
		
	wi_mutable_set_remove_data(user->subscribed_paths, realpath);

	if(wd_files_fsevents)
		wi_fsevents_remove_path(wd_files_fsevents, realpath);
		
	metapath = wi_string_by_appending_path_component(realpath, WI_STR(WD_FILES_META_PATH));
		
	wi_mutable_set_add_data(user->subscribed_paths, metapath);

	if(wd_files_fsevents)
		wi_fsevents_add_path(wd_files_fsevents, metapath);

	wi_mutable_dictionary_remove_data_for_key(user->subscribed_virtualpaths, realpath);
	
	wi_recursive_lock_unlock(user->user_lock);
}
Example #12
0
void wi_test_plist(void) {
#ifdef WI_PLIST
	wi_string_t			*string1, *string2;
	wi_dictionary_t		*dictionary1, *dictionary2;
	
	string1 = wi_autorelease(wi_string_init_with_contents_of_file(wi_string_alloc(), wi_string_by_appending_path_component(wi_test_fixture_path, WI_STR("wi-plist-tests-1.plist"))));

	dictionary1 = wi_plist_instance_for_string(string1);
	
	WI_TEST_ASSERT_NOT_NULL(dictionary1, "%m");
	
	dictionary2 = wi_dictionary_with_data_and_keys(
		WI_STR("hello world"),
			WI_STR("string"),
		wi_number_with_bool(true),
			WI_STR("true"),
		wi_number_with_bool(false),
			WI_STR("false"),
		wi_number_with_integer(42),
			WI_STR("integer"),
		wi_number_with_double(3.14),
			WI_STR("real"),
		wi_date_with_rfc3339_string(WI_STR("2008-06-01T17:28:00Z")),
			WI_STR("date"),
		wi_data_with_base64(wi_string_base64(WI_STR("hello world"))),
			WI_STR("data"),
		wi_dictionary_with_data_and_keys(WI_STR("value1"), WI_STR("key1"), WI_STR("value2"), WI_STR("key2"), NULL),
			WI_STR("dict"),
		wi_array_with_data(WI_STR("value1"), WI_STR("value2"), NULL),
			WI_STR("array"),
		NULL);
	
	WI_TEST_ASSERT_EQUAL_INSTANCES(dictionary1, dictionary2, "");
	
	string2 = wi_plist_string_for_instance(dictionary2);
	
	WI_TEST_ASSERT_EQUAL_INSTANCES(string1, string2, "");
#endif
}
Example #13
0
int main(int argc, const char **argv) {
	wi_pool_t		*pool;
	
	wi_initialize();
	wi_load(argc, argv);
	
	wi_log_plain = true;
	wi_log_level = WI_LOG_DEBUG;
	
	pool = wi_pool_init(wi_pool_alloc());

	wi_tests_start();
	
	wi_test_fixture_path = wi_string_by_appending_path_component(WI_STR(WI_TEST_ROOT), WI_STR("fixture"));
	
#include "test/testlist.inc"

	wi_tests_stop_and_report();
	
	wi_release(pool);
	
	return wi_tests_failed;
}
void wi_test_filesystem_events(void) {
#if defined(WI_FILESYSTEM_EVENTS)
    wi_filesystem_events_t  *filesystem_events;
    wi_string_t             *path;
    wi_boolean_t            result;
    
    _wi_test_filesystem_events_lock = wi_autorelease(wi_condition_lock_init_with_condition(wi_condition_lock_alloc(), 0));
    _wi_test_filesystem_events_paths = wi_mutable_set();
    
    path = wi_filesystem_temporary_path_with_template(WI_STR("/tmp/libwired-test-filesystem.XXXXXXX"));
    
    WI_TEST_ASSERT_NOT_NULL(path, "");
    
    result = wi_filesystem_create_directory_at_path(path);
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    filesystem_events = wi_filesystem_events();
    
    WI_TEST_ASSERT_NOT_NULL(filesystem_events, "");
    
    result = wi_filesystem_events_add_path_with_callback(filesystem_events, path, _wi_test_filesystem_events_callback);
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    result = wi_string_write_utf8_string_to_path(WI_STR("hello world"), wi_string_by_appending_path_component(path, WI_STR("foobar")));
    
    WI_TEST_ASSERT_TRUE(result, "");
    
    if(!wi_condition_lock_lock_when_condition(_wi_test_filesystem_events_lock, 1, 1.0))
        WI_TEST_FAIL("timed out waiting for filesystem events thread");
    
    WI_TEST_ASSERT_EQUAL_INSTANCES(_wi_test_filesystem_events_paths, wi_set_with_data(path, NULL), "");
    
    wi_condition_lock_unlock(_wi_test_filesystem_events_lock);
#endif
}
Example #15
0
int main(int argc, const char **argv) {
	wi_pool_t			*pool;
	wi_string_t			*homepath, *wirepath, *path, *component;
	wi_file_t			*file;	
	int					ch;

	/* init libwired */
	wi_initialize();
	wi_load(argc, argv);
	
	pool				= wi_pool_init(wi_pool_alloc());
	wi_log_callback		= wr_wi_log_callback;
	
	/* init core systems */
	wr_version_init();
	wr_start_date		= wi_date_init(wi_date_alloc());
	
	/* set defaults */
	wr_nick				= wi_retain(wi_user_name());
	homepath			= wi_user_home();
	wr_timestamp_format	= wi_retain(WI_STR("%H:%M"));

	/* parse command line switches */
	while((ch = getopt(argc, (char * const *) argv, "DhVv")) != -1) {
		switch(ch) {
			case 'D':
				wr_debug = true;

				wi_log_level = WI_LOG_DEBUG;
				wi_log_file = true;
				wi_log_path = WI_STR("wire.out");
				wi_log_callback = NULL;
				break;

			case 'V':
			case 'v':
				wr_version();
				break;

			case '?':
			case 'h':
			default:
				wr_usage();
				break;
		}
	}

	argc -= optind;
	argv += optind;

	/* open log */
	wi_log_open();
	
	/* create ~/.wire */
	wirepath = wi_string_by_appending_path_component(homepath, WI_STR(WR_WIRE_PATH));
	wi_file_create_directory(wirepath, 0700);
	
	/* init subsystems */
	wr_signals_init();
	wr_terminal_init();
	wr_readline_init();
	wr_chats_init();
	wr_windows_init();
	wr_client_init();
	wr_runloop_init();
	wr_users_init();
	wr_ignores_init();
	wr_files_init();
	wr_transfers_init();
	wr_servers_init();
	
	/* open default settings */
	path = wi_string_by_appending_path_component(homepath, WI_STR(WR_WIRE_CONFIG_PATH));
	file = wi_file_for_reading(path);

	if(file)
		wr_parse_file(file);
	else
		wr_printf_prefix(WI_STR("%@: %m"), path);

	/* read specified bookmark */
	if(*argv) {
		component	= wi_string_with_cstring(*argv);
		path		= wi_string_by_appending_path_component(wirepath, component);
		file		= wi_file_for_reading(path);

		if(file)
			wr_parse_file(file);
		else
			wr_printf_prefix(WI_STR("%@: %m"), path);
	}
	
	/* clean up pool after startup */
	wi_pool_drain(pool);
	
	/* enter event loop */
	wr_runloop_run();

	/* clean up */
	wr_cleanup();
	wi_release(pool);
	
	return 0;
}
Example #16
0
wi_boolean_t wr_transfer_upload_add_file(wr_transfer_t *transfer, wr_file_t *file) {
	WI_FTS			*fts = NULL;
	WI_FTSENT		*p;
	wi_string_t		*local_path, *remote_path;
	wr_file_t		*fts_file;
	char			*paths[2];
	
	if(wr_file_type(file) == WR_FILE_FILE) {
		wi_mutable_array_add_data(transfer->local_paths, wr_file_path(file));
		wi_mutable_array_add_data(transfer->remote_paths, wr_files_full_path(transfer->name));
		wi_mutable_array_add_data(transfer->files, file);
		
		transfer->total_size += wr_file_size(file);
	} else {
		wr_transfers_recursive_upload = true;
		transfer->recursive = true;
        
		paths[0] = (char *) wi_string_cstring(wr_file_path(file));
		paths[1] = NULL;
		
		errno = 0;
		fts = wi_fts_open(paths, WI_FTS_NOSTAT | WI_FTS_LOGICAL, NULL);
		
		if(!fts)
			return false;
		
		if(fts && errno != 0) {
			wi_fts_close(fts);
			
			return false;
		}
		
		while((p = wi_fts_read(fts))) {
			if(p->fts_level > 10) {
				wi_fts_set(fts, p, WI_FTS_SKIP);
				
				continue;
			}
			
			switch(p->fts_info) {
				case WI_FTS_DC:
					errno = ELOOP;
					
					wr_printf_prefix(WI_STR("put: Could not read %s: %s"),
                                     strerror(errno));
					
					continue;
					break;
					
				case WI_FTS_DP:
					continue;
					break;
					
				case WI_FTS_DNR:
				case WI_FTS_ERR:
					wr_printf_prefix(WI_STR("put: Could not read %s: %s"),
                                     strerror(p->fts_errno));
					
					continue;
					break;
			}
			
			if(p->fts_name[0] == '.') {
				wi_fts_set(fts, p, WI_FTS_SKIP);
				
				continue;
			}
			
			local_path = wi_string_with_cstring(p->fts_path);
			remote_path = wi_string_by_normalizing_path(wi_string_by_appending_path_component(transfer->master_path,
                                                                                              wi_string_substring_from_index(local_path, wi_string_length(transfer->source_path))));
			
			if(p->fts_info == WI_FTS_D) {
				// wr_send_command(WI_STR("FOLDER %#@"), remote_path);
			} else {
				wi_mutable_array_add_data(transfer->local_paths, local_path);
				wi_mutable_array_add_data(transfer->remote_paths, remote_path);
                
				fts_file = wr_file_init_with_local_path(wr_file_alloc(), local_path);
				transfer->total_size += wr_file_size(fts_file);
				wi_mutable_array_add_data(transfer->files, fts_file);
				wi_release(fts_file);
			}
		}
		
		wi_fts_close(fts);
	}
	
	return true;
}