From 78f97fe198286a120370f6c56921205191f986b0 Mon Sep 17 00:00:00 2001 From: Alexander Lantsev Date: Fri, 10 Apr 2015 12:01:55 +0000 Subject: Tox: - switched to new api - updated tox core git-svn-id: http://svn.miranda-ng.org/main/trunk@12726 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/Tox/src/api_avatars.cpp | 5 - protocols/Tox/src/api_connection.cpp | 22 +- protocols/Tox/src/api_encryption.cpp | 82 +-- protocols/Tox/src/api_main.cpp | 134 ++--- protocols/Tox/src/api_transfer.cpp | 40 +- protocols/Tox/src/common.h | 2 + protocols/Tox/src/resource.h | 40 +- protocols/Tox/src/tox_accounts.cpp | 13 +- protocols/Tox/src/tox_address.h | 10 +- protocols/Tox/src/tox_avatars.cpp | 173 +++--- protocols/Tox/src/tox_chatrooms.cpp | 5 - protocols/Tox/src/tox_contacts.cpp | 188 ++++--- protocols/Tox/src/tox_core.cpp | 152 +++--- protocols/Tox/src/tox_dialogs.h | 21 + protocols/Tox/src/tox_events.cpp | 12 +- protocols/Tox/src/tox_menus.cpp | 7 +- protocols/Tox/src/tox_menus.h | 12 +- protocols/Tox/src/tox_messages.cpp | 104 ++-- protocols/Tox/src/tox_network.cpp | 37 +- protocols/Tox/src/tox_options.cpp | 983 ++++++++++++++--------------------- protocols/Tox/src/tox_options.h | 108 +++- protocols/Tox/src/tox_profile.cpp | 194 +++---- protocols/Tox/src/tox_proto.cpp | 72 ++- protocols/Tox/src/tox_proto.h | 57 +- protocols/Tox/src/tox_search.cpp | 4 +- protocols/Tox/src/tox_services.cpp | 9 +- protocols/Tox/src/tox_transfer.cpp | 301 +++++------ protocols/Tox/src/tox_transfer.h | 12 +- protocols/Tox/src/tox_utils.cpp | 26 +- protocols/Tox/src/version.h | 4 +- 30 files changed, 1342 insertions(+), 1487 deletions(-) create mode 100644 protocols/Tox/src/tox_dialogs.h (limited to 'protocols/Tox/src') diff --git a/protocols/Tox/src/api_avatars.cpp b/protocols/Tox/src/api_avatars.cpp index 5b5aa0c487..e15773b94f 100644 --- a/protocols/Tox/src/api_avatars.cpp +++ b/protocols/Tox/src/api_avatars.cpp @@ -27,11 +27,6 @@ int tox_get_self_avatar(const Tox *tox, uint8_t *format, uint8_t *buf, uint32_t return CreateFunction(__FUNCTION__)(tox, format, buf, length, maxlen, hash); } -int tox_hash(uint8_t *hash, const uint8_t *data, const uint32_t datalen) -{ - return CreateFunction(__FUNCTION__)(hash, data, datalen); -} - int tox_request_avatar_info(const Tox *tox, const int32_t friendnumber) { return CreateFunction(__FUNCTION__)(tox, friendnumber); diff --git a/protocols/Tox/src/api_connection.cpp b/protocols/Tox/src/api_connection.cpp index 6a854612fb..7777755fd6 100644 --- a/protocols/Tox/src/api_connection.cpp +++ b/protocols/Tox/src/api_connection.cpp @@ -2,31 +2,27 @@ /* CONNECTION FUNCTIONS */ -int tox_bootstrap_from_address(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key) +bool tox_bootstrap(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) { - if (public_key == NULL) - return 0; - return CreateFunction(__FUNCTION__)(tox, address, port, public_key); + return CreateFunction(__FUNCTION__)(tox, host, port, public_key, error); } -int tox_add_tcp_relay(Tox *tox, const char *address, uint16_t port, const uint8_t *public_key) +bool tox_add_tcp_relay(Tox *tox, const char *host, uint16_t port, const uint8_t *public_key, TOX_ERR_BOOTSTRAP *error) { - if (public_key == NULL) - return 0; - return CreateFunction(__FUNCTION__)(tox, address, port, public_key); + return CreateFunction(__FUNCTION__)(tox, host, port, public_key, error); } -int tox_isconnected(const Tox *tox) +TOX_CONNECTION tox_self_get_connection_status(const Tox *tox) { - return CreateFunction(__FUNCTION__)(tox); + return CreateFunction(__FUNCTION__)(tox); } -uint32_t tox_do_interval(Tox *tox) +uint32_t tox_iteration_interval(const Tox *tox) { - return CreateFunction(__FUNCTION__)(tox); + return CreateFunction(__FUNCTION__)(tox); } -void tox_do(Tox *tox) +void tox_iterate(Tox *tox) { CreateFunction(__FUNCTION__)(tox); } \ No newline at end of file diff --git a/protocols/Tox/src/api_encryption.cpp b/protocols/Tox/src/api_encryption.cpp index 7125743096..f5fd2634e3 100644 --- a/protocols/Tox/src/api_encryption.cpp +++ b/protocols/Tox/src/api_encryption.cpp @@ -2,87 +2,17 @@ /* ENCRYPTION FUNCTIONS */ -int tox_pass_encryption_extra_length() +bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error) { - return CreateFunction(__FUNCTION__)(); + return CreateFunction(__FUNCTION__)(data, length, passphrase, pplength, out, error); } -int tox_pass_key_length() +bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_ENCRYPTION *error) { - return CreateFunction(__FUNCTION__)(); + return CreateFunction(__FUNCTION__)(data, data_len, passphrase, pplength, out, error); } -int tox_pass_salt_length() +bool tox_is_data_encrypted(const uint8_t *data) { - return CreateFunction(__FUNCTION__)(); -} - -uint32_t tox_encrypted_size(const Tox *tox) -{ - return CreateFunction(__FUNCTION__)(tox); -} - -int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out) -{ - return CreateFunction(__FUNCTION__)(data, data_len, passphrase, pplength, out); -} - -int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) -{ - return CreateFunction(__FUNCTION__)(tox, data, passphrase, pplength); -} - -int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) -{ - return CreateFunction(__FUNCTION__)(data, length, passphrase, pplength, out); -} - -int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) -{ - return CreateFunction(__FUNCTION__)(tox, data, length, passphrase, pplength); -} - -int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) -{ - return CreateFunction(__FUNCTION__)(passphrase, pplength, out_key); -} - -int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key) -{ - return CreateFunction(__FUNCTION__)(passphrase, pplength, salt, out_key); -} - -int tox_get_salt(uint8_t *data, uint8_t *salt) -{ - return CreateFunction(__FUNCTION__)(data, salt); -} - -int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out) -{ - return CreateFunction(__FUNCTION__)(data, data_len, key, out); -} - -int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key) -{ - return CreateFunction(__FUNCTION__)(tox, data, key); -} - -int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) -{ - return CreateFunction(__FUNCTION__)(data, length, key, out); -} - -int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key) -{ - return CreateFunction(__FUNCTION__)(tox, data, length, key); -} - -int tox_is_data_encrypted(const uint8_t *data) -{ - return CreateFunction(__FUNCTION__)(data); -} - -int tox_is_save_encrypted(const uint8_t *data) -{ - return CreateFunction(__FUNCTION__)(data); + return CreateFunction(__FUNCTION__)(data); } \ No newline at end of file diff --git a/protocols/Tox/src/api_main.cpp b/protocols/Tox/src/api_main.cpp index fc23165d44..19bb82f586 100644 --- a/protocols/Tox/src/api_main.cpp +++ b/protocols/Tox/src/api_main.cpp @@ -2,9 +2,19 @@ /* MAIN FUNCTIONS */ -Tox *tox_new(Tox_Options *options) +struct Tox_Options *tox_options_new(TOX_ERR_OPTIONS_NEW *error) { - return CreateFunction(__FUNCTION__)(options); + return CreateFunction(__FUNCTION__)(error); +} + +void tox_options_free(struct Tox_Options *options) +{ + CreateFunction(__FUNCTION__)(options); +} + +Tox *tox_new(const struct Tox_Options *options, const uint8_t *data, size_t length, TOX_ERR_NEW *error) +{ + return CreateFunction(__FUNCTION__)(options, data, length, error); } void tox_kill(Tox *tox) @@ -13,34 +23,34 @@ void tox_kill(Tox *tox) tox = NULL; } -void tox_get_address(const Tox *tox, uint8_t *address) +void tox_self_get_address(const Tox *tox, uint8_t *address) { CreateFunction(__FUNCTION__)(tox, address); } -int32_t tox_add_friend(Tox *tox,const uint8_t *address, const uint8_t *data, uint16_t length) +uint32_t tox_friend_add(Tox *tox, const uint8_t *address, const uint8_t *message, size_t length, TOX_ERR_FRIEND_ADD *error) { - return CreateFunction(__FUNCTION__)(tox, address, data, length); + return CreateFunction(__FUNCTION__)(tox, address, message, length, error); } -int32_t tox_add_friend_norequest(Tox *tox, const uint8_t *client_id) +uint32_t tox_friend_add_norequest(Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_ADD *error) { - return CreateFunction(__FUNCTION__)(tox, client_id); + return CreateFunction(__FUNCTION__)(tox, public_key, error); } -int32_t tox_get_friend_number(const Tox *tox, const uint8_t *client_id) +uint32_t tox_friend_by_public_key(const Tox *tox, const uint8_t *public_key, TOX_ERR_FRIEND_BY_PUBLIC_KEY *error) { - return CreateFunction(__FUNCTION__)(tox, client_id); + return CreateFunction(__FUNCTION__)(tox, public_key, error); } -int tox_get_client_id(const Tox *tox, int32_t friendnumber, uint8_t *client_id) +bool tox_friend_get_public_key(const Tox *tox, uint32_t friend_number, uint8_t *public_key, TOX_ERR_FRIEND_GET_PUBLIC_KEY *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber, client_id); + return CreateFunction(__FUNCTION__)(tox, friend_number, public_key, error); } -int tox_del_friend(Tox *tox, int32_t friendnumber) +bool tox_friend_delete(Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_DELETE *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber); + return CreateFunction(__FUNCTION__)(tox, friend_number, error); } int tox_get_friend_connection_status(const Tox *tox, int32_t friendnumber) @@ -53,34 +63,29 @@ int tox_friend_exists(const Tox *tox, int32_t friendnumber) return CreateFunction(__FUNCTION__)(tox, friendnumber); } -uint32_t tox_send_message(Tox *tox, int32_t friendnumber, const uint8_t *message, uint32_t length) -{ - return CreateFunction(__FUNCTION__)(tox, friendnumber, message, length); -} - -uint32_t tox_send_action(Tox *tox, int32_t friendnumber, const uint8_t *action, uint32_t length) +uint32_t tox_friend_send_message(Tox *tox, uint32_t friend_number, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, TOX_ERR_FRIEND_SEND_MESSAGE *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber, action, length); + return CreateFunction(__FUNCTION__)(tox, friend_number, type, message, length, error); } -int tox_set_name(Tox *tox, const uint8_t *name, uint16_t length) +bool tox_self_set_name(Tox *tox, const uint8_t *name, size_t length, TOX_ERR_SET_INFO *error) { - return CreateFunction(__FUNCTION__ )(tox, name, length); + return CreateFunction(__FUNCTION__)(tox, name, length, error); } -uint16_t tox_get_self_name(const Tox *tox, uint8_t *name) +void tox_self_get_name(const Tox *tox, uint8_t *name) { - return CreateFunction(__FUNCTION__)(tox, name); + CreateFunction(__FUNCTION__)(tox, name); } -int tox_get_name(const Tox *tox, int32_t friendnumber, uint8_t *name) +bool tox_friend_get_name(const Tox *tox, uint32_t friend_number, uint8_t *name, TOX_ERR_FRIEND_QUERY *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber, name); + return CreateFunction(__FUNCTION__)(tox, friend_number, name, error); } -int tox_get_name_size(const Tox *tox, int32_t friendnumber) +size_t tox_friend_get_name_size(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_QUERY *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber); + return CreateFunction(__FUNCTION__)(tox, friend_number, error); } int tox_get_self_name_size(const Tox *tox) @@ -88,14 +93,14 @@ int tox_get_self_name_size(const Tox *tox) return CreateFunction(__FUNCTION__)(tox); } -int tox_set_status_message(Tox *tox, const uint8_t *status, uint16_t length) +bool tox_self_set_status_message(Tox *tox, const uint8_t *status, size_t length, TOX_ERR_SET_INFO *error) { - return CreateFunction(__FUNCTION__)(tox, status, length); + return CreateFunction(__FUNCTION__)(tox, status, length, error); } -int tox_set_user_status(Tox *tox, uint8_t userstatus) +void tox_self_set_status(Tox *tox, TOX_USER_STATUS user_status) { - return CreateFunction(__FUNCTION__)(tox, userstatus); + CreateFunction(__FUNCTION__)(tox, user_status); } int tox_get_status_message_size(const Tox *tox, int32_t friendnumber) @@ -103,9 +108,9 @@ int tox_get_status_message_size(const Tox *tox, int32_t friendnumber) return CreateFunction(__FUNCTION__)(tox, friendnumber); } -int tox_get_self_status_message_size(const Tox *tox) +void tox_self_get_status_message(const Tox *tox, uint8_t *status) { - return CreateFunction(__FUNCTION__)(tox); + CreateFunction(__FUNCTION__)(tox, status); } int tox_get_status_message(const Tox *tox, int32_t friendnumber, uint8_t *buf, uint32_t maxlen) @@ -128,24 +133,24 @@ uint8_t tox_get_self_user_status(const Tox *tox) return CreateFunction(__FUNCTION__)(tox); } -uint64_t tox_get_last_online(const Tox *tox, int32_t friendnumber) +uint64_t tox_friend_get_last_online(const Tox *tox, uint32_t friend_number, TOX_ERR_FRIEND_GET_LAST_ONLINE *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber); + return CreateFunction(__FUNCTION__)(tox, friend_number, error); } -int tox_set_user_is_typing(Tox *tox, int32_t friendnumber, uint8_t is_typing) +int tox_friend_get_typing(Tox *tox, int32_t friendnumber, uint8_t is_typing) { return CreateFunction(__FUNCTION__)(tox, friendnumber, is_typing); } -uint8_t tox_get_is_typing(const Tox *tox, int32_t friendnumber) +bool tox_self_set_typing(Tox *tox, uint32_t friend_number, bool is_typing, TOX_ERR_SET_TYPING *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber); + return CreateFunction(__FUNCTION__)(tox, friend_number, is_typing, error); } -uint32_t tox_count_friendlist(const Tox *tox) +size_t tox_self_get_friend_list_size(const Tox *tox) { - return CreateFunction(__FUNCTION__)(tox); + return CreateFunction(__FUNCTION__)(tox); } uint32_t tox_get_num_online_friends(const Tox *tox) @@ -153,64 +158,59 @@ uint32_t tox_get_num_online_friends(const Tox *tox) return CreateFunction(__FUNCTION__)(tox); } -uint32_t tox_get_friendlist(const Tox *tox, int32_t *out_list, uint32_t list_size) +void tox_self_get_friend_list(const Tox *tox, uint32_t *list) { - return CreateFunction(__FUNCTION__)(tox, out_list, list_size); + CreateFunction(__FUNCTION__)(tox, list); } -void tox_callback_friend_request(Tox *tox, void(*function)(Tox *tox, const uint8_t *, const uint8_t *, uint16_t, void *), void *userdata) +void tox_callback_friend_request(Tox *tox, tox_friend_request_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_friend_message(Tox *tox, void(*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), void *userdata) +void tox_callback_friend_message(Tox *tox, tox_friend_message_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_friend_action(Tox *tox, void(*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), void *userdata) +void tox_callback_friend_name(Tox *tox, tox_friend_name_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_name_change(Tox *tox, void(*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), void *userdata) +void tox_callback_friend_status_message(Tox *tox, tox_friend_status_message_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_status_message(Tox *tox, void(*function)(Tox *tox, int32_t, const uint8_t *, uint16_t, void *), void *userdata) +void tox_callback_friend_status(Tox *tox, tox_friend_status_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_user_status(Tox *tox, void(*function)(Tox *tox, int32_t, uint8_t, void *), void *userdata) +void tox_callback_friend_read_receipt(Tox *tox, tox_friend_read_receipt_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_typing_change(Tox *tox, void(*function)(Tox *tox, int32_t, uint8_t, void *), void *userdata) +void tox_callback_friend_typing(Tox *tox, tox_friend_typing_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } -void tox_callback_read_receipt(Tox *tox, void(*function)(Tox *tox, int32_t, uint32_t, void *), void *userdata) +void tox_callback_friend_connection_status(Tox *tox, tox_friend_connection_status_cb *function, void *user_data) { - CreateFunction(__FUNCTION__)(tox, function, userdata); -} - -void tox_callback_connection_status(Tox *tox, void(*function)(Tox *tox, int32_t, uint8_t, void *), void *userdata) -{ - CreateFunction(__FUNCTION__)(tox, function, userdata); + CreateFunction(__FUNCTION__)(tox, function, user_data); } /* SAVING AND LOADING FUNCTIONS */ -uint32_t tox_size(const Tox *tox) +size_t tox_get_savedata_size(const Tox *tox) { - return CreateFunction(__FUNCTION__)(tox); + return CreateFunction(__FUNCTION__)(tox); } -void tox_save(const Tox *tox, uint8_t *data) +void tox_get_savedata(const Tox *tox, uint8_t *data) { CreateFunction(__FUNCTION__)(tox, data); } diff --git a/protocols/Tox/src/api_transfer.cpp b/protocols/Tox/src/api_transfer.cpp index c5ba1b5f4a..f3aceab334 100644 --- a/protocols/Tox/src/api_transfer.cpp +++ b/protocols/Tox/src/api_transfer.cpp @@ -2,29 +2,49 @@ /* FILE SENDING FUNCTIONS */ -void tox_callback_file_send_request(Tox *tox, void(*function)(Tox *m, int32_t, uint8_t, uint64_t, const uint8_t *, uint16_t, void *), void *userdata) +bool tox_hash(uint8_t *hash, const uint8_t *data, size_t datalen) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + return CreateFunction(__FUNCTION__)(hash, data, datalen); } -void tox_callback_file_control(Tox *tox, void(*function)(Tox *m, int32_t, uint8_t, uint8_t, uint8_t, const uint8_t *, uint16_t, void *), void *userdata) +bool tox_file_get_file_id(const Tox *tox, uint32_t friend_number, uint32_t file_number, uint8_t *file_id, TOX_ERR_FILE_GET *error) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + return CreateFunction(__FUNCTION__)(tox, friend_number, file_number, file_id, error); } -void tox_callback_file_data(Tox *tox, void(*function)(Tox *m, int32_t, uint8_t, const uint8_t *, uint16_t length, void *), void *userdata) +uint32_t tox_file_send(Tox *tox, uint32_t friend_number, uint32_t kind, uint64_t file_size, const uint8_t *file_id, const uint8_t *filename, size_t filename_length, TOX_ERR_FILE_SEND *error) { - CreateFunction(__FUNCTION__)(tox, function, userdata); + return CreateFunction(__FUNCTION__)(tox, friend_number, kind, file_size, file_id, filename, filename_length, error); } -int tox_new_file_sender(Tox *tox, int32_t friendnumber, uint64_t filesize, const uint8_t *filename, uint16_t filename_length) +bool tox_file_send_chunk(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, const uint8_t *data, size_t length, TOX_ERR_FILE_SEND_CHUNK *error) { - return CreateFunction(__FUNCTION__)(tox, friendnumber, filesize, filename, filename_length); + return CreateFunction(__FUNCTION__)(tox, friend_number, file_number, position, data, length, error); } -int tox_file_send_control(Tox *tox, int32_t friendnumber, uint8_t send_receive, uint8_t filenumber, uint8_t message_id, const uint8_t *data, uint16_t length) +void tox_callback_file_chunk_request(Tox *tox, tox_file_chunk_request_cb *function, void *user_data) { - return CreateFunction(__FUNCTION__)(tox, friendnumber, send_receive, filenumber, message_id, data, length); + CreateFunction(__FUNCTION__)(tox, function, user_data); +} + +void tox_callback_file_recv(Tox *tox, tox_file_recv_cb *function, void *user_data) +{ + CreateFunction(__FUNCTION__)(tox, function, user_data); +} + +void tox_callback_file_recv_control(Tox *tox, tox_file_recv_control_cb *function, void *user_data) +{ + CreateFunction(__FUNCTION__)(tox, function, user_data); +} + +void tox_callback_file_recv_chunk(Tox *tox, tox_file_recv_chunk_cb *function, void *user_data) +{ + CreateFunction(__FUNCTION__)(tox, function, user_data); +} + +bool tox_file_control(Tox *tox, uint32_t friend_number, uint32_t file_number, TOX_FILE_CONTROL control, TOX_ERR_FILE_CONTROL *error) +{ + return CreateFunction(__FUNCTION__)(tox, friend_number, file_number, control, error); } int tox_file_send_data(Tox *tox, int32_t friendnumber, uint8_t filenumber, const uint8_t *data, uint16_t length) diff --git a/protocols/Tox/src/common.h b/protocols/Tox/src/common.h index a0fa494107..d5450728cc 100644 --- a/protocols/Tox/src/common.h +++ b/protocols/Tox/src/common.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -48,6 +49,7 @@ struct CToxProto; #include "tox_icons.h" #include "tox_menus.h" #include "tox_address.h" +#include "tox_dialogs.h" #include "tox_options.h" #include "tox_transfer.h" #include "tox_chatrooms.h" diff --git a/protocols/Tox/src/resource.h b/protocols/Tox/src/resource.h index 241fda6951..69770bb555 100644 --- a/protocols/Tox/src/resource.h +++ b/protocols/Tox/src/resource.h @@ -2,7 +2,7 @@ // Microsoft Visual C++ generated include file. // Used by e:\Projects\C++\MirandaNG\protocols\Tox\res\resource.rc // -#define IDD_CHATROOM_INVITE 16 +#define IDI_TOX 100 #define IDD_USER_INFO 101 #define IDD_PASSWORD 102 #define IDD_ACCOUNT_MANAGER 104 @@ -10,29 +10,31 @@ #define IDD_OPTIONS_MAIN 106 #define IDD_OPTIONS_NODES 107 #define IDD_ADDNODE 108 -#define IDD_NODE_EDITOR 108 -#define IDD_OPTIONS_AV 109 -#define IDI_TOX 120 +#define IDD_NODE_EDITOR 109 +#define IDD_OPTIONS_AV 110 +#define IDD_CHATROOM_INVITE 172 #define IDC_CCLIST 173 #define IDC_EDITSCR 174 #define IDC_TOXID 1001 #define IDC_CLIPBOARD 1002 -#define IDC_SEARCH 1004 -#define IDC_PASSWORD 1005 -#define IDC_NAME 1007 -#define IDC_GROUP 1008 -#define IDC_DISABLE_UDP 1009 -#define IDC_DISABLE_IPV6 1010 -#define IDC_DNS_ID 1011 +#define IDC_SEARCH 1003 +#define IDC_PASSWORD 1004 +#define IDC_NAME 1005 +#define IDC_GROUP 1006 +#define IDC_ENABLE_UDP 1007 +#define IDC_ENABLE_IPV6 1008 +#define IDC_PROFILE_EXPORT 1009 +#define IDC_DNS_ID 1010 +#define IDC_PROFILE_NEW 1011 #define IDC_SAVEPERMANENT 1012 -#define IDC_SAVEPERMANENTLY 1013 -#define IDC_NODESLIST 1014 -#define IDC_ADDNODE 1015 -#define IDC_IPV4 1016 -#define IDC_IPV6 1017 -#define IDC_PORT 1018 -#define IDC_PKEY 1019 -#define IDC_IMPORT_PROFILE 1020 +#define IDC_PROFILE_IMPORT 1013 +#define IDC_SAVEPERMANENTLY 1014 +#define IDC_NODESLIST 1015 +#define IDC_ADDNODE 1016 +#define IDC_IPV4 1017 +#define IDC_IPV6 1018 +#define IDC_PORT 1019 +#define IDC_PKEY 1020 #define IDC_COMBO_AUDIOINPUT 1021 #define IDC_COMBO_AUDIOOUTPUT 1022 #define IDC_AUDIOFILTER 1023 diff --git a/protocols/Tox/src/tox_accounts.cpp b/protocols/Tox/src/tox_accounts.cpp index 618105dba7..228599866d 100644 --- a/protocols/Tox/src/tox_accounts.cpp +++ b/protocols/Tox/src/tox_accounts.cpp @@ -4,7 +4,7 @@ LIST CToxProto::Accounts(1, CToxProto::CompareAccounts); int CToxProto::CompareAccounts(const CToxProto *p1, const CToxProto *p2) { - return _tcscmp(p1->m_tszUserName, p2->m_tszUserName); + return mir_tstrcmp(p1->m_tszUserName, p2->m_tszUserName); } CToxProto* CToxProto::InitAccount(const char *protoName, const wchar_t *userName) @@ -24,12 +24,8 @@ int CToxProto::UninitAccount(CToxProto *proto) CToxProto* CToxProto::GetContactAccount(MCONTACT hContact) { for (int i = 0; i < Accounts.getCount(); i++) - { if (mir_strcmpi(GetContactProto(hContact), Accounts[i]->m_szModuleName) == 0) - { return Accounts[i]; - } - } return NULL; } @@ -58,10 +54,5 @@ int CToxProto::OnAccountRenamed(WPARAM, LPARAM) INT_PTR CToxProto::OnAccountManagerInit(WPARAM, LPARAM lParam) { - return (INT_PTR)CreateDialogParam( - g_hInstance, - MAKEINTRESOURCE(IDD_ACCOUNT_MANAGER), - (HWND)lParam, - CToxProto::MainOptionsProc, - (LPARAM)this); + return (INT_PTR)(CToxOptionsMain::CreateAccountManagerPage(this, (HWND)lParam))->GetHwnd(); } \ No newline at end of file diff --git a/protocols/Tox/src/tox_address.h b/protocols/Tox/src/tox_address.h index f9be08c767..265ed2f94e 100644 --- a/protocols/Tox/src/tox_address.h +++ b/protocols/Tox/src/tox_address.h @@ -10,12 +10,12 @@ private: std::string hexData; public: ToxHexAddress(const ToxHexAddress &address) : hexData(address.hexData) { } - ToxHexAddress(const char *hex, size_t size = TOX_FRIEND_ADDRESS_SIZE * 2) : hexData(hex, hex + size) { } + ToxHexAddress(const char *hex, size_t size = TOX_ADDRESS_SIZE * 2) : hexData(hex, hex + size) { } ToxHexAddress(const std::string &hex) { this->ToxHexAddress::ToxHexAddress(hex.c_str(), hex.size()); } - ToxHexAddress(const uint8_t *bin, size_t size = TOX_FRIEND_ADDRESS_SIZE) + ToxHexAddress(const uint8_t *bin, size_t size = TOX_ADDRESS_SIZE) { char *hex = (char*)mir_alloc(size * 2 + 1); hexData = bin2hex(bin, size, hex); @@ -56,9 +56,9 @@ private: std::vector binData; public: ToxBinAddress(const ToxBinAddress &address) : binData(address.binData) { } - ToxBinAddress(const uint8_t *bin, size_t size = TOX_FRIEND_ADDRESS_SIZE) : binData(bin, bin + size) { } - ToxBinAddress(const std::vector &bin, size_t size = TOX_FRIEND_ADDRESS_SIZE) : binData(bin.begin(), bin.begin() + size) { } - ToxBinAddress(const char *hex, size_t size = TOX_FRIEND_ADDRESS_SIZE * 2) + ToxBinAddress(const uint8_t *bin, size_t size = TOX_ADDRESS_SIZE) : binData(bin, bin + size) { } + ToxBinAddress(const std::vector &bin, size_t size = TOX_ADDRESS_SIZE) : binData(bin.begin(), bin.begin() + size) { } + ToxBinAddress(const char *hex, size_t size = TOX_ADDRESS_SIZE * 2) { char *endptr; const char *pos = hex; diff --git a/protocols/Tox/src/tox_avatars.cpp b/protocols/Tox/src/tox_avatars.cpp index 7ab5d4526d..6f2b1c6831 100644 --- a/protocols/Tox/src/tox_avatars.cpp +++ b/protocols/Tox/src/tox_avatars.cpp @@ -30,36 +30,28 @@ std::tstring CToxProto::GetAvatarFilePath(MCONTACT hContact) void CToxProto::SetToxAvatar(std::tstring path, bool checkHash) { - /*if (!IsOnline()) - { - return; - }*/ - - size_t length; - uint8_t *data; FILE *hFile = _tfopen(path.c_str(), L"rb"); if (!hFile) { - debugLogA("CToxProto::SetToxAvatar: failed to open avatar file"); + debugLogA(__FUNCTION__": failed to open avatar file"); return; } fseek(hFile, 0, SEEK_END); - length = ftell(hFile); + size_t length = ftell(hFile); rewind(hFile); - if (length > TOX_AVATAR_MAX_DATA_LENGTH) + if (length > 1024 * 1024) { fclose(hFile); - debugLogA("CToxProto::SetToxAvatar: new avatar size is excessive"); + debugLogA(__FUNCTION__": new avatar size is excessive"); return; } - data = (uint8_t*)mir_alloc(length); - size_t read = fread(data, sizeof(uint8_t), length, hFile); - if (read != length) + uint8_t *data = (uint8_t*)mir_alloc(length); + if (fread(data, sizeof(uint8_t), length, hFile) != length) { fclose(hFile); - debugLogA("CToxProto::SetToxAvatar: failed to read avatar file"); + debugLogA(__FUNCTION__": failed to read avatar file"); return; } fclose(hFile); @@ -73,18 +65,42 @@ void CToxProto::SetToxAvatar(std::tstring path, bool checkHash) { db_free(&dbv); mir_free(data); - debugLogA("CToxProto::SetToxAvatar: new avatar is same with old"); + debugLogA(__FUNCTION__": new avatar is same with old"); return; } db_free(&dbv); } - if (tox_set_avatar(tox, TOX_AVATAR_FORMAT_PNG, data, length) == TOX_ERROR) + for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) { - mir_free(data); - debugLogA("CToxProto::SetToxAvatar: failed to set new avatar"); - return; + if (GetContactStatus(hContact) == ID_STATUS_OFFLINE) + continue; + + int32_t friendNumber = GetToxFriendNumber(hContact); + if (friendNumber == UINT32_MAX) + { + mir_free(data); + debugLogA(__FUNCTION__": failed to set new avatar"); + return; + } + + TOX_ERR_FILE_SEND error; + uint32_t fileNumber = tox_file_send(tox, friendNumber, TOX_FILE_KIND_AVATAR, length, NULL, hash, TOX_HASH_LENGTH, &error); + if (error != TOX_ERR_FILE_SEND_OK) + { + mir_free(data); + debugLogA(__FUNCTION__": failed to set new avatar"); + return; + } + + FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, _T("avatar"), length); + transfer->pfts.hContact = hContact; + transfer->pfts.flags |= PFTS_SENDING; + //transfer->pfts.tszWorkingDir = fileDir; + transfer->hFile = hFile; + transfers.Add(transfer); } + mir_free(data); if (checkHash) @@ -106,7 +122,7 @@ INT_PTR CToxProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam) size->y = 300; } } - break; + break; case AF_ENABLED: return 1; @@ -115,7 +131,7 @@ INT_PTR CToxProto::GetAvatarCaps(WPARAM wParam, LPARAM lParam) return lParam == PA_FORMAT_PNG; case AF_MAXFILESIZE: - return TOX_AVATAR_MAX_DATA_LENGTH; + return 1024 * 1024; } return 0; @@ -171,14 +187,32 @@ INT_PTR CToxProto::SetMyAvatar(WPARAM, LPARAM lParam) return -1; } - SetToxAvatar(avatarPath, true); + if (IsOnline()) + SetToxAvatar(avatarPath, true); } else { - if (tox_unset_avatar(tox) == TOX_ERROR) + if (IsOnline()) { - debugLogA("CToxProto::SetMyAvatar: failed to unset avatar"); - return -1; + for (MCONTACT hContact = db_find_first(m_szModuleName); hContact; hContact = db_find_next(hContact, m_szModuleName)) + { + if (GetContactStatus(hContact) == ID_STATUS_OFFLINE) + continue; + + int32_t friendNumber = GetToxFriendNumber(hContact); + if (friendNumber == UINT32_MAX) + { + debugLogA(__FUNCTION__": failed to unset avatar"); + return -1; + } + + TOX_ERR_FILE_SEND error; + if (!tox_file_send(tox, NULL, TOX_FILE_KIND_AVATAR, 0, NULL, NULL, 0, &error)) + { + debugLogA(__FUNCTION__": failed to unset avatar"); + return -1; + } + } } if (IsFileExists(avatarPath)) @@ -192,65 +226,60 @@ INT_PTR CToxProto::SetMyAvatar(WPARAM, LPARAM lParam) return 0; } -void CToxProto::OnGotFriendAvatarInfo(Tox *, int32_t number, uint8_t format, uint8_t *hash, void *arg) +void CToxProto::OnGotFriendAvatarInfo(FileTransferParam *transfer, const uint8_t *hash) { - CToxProto *proto = (CToxProto*)arg; - - MCONTACT hContact = proto->GetContact(number); - if (hContact) + MCONTACT hContact = transfer->pfts.hContact; + std::tstring path = GetAvatarFilePath(); + if (transfer->pfts.totalBytes == 0) { - std::tstring path = proto->GetAvatarFilePath(hContact); - if (format == TOX_AVATAR_FORMAT_NONE) + delSetting(hContact, TOX_SETTINGS_AVATAR_HASH); + ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, 0, 0); + if (IsFileExists(path)) { - proto->delSetting(hContact, TOX_SETTINGS_AVATAR_HASH); - proto->ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, 0, 0); - if (IsFileExists(path)) - { - DeleteFile(path.c_str()); - } + DeleteFile(path.c_str()); } - else + OnFileCancel(hContact, transfer); + } + else + { + DBVARIANT dbv; + if (!db_get(transfer->pfts.hContact, m_szModuleName, TOX_SETTINGS_AVATAR_HASH, &dbv)) { - DBVARIANT dbv; - if (!db_get(hContact, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, &dbv)) + if (memcmp(hash, dbv.pbVal, TOX_HASH_LENGTH) == 0) { - if (memcmp(hash, dbv.pbVal, TOX_HASH_LENGTH) != 0) - { - tox_request_avatar_data(proto->tox, number); - } db_free(&dbv); + OnFileCancel(hContact, transfer); + return; } - else - { - tox_request_avatar_data(proto->tox, number); - } + db_free(&dbv); } + OnFileAllow(hContact, transfer, path.c_str()); } } -void CToxProto::OnGotFriendAvatarData(Tox *, int32_t number, uint8_t, uint8_t *hash, uint8_t *data, uint32_t length, void *arg) +/*void CToxProto::OnGotFriendAvatarData(Tox *, int32_t number, uint8_t, uint8_t *hash, uint8_t *data, uint32_t length, void *arg) { - CToxProto *proto = (CToxProto*)arg; +CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->GetContact(number); - if (hContact) - { - db_set_blob(hContact, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, hash, TOX_HASH_LENGTH); +MCONTACT hContact = proto->GetContact(number); +if (hContact) +{ +db_set_blob(hContact, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, hash, TOX_HASH_LENGTH); - std::tstring path = proto->GetAvatarFilePath(hContact); - FILE *hFile = _tfopen(path.c_str(), L"wb"); - if (hFile) - { - if (fwrite(data, sizeof(uint8_t), length, hFile) == length) - { - PROTO_AVATAR_INFORMATIONW pai = { sizeof(pai) }; - pai.format = PA_FORMAT_PNG; - pai.hContact = hContact; - _tcscpy(pai.filename, path.c_str()); +std::tstring path = proto->GetAvatarFilePath(hContact); +FILE *hFile = _tfopen(path.c_str(), L"wb"); +if (hFile) +{ +if (fwrite(data, sizeof(uint8_t), length, hFile) == length) +{ +PROTO_AVATAR_INFORMATIONW pai = { sizeof(pai) }; +pai.format = PA_FORMAT_PNG; +pai.hContact = hContact; +_tcscpy(pai.filename, path.c_str()); - proto->ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0); - } - fclose(hFile); - } - } -} \ No newline at end of file +proto->ProtoBroadcastAck(hContact, ACKTYPE_AVATAR, ACKRESULT_SUCCESS, (HANDLE)&pai, 0); +} +fclose(hFile); +} +} +}*/ \ No newline at end of file diff --git a/protocols/Tox/src/tox_chatrooms.cpp b/protocols/Tox/src/tox_chatrooms.cpp index d4b134faed..deb0ad7f48 100644 --- a/protocols/Tox/src/tox_chatrooms.cpp +++ b/protocols/Tox/src/tox_chatrooms.cpp @@ -115,11 +115,6 @@ INT_PTR CToxProto::OnLeaveChatRoom(WPARAM hContact, LPARAM) INT_PTR CToxProto::OnCreateChatRoom(WPARAM, LPARAM) { - if (!IsToxCoreInited()) - { - return 1; - } - ChatRoomInviteParam param = { this }; if (DialogBoxParam( diff --git a/protocols/Tox/src/tox_contacts.cpp b/protocols/Tox/src/tox_contacts.cpp index c972a2c07c..a735903756 100644 --- a/protocols/Tox/src/tox_contacts.cpp +++ b/protocols/Tox/src/tox_contacts.cpp @@ -44,7 +44,12 @@ MCONTACT CToxProto::GetContactFromAuthEvent(MEVENT hEvent) MCONTACT CToxProto::GetContact(const int friendNumber) { uint8_t data[TOX_PUBLIC_KEY_SIZE]; - tox_get_client_id(tox, friendNumber, data); + TOX_ERR_FRIEND_GET_PUBLIC_KEY error; + if (!tox_friend_get_public_key(tox, friendNumber, data, &error)) + { + debugLogA(__FUNCTION__": failed to get friend public key (%d)", error); + return NULL; + } ToxHexAddress pubKey(data, TOX_PUBLIC_KEY_SIZE); return GetContact(pubKey); } @@ -97,30 +102,36 @@ MCONTACT CToxProto::AddContact(const char *address, const std::tstring &dnsId, b return hContact; } -int32_t CToxProto::GetToxFriendNumber(MCONTACT hContact) +uint32_t CToxProto::GetToxFriendNumber(MCONTACT hContact) { ToxBinAddress pubKey = ptrA(getStringA(hContact, TOX_SETTINGS_ID)); - int32_t friendNumber = tox_get_friend_number(tox, pubKey); - if (friendNumber == TOX_ERROR) + TOX_ERR_FRIEND_BY_PUBLIC_KEY error; + uint32_t friendNumber = tox_friend_by_public_key(tox, pubKey, &error); + if (error != TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK) { - debugLogA("CToxProto::GetToxFriendNumber: failed to get friend number"); + debugLogA(__FUNCTION__": failed to get friend number (%d)", error); } return friendNumber; } void CToxProto::LoadFriendList(void*) { - uint32_t count = tox_count_friendlist(tox); + size_t count = tox_self_get_friend_list_size(tox); if (count > 0) { - int32_t *friends = (int32_t*)mir_alloc(count * sizeof(int32_t)); - tox_get_friendlist(tox, friends, count); + uint32_t *friends = (uint32_t*)mir_alloc(count * sizeof(uint32_t)); + tox_self_get_friend_list(tox, friends); uint8_t data[TOX_PUBLIC_KEY_SIZE]; - for (uint32_t i = 0; i < count; i++) + for (size_t i = 0; i < count; i++) { uint32_t friendNumber = friends[i]; - tox_get_client_id(tox, friendNumber, data); + TOX_ERR_FRIEND_GET_PUBLIC_KEY getPublicKeyResult; + if (!tox_friend_get_public_key(tox, friendNumber, data, &getPublicKeyResult)) + { + debugLogA(__FUNCTION__": failed to get friend public key (%d)", getPublicKeyResult); + continue; + } ToxHexAddress pubKey(data, TOX_PUBLIC_KEY_SIZE); MCONTACT hContact = AddContact(pubKey, _T("")); if (hContact) @@ -128,46 +139,42 @@ void CToxProto::LoadFriendList(void*) delSetting(hContact, "Auth"); delSetting(hContact, "Grant"); - int size = tox_get_name_size(tox, friendNumber); - if (size != TOX_ERROR) - { - std::string nick(size, 0); - tox_get_name(tox, friendNumber, (uint8_t*)nick.data()); - setWString(hContact, "Nick", ptrT(Utf8DecodeT(nick.c_str()))); - } + TOX_ERR_FRIEND_QUERY getNameResult; + uint8_t nick[TOX_MAX_NAME_LENGTH] = { 0 }; + if (tox_friend_get_name(tox, friendNumber, nick, &getNameResult)) + setWString(hContact, "Nick", ptrT(mir_utf8decodeW((char*)nick))); + else + debugLogA(__FUNCTION__": failed to get friend name (%d)", getNameResult); - uint64_t timestamp = tox_get_last_online(tox, friendNumber); - if (timestamp > getDword(hContact, "LastEventDateTS", 0)) - { + TOX_ERR_FRIEND_GET_LAST_ONLINE getLastOnlineResult; + uint64_t timestamp = tox_friend_get_last_online(tox, friendNumber, &getLastOnlineResult); + if (getLastOnlineResult == TOX_ERR_FRIEND_GET_LAST_ONLINE_OK) setDword(hContact, "LastEventDateTS", timestamp); - } + else + debugLogA(__FUNCTION__": failed to get friend last online (%d)", getLastOnlineResult); } } - mir_free(friends); } - else - { - debugLogA("CToxProto::LoadContactList: your friend list is empty"); - } } INT_PTR CToxProto::OnRequestAuth(WPARAM hContact, LPARAM lParam) { if (!IsOnline()) { - return 1; + return -1; // ??? } char *reason = lParam ? (char*)lParam : " "; size_t length = mir_strlen(reason); ToxBinAddress address(ptrA(getStringA(hContact, TOX_SETTINGS_ID))); - int32_t friendNumber = tox_add_friend(tox, address, (uint8_t*)reason, length); - if (friendNumber <= TOX_ERROR) + TOX_ERR_FRIEND_ADD addFriendResult; + int32_t friendNumber = tox_friend_add(tox, address, (uint8_t*)reason, length, &addFriendResult); + if (addFriendResult != TOX_ERR_FRIEND_ADD_OK) { - debugLogA("CToxProto::OnRequestAuth: failed to request auth"); - return 2; + debugLogA(__FUNCTION__": failed to request auth (%d)", addFriendResult); + return addFriendResult; } // trim address to public key @@ -175,9 +182,12 @@ INT_PTR CToxProto::OnRequestAuth(WPARAM hContact, LPARAM lParam) db_unset(hContact, "CList", "NotOnList"); delSetting(hContact, "Grant"); - std::string nick("", TOX_MAX_NAME_LENGTH); - tox_get_name(tox, friendNumber, (uint8_t*)&nick[0]); - setString(hContact, "Nick", nick.c_str()); + uint8_t nick[TOX_MAX_NAME_LENGTH] = { 0 }; + TOX_ERR_FRIEND_QUERY errorFriendQuery; + if (tox_friend_get_name(tox, friendNumber, nick, &errorFriendQuery)) + setWString(hContact, "Nick", ptrT(mir_utf8decodeW((char*)nick))); + else + debugLogA(__FUNCTION__": failed to get friend name (%d)", errorFriendQuery); return 0; } @@ -186,14 +196,16 @@ INT_PTR CToxProto::OnGrantAuth(WPARAM hContact, LPARAM) { if (!IsOnline()) { - return 1; + return -1; } - ToxBinAddress pubKey(ptrA(getStringA(hContact, TOX_SETTINGS_ID)), TOX_CLIENT_ID_SIZE * 2); - if (tox_add_friend_norequest(tox, pubKey) == TOX_ERROR) + ToxBinAddress pubKey(ptrA(getStringA(hContact, TOX_SETTINGS_ID)), TOX_PUBLIC_KEY_SIZE * 2); + TOX_ERR_FRIEND_ADD error; + tox_friend_add_norequest(tox, pubKey, &error); + if (error != TOX_ERR_FRIEND_ADD_OK) { - debugLogA("CToxProto::OnGrantAuth: failed to grant auth"); - return 2; + debugLogA(__FUNCTION__": failed to grant auth (%d)", error); + return error; } // trim address to public key @@ -204,15 +216,16 @@ INT_PTR CToxProto::OnGrantAuth(WPARAM hContact, LPARAM) return 0; } -void CToxProto::OnFriendRequest(Tox *, const uint8_t *data, const uint8_t *message, const uint16_t messageSize, void *arg) +void CToxProto::OnFriendRequest(Tox*, const uint8_t *pubKey, const uint8_t *message, size_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; - ToxHexAddress address(data, TOX_FRIEND_ADDRESS_SIZE); + ToxHexAddress address(pubKey, TOX_ADDRESS_SIZE); MCONTACT hContact = proto->AddContact(address, _T("")); if (!hContact) { - proto->debugLogA("CToxProto::OnFriendRequest: failed to create contact"); + proto->debugLogA(__FUNCTION__": failed to create contact"); + return; } proto->delSetting(hContact, "Auth"); @@ -220,7 +233,7 @@ void CToxProto::OnFriendRequest(Tox *, const uint8_t *data, const uint8_t *messa PROTORECVEVENT pre = { 0 }; pre.flags = PREF_UTF; pre.timestamp = time(NULL); - pre.lParam = (DWORD)(sizeof(DWORD) * 2 + address.GetLength() + messageSize + 5); + pre.lParam = (DWORD)(sizeof(DWORD) * 2 + address.GetLength() + length + 5); /*blob is: 0(DWORD), hContact(DWORD), nick(ASCIIZ), firstName(ASCIIZ), lastName(ASCIIZ), id(ASCIIZ), reason(ASCIIZ)*/ PBYTE pBlob, pCurBlob; @@ -239,71 +252,120 @@ void CToxProto::OnFriendRequest(Tox *, const uint8_t *data, const uint8_t *messa ProtoChainRecv(hContact, PSR_AUTH, 0, (LPARAM)&pre); } -void CToxProto::OnFriendNameChange(Tox *, const int friendNumber, const uint8_t *name, const uint16_t, void *arg) +void CToxProto::OnFriendNameChange(Tox*, uint32_t friendNumber, const uint8_t *name, size_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->GetContact(friendNumber); - if (hContact) + if (MCONTACT hContact = proto->GetContact(friendNumber)) { - proto->setString(hContact, "Nick", (char*)name); + ptrA rawName((char*)mir_alloc(length + 1)); + memcpy(rawName, name, length); + rawName[length] = 0; + + ptrT nickname(mir_utf8decodeW(rawName)); + proto->setTString(hContact, "Nick", nickname); } } -void CToxProto::OnStatusMessageChanged(Tox *, const int friendNumber, const uint8_t* message, const uint16_t, void *arg) +void CToxProto::OnStatusMessageChanged(Tox*, uint32_t friendNumber, const uint8_t *message, size_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->GetContact(friendNumber); - if (hContact) + if (MCONTACT hContact = proto->GetContact(friendNumber)) { - ptrW statusMessage(mir_utf8decodeW((char*)message)); - db_set_ws(hContact, "CList", "StatusMsg", statusMessage); + ptrA rawMessage((char*)mir_alloc(length + 1)); + memcpy(rawMessage, message, length); + rawMessage[length] = 0; + + ptrT statusMessage(mir_utf8decodeT(rawMessage)); + db_set_ts(hContact, "CList", "StatusMsg", statusMessage); } } -void CToxProto::OnUserStatusChanged(Tox *, int32_t friendNumber, uint8_t usertatus, void *arg) +void CToxProto::OnUserStatusChanged(Tox*, uint32_t friendNumber, TOX_USER_STATUS userstatus, void *arg) { CToxProto *proto = (CToxProto*)arg; MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { - TOX_USERSTATUS userstatus = (TOX_USERSTATUS)usertatus; int status = proto->ToxToMirandaStatus(userstatus); proto->SetContactStatus(hContact, status); } } -void CToxProto::OnConnectionStatusChanged(Tox *tox, const int friendNumber, const uint8_t status, void *arg) +void CToxProto::OnConnectionStatusChanged(Tox*, uint32_t friendNumber, TOX_CONNECTION status, void *arg) { CToxProto *proto = (CToxProto*)arg; MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { - int newStatus = status ? ID_STATUS_ONLINE : ID_STATUS_OFFLINE; - proto->SetContactStatus(hContact, newStatus); - if (status) + if (status != TOX_CONNECTION_NONE) { - tox_send_avatar_info(proto->tox, friendNumber); + proto->SetContactStatus(hContact, ID_STATUS_OFFLINE); + proto->delSetting(hContact, "Auth"); proto->delSetting(hContact, "Grant"); + // resume transfers for (size_t i = 0; i < proto->transfers.Count(); i++) { // only for receiving FileTransferParam *transfer = proto->transfers.GetAt(i); if (transfer->friendNumber == friendNumber && transfer->GetDirection() == 1) { - proto->debugLogA("CToxProto::OnConnectionStatusChanged: sending ask to resume the transfer of file (%d)", transfer->fileNumber); + proto->debugLogA(__FUNCTION__": sending ask to resume the transfer of file (%d)", transfer->fileNumber); transfer->status = STARTED; - if (tox_file_send_control(tox, friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_RESUME_BROKEN, (uint8_t*)&transfer->pfts.currentFileProgress, sizeof(transfer->pfts.currentFileProgress)) == TOX_ERROR) + TOX_ERR_FILE_CONTROL error; + if (!tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) { - tox_file_send_control(tox, friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + proto->debugLogA(__FUNCTION__": failed to resume the transfer (%d)", error); + tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, NULL); } } } + + // update avatar + std::tstring avatarPath = proto->GetAvatarFilePath(); + if (IsFileExists(avatarPath)) + { + FILE *hFile = _tfopen(avatarPath.c_str(), L"rb"); + if (!hFile) + { + proto->debugLogA(__FUNCTION__": failed to open avatar file"); + return; + } + + fseek(hFile, 0, SEEK_END); + size_t length = ftell(hFile); + rewind(hFile); + + uint8_t hash[TOX_HASH_LENGTH]; + DBVARIANT dbv; + if (!db_get(NULL, proto->m_szModuleName, TOX_SETTINGS_AVATAR_HASH, &dbv)) + { + memcpy(hash, dbv.pbVal, TOX_HASH_LENGTH); + db_free(&dbv); + } + + TOX_ERR_FILE_SEND error; + uint32_t fileNumber = tox_file_send(proto->tox, friendNumber, TOX_FILE_KIND_AVATAR, length, NULL, hash, TOX_HASH_LENGTH, &error); + if (error != TOX_ERR_FILE_SEND_OK) + { + proto->debugLogA(__FUNCTION__": failed to set new avatar"); + return; + } + + FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, _T("avatar"), length); + transfer->pfts.hContact = hContact; + transfer->pfts.flags |= PFTS_SENDING; + //transfer->pfts.tszWorkingDir = fileDir; + transfer->hFile = hFile; + proto->transfers.Add(transfer); + } + else + tox_file_send(proto->tox, NULL, TOX_FILE_KIND_AVATAR, 0, NULL, NULL, 0, NULL); } else { @@ -313,9 +375,7 @@ void CToxProto::OnConnectionStatusChanged(Tox *tox, const int friendNumber, cons { FileTransferParam *transfer = proto->transfers.GetAt(i); if (transfer->friendNumber == friendNumber) - { transfer->status = BROKEN; - } } } } diff --git a/protocols/Tox/src/tox_core.cpp b/protocols/Tox/src/tox_core.cpp index 5e1eae29d1..6ca63506b0 100644 --- a/protocols/Tox/src/tox_core.cpp +++ b/protocols/Tox/src/tox_core.cpp @@ -1,17 +1,18 @@ #include "common.h" -bool CToxProto::IsToxCoreInited() -{ - return tox != NULL; -} - bool CToxProto::InitToxCore() { - debugLogA("CToxProto::InitToxCore: initializing tox core"); + debugLogA(__FUNCTION__": initializing tox core"); - Tox_Options options = { 0 }; - options.udp_disabled = getBool("DisableUDP", 0); - options.ipv6enabled = !getBool("DisableIPv6", 0); + TOX_ERR_OPTIONS_NEW error; + Tox_Options *options = tox_options_new(&error); + if (error != TOX_ERR_OPTIONS_NEW::TOX_ERR_OPTIONS_NEW_OK) + { + debugLogA(__FUNCTION__": failed to initialize tox options (%d)", error); + return false; + } + options->udp_enabled = getBool("EnableUDP", 1); + options->ipv6_enabled = getBool("EnableIPv6", 0); if (hNetlib != NULL) { @@ -23,114 +24,91 @@ bool CToxProto::InitToxCore() if (nlus.proxyType == PROXYTYPE_HTTP || nlus.proxyType == PROXYTYPE_HTTPS) { debugLogA("CToxProto::InitToxCore: setting http user proxy config"); - options.proxy_type = TOX_PROXY_HTTP; - strcpy(&options.proxy_address[0], nlus.szProxyServer); - options.proxy_port = nlus.wProxyPort; + options->proxy_type = TOX_PROXY_TYPE_HTTP; + mir_strcpy((char*)&options->proxy_host[0], nlus.szProxyServer); + options->proxy_port = nlus.wProxyPort; } if (nlus.proxyType == PROXYTYPE_SOCKS4 || nlus.proxyType == PROXYTYPE_SOCKS5) { debugLogA("CToxProto::InitToxCore: setting socks user proxy config"); - options.proxy_type = TOX_PROXY_SOCKS5; - strcpy(&options.proxy_address[0], nlus.szProxyServer); - options.proxy_port = nlus.wProxyPort; + options->proxy_type = TOX_PROXY_TYPE_SOCKS5; + mir_strcpy((char*)&options->proxy_host[0], nlus.szProxyServer); + options->proxy_port = nlus.wProxyPort; } } } debugLogA("CToxProto::InitToxCore: loading tox profile"); - tox = tox_new(&options); - password = mir_utf8encodeW(ptrT(getTStringA("Password"))); - bool isProfileLoaded = LoadToxProfile(); - if (isProfileLoaded) + if (LoadToxProfile(options)) { - debugLogA("CToxProto::InitToxCore: tox profile load successfully"); - tox_callback_friend_request(tox, OnFriendRequest, this); tox_callback_friend_message(tox, OnFriendMessage, this); - tox_callback_friend_action(tox, OnFriendAction, this); - tox_callback_typing_change(tox, OnTypingChanged, this); - tox_callback_name_change(tox, OnFriendNameChange, this); - tox_callback_status_message(tox, OnStatusMessageChanged, this); - tox_callback_user_status(tox, OnUserStatusChanged, this); - tox_callback_read_receipt(tox, OnReadReceipt, this); - tox_callback_connection_status(tox, OnConnectionStatusChanged, this); + tox_callback_friend_read_receipt(tox, OnReadReceipt, this); + tox_callback_friend_typing(tox, OnTypingChanged, this); + tox_callback_friend_name(tox, OnFriendNameChange, this); + tox_callback_friend_status_message(tox, OnStatusMessageChanged, this); + tox_callback_friend_status(tox, OnUserStatusChanged, this); + tox_callback_friend_connection_status(tox, OnConnectionStatusChanged, this); // file transfers - tox_callback_file_control(tox, OnFileRequest, this); - tox_callback_file_send_request(tox, OnFriendFile, this); - tox_callback_file_data(tox, OnFileData, this); - // avatars - tox_callback_avatar_info(tox, OnGotFriendAvatarInfo, this); - tox_callback_avatar_data(tox, OnGotFriendAvatarData, this); + tox_callback_file_recv_control(tox, OnFileRequest, this); + tox_callback_file_recv(tox, OnFriendFile, this); + tox_callback_file_recv_chunk(tox, OnFileReceiveData, this); + tox_callback_file_chunk_request(tox, OnFileSendData, this); // group chats - tox_callback_group_invite(tox, OnGroupChatInvite, this); + //tox_callback_group_invite(tox, OnGroupChatInvite, this); - uint8_t data[TOX_FRIEND_ADDRESS_SIZE]; - tox_get_address(tox, data); - ToxHexAddress address(data, TOX_FRIEND_ADDRESS_SIZE); + uint8_t data[TOX_ADDRESS_SIZE]; + tox_self_get_address(tox, data); + ToxHexAddress address(data, TOX_ADDRESS_SIZE); setString(TOX_SETTINGS_ID, address); - int size = tox_get_self_name_size(tox); - std::string nick(size, 0); - tox_get_self_name(tox, (uint8_t*)nick.data()); - setWString("Nick", ptrW(Utf8DecodeW(nick.c_str()))); + uint8_t nick[TOX_MAX_NAME_LENGTH] = { 0 }; + tox_self_get_name(tox, nick); + setWString("Nick", ptrW(Utf8DecodeW((char*)nick))); - //temporary - size = tox_get_self_status_message_size(tox); - std::string statusmes(size, 0); - tox_get_self_status_message(tox, (uint8_t*)statusmes.data(), size); - setWString("StatusMsg", ptrW(Utf8DecodeW(statusmes.c_str()))); + uint8_t statusMessage[TOX_MAX_STATUS_MESSAGE_LENGTH] = { 0 }; + tox_self_get_status_message(tox, statusMessage); + setWString("StatusMsg", ptrW(Utf8DecodeW((char*)statusMessage))); - std::tstring avatarPath = GetAvatarFilePath(); - if (IsFileExists(avatarPath)) - { - SetToxAvatar(avatarPath); - } + return true; } - else - { - debugLogA("CToxProto::InitToxCore: failed to load tox profile"); - if (password != NULL) - { - mir_free(password); - password = NULL; - } - tox_kill(tox); - tox = NULL; - } + tox_options_free(options); - return isProfileLoaded; + return false; } void CToxProto::UninitToxCore() { - for (size_t i = 0; i < transfers.Count(); i++) - { - FileTransferParam *transfer = transfers.GetAt(i); - transfer->status = CANCELED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); - transfers.Remove(transfer); - } + if (tox) { + for (size_t i = 0; i < transfers.Count(); i++) + { + FileTransferParam *transfer = transfers.GetAt(i); + transfer->status = CANCELED; + tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); + ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); + transfers.Remove(transfer); + } - if (IsToxCoreInited()) - { - ptrA nickname(mir_utf8encodeW(ptrT(getTStringA("Nick")))); - tox_set_name(tox, (uint8_t*)(char*)nickname, mir_strlen(nickname)); + //if (IsToxCoreInited()) + //{ + // ptrA nickname(mir_utf8encodeW(ptrT(getTStringA("Nick")))); + // tox_set_name(tox, (uint8_t*)(char*)nickname, mir_strlen(nickname)); - //temporary - ptrA statusmes(mir_utf8encodeW(ptrT(getTStringA("StatusMsg")))); - tox_set_status_message(tox, (uint8_t*)(char*)statusmes, mir_strlen(statusmes)); - } + // //temporary + // ptrA statusmes(mir_utf8encodeW(ptrT(getTStringA("StatusMsg")))); + // tox_set_status_message(tox, (uint8_t*)(char*)statusmes, mir_strlen(statusmes)); + //} - SaveToxProfile(); - if (password != NULL) - { - mir_free(password); - password = NULL; + SaveToxProfile(); + if (password != NULL) + { + mir_free(password); + password = NULL; + } + tox_kill(tox); + tox = NULL; } - tox_kill(tox); - tox = NULL; } \ No newline at end of file diff --git a/protocols/Tox/src/tox_dialogs.h b/protocols/Tox/src/tox_dialogs.h new file mode 100644 index 0000000000..c78c7a8943 --- /dev/null +++ b/protocols/Tox/src/tox_dialogs.h @@ -0,0 +1,21 @@ +#ifndef _TOX_DIALOGS_H_ +#define _TOX_DIALOGS_H_ + +typedef CProtoDlgBase CToxDlgBase; + +class CToxPasswordEditor : public CToxDlgBase +{ +private: + CCtrlEdit password; + CCtrlCheck savePermanently; + + CCtrlButton ok; + +protected: + void OnOk(CCtrlButton*); + +public: + CToxPasswordEditor(CToxProto *proto); +}; + +#endif //_TOX_DIALOGS_H_ \ No newline at end of file diff --git a/protocols/Tox/src/tox_events.cpp b/protocols/Tox/src/tox_events.cpp index fb1ce6ba43..406999549a 100644 --- a/protocols/Tox/src/tox_events.cpp +++ b/protocols/Tox/src/tox_events.cpp @@ -11,18 +11,20 @@ int CToxProto::OnContactDeleted(MCONTACT hContact, LPARAM) { if (!IsOnline()) { - return 1; + return -1; } if (!isChatRoom(hContact)) { int32_t friendNumber = GetToxFriendNumber(hContact); - if (friendNumber == TOX_ERROR || tox_del_friend(tox, friendNumber) == TOX_ERROR) + TOX_ERR_FRIEND_DELETE error; + if (!tox_friend_delete(tox, friendNumber, &error)) { - return 1; + debugLogA(__FUNCTION__": failed to delete friend (%d)", error); + return error; } } - else + /*else { OnLeaveChatRoom(hContact, 0); int groupNumber = 0; // ??? @@ -30,7 +32,7 @@ int CToxProto::OnContactDeleted(MCONTACT hContact, LPARAM) { return 1; } - } + }*/ return 0; } \ No newline at end of file diff --git a/protocols/Tox/src/tox_menus.cpp b/protocols/Tox/src/tox_menus.cpp index 22398b3a01..9b6cc1b875 100644 --- a/protocols/Tox/src/tox_menus.cpp +++ b/protocols/Tox/src/tox_menus.cpp @@ -29,9 +29,7 @@ int CToxProto::OnPrebuildContactMenu(WPARAM hContact, LPARAM) int CToxProto::PrebuildContactMenu(WPARAM hContact, LPARAM lParam) { for (int i = 0; i < SIZEOF(ContactMenuItems); i++) - { - Menu_ShowItem(ContactMenuItems[i], false); - } + Menu_ShowItem(ContactMenuItems[i], FALSE); CToxProto *proto = CToxProto::GetContactAccount(hContact); return proto ? proto->OnPrebuildContactMenu(hContact, lParam) : 0; } @@ -103,13 +101,14 @@ int CToxProto::OnInitStatusMenu() mi.position = SMI_POSITION + SMI_TOXID_COPY; Menu_AddProtoMenuItem(&mi); + // Create group chat command /*mir_strcpy(tDest, "/CreateChatRoom"); CreateProtoService(tDest, &CToxProto::OnCreateChatRoom); mi.ptszName = LPGENT("Create group chat"); mi.position = SMI_POSITION + SMI_GROUPCHAT_CREATE; mi.icolibItem = GetSkinIconHandle("conference"); - Menu_AddProtoMenuItem(&mi);*/ + HGENMENU hCreateChatRoom = Menu_AddProtoMenuItem(&mi);*/ return 0; } \ No newline at end of file diff --git a/protocols/Tox/src/tox_menus.h b/protocols/Tox/src/tox_menus.h index e75f9c8b45..bd3308afdd 100644 --- a/protocols/Tox/src/tox_menus.h +++ b/protocols/Tox/src/tox_menus.h @@ -2,12 +2,14 @@ #define _TOX_MENUS_H_ #define CMI_POSITION -201001000 -#define CMI_AUTH_REQUEST 1 -#define CMI_AUTH_GRANT 2 -#define CMI_MAX 3 // this item shall be the last one + +#define CMI_AUTH_REQUEST 0 +#define CMI_AUTH_GRANT 1 +#define CMI_MAX 2 // this item shall be the last one #define SMI_POSITION 200000 -#define SMI_TOXID_COPY 1 -#define SMI_GROUPCHAT_CREATE 2 + +#define SMI_TOXID_COPY 0 +#define SMI_GROUPCHAT_CREATE 1 #endif //_TOX_MENUS_H_ \ No newline at end of file diff --git a/protocols/Tox/src/tox_messages.cpp b/protocols/Tox/src/tox_messages.cpp index 13d0adffcd..a73aec2f7c 100644 --- a/protocols/Tox/src/tox_messages.cpp +++ b/protocols/Tox/src/tox_messages.cpp @@ -3,42 +3,23 @@ /* MESSAGE RECEIVING */ // incoming message flow -void CToxProto::OnFriendMessage(Tox*, const int friendNumber, const uint8_t *message, const uint16_t messageSize, void *arg) +void CToxProto::OnFriendMessage(Tox*, uint32_t friendNumber, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { - ptrA szMessage((char*)mir_alloc(messageSize + 1)); - mir_strncpy(szMessage, (const char*)message, messageSize + 1); + std::string test((char*)message); + ptrA szMessage((char*)mir_alloc(length + 1)); + mir_strncpy(szMessage, (const char*)message, length); PROTORECVEVENT recv = { 0 }; recv.flags = PREF_UTF; recv.timestamp = time(NULL); recv.szMessage = szMessage; - recv.lParam = EVENTTYPE_MESSAGE; - - ProtoChainRecvMsg(hContact, &recv); - } -} - -// incoming action flow -void CToxProto::OnFriendAction(Tox*, const int friendNumber, const uint8_t *action, const uint16_t actionSize, void *arg) -{ - CToxProto *proto = (CToxProto*)arg; - - MCONTACT hContact = proto->GetContact(friendNumber); - if (hContact) - { - ptrA szMessage((char*)mir_alloc(actionSize + 1)); - mir_strncpy(szMessage, (const char*)action, actionSize + 1); - - PROTORECVEVENT recv = { 0 }; - recv.flags = PREF_UTF; - recv.timestamp = time(NULL); - recv.szMessage = szMessage; - recv.lParam = TOX_DB_EVENT_TYPE_ACTION; + recv.lParam = type == TOX_MESSAGE_TYPE_NORMAL + ? EVENTTYPE_MESSAGE : TOX_DB_EVENT_TYPE_ACTION; ProtoChainRecvMsg(hContact, &recv); } @@ -68,62 +49,51 @@ int CToxProto::OnReceiveMessage(MCONTACT hContact, PROTORECVEVENT *pre) int CToxProto::OnSendMessage(MCONTACT hContact, int flags, const char *szMessage) { int32_t friendNumber = GetToxFriendNumber(hContact); - if (friendNumber == TOX_ERROR) - { + if (friendNumber == UINT32_MAX) return 0; - } ptrA message; if (flags & PREF_UNICODE) - { message = mir_utf8encodeW((wchar_t*)&szMessage[mir_strlen(szMessage) + 1]); - } else if (flags & PREF_UTF) - { message = mir_strdup(szMessage); - } else - { message = mir_utf8encode(szMessage); - } - int receipt = 0; - if (strncmp(message, "/me ", 4) != 0) - { - receipt = tox_send_message(tox, friendNumber, (uint8_t*)(char*)message, mir_strlen(message)); - } - else + size_t msgLen = mir_strlen(message); + uint8_t *msg = (uint8_t*)(char*)message; + TOX_MESSAGE_TYPE type = TOX_MESSAGE_TYPE_NORMAL; + if (strncmp(message, "/me ", 4) == 0) { - receipt = tox_send_action(tox, friendNumber, (uint8_t*)&message[4], mir_strlen(message) - 4); + msg += 4; msgLen -= 4; + type = TOX_MESSAGE_TYPE_ACTION; } - if (receipt == TOX_ERROR) + TOX_ERR_FRIEND_SEND_MESSAGE error; + int messageId = tox_friend_send_message(tox, friendNumber, type, msg, msgLen, &error); + if (error != TOX_ERR_FRIEND_SEND_MESSAGE_OK) { - debugLogA("CToxProto::OnSendMessage: failed to send message"); + debugLogA(__FUNCTION__": failed to send message (%d)", error); } - return receipt; + return messageId; } // message is received by the other side -void CToxProto::OnReadReceipt(Tox*, int32_t friendNumber, uint32_t receipt, void *arg) +void CToxProto::OnReadReceipt(Tox*, uint32_t friendNumber, uint32_t messageId, void *arg) { CToxProto *proto = (CToxProto*)arg; MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) - { proto->ProtoBroadcastAck( - hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)receipt, 0); - } + hContact, ACKTYPE_MESSAGE, ACKRESULT_SUCCESS, (HANDLE)messageId, 0); } // preparing message/action to writing into db int CToxProto::OnPreCreateMessage(WPARAM, LPARAM lParam) { MessageWindowEvent *evt = (MessageWindowEvent*)lParam; - if (strcmp(GetContactProto(evt->hContact), m_szModuleName)) - { + if (mir_strcmp(GetContactProto(evt->hContact), m_szModuleName)) return 0; - } char *message = (char*)evt->dbei->pBlob; if (strncmp(message, "/me ", 4) == 0) @@ -141,28 +111,26 @@ int CToxProto::OnPreCreateMessage(WPARAM, LPARAM lParam) /* TYPING */ -void CToxProto::OnTypingChanged(Tox*, const int number, uint8_t isTyping, void *arg) +int CToxProto::OnUserIsTyping(MCONTACT hContact, int type) { - CToxProto *proto = (CToxProto*)arg; + int32_t friendNumber = GetToxFriendNumber(hContact); + if (friendNumber == UINT32_MAX) + return 0; + + TOX_ERR_SET_TYPING error; + if (!tox_self_set_typing(tox, friendNumber, type == PROTOTYPE_SELFTYPING_ON, &error)) + debugLogA(__FUNCTION__": failed to send typing (%d)", error); - MCONTACT hContact = proto->GetContact(number); - if (hContact) - { - CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)isTyping); - } + return 0; } -int CToxProto::UserIsTyping(MCONTACT hContact, int type) +void CToxProto::OnTypingChanged(Tox*, uint32_t friendNumber, bool isTyping, void *arg) { - if (hContact && IsOnline()) + CToxProto *proto = (CToxProto*)arg; + + if (MCONTACT hContact = proto->GetContact(friendNumber)) { - int32_t friendNumber = GetToxFriendNumber(hContact); - if (friendNumber >= 0) - { - tox_set_user_is_typing(tox, friendNumber, type); - return 0; - } + int typingStatus = (isTyping ? PROTOTYPE_CONTACTTYPING_INFINITE : PROTOTYPE_CONTACTTYPING_OFF); + CallService(MS_PROTO_CONTACTISTYPING, hContact, (LPARAM)typingStatus); } - - return 1; } \ No newline at end of file diff --git a/protocols/Tox/src/tox_network.cpp b/protocols/Tox/src/tox_network.cpp index 86ba7fff37..29e261e0cd 100644 --- a/protocols/Tox/src/tox_network.cpp +++ b/protocols/Tox/src/tox_network.cpp @@ -7,9 +7,10 @@ bool CToxProto::IsOnline() void CToxProto::BootstrapNode(const char *address, int port, const uint8_t *pubKey) { - if (!tox_bootstrap_from_address(tox, address, port, pubKey)) + TOX_ERR_BOOTSTRAP error; + if (!tox_bootstrap(tox, address, port, pubKey, &error)) { - debugLogA("CToxProto::BootstrapNode: failed to bootstrap node %s:%d (%s)", address, port, (const char*)ToxHexAddress(pubKey)); + debugLogA("CToxProto::BootstrapNode: failed to bootstrap node %s:%d \"%s\" (%d)", address, port, (const char*)ToxHexAddress(pubKey), error); } } @@ -74,31 +75,31 @@ void CToxProto::BootstrapNodesFromIni(bool isIPv6) void CToxProto::BootstrapNodes() { - debugLogA("CToxProto::BootstrapDht: bootstraping DHT"); - bool isIPv6 = !getBool("DisableIPv6", 0); + debugLogA(__FUNCTION__": bootstraping DHT"); + bool isIPv6 = getBool("EnableIPv6", 0); BootstrapNodesFromDb(isIPv6); BootstrapNodesFromIni(isIPv6); } void CToxProto::TryConnect() { - if (tox_isconnected(tox)) + if (tox_self_get_connection_status(tox) != TOX_CONNECTION_NONE) { isConnected = true; - debugLogA("CToxProto::PollingThread: successfuly connected to DHT"); + debugLogA(__FUNCTION__": successfuly connected to DHT"); ForkThread(&CToxProto::LoadFriendList, NULL); m_iStatus = m_iDesiredStatus; ProtoBroadcastAck(NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)ID_STATUS_CONNECTING, m_iStatus); - tox_set_user_status(tox, MirandaToToxStatus(m_iStatus)); - debugLogA("CToxProto::PollingThread: changing status from %i to %i", ID_STATUS_CONNECTING, m_iDesiredStatus); + tox_self_set_status(tox, MirandaToToxStatus(m_iStatus)); + debugLogA(__FUNCTION__": changing status from %i to %i", ID_STATUS_CONNECTING, m_iDesiredStatus); } else if (m_iStatus++ > TOX_MAX_CONNECT_RETRIES) { SetStatus(ID_STATUS_OFFLINE); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, LOGINERR_NONETWORK); - debugLogA("CToxProto::PollingThread: failed to connect to DHT"); + debugLogA(__FUNCTION__": failed to connect to DHT"); } } @@ -108,11 +109,11 @@ void CToxProto::CheckConnection(int &retriesCount) { TryConnect(); } - else if (tox_isconnected(tox)) + else if (tox_self_get_connection_status(tox) != TOX_CONNECTION_NONE) { if (retriesCount < TOX_MAX_DISCONNECT_RETRIES) { - debugLogA("CToxProto::CheckConnection: restored connection with DHT"); + debugLogA(__FUNCTION__": restored connection with DHT"); retriesCount = TOX_MAX_DISCONNECT_RETRIES; } } @@ -121,7 +122,7 @@ void CToxProto::CheckConnection(int &retriesCount) if (retriesCount == TOX_MAX_DISCONNECT_RETRIES) { retriesCount--; - debugLogA("CToxProto::CheckConnection: lost connection with DHT"); + debugLogA(__FUNCTION__": lost connection with DHT"); } else if (retriesCount % 50 == 0) { @@ -131,7 +132,7 @@ void CToxProto::CheckConnection(int &retriesCount) else if (!(--retriesCount)) { isConnected = false; - debugLogA("CToxProto::CheckConnection: disconnected from DHT"); + debugLogA(__FUNCTION__": disconnected from DHT"); SetStatus(ID_STATUS_OFFLINE); } } @@ -141,21 +142,21 @@ void CToxProto::DoTox() { { mir_cslock lock(toxLock); - tox_do(tox); + tox_iterate(tox); } - uint32_t interval = tox_do_interval(tox); + uint32_t interval = tox_iteration_interval(tox); Sleep(interval); } void CToxProto::PollingThread(void*) { - debugLogA("CToxProto::PollingThread: entering"); + debugLogA(__FUNCTION__": entering"); if (!InitToxCore()) { SetStatus(ID_STATUS_OFFLINE); ProtoBroadcastAck(NULL, ACKTYPE_LOGIN, ACKRESULT_FAILED, (HANDLE)NULL, LOGINERR_WRONGPASSWORD); - debugLogA("CToxProto::PollingThread: leaving"); + debugLogA(__FUNCTION__": leaving"); return; } @@ -172,5 +173,5 @@ void CToxProto::PollingThread(void*) UninitToxCore(); isConnected = false; - debugLogA("CToxProto::PollingThread: leaving"); + debugLogA(__FUNCTION__": leaving"); } \ No newline at end of file diff --git a/protocols/Tox/src/tox_options.cpp b/protocols/Tox/src/tox_options.cpp index f282c0cbd0..4e7fb3103e 100644 --- a/protocols/Tox/src/tox_options.cpp +++ b/protocols/Tox/src/tox_options.cpp @@ -1,665 +1,476 @@ #include "common.h" -INT_PTR CToxProto::MainOptionsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +CToxOptionsMain::CToxOptionsMain(CToxProto *proto, int idDialog, HWND hwndParent) + : CToxDlgBase(proto, idDialog, hwndParent, false), + m_toxAddress(this, IDC_TOXID), m_toxAddressCopy(this, IDC_CLIPBOARD), + m_profileCreate(this, IDC_PROFILE_NEW), m_profileImport(this, IDC_PROFILE_IMPORT), + m_profileExport(this, IDC_PROFILE_EXPORT), m_nickname(this, IDC_NAME), + m_password(this, IDC_PASSWORD), m_group(this, IDC_GROUP), + m_enableUdp(this, IDC_ENABLE_UDP), m_enableIPv6(this, IDC_ENABLE_IPV6) { - CToxProto *proto = (CToxProto*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + CreateLink(m_toxAddress, TOX_SETTINGS_ID, _T("")); + CreateLink(m_nickname, "Nick", _T("")); + CreateLink(m_password, "Password", _T("")); + CreateLink(m_group, TOX_SETTINGS_GROUP, _T("Tox")); + CreateLink(m_enableUdp, "EnableUDP", DBVT_BYTE, TRUE); + CreateLink(m_enableIPv6, "EnableIPv6", DBVT_BYTE, FALSE); + + m_toxAddressCopy.OnClick = Callback(this, &CToxOptionsMain::ToxAddressCopy_OnClick); + m_profileCreate.OnClick = Callback(this, &CToxOptionsMain::ProfileCreate_OnClick); + m_profileImport.OnClick = Callback(this, &CToxOptionsMain::ProfileImport_OnClick); + m_profileExport.OnClick = Callback(this, &CToxOptionsMain::ProfileExport_OnClick); +} - switch (uMsg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwnd); - { - proto = (CToxProto*)lParam; - SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); +void CToxOptionsMain::OnInitDialog() +{ + CToxDlgBase::OnInitDialog(); - ptrT nick(proto->getTStringA("Nick")); - SetDlgItemText(hwnd, IDC_NAME, nick); + std::tstring profilePath = m_proto->GetToxProfilePath(); + if (CToxProto::IsFileExists(profilePath)) + { + m_toxAddress.Enable(); - ptrT pass(proto->getTStringA("Password")); - SetDlgItemText(hwnd, IDC_PASSWORD, pass); + ShowWindow(m_profileCreate.GetHwnd(), FALSE); + ShowWindow(m_profileImport.GetHwnd(), FALSE); - ptrA address(proto->getStringA(TOX_SETTINGS_ID)); - if (address != NULL) - { - SetDlgItemTextA(hwnd, IDC_TOXID, address); - } + ShowWindow(m_toxAddressCopy.GetHwnd(), TRUE); + //ShowWindow(m_profileExport.GetHwnd(), TRUE); + } - ptrT group(proto->getTStringA(TOX_SETTINGS_GROUP)); - SetDlgItemText(hwnd, IDC_GROUP, group ? group : _T("Tox")); - SendDlgItemMessage(hwnd, IDC_GROUP, EM_LIMITTEXT, 64, 0); + if (m_proto->IsOnline()) + { + EnableWindow(m_nickname.GetHwnd(), TRUE); + EnableWindow(m_password.GetHwnd(), TRUE); + } - CheckDlgButton(hwnd, IDC_DISABLE_UDP, proto->getBool("DisableUDP", 0)); - CheckDlgButton(hwnd, IDC_DISABLE_IPV6, proto->getBool("DisableIPv6", 0)); - if (!proto->IsToxCoreInited()) - { - EnableWindow(GetDlgItem(hwnd, IDC_IMPORT_PROFILE), TRUE); - } - } - return TRUE; + SendMessage(m_toxAddress.GetHwnd(), EM_LIMITTEXT, TOX_ADDRESS_SIZE * 2, 0); + SendMessage(m_nickname.GetHwnd(), EM_LIMITTEXT, TOX_MAX_NAME_LENGTH, 0); + SendMessage(m_password.GetHwnd(), EM_LIMITTEXT, 32, 0); + SendMessage(m_group.GetHwnd(), EM_LIMITTEXT, 64, 0); +} - case WM_COMMAND: +void CToxOptionsMain::ToxAddressCopy_OnClick(CCtrlButton*) +{ + char *toxAddress = m_toxAddress.GetTextA(); + int toxAddressLength = mir_strlen(toxAddress) + 1; + if (OpenClipboard(m_toxAddress.GetHwnd())) { - switch (LOWORD(wParam)) - { - case IDC_NAME: - case IDC_GROUP: - case IDC_PASSWORD: - if ((HWND)lParam == GetFocus()) - { - if (HIWORD(wParam) != EN_CHANGE) return 0; - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - } - break; + EmptyClipboard(); + HGLOBAL hMemory = GlobalAlloc(GMEM_FIXED, toxAddressLength); + memcpy(GlobalLock(hMemory), toxAddress, toxAddressLength); + GlobalUnlock(hMemory); + SetClipboardData(CF_TEXT, hMemory); + CloseClipboard(); + } +} - case IDC_DISABLE_UDP: - case IDC_DISABLE_IPV6: - SendMessage(GetParent(hwnd), PSM_CHANGED, 0, 0); - break; +void CToxOptionsMain::ProfileCreate_OnClick(CCtrlButton*) +{ + if (m_proto->InitToxCore()) + { + TCHAR *group = m_group.GetText(); + if (mir_tstrlen(group) > 0 && Clist_GroupExists(group)) + Clist_CreateGroup(0, group); - case IDC_CLIPBOARD: - { - char toxId[TOX_FRIEND_ADDRESS_SIZE * 2 + 1]; - GetDlgItemTextA(hwnd, IDC_TOXID, toxId, SIZEOF(toxId)); - if (OpenClipboard(GetDlgItem(hwnd, IDC_TOXID))) - { - EmptyClipboard(); - HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, sizeof(toxId)); - memcpy(GlobalLock(hMem), toxId, sizeof(toxId)); - GlobalUnlock(hMem); - SetClipboardData(CF_TEXT, hMem); - CloseClipboard(); - } - } - break; + m_proto->LoadFriendList(NULL); + m_proto->UninitToxCore(); - case IDC_IMPORT_PROFILE: - { - TCHAR filter[MAX_PATH]; - mir_sntprintf(filter, SIZEOF(filter), _T("%s(*.tox)%c*.tox%c%s(*.*)%c*.*%c%c"), - TranslateT("Tox profile"), 0, 0, TranslateT("All files"), 0, 0, 0); - - TCHAR profilePath[MAX_PATH] = { 0 }; - - OPENFILENAME ofn = { sizeof(ofn) }; - ofn.hwndOwner = hwnd; - ofn.lpstrFilter = filter; - ofn.nFilterIndex = 1; - ofn.lpstrFile = profilePath; - ofn.lpstrTitle = TranslateT("Select tox profile"); - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER; - ofn.lpstrInitialDir = _T("%APPDATA%\\Tox"); - - if (GetOpenFileName(&ofn)) - { - if (!proto->IsToxCoreInited()) - { - std::tstring defaultProfilePath = GetToxProfilePath(proto->accountName); - if (CToxProto::IsFileExists(defaultProfilePath.c_str())) - { - if (MessageBox( - hwnd, - TranslateT("You have existing profile. Do you want remove it with all tox contacts and history and continue import?"), - TranslateT("Tox profile import"), - MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2) == IDYES) - { - while (MCONTACT hContact = db_find_first(proto->m_szModuleName)) - { - CallService(MS_DB_CONTACT_DELETE, hContact, 0); - } - } - else break; - } - if (profilePath && _tcslen(profilePath)) - { - if (_tcsicmp(profilePath, defaultProfilePath.c_str()) != 0) - { - CopyFile(profilePath, defaultProfilePath.c_str(), FALSE); - } - } - - if (proto->InitToxCore()) - { - TCHAR group[64]; - GetDlgItemText(hwnd, IDC_GROUP, group, SIZEOF(group)); - if (_tcslen(group) > 0) - { - proto->setTString(TOX_SETTINGS_GROUP, group); - Clist_CreateGroup(0, group); - } - else - { - proto->delSetting(TOX_SETTINGS_GROUP); - } - proto->LoadFriendList(NULL); - proto->UninitToxCore(); - - ptrT nick(proto->getTStringA("Nick")); - SetDlgItemText(hwnd, IDC_NAME, nick); - - ptrT pass(proto->getTStringA("Password")); - SetDlgItemText(hwnd, IDC_PASSWORD, pass); - - ptrA address(proto->getStringA(TOX_SETTINGS_ID)); - if (address != NULL) - { - SetDlgItemTextA(hwnd, IDC_TOXID, address); - } - } - } - } - } - break; - } - } - break; + m_toxAddress.Enable(); + m_toxAddress.SetTextA(ptrA(m_proto->getStringA(TOX_SETTINGS_ID))); - case WM_NOTIFY: - if (reinterpret_cast(lParam)->code == PSN_APPLY) - { - TCHAR nick[TOX_MAX_NAME_LENGTH]; - GetDlgItemText(hwnd, IDC_NAME, nick, TOX_MAX_NAME_LENGTH); - CallProtoService(proto->m_szModuleName, PS_SETMYNICKNAME, SMNN_TCHAR, (LPARAM)nick); - - TCHAR password[MAX_PATH]; - GetDlgItemText(hwnd, IDC_PASSWORD, password, SIZEOF(password)); - proto->setTString("Password", password); - if (proto->password != NULL) - { - mir_free(proto->password); - proto->password = NULL; - } - proto->password = mir_utf8encodeW(password); + m_nickname.SetText(ptrT(m_proto->getTStringA("Nick"))); + m_password.SetText(ptrT(m_proto->getTStringA("Password"))); + m_group.SetText(ptrT(m_proto->getTStringA(TOX_SETTINGS_GROUP))); - TCHAR group[64]; - GetDlgItemText(hwnd, IDC_GROUP, group, SIZEOF(group)); - if (_tcslen(group) > 0) - { - proto->setTString(TOX_SETTINGS_GROUP, group); - Clist_CreateGroup(0, group); - } - else - { - proto->delSetting(NULL, TOX_SETTINGS_GROUP); - } + ShowWindow(m_profileCreate.GetHwnd(), FALSE); + ShowWindow(m_profileImport.GetHwnd(), FALSE); - proto->setByte("DisableUDP", (BYTE)IsDlgButtonChecked(hwnd, IDC_DISABLE_UDP)); - proto->setByte("DisableIPv6", (BYTE)IsDlgButtonChecked(hwnd, IDC_DISABLE_IPV6)); + ShowWindow(m_toxAddressCopy.GetHwnd(), TRUE); + //ShowWindow(m_profileExport.GetHwnd(), TRUE); + } +} - if (proto->IsOnline()) - { - //proto->SaveToxProfile(); - } +void CToxOptionsMain::ProfileImport_OnClick(CCtrlButton*) +{ + TCHAR filter[MAX_PATH]; + mir_sntprintf(filter, SIZEOF(filter), _T("%s(*.tox)%c*.tox%c%s(*.*)%c*.*%c%c"), + TranslateT("Tox profile"), 0, 0, TranslateT("All files"), 0, 0, 0); + + TCHAR profilePath[MAX_PATH] = { 0 }; + + OPENFILENAME ofn = { sizeof(ofn) }; + ofn.hwndOwner = m_hwnd; + ofn.lpstrFilter = filter; + ofn.nFilterIndex = 1; + ofn.lpstrFile = profilePath; + ofn.lpstrTitle = TranslateT("Select tox profile"); + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER; + ofn.lpstrInitialDir = _T("%APPDATA%\\Tox"); + + if (!GetOpenFileName(&ofn)) + { + return; + } - return TRUE; - } - break; + std::tstring defaultProfilePath = m_proto->GetToxProfilePath(); + if (_tcsicmp(profilePath, defaultProfilePath.c_str()) != 0) + { + CopyFile(profilePath, defaultProfilePath.c_str(), FALSE); } - return FALSE; + m_profileCreate.OnClick(&m_profileCreate); } -int AddItemToListView(HWND hwndList, UINT mask, int iGroupId, int iItem, int iSubItem, char *pszText, int iImage = -1) +void CToxOptionsMain::ProfileExport_OnClick(CCtrlButton*) { - LVITEMA lvi = { 0 }; - lvi.mask = mask; - lvi.iItem = iItem; - lvi.iSubItem = iSubItem; - lvi.iGroupId = iGroupId; - lvi.iImage = iImage; - lvi.pszText = mir_strdup(pszText); - return SendMessage(hwndList, LVM_INSERTITEMA, 0, (LPARAM)&lvi); } -int SetSubItemToListView(HWND hwndList, UINT mask, int iGroupId, int iItem, int iSubItem, char *pszText, int iImage = -1) +void CToxOptionsMain::OnApply() { - LVITEMA lvi = { 0 }; - lvi.mask = mask; - lvi.iItem = iItem; - lvi.iSubItem = iSubItem; - lvi.iGroupId = iGroupId; - lvi.iImage = iImage; - lvi.pszText = mir_strdup(pszText); - return SendMessage(hwndList, LVM_SETITEMA, 0, (LPARAM)&lvi); + TCHAR *group = m_group.GetText(); + if (mir_tstrlen(group) > 0 && Clist_GroupExists(group)) + Clist_CreateGroup(0, group); + + if (m_proto->IsOnline()) + { + CallProtoService(m_proto->m_szModuleName, PS_SETMYNICKNAME, SMNN_TCHAR, (LPARAM)m_nickname.GetText()); + + if (m_proto->password != NULL) + mir_free(m_proto->password); + m_proto->password = mir_utf8encodeW(ptrT(m_password.GetText())); + + m_proto->SaveToxProfile(); + } +} + +///////////////////////////////////////////////////////////////////////////////// + +CToxNodeEditor::CToxNodeEditor(int iItem, CCtrlListView *m_nodes) + : CSuper(g_hInstance, IDD_NODE_EDITOR, NULL), + m_ipv4(this, IDC_IPV4), m_ipv6(this, IDC_IPV6), + m_port(this, IDC_PORT), m_pkey(this, IDC_PKEY), + m_ok(this, IDOK), m_iItem(iItem) +{ + m_list = m_nodes; + m_ok.OnClick = Callback(this, &CToxNodeEditor::OnOk); } -INT_PTR CALLBACK EditNodeDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) +void CToxNodeEditor::OnInitDialog() { - ItemInfo *itemInfo = (ItemInfo*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + SetWindowText(m_hwnd, m_iItem == -1 ? TranslateT("Add node") : TranslateT("Change node")); - switch (msg) + if (m_iItem > -1) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); - { - itemInfo = (ItemInfo*)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); + LVITEM lvi = { 0 }; + lvi.mask = LVIF_TEXT; + lvi.iItem = m_iItem; + lvi.cchTextMax = MAX_PATH; + lvi.pszText = (TCHAR*)mir_alloc(MAX_PATH * sizeof(TCHAR)); - SendDlgItemMessage(hwndDlg, IDC_IPV4, EM_SETLIMITTEXT, MAX_PATH, 0); - SendDlgItemMessage(hwndDlg, IDC_IPV6, EM_SETLIMITTEXT, 39, 0); - SendDlgItemMessage(hwndDlg, IDC_PORT, EM_SETLIMITTEXT, 5, 0); - SendDlgItemMessage(hwndDlg, IDC_PKEY, EM_SETLIMITTEXT, TOX_PUBLIC_KEY_SIZE * 2, 0); + lvi.iSubItem = 0; + m_list->GetItem(&lvi); + m_ipv4.SetText(lvi.pszText); - if (itemInfo->iItem == -1) - { - SetWindowText(hwndDlg, TranslateT("Add node")); - } - else - { - SetWindowText(hwndDlg, TranslateT("Change node")); + lvi.iSubItem = 1; + m_list->GetItem(&lvi); + m_ipv6.SetText(lvi.pszText); - LVITEMA lvi = { 0 }; - lvi.mask = LVIF_TEXT; - lvi.iItem = itemInfo->iItem; - lvi.cchTextMax = MAX_PATH; - lvi.pszText = (char*)mir_alloc(MAX_PATH); + lvi.iSubItem = 2; + m_list->GetItem(&lvi); + m_port.SetText(lvi.pszText); - lvi.iSubItem = 0; - SendMessage(itemInfo->hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - SetDlgItemTextA(hwndDlg, IDC_IPV4, lvi.pszText); + lvi.iSubItem = 3; + m_list->GetItem(&lvi); + m_pkey.SetText(lvi.pszText); - lvi.iSubItem = 1; - SendMessage(itemInfo->hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); + mir_free(lvi.pszText); + } - SetDlgItemTextA(hwndDlg, IDC_IPV6, lvi.pszText); + Utils_RestoreWindowPositionNoSize(m_hwnd, NULL, MODULE, "EditNodeDlg"); +} - lvi.iSubItem = 2; - SendMessage(itemInfo->hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - SetDlgItemTextA(hwndDlg, IDC_PORT, lvi.pszText); +void CToxNodeEditor::OnOk(CCtrlBase*) +{ + if (!m_ipv4.GetInt()) + { + MessageBox(m_hwnd, TranslateT("Enter IPv4"), TranslateT("Error"), MB_OK); + return; + } + if (!m_pkey.GetInt()) + { + MessageBox(m_hwnd, TranslateT("Enter public key"), TranslateT("Error"), MB_OK); + return; + } - lvi.iSubItem = 3; - SendMessage(itemInfo->hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - SetDlgItemTextA(hwndDlg, IDC_PKEY, lvi.pszText); + ptrT ipv4(m_ipv4.GetText()); + if (m_iItem == -1) + { + m_iItem = m_list->AddItem(ipv4, -1, NULL, 1); + m_list->SetItemState(m_iItem, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); + m_list->EnsureVisible(m_iItem, TRUE); + } + else + m_list->SetItem(m_iItem, 0, ipv4); + m_list->SetItem(m_iItem, 1, ptrT(m_ipv6.GetText())); + m_list->SetItem(m_iItem, 2, ptrT(m_port.GetText())); + m_list->SetItem(m_iItem, 3, ptrT(m_pkey.GetText())); + m_list->SetItem(m_iItem, 4, _T(""), 0); + m_list->SetItem(m_iItem, 5, _T(""), 1); + + EndDialog(m_hwnd, 1); +} - mir_free(lvi.pszText); - } +void CToxNodeEditor::OnClose() +{ + Utils_SaveWindowPosition(m_hwnd, NULL, MODULE, "EditNodeDlg"); +} - Utils_RestoreWindowPositionNoSize(hwndDlg, NULL, MODULE, "EditNodeDlg"); - } +/****************************************/ + +CCtrlNodeList::CCtrlNodeList(CDlgBase* dlg, int ctrlId) + : CCtrlListView(dlg, ctrlId) +{ +} + +BOOL CCtrlNodeList::OnNotify(int idCtrl, NMHDR *pnmh) +{ + if (pnmh->code == NM_CLICK) + { + TEventInfo evt = { this, pnmh }; + OnClick(&evt); return TRUE; + } + return CCtrlListView::OnNotify(idCtrl, pnmh); +} - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: +/****************************************/ + +CToxOptionsNodeList::CToxOptionsNodeList(CToxProto *proto) + : CSuper(proto, IDD_OPTIONS_NODES, NULL, false), + m_nodes(this, IDC_NODESLIST), m_addNode(this, IDC_ADDNODE) +{ + m_addNode.OnClick = Callback(this, &CToxOptionsNodeList::OnAddNode); + m_nodes.OnClick = Callback(this, &CToxOptionsNodeList::OnNodeListClick); + m_nodes.OnDoubleClick = Callback(this, &CToxOptionsNodeList::OnNodeListDoubleClick); + m_nodes.OnKeyDown = Callback(this, &CToxOptionsNodeList::OnNodeListKeyDown); +} + +void CToxOptionsNodeList::OnInitDialog() +{ + m_nodes.SetExtendedListViewStyle(LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP); + + HIMAGELIST hImageList = m_nodes.CreateImageList(LVSIL_SMALL); + HICON icon = LoadSkinnedIcon(SKINICON_OTHER_TYPING); + ImageList_AddIcon(hImageList, icon); Skin_ReleaseIcon(icon); + icon = LoadSkinnedIcon(SKINICON_OTHER_DELETE); + ImageList_AddIcon(hImageList, icon); Skin_ReleaseIcon(icon); + + m_nodes.AddColumn(0, _T("IPv4"), 100); + m_nodes.AddColumn(1, _T("IPv6"), 100); + m_nodes.AddColumn(2, TranslateT("Port"), 50); + m_nodes.AddColumn(3, TranslateT("Public key"), 130); + m_nodes.AddColumn(4, _T(""), 32 - GetSystemMetrics(SM_CXVSCROLL)); + m_nodes.AddColumn(5, _T(""), 32 - GetSystemMetrics(SM_CXVSCROLL)); + + m_nodes.EnableGroupView(TRUE); + m_nodes.AddGroup(0, TranslateT("Common nodes")); + m_nodes.AddGroup(1, TranslateT("User nodes")); + + //////////////////////////////////////// + + int iItem = -1; + + if (CToxProto::IsFileExists((TCHAR*)VARST(_T(TOX_INI_PATH)))) + { + char fileName[MAX_PATH]; + mir_strcpy(fileName, VARS(TOX_INI_PATH)); + + char *section, sections[MAX_PATH], value[MAX_PATH]; + GetPrivateProfileSectionNamesA(sections, SIZEOF(sections), fileName); + section = sections; + while (*section != NULL) { - char value[MAX_PATH]; - if (!GetDlgItemTextA(hwndDlg, IDC_IPV4, value, SIZEOF(value))) - { - MessageBox(hwndDlg, TranslateT("Enter IPv4"), TranslateT("Error"), MB_OK); - break; - } - if (!GetDlgItemTextA(hwndDlg, IDC_PKEY, value, SIZEOF(value))) + if (strstr(section, TOX_SETTINGS_NODE_PREFIX) == section) { - MessageBox(hwndDlg, TranslateT("Enter public key"), TranslateT("Error"), MB_OK); - break; - } + GetPrivateProfileStringA(section, "IPv4", NULL, value, SIZEOF(value), fileName); + iItem = m_nodes.AddItem(mir_a2t(value), -1, NULL, 0); - GetDlgItemTextA(hwndDlg, IDC_IPV4, value, SIZEOF(value)); - int iItem = itemInfo->iItem; - if (iItem == -1) - { - iItem = ListView_GetItemCount(itemInfo->hwndList); - AddItemToListView(itemInfo->hwndList, LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE, 1, iItem, 0, value); - ListView_SetItemState(itemInfo->hwndList, iItem, LVIS_FOCUSED | LVIS_SELECTED, 0x000F); - ListView_EnsureVisible(itemInfo->hwndList, iItem, TRUE); - } - else - { - SetSubItemToListView(itemInfo->hwndList, LVIF_TEXT, 1, iItem, 0, value); + GetPrivateProfileStringA(section, "IPv6", NULL, value, SIZEOF(value), fileName); + m_nodes.SetItem(iItem, 1, mir_a2t(value)); + + GetPrivateProfileStringA(section, "Port", NULL, value, SIZEOF(value), fileName); + m_nodes.SetItem(iItem, 2, mir_a2t(value)); + + GetPrivateProfileStringA(section, "PubKey", NULL, value, SIZEOF(value), fileName); + m_nodes.SetItem(iItem, 3, mir_a2t(value)); } - GetDlgItemTextA(hwndDlg, IDC_IPV6, value, SIZEOF(value)); - SetSubItemToListView(itemInfo->hwndList, LVIF_TEXT, 1, iItem, 1, value); - GetDlgItemTextA(hwndDlg, IDC_PORT, value, SIZEOF(value)); - SetSubItemToListView(itemInfo->hwndList, LVIF_TEXT, 1, iItem, 2, value); - GetDlgItemTextA(hwndDlg, IDC_PKEY, value, SIZEOF(value)); - SetSubItemToListView(itemInfo->hwndList, LVIF_TEXT, 1, iItem, 3, value); - SetSubItemToListView(itemInfo->hwndList, LVIF_IMAGE, 1, iItem, 4, value, 0); - SetSubItemToListView(itemInfo->hwndList, LVIF_IMAGE, 1, iItem, 5, value, 1); - - EndDialog(hwndDlg, IDOK); + section += strlen(section) + 1; } - break; + } + + char module[MAX_PATH], setting[MAX_PATH]; + mir_snprintf(module, SIZEOF(module), "%s_Nodes", m_proto->m_szModuleName); + int nodeCount = db_get_w(NULL, module, TOX_SETTINGS_NODE_COUNT, 0); + for (int i = 0; i < nodeCount; i++) + { + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV4, i); + ptrT value(db_get_tsa(NULL, module, setting)); + iItem = m_nodes.AddItem(value, -1, NULL, 1); + + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV6, i); + value = db_get_tsa(NULL, module, setting); + m_nodes.SetItem(iItem, 1, value); - case IDCANCEL: - EndDialog(hwndDlg, IDCANCEL); - break; + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PORT, i); + int port = db_get_w(NULL, module, setting, 0); + if (port > 0) + { + char portNum[10]; + itoa(port, portNum, 10); + m_nodes.SetItem(iItem, 2, mir_a2t(portNum)); } - break; - case WM_DESTROY: - Utils_SaveWindowPosition(hwndDlg, NULL, MODULE, "EditNodeDlg"); - break; + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PKEY, i); + value = db_get_tsa(NULL, module, setting); + m_nodes.SetItem(iItem, 3, value); + + m_nodes.SetItem(iItem, 4, _T(""), 0); + m_nodes.SetItem(iItem, 5, _T(""), 1); } +} - return FALSE; +void CToxOptionsNodeList::OnAddNode(CCtrlBase*) +{ + CToxNodeEditor nodeEditor(-1, &m_nodes); + if (nodeEditor.DoModal()) + SendMessage(GetParent(m_hwnd), PSM_CHANGED, 0, 0); } -INT_PTR CALLBACK NodeListSubProc(HWND hwndList, UINT uMsg, WPARAM wParam, LPARAM lParam) +void CToxOptionsNodeList::OnNodeListDoubleClick(CCtrlBase*) { - LVITEMA lvi = { 0 }; + int iItem = m_nodes.GetNextItem(-1, LVNI_SELECTED); - switch (uMsg) - { - case WM_INITDIALOG: + LVITEM lvi = { 0 }; + lvi.iItem = iItem; + lvi.mask = LVIF_GROUPID; + m_nodes.GetItem(&lvi); + if (lvi.iGroupId || (lvi.iGroupId == 0 && lvi.iItem == -1)) { - TCHAR *userName = (TCHAR*)lParam; - - HIMAGELIST hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR32, 2, 0); - HICON icon = LoadSkinnedIcon(SKINICON_OTHER_TYPING); - ImageList_AddIcon(hImageList, icon); Skin_ReleaseIcon(icon); - icon = LoadSkinnedIcon(SKINICON_OTHER_DELETE); - ImageList_AddIcon(hImageList, icon); Skin_ReleaseIcon(icon); - ListView_SetImageList(hwndList, hImageList, LVSIL_SMALL); - - LVCOLUMN lvc = { 0 }; - lvc.mask = LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; - - lvc.iOrder = 0; - lvc.pszText = L"IPv4"; - lvc.cx = 100; - ListView_InsertColumn(hwndList, lvc.iOrder, (LPARAM)&lvc); - - lvc.iOrder = 1; - lvc.pszText = L"IPv6"; - lvc.cx = 100; - ListView_InsertColumn(hwndList, lvc.iOrder, (LPARAM)&lvc); - - lvc.iOrder = 2; - lvc.pszText = TranslateT("Port"); - lvc.cx = 50; - ListView_InsertColumn(hwndList, lvc.iOrder, (LPARAM)&lvc); - - lvc.iOrder = 3; - lvc.pszText = TranslateT("Public key"); - lvc.cx = 130; - ListView_InsertColumn(hwndList, lvc.iOrder, (LPARAM)&lvc); - - lvc.iOrder = 4; - lvc.pszText = NULL; - lvc.cx = 32 - GetSystemMetrics(SM_CXVSCROLL); - ListView_InsertColumn(hwndList, lvc.iOrder, (LPARAM)&lvc); - - lvc.iOrder = 5; - lvc.cx = 32 - GetSystemMetrics(SM_CXVSCROLL); - ListView_InsertColumn(hwndList, lvc.iOrder, (LPARAM)&lvc); - - LVGROUP lvg = { sizeof(LVGROUP) }; - lvg.mask = LVGF_HEADER | LVGF_GROUPID; - - lvg.pszHeader = TranslateT("Common nodes"); - lvg.iGroupId = 0; - ListView_InsertGroup(hwndList, lvg.iGroupId, &lvg); - - TCHAR userGroupName[MAX_PATH]; - mir_sntprintf(userGroupName, SIZEOF(userGroupName), _T("%s %s"), userName, TranslateT("nodes")); - lvg.pszHeader = mir_tstrdup(userGroupName); - lvg.iGroupId = 1; - ListView_InsertGroup(hwndList, lvg.iGroupId, &lvg); - - ListView_EnableGroupView(hwndList, TRUE); - - ListView_SetExtendedListViewStyle(hwndList, LVS_EX_SUBITEMIMAGES | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP); - ListView_DeleteAllItems(hwndList); + CToxNodeEditor nodeEditor(lvi.iItem, &m_nodes); + if (nodeEditor.DoModal()) + SendMessage(GetParent(m_hwnd), PSM_CHANGED, 0, 0); } - break; - - case WM_NOTIFY: - switch (((NMHDR*)lParam)->code) - { - case NM_CLICK: - { - lvi.iItem = ((NMITEMACTIVATE*)lParam)->iItem; - lvi.mask = LVIF_GROUPID; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - lvi.iSubItem = ((NMITEMACTIVATE*)lParam)->iSubItem; - if (lvi.iGroupId && lvi.iSubItem == 4) - { - ItemInfo itemInfo = { lvi.iItem, hwndList }; - if (DialogBoxParam( - g_hInstance, - MAKEINTRESOURCE(IDD_ADDNODE), - GetParent(hwndList), EditNodeDlgProc, - (LPARAM)&itemInfo) == IDOK) - { - SendMessage(GetParent(GetParent(hwndList)), PSM_CHANGED, 0, 0); - } - } - else if (lvi.iGroupId && lvi.iSubItem == 5) - { - if (MessageBox(hwndList, TranslateT("Are you sure?"), TranslateT("Node deleting"), MB_YESNO | MB_ICONWARNING) == IDYES) - { - ListView_DeleteItem(hwndList, lvi.iItem); - SendMessage(GetParent(GetParent(hwndList)), PSM_CHANGED, 0, 0); - } - } - } - break; - - case NM_DBLCLK: - { - lvi.iItem = ((NMITEMACTIVATE*)lParam)->iItem; - lvi.mask = LVIF_GROUPID; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - if (lvi.iGroupId || (lvi.iGroupId == 0 && lvi.iItem == -1)) - { - ItemInfo itemInfo = { lvi.iItem, hwndList }; - if (DialogBoxParam( - g_hInstance, - MAKEINTRESOURCE(IDD_ADDNODE), - GetParent(hwndList), EditNodeDlgProc, - (LPARAM)&itemInfo) == IDOK) - { - SendMessage(GetParent(GetParent(hwndList)), PSM_CHANGED, 0, 0); - } - } - } - break; +} - case LVN_KEYDOWN: +void CToxOptionsNodeList::OnNodeListClick(CCtrlListView::TEventInfo *evt) +{ + LVITEM lvi = { 0 }; + lvi.iItem = evt->nmlvia->iItem; + lvi.mask = LVIF_GROUPID; + m_nodes.GetItem(&lvi); + lvi.iSubItem = evt->nmlvia->iSubItem; + if (lvi.iGroupId && lvi.iSubItem == 4) + { + CToxNodeEditor nodeEditor(lvi.iItem, &m_nodes); + if (nodeEditor.DoModal()) + SendMessage(GetParent(GetParent(m_hwnd)), PSM_CHANGED, 0, 0); + } + else if (lvi.iGroupId && lvi.iSubItem == 5) + { + if (MessageBox(m_hwnd, TranslateT("Are you sure?"), TranslateT("Node deleting"), MB_YESNO | MB_ICONWARNING) == IDYES) { - lvi.iItem = ListView_GetSelectionMark(hwndList); - lvi.mask = LVIF_GROUPID; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - if (lvi.iGroupId && lvi.iItem != -1 && ((LPNMLVKEYDOWN)lParam)->wVKey == VK_DELETE) - { - if (MessageBox( - GetParent(hwndList), - TranslateT("Are you sure?"), - TranslateT("Node deleting"), - MB_YESNO | MB_ICONWARNING) == IDYES) - { - ListView_DeleteItem(hwndList, lvi.iItem); - SendMessage(GetParent(GetParent(hwndList)), PSM_CHANGED, 0, 0); - } - } - } - break; + m_nodes.DeleteItem(lvi.iItem); + SendMessage(GetParent(GetParent(m_hwnd)), PSM_CHANGED, 0, 0); } - break; - - default: - return CallWindowProc((WNDPROC)GetClassLongPtr(hwndList, GCLP_WNDPROC), hwndList, uMsg, wParam, lParam); } - return FALSE; } -INT_PTR CALLBACK CToxProto::NodesOptionsProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +void CToxOptionsNodeList::OnNodeListKeyDown(CCtrlListView::TEventInfo *evt) { - CToxProto *proto = (CToxProto*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - HWND hwndList = GetDlgItem(hwndDlg, IDC_NODESLIST); + LVITEM lvi = { 0 }; + lvi.iItem = m_nodes.GetSelectionMark(); + lvi.mask = LVIF_GROUPID; + m_nodes.GetItem(&lvi); - switch (uMsg) + if (lvi.iGroupId && lvi.iItem != -1 && (evt->nmlvkey)->wVKey == VK_DELETE) { - case WM_INITDIALOG: - TranslateDialogDefault(hwndDlg); + if (MessageBox( + GetParent(m_hwnd), + TranslateT("Are you sure?"), + TranslateT("Node deleting"), + MB_YESNO | MB_ICONWARNING) == IDYES) { - proto = (CToxProto*)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam); - - CallWindowProc((WNDPROC)NodeListSubProc, hwndList, WM_INITDIALOG, wParam, (LPARAM)proto->m_tszUserName); + m_nodes.DeleteItem(lvi.iItem); + SendMessage(GetParent(GetParent(m_hwnd)), PSM_CHANGED, 0, 0); + } + } +} - int iItem = 0; +void CToxOptionsNodeList::OnApply() +{ + char setting[MAX_PATH]; - if (IsFileExists((TCHAR*)VARST(_T(TOX_INI_PATH)))) - { - char fileName[MAX_PATH]; - mir_strcpy(fileName, VARS(TOX_INI_PATH)); - - char *section, sections[MAX_PATH], value[MAX_PATH]; - GetPrivateProfileSectionNamesA(sections, SIZEOF(sections), fileName); - section = sections; - while (*section != NULL) - { - if (strstr(section, TOX_SETTINGS_NODE_PREFIX) == section) - { - GetPrivateProfileStringA(section, "IPv4", NULL, value, SIZEOF(value), fileName); - AddItemToListView(hwndList, LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE, 0, iItem, 0, value); - - GetPrivateProfileStringA(section, "IPv6", NULL, value, SIZEOF(value), fileName); - SetSubItemToListView(hwndList, LVIF_TEXT, 0, iItem, 1, value); - - GetPrivateProfileStringA(section, "Port", NULL, value, SIZEOF(value), fileName); - SetSubItemToListView(hwndList, LVIF_TEXT, 0, iItem, 2, value); - - GetPrivateProfileStringA(section, "PubKey", NULL, value, SIZEOF(value), fileName); - SetSubItemToListView(hwndList, LVIF_TEXT, 0, iItem, 3, value); - - iItem++; - } - section += strlen(section) + 1; - } - } + LVITEM lvi = { 0 }; + lvi.cchTextMax = MAX_PATH; + lvi.pszText = (TCHAR*)mir_alloc(MAX_PATH * sizeof(TCHAR)); - char module[MAX_PATH], setting[MAX_PATH]; - mir_snprintf(module, SIZEOF(module), "%s_Nodes", proto->m_szModuleName); - int nodeCount = db_get_w(NULL, module, TOX_SETTINGS_NODE_COUNT, 0); - for (int i = 0; i < nodeCount; i++, iItem++) - { - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV4, i); - ptrA value(db_get_sa(NULL, module, setting)); - AddItemToListView(hwndList, LVIF_GROUPID | LVIF_TEXT | LVIF_IMAGE, 1, iItem, 0, value); - - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV6, i); - value = db_get_sa(NULL, module, setting); - SetSubItemToListView(hwndList, LVIF_TEXT, 1, iItem, 1, value); - - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PORT, i); - int port = db_get_w(NULL, module, setting, 0); - if (port > 0) - { - char portNum[10]; - itoa(port, portNum, 10); - SetSubItemToListView(hwndList, LVIF_TEXT, 1, iItem, 2, portNum); - } - - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PKEY, i); - value = db_get_sa(NULL, module, setting); - SetSubItemToListView(hwndList, LVIF_TEXT, 1, iItem, 3, value); - - SetSubItemToListView(hwndList, LVIF_IMAGE, 1, iItem, 4, value, 0); - SetSubItemToListView(hwndList, LVIF_IMAGE, 1, iItem, 5, value, 1); - } - } - return TRUE; + char module[MAX_PATH]; + mir_snprintf(module, SIZEOF(module), "%s_Nodes", m_proto->m_szModuleName); - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDC_ADDNODE: + int iItem = 0; + int itemCount = m_nodes.GetItemCount(); + for (int i = 0; i < itemCount; i++) + { + lvi.iItem = i; + lvi.mask = LVIF_GROUPID; + m_nodes.GetItem(&lvi); + if (lvi.iGroupId == 0) { - ItemInfo itemInfo = { -1, hwndList }; - if (DialogBoxParam( - g_hInstance, - MAKEINTRESOURCE(IDD_ADDNODE), - GetParent(hwndList), EditNodeDlgProc, - (LPARAM)&itemInfo) == IDOK) - { - SendMessage(GetParent(GetParent(hwndList)), PSM_CHANGED, 0, 0); - } - } + continue; } - break; - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) - { - case NM_CLICK: - case NM_DBLCLK: - case LVN_KEYDOWN: - if (((NMHDR*)lParam)->hwndFrom == hwndList) - { - return CallWindowProc((WNDPROC)NodeListSubProc, hwndList, uMsg, wParam, lParam); - } - break; + lvi.mask = LVIF_TEXT; + lvi.iSubItem = 0; + m_nodes.GetItem(&lvi); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV4, iItem); + db_set_s(NULL, module, setting, _T2A(lvi.pszText)); - case PSN_APPLY: - { - char setting[MAX_PATH]; + lvi.iSubItem = 1; + m_nodes.GetItem(&lvi); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV6, iItem); + db_set_s(NULL, module, setting, _T2A(lvi.pszText)); - LVITEMA lvi = { 0 }; - lvi.cchTextMax = MAX_PATH; - lvi.pszText = (char*)mir_alloc(MAX_PATH); + lvi.iSubItem = 2; + m_nodes.GetItem(&lvi); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PORT, iItem); + db_set_w(NULL, module, setting, _ttoi(lvi.pszText)); - char module[MAX_PATH]; - mir_snprintf(module, SIZEOF(module), "%s_Nodes", proto->m_szModuleName); + lvi.iSubItem = 3; + m_nodes.GetItem(&lvi); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PKEY, iItem); + db_set_s(NULL, module, setting, _T2A(lvi.pszText)); - int iItem = 0; - int itemCount = ListView_GetItemCount(hwndList); - for (int i = 0; i < itemCount; i++) - { - lvi.iItem = i; - lvi.mask = LVIF_GROUPID; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - if (lvi.iGroupId == 0) - { - continue; - } - - lvi.mask = LVIF_TEXT; - lvi.iSubItem = 0; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV4, iItem); - db_set_s(NULL, module, setting, lvi.pszText); - - lvi.iSubItem = 1; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV6, iItem); - db_set_s(NULL, module, setting, lvi.pszText); - - lvi.iSubItem = 2; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PORT, iItem); - db_set_w(NULL, module, setting, atoi(lvi.pszText)); - - lvi.iSubItem = 3; - SendMessage(hwndList, LVM_GETITEMA, 0, (LPARAM)&lvi); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PKEY, iItem); - db_set_s(NULL, module, setting, lvi.pszText); - - iItem++; - } - itemCount = iItem; - int nodeCount = db_get_b(NULL, module, TOX_SETTINGS_NODE_COUNT, 0); - for (iItem = itemCount; iItem < nodeCount; iItem++) - { - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV4, iItem); - db_unset(NULL, module, setting); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV6, iItem); - db_unset(NULL, module, setting); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PORT, iItem); - db_unset(NULL, module, setting); - mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PKEY, iItem); - db_unset(NULL, module, setting); - } - db_set_b(NULL, module, TOX_SETTINGS_NODE_COUNT, itemCount); - } - return TRUE; - } + iItem++; + } + itemCount = iItem; + int nodeCount = db_get_b(NULL, module, TOX_SETTINGS_NODE_COUNT, 0); + for (iItem = itemCount; iItem < nodeCount; iItem++) + { + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV4, iItem); + db_unset(NULL, module, setting); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_IPV6, iItem); + db_unset(NULL, module, setting); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PORT, iItem); + db_unset(NULL, module, setting); + mir_snprintf(setting, SIZEOF(setting), TOX_SETTINGS_NODE_PKEY, iItem); + db_unset(NULL, module, setting); } - return FALSE; + db_set_b(NULL, module, TOX_SETTINGS_NODE_COUNT, itemCount); } +///////////////////////////////////////////////////////////////////////////////// + int CToxProto::OnOptionsInit(WPARAM wParam, LPARAM) { char *title = mir_t2a(m_tszUserName); @@ -667,23 +478,23 @@ int CToxProto::OnOptionsInit(WPARAM wParam, LPARAM) OPTIONSDIALOGPAGE odp = { sizeof(odp) }; odp.hInstance = g_hInstance; odp.pszTitle = title; - odp.dwInitParam = (LPARAM)this; odp.flags = ODPF_BOLDGROUPS; odp.pszGroup = LPGEN("Network"); odp.pszTab = LPGEN("Account"); odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_MAIN); - odp.pfnDlgProc = MainOptionsProc; + odp.pfnDlgProc = CDlgBase::DynamicDlgProc; + odp.dwInitParam = (LPARAM)&ToxMainOptions; + ToxMainOptions.create = CToxOptionsMain::CreateOptionsPage; + ToxMainOptions.param = this; Options_AddPage(wParam, &odp); - /*odp.pszTab = LPGEN("Audio/Video"); - odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_AV); - odp.pfnDlgProc = AVOptionsProc; - Options_AddPage(wParam, &odp);*/ - odp.pszTab = LPGEN("Nodes"); odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPTIONS_NODES); - odp.pfnDlgProc = NodesOptionsProc; + odp.pfnDlgProc = CDlgBase::DynamicDlgProc; + odp.dwInitParam = (LPARAM)&ToxNodeListOptions; + ToxNodeListOptions.create = CToxOptionsNodeList::CreateOptionsPage; + ToxNodeListOptions.param = this; Options_AddPage(wParam, &odp); mir_free(title); diff --git a/protocols/Tox/src/tox_options.h b/protocols/Tox/src/tox_options.h index 19b61d6710..0b0e111513 100644 --- a/protocols/Tox/src/tox_options.h +++ b/protocols/Tox/src/tox_options.h @@ -1,10 +1,112 @@ #ifndef _TOX_OPTIONS_H_ #define _TOX_OPTIONS_H_ -struct ItemInfo +class CToxOptionsMain : public CToxDlgBase { - int iItem; - HWND hwndList; +private: + typedef CToxDlgBase CSuper; + + CCtrlEdit m_toxAddress; + CCtrlButton m_toxAddressCopy; + CCtrlButton m_profileCreate; + CCtrlButton m_profileImport; + CCtrlButton m_profileExport; + + CCtrlEdit m_nickname; + CCtrlEdit m_password; + CCtrlEdit m_group; + + CCtrlCheck m_enableUdp; + CCtrlCheck m_enableIPv6; + +protected: + void OnInitDialog(); + + void ToxAddressCopy_OnClick(CCtrlButton*); + void ProfileCreate_OnClick(CCtrlButton*); + void ProfileImport_OnClick(CCtrlButton*); + void ProfileExport_OnClick(CCtrlButton*); + + void OnApply(); + +public: + CToxOptionsMain(CToxProto *proto, int idDialog, HWND hwndParent = NULL); + + static CDlgBase *CreateAccountManagerPage(void *param, HWND owner) + { + CToxOptionsMain *page = new CToxOptionsMain((CToxProto*)param, IDD_ACCOUNT_MANAGER, owner); + page->Show(); + return page; + } + + static CDlgBase *CreateOptionsPage(void *param) { return new CToxOptionsMain((CToxProto*)param, IDD_OPTIONS_MAIN); } +}; + +///////////////////////////////////////////////////////////////////////////////// + +class CToxNodeEditor : public CDlgBase +{ +private: + typedef CDlgBase CSuper; + + int m_iItem; + CCtrlListView *m_list; + + CCtrlEdit m_ipv4; + CCtrlEdit m_ipv6; + CCtrlEdit m_port; + CCtrlEdit m_pkey; + + CCtrlButton m_ok; + +protected: + void OnInitDialog(); + void OnOk(CCtrlBase*); + void OnClose(); + +public: + CToxNodeEditor(int iItem, CCtrlListView *m_list); +}; + +/****************************************/ + +class CCtrlNodeList : public CCtrlListView +{ +private: + typedef CCtrlListView CSuper; + +protected: + BOOL OnNotify(int idCtrl, NMHDR *pnmh); + +public: + CCtrlNodeList(CDlgBase* dlg, int ctrlId); + + CCallback OnClick; +}; + +/****************************************/ + +class CToxOptionsNodeList : public CToxDlgBase +{ +private: + typedef CToxDlgBase CSuper; + + CCtrlNodeList m_nodes; + CCtrlButton m_addNode; + +protected: + CToxOptionsNodeList(CToxProto *proto); + + void OnInitDialog(); + void OnApply(); + + void OnAddNode(CCtrlBase*); + void OnNodeListDoubleClick(CCtrlBase*); + void OnNodeListClick(CCtrlListView::TEventInfo *evt); + void OnNodeListKeyDown(CCtrlListView::TEventInfo *evt); + +public: + static CDlgBase *CreateOptionsPage(void *param) { return new CToxOptionsNodeList((CToxProto*)param); } }; #endif //_TOX_OPTIONS_H_ \ No newline at end of file diff --git a/protocols/Tox/src/tox_profile.cpp b/protocols/Tox/src/tox_profile.cpp index 29c84fb040..8ca4bf84a4 100644 --- a/protocols/Tox/src/tox_profile.cpp +++ b/protocols/Tox/src/tox_profile.cpp @@ -16,114 +16,101 @@ std::tstring CToxProto::GetToxProfilePath(const TCHAR *accountName) return profilePath; } -bool CToxProto::LoadToxProfile() +bool CToxProto::LoadToxProfile(Tox_Options *options) { - std::tstring profilePath = GetToxProfilePath(); - if (!IsFileExists(profilePath)) - { - return true; - } + debugLogA(__FUNCTION__": loading tox profile"); - FILE *profile = _tfopen(profilePath.c_str(), _T("rb")); - if (profile == NULL) + size_t size = 0; + uint8_t *data = NULL; + std::tstring profilePath = GetToxProfilePath(); + if (IsFileExists(profilePath)) { - debugLogA("CToxProto::LoadToxData: could not open tox profile"); - return false; - } + FILE *profile = _tfopen(profilePath.c_str(), _T("rb")); + if (profile == NULL) + { + debugLogA(__FUNCTION__": failed to open tox profile"); + return false; + } - fseek(profile, 0, SEEK_END); - size_t size = ftell(profile); - rewind(profile); - if (size == 0) - { - fclose(profile); - debugLogA("CToxProto::LoadToxData: tox profile is empty"); - return true; - } + fseek(profile, 0, SEEK_END); + size = ftell(profile); + rewind(profile); + if (size == 0) + { + fclose(profile); + debugLogA(__FUNCTION__": tox profile is empty"); + return true; + } - uint8_t *data = (uint8_t*)mir_calloc(size); - if (fread((char*)data, sizeof(char), size, profile) != size) - { + data = (uint8_t*)mir_calloc(size); + if (fread((char*)data, sizeof(char), size, profile) != size) + { + fclose(profile); + debugLogA(__FUNCTION__": failed to read tox profile"); + mir_free(data); + return false; + } fclose(profile); - debugLogA("CToxProto::LoadToxData: could not read tox profile"); - mir_free(data); - return false; } - fclose(profile); - if (tox_is_data_encrypted(data)) + if (data != NULL && tox_is_data_encrypted(data)) { - if (password == NULL || strlen(password) == 0) + password = mir_utf8encodeW(ptrT(getTStringA("Password"))); + if (password == NULL || mir_strlen(password) == 0) { - if (!DialogBoxParam( - g_hInstance, - MAKEINTRESOURCE(IDD_PASSWORD), - NULL, - ToxProfilePasswordProc, - (LPARAM)this)) + CToxPasswordEditor passwordEditor(this); + if (!passwordEditor.DoModal()) { + mir_free(data); return false; } } - - if (tox_encrypted_load(tox, data, size, (uint8_t*)password, mir_strlen(password)) == TOX_ERROR) + TOX_ERR_DECRYPTION coreDecryptError; + if (!tox_pass_decrypt(data, size, (uint8_t*)password, mir_strlen(password), data, &coreDecryptError)) { - debugLogA("CToxProto::LoadToxData: could not decrypt tox profile"); + debugLogA(__FUNCTION__": failed to load tox profile (%d)", coreDecryptError); mir_free(data); return false; } + size -= TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } - else + + TOX_ERR_NEW initError; + tox = tox_new(options, data, size, &initError); + if (initError != TOX_ERR_NEW_OK) { - // it return -1 but load, wtf? - if (tox_load(tox, data, size) > 0) - { - debugLogA("CToxProto::LoadToxData: could not load tox profile"); - mir_free(data); - return false; - } + debugLogA(__FUNCTION__": failed to load tox profile (%d)", initError); + mir_free(data); + return false; } - mir_free(data); + debugLogA(__FUNCTION__": tox profile load successfully"); return true; } void CToxProto::SaveToxProfile() { - size_t size = 0; - uint8_t *data = NULL; + size_t size = tox_get_savedata_size(tox); + uint8_t *data = (uint8_t*)mir_calloc(size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH); + tox_get_savedata(tox, data); + if (password && strlen(password)) { - mir_cslock lock(toxLock); - - if (password && strlen(password)) + TOX_ERR_ENCRYPTION coreEncryptError; + if (!tox_pass_encrypt(data, size, (uint8_t*)password, strlen(password), data, &coreEncryptError)) { - size = tox_encrypted_size(tox); - data = (uint8_t*)mir_calloc(size); - if (tox_encrypted_save(tox, data, (uint8_t*)password, strlen(password)) == TOX_ERROR) - { - debugLogA("CToxProto::LoadToxData: could not encrypt tox profile"); - mir_free(data); - return; - } - } - else - { - size = tox_size(tox); - data = (uint8_t*)mir_calloc(size); - tox_save(tox, data); + debugLogA(__FUNCTION__": failed to encrypt tox profile"); + mir_free(data); + return; } + size += TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } - /*size_t size = tox_size(tox); - uint8_t *data = (uint8_t*)mir_calloc(size); - tox_save(tox, data);*/ - std::tstring profilePath = GetToxProfilePath(); FILE *profile = _tfopen(profilePath.c_str(), _T("wb")); if (profile == NULL) { - debugLogA("CToxProto::LoadToxData: could not open tox profile"); + debugLogA(__FUNCTION__": failed to open tox profile"); return; } @@ -131,7 +118,7 @@ void CToxProto::SaveToxProfile() if (size != written) { fclose(profile); - debugLogA("CToxProto::LoadToxData: could not write tox profile"); + debugLogA(__FUNCTION__": failed to write tox profile"); } fclose(profile); @@ -145,56 +132,29 @@ INT_PTR CToxProto::OnCopyToxID(WPARAM, LPARAM) if (OpenClipboard(NULL)) { EmptyClipboard(); - HGLOBAL hMem = GlobalAlloc(GMEM_FIXED, length); - memcpy(GlobalLock(hMem), address, length); - GlobalUnlock(hMem); - SetClipboardData(CF_TEXT, hMem); + HGLOBAL hMemory = GlobalAlloc(GMEM_FIXED, length); + memcpy(GlobalLock(hMemory), address, length); + GlobalUnlock(hMemory); + SetClipboardData(CF_TEXT, hMemory); CloseClipboard(); } return 0; } -INT_PTR CToxProto::ToxProfilePasswordProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +CToxPasswordEditor::CToxPasswordEditor(CToxProto *proto) : + CToxDlgBase(proto, IDD_PASSWORD, NULL, false), ok(this, IDOK), + password(this, IDC_PASSWORD), savePermanently(this, IDC_SAVEPERMANENTLY) { - CToxProto *proto = (CToxProto*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - - switch (uMsg) - { - case WM_INITDIALOG: - TranslateDialogDefault(hwnd); - { - proto = (CToxProto*)lParam; - SetWindowLongPtr(hwnd, GWLP_USERDATA, lParam); - } - return TRUE; - - case WM_COMMAND: - switch (LOWORD(wParam)) - { - case IDOK: - { - TCHAR password[MAX_PATH]; - GetDlgItemText(hwnd, IDC_PASSWORD, password, SIZEOF(password)); - if (IsDlgButtonChecked(hwnd, IDC_SAVEPERMANENTLY)) - { - proto->setTString("Password", password); - } - if (proto->password != NULL) - { - mir_free(proto->password); - } - proto->password = mir_utf8encodeW(password); - - EndDialog(hwnd, 1); - } - break; + ok.OnClick = Callback(this, &CToxPasswordEditor::OnOk); +} - case IDCANCEL: - EndDialog(hwnd, 0); - break; - } - break; - } +void CToxPasswordEditor::OnOk(CCtrlButton*) +{ + if (savePermanently.Enabled()) + m_proto->setTString("Password", password.GetText()); + if (m_proto->password != NULL) + mir_free(m_proto->password); + m_proto->password = mir_utf8encodeW(password.GetText()); - return FALSE; -} \ No newline at end of file + EndDialog(m_hwnd, 1); +} diff --git a/protocols/Tox/src/tox_proto.cpp b/protocols/Tox/src/tox_proto.cpp index 045cf3117e..98a048d6d7 100644 --- a/protocols/Tox/src/tox_proto.cpp +++ b/protocols/Tox/src/tox_proto.cpp @@ -35,7 +35,7 @@ CToxProto::~CToxProto() UninitNetlib(); } -DWORD_PTR __cdecl CToxProto::GetCaps(int type, MCONTACT) +DWORD_PTR CToxProto::GetCaps(int type, MCONTACT) { switch (type) { @@ -59,26 +59,26 @@ DWORD_PTR __cdecl CToxProto::GetCaps(int type, MCONTACT) return 0; } -MCONTACT __cdecl CToxProto::AddToList(int flags, PROTOSEARCHRESULT *psr) +MCONTACT CToxProto::AddToList(int flags, PROTOSEARCHRESULT *psr) { - std::string address(ptrA(mir_t2a(psr->id))); + ptrA address(mir_t2a(psr->id)); ptrA myAddress(getStringA(NULL, TOX_SETTINGS_ID)); - if (strnicmp(address.c_str(), myAddress, TOX_PUBLIC_KEY_SIZE) == 0) + if (strnicmp(address, myAddress, TOX_PUBLIC_KEY_SIZE) == 0) { ShowNotification(TranslateT("You cannot add yourself to your contact list"), 0); return NULL; } - MCONTACT hContact = GetContact(address.c_str()); + MCONTACT hContact = GetContact((char*)address); if (hContact) { ShowNotification(TranslateT("Contact already in your contact list"), 0, hContact); return NULL; } // set tox address as contact public key - return AddContact(address.c_str(), _T(""), flags & PALF_TEMPORARY); + return AddContact(address, _T(""), flags & PALF_TEMPORARY); } -int __cdecl CToxProto::Authorize(MEVENT hDbEvent) +int CToxProto::Authorize(MEVENT hDbEvent) { MCONTACT hContact = GetContactFromAuthEvent(hDbEvent); if (hContact == INVALID_CONTACT_ID) @@ -87,28 +87,48 @@ int __cdecl CToxProto::Authorize(MEVENT hDbEvent) return OnGrantAuth(hContact, 0); } -int __cdecl CToxProto::AuthRecv(MCONTACT, PROTORECVEVENT* pre) +int CToxProto::AuthRecv(MCONTACT, PROTORECVEVENT* pre) { return Proto_AuthRecv(m_szModuleName, pre); } -int __cdecl CToxProto::AuthRequest(MCONTACT hContact, const PROTOCHAR *szMessage) +int CToxProto::AuthRequest(MCONTACT hContact, const PROTOCHAR *szMessage) { ptrA reason(mir_utf8encodeW(szMessage)); return OnRequestAuth(hContact, (LPARAM)reason); } -HWND __cdecl CToxProto::SearchAdvanced(HWND owner) +HANDLE CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR *tszPath) +{ + return OnFileAllow(hContact, hTransfer, tszPath); +} + +int CToxProto::FileCancel(MCONTACT hContact, HANDLE hTransfer) +{ + return OnFileCancel(hContact, hTransfer); +} + +int CToxProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR*) +{ + return FileCancel(hContact, hTransfer); +} + +int CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR **szFilename) +{ + return OnFileResume(hTransfer, action, szFilename); +} + +HWND CToxProto::SearchAdvanced(HWND owner) { return OnSearchAdvanced(owner); } -HWND __cdecl CToxProto::CreateExtendedSearchUI(HWND owner) +HWND CToxProto::CreateExtendedSearchUI(HWND owner) { return OnCreateExtendedSearchUI(owner); } -int __cdecl CToxProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) +int CToxProto::RecvMsg(MCONTACT hContact, PROTORECVEVENT *pre) { return OnReceiveMessage(hContact, pre); } @@ -118,7 +138,12 @@ int CToxProto::SendMsg(MCONTACT hContact, int flags, const char *msg) return OnSendMessage(hContact, flags, msg); } -int __cdecl CToxProto::SetStatus(int iNewStatus) +HANDLE CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR *msg, PROTOCHAR **ppszFiles) +{ + return OnSendFile(hContact, msg, ppszFiles); +} + +int CToxProto::SetStatus(int iNewStatus) { if (iNewStatus == m_iDesiredStatus) return 0; @@ -178,10 +203,7 @@ int __cdecl CToxProto::SetStatus(int iNewStatus) { // set tox status m_iStatus = iNewStatus; - if (tox_set_user_status(tox, MirandaToToxStatus(iNewStatus)) == TOX_ERROR) - { - debugLogA("CToxProto::SetStatus: failed to change status from %i", m_iStatus, iNewStatus); - } + tox_self_set_status(tox, MirandaToToxStatus(iNewStatus)); } } @@ -189,23 +211,29 @@ int __cdecl CToxProto::SetStatus(int iNewStatus) return 0; } -HANDLE __cdecl CToxProto::GetAwayMsg(MCONTACT) { return 0; } +HANDLE CToxProto::GetAwayMsg(MCONTACT) { return 0; } -int __cdecl CToxProto::SetAwayMsg(int, const PROTOCHAR *msg) +int CToxProto::SetAwayMsg(int, const PROTOCHAR *msg) { if (IsOnline()) { ptrA statusMessage(msg == NULL ? mir_strdup("") : mir_utf8encodeT(msg)); - if (tox_set_status_message(tox, (uint8_t*)(char*)statusMessage, min(TOX_MAX_STATUSMESSAGE_LENGTH, mir_strlen(statusMessage))) == TOX_ERROR) + TOX_ERR_SET_INFO error; + if (tox_self_set_status_message(tox, (uint8_t*)(char*)statusMessage, min(TOX_MAX_STATUS_MESSAGE_LENGTH, mir_strlen(statusMessage)), &error)) { - debugLogA("CToxProto::SetAwayMsg: failed to set status status message %s", msg); + debugLogA("CToxProto::SetAwayMsg: failed to set status status message %s (%d)", msg, error); } } return 0; } -int __cdecl CToxProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam) +int CToxProto::UserIsTyping(MCONTACT hContact, int type) +{ + return OnUserIsTyping(hContact, type); +} + +int CToxProto::OnEvent(PROTOEVENTTYPE iEventType, WPARAM wParam, LPARAM lParam) { switch (iEventType) { diff --git a/protocols/Tox/src/tox_proto.h b/protocols/Tox/src/tox_proto.h index 39b67e761f..a329252fda 100644 --- a/protocols/Tox/src/tox_proto.h +++ b/protocols/Tox/src/tox_proto.h @@ -3,6 +3,10 @@ struct CToxProto : public PROTO { + friend CToxPasswordEditor; + friend CToxOptionsMain; + friend CToxOptionsNodeList; + public: ////////////////////////////////////////////////////////////////////////////////////// @@ -74,17 +78,12 @@ private: std::tstring GetToxProfilePath(); static std::tstring CToxProto::GetToxProfilePath(const TCHAR *accountName); - bool LoadToxProfile(); + bool LoadToxProfile(Tox_Options *options); void SaveToxProfile(); INT_PTR __cdecl OnCopyToxID(WPARAM, LPARAM); - static INT_PTR CALLBACK ToxProfileImportProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static INT_PTR CALLBACK ToxProfilePasswordProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - // tox core - bool IsToxCoreInited(); - bool InitToxCore(); void UninitToxCore(); @@ -132,8 +131,8 @@ private: INT_PTR __cdecl CToxProto::SetMyNickname(WPARAM wParam, LPARAM lParam); // options - static INT_PTR CALLBACK MainOptionsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - static INT_PTR CALLBACK NodesOptionsProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam); + CToxDlgBase::CreateParam ToxMainOptions; + CToxDlgBase::CreateParam ToxNodeListOptions; int __cdecl OnOptionsInit(WPARAM wParam, LPARAM lParam); @@ -156,18 +155,18 @@ private: MCONTACT GetContactFromAuthEvent(MEVENT hEvent); - int32_t GetToxFriendNumber(MCONTACT hContact); + uint32_t GetToxFriendNumber(MCONTACT hContact); void __cdecl LoadFriendList(void*); INT_PTR __cdecl OnRequestAuth(WPARAM hContact, LPARAM lParam); INT_PTR __cdecl OnGrantAuth(WPARAM hContact, LPARAM); - static void OnFriendRequest(Tox *tox, const uint8_t *pubKey, const uint8_t *message, const uint16_t messageSize, void *arg); - static void OnFriendNameChange(Tox *tox, const int friendNumber, const uint8_t *name, const uint16_t nameSize, void *arg); - static void OnStatusMessageChanged(Tox *tox, const int friendNumber, const uint8_t* message, const uint16_t messageSize, void *arg); - static void OnUserStatusChanged(Tox *tox, int32_t friendNumber, uint8_t usertatus, void *arg); - static void OnConnectionStatusChanged(Tox *tox, const int friendNumber, const uint8_t status, void *arg); + static void OnFriendRequest(Tox *tox, const uint8_t *pubKey, const uint8_t *message, size_t length, void *arg); + static void OnFriendNameChange(Tox *tox, uint32_t friendNumber, const uint8_t *name, size_t length, void *arg); + static void OnStatusMessageChanged(Tox *tox, uint32_t friendNumber, const uint8_t *message, size_t length, void *arg); + static void OnUserStatusChanged(Tox *tox, uint32_t friendNumber, TOX_USER_STATUS status, void *arg); + static void OnConnectionStatusChanged(Tox *tox, uint32_t friendNumber, TOX_CONNECTION status, void *arg); // contacts search void __cdecl SearchByNameAsync(void* arg); @@ -208,20 +207,25 @@ private: int OnReceiveMessage(MCONTACT hContact, PROTORECVEVENT *pre); int OnSendMessage(MCONTACT hContact, int flags, const char *message); - static void OnFriendMessage(Tox *tox, const int friendNumber, const uint8_t *message, const uint16_t messageSize, void *arg); - static void OnFriendAction(Tox *tox, const int friendNumber, const uint8_t *action, const uint16_t actionSize, void *arg); - static void OnTypingChanged(Tox *tox, const int friendNumber, uint8_t isTyping, void *arg); - static void OnReadReceipt(Tox *tox, int32_t friendNumber, uint32_t receipt, void *arg); + static void OnFriendMessage(Tox *tox, uint32_t friendNumber, TOX_MESSAGE_TYPE type, const uint8_t *message, size_t length, void *arg); + static void OnReadReceipt(Tox *tox, uint32_t friendNumber, uint32_t messageId, void *arg); + + int OnUserIsTyping(MCONTACT hContact, int type); + static void OnTypingChanged(Tox *tox, uint32_t friendNumber, bool isTyping, void *arg); int __cdecl OnPreCreateMessage(WPARAM wParam, LPARAM lParam); // transfer - void __cdecl SendFileAsync(void* arg); + HANDLE OnFileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR *tszPath); + int OnFileResume(HANDLE hTransfer, int *action, const PROTOCHAR **szFilename); + int OnFileCancel(MCONTACT hContact, HANDLE hTransfer); + HANDLE OnSendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHAR **ppszFiles); + + static void OnFileRequest(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, TOX_FILE_CONTROL control, void *arg); + static void OnFriendFile(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, uint32_t kind, uint64_t fileSize, const uint8_t *fileName, size_t filenameLength, void *arg); + static void OnFileReceiveData(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, const uint8_t *data, size_t length, void *arg); - //static void OnFileControlCallback(Tox *tox, int32_t number, uint8_t hFile, uint64_t fileSize, uint8_t *name, uint16_t nameSize, void *arg); - static void OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_send, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg); - static void OnFriendFile(Tox *tox, int32_t friendNumber, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t length, void *arg); - static void OnFileData(Tox *tox, int32_t friendNumber, uint8_t fileNumber, const uint8_t *data, uint16_t length, void *arg); + static void OnFileSendData(Tox *tox, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, size_t length, void *arg); // avatars std::tstring GetAvatarFilePath(MCONTACT hContact = NULL); @@ -232,14 +236,13 @@ private: INT_PTR __cdecl GetMyAvatar(WPARAM wParam, LPARAM lParam); INT_PTR __cdecl SetMyAvatar(WPARAM wParam, LPARAM lParam); - static void OnGotFriendAvatarInfo(Tox *tox, int32_t number, uint8_t format, uint8_t *hash, void *arg); - static void OnGotFriendAvatarData(Tox *tox, int32_t number, uint8_t format, uint8_t *hash, uint8_t *data, uint32_t length, void *arg); + void OnGotFriendAvatarInfo(FileTransferParam *transfer, const uint8_t *hash); // folders // utils - TOX_USERSTATUS MirandaToToxStatus(int status); - int ToxToMirandaStatus(TOX_USERSTATUS userstatus); + TOX_USER_STATUS MirandaToToxStatus(int status); + int ToxToMirandaStatus(TOX_USER_STATUS userstatus); static void ShowNotification(const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); static void ShowNotification(const TCHAR *caption, const TCHAR *message, int flags = 0, MCONTACT hContact = NULL); diff --git a/protocols/Tox/src/tox_search.cpp b/protocols/Tox/src/tox_search.cpp index ea2a571a32..f5d5b001b3 100644 --- a/protocols/Tox/src/tox_search.cpp +++ b/protocols/Tox/src/tox_search.cpp @@ -29,10 +29,10 @@ ToxHexAddress ResolveToxAddressFromDnsRecordV3(void *dns, uint32_t requestId, co if (std::regex_search(dnsRecord, match, regex)) { std::string id = match[1]; - uint8_t data[TOX_FRIEND_ADDRESS_SIZE]; + uint8_t data[TOX_ADDRESS_SIZE]; if (tox_decrypt_dns3_TXT(dns, data, (uint8_t*)id.c_str(), id.length(), requestId) != TOX_ERROR) { - return ToxHexAddress(data, TOX_FRIEND_ADDRESS_SIZE); + return ToxHexAddress(data, TOX_ADDRESS_SIZE); } } return ToxHexAddress::Empty(); diff --git a/protocols/Tox/src/tox_services.cpp b/protocols/Tox/src/tox_services.cpp index 136c7baa5b..cf3d3f142f 100644 --- a/protocols/Tox/src/tox_services.cpp +++ b/protocols/Tox/src/tox_services.cpp @@ -1,13 +1,16 @@ #include "common.h" -INT_PTR __cdecl CToxProto::SetMyNickname(WPARAM wParam, LPARAM lParam) +INT_PTR CToxProto::SetMyNickname(WPARAM wParam, LPARAM lParam) { ptrT nickname((wParam & SMNN_UNICODE) ? mir_u2t((TCHAR*)lParam) : mir_a2t((char*)lParam)); setTString("Nick", nickname); - if (IsToxCoreInited()) + TOX_ERR_SET_INFO error; + if (!tox_self_set_name(tox, (uint8_t*)(char*)ptrA(mir_utf8encodeT(nickname)), mir_tstrlen(nickname), &error)) { - tox_set_name(tox, (uint8_t*)(char*)ptrA(mir_utf8encodeT(nickname)), mir_tstrlen(nickname)); + debugLogA(__FUNCTION__": failed to set nick name"); + return 1; } + return 0; } diff --git a/protocols/Tox/src/tox_transfer.cpp b/protocols/Tox/src/tox_transfer.cpp index 7b5a011786..c2cbad33cd 100644 --- a/protocols/Tox/src/tox_transfer.cpp +++ b/protocols/Tox/src/tox_transfer.cpp @@ -3,40 +3,56 @@ /* FILE RECEIVING */ // incoming file flow -void CToxProto::OnFriendFile(Tox *, int32_t friendNumber, uint8_t fileNumber, uint64_t fileSize, const uint8_t *fileName, uint16_t, void *arg) +void CToxProto::OnFriendFile(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint32_t kind, uint64_t fileSize, const uint8_t *fileName, size_t filenameLength, void *arg) { CToxProto *proto = (CToxProto*)arg; MCONTACT hContact = proto->GetContact(friendNumber); if (hContact) { - TCHAR *name = mir_utf8decodeT((char*)fileName); - if (name == NULL) + switch (kind) { - // uTox send file name in ansi - name = mir_a2u((char*)fileName); + case TOX_FILE_KIND_AVATAR: + case TOX_FILE_KIND_DATA: + { + ptrA rawName((char*)mir_alloc(filenameLength + 1)); + memcpy(rawName, fileName, filenameLength); + rawName[filenameLength] = 0; + TCHAR *name = mir_utf8decodeT(rawName); + + FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, name, fileSize); + transfer->pfts.hContact = hContact; + transfer->pfts.flags |= PFTS_RECEIVING; + proto->transfers.Add(transfer); + + if (kind == TOX_FILE_KIND_AVATAR) + { + proto->OnGotFriendAvatarInfo(transfer, fileName); + return; + } + + PROTORECVFILET pre = { 0 }; + pre.flags = PREF_TCHAR; + pre.fileCount = 1; + pre.timestamp = time(NULL); + pre.tszDescription = _T(""); + pre.ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*) * 2); + pre.ptszFiles[0] = name; + pre.ptszFiles[1] = NULL; + pre.lParam = (LPARAM)transfer; + ProtoChainRecvFile(hContact, &pre); } + break; - FileTransferParam *transfer = new FileTransferParam(friendNumber, fileNumber, name, fileSize); - transfer->pfts.hContact = hContact; - transfer->pfts.flags |= PFTS_RECEIVING; - proto->transfers.Add(transfer); - - PROTORECVFILET pre = { 0 }; - pre.flags = PREF_TCHAR; - pre.fileCount = 1; - pre.timestamp = time(NULL); - pre.tszDescription = _T(""); - pre.ptszFiles = (TCHAR**)mir_alloc(sizeof(TCHAR*)*2); - pre.ptszFiles[0] = name; - pre.ptszFiles[1] = NULL; - pre.lParam = (LPARAM)transfer; - ProtoChainRecvFile(hContact, &pre); + default: + proto->debugLogA(__FUNCTION__": unknown file kind (%d)", kind); + return; + } } } // file request is allowed -HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR *tszPath) +HANDLE CToxProto::OnFileAllow(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR *tszPath) { FileTransferParam *transfer = (FileTransferParam*)hTransfer; transfer->pfts.tszWorkingDir = mir_tstrdup(tszPath); @@ -52,17 +68,18 @@ HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const P { debugLogA("CToxProto::FileAllow: failed to open file (%d)", transfer->fileNumber); transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); transfers.Remove(transfer); return NULL; } debugLogA("CToxProto::FileAllow: start receiving file (%d)", transfer->fileNumber); transfer->status = STARTED; - if (tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0) == TOX_ERROR) + TOX_ERR_FILE_CONTROL error; + if (!tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) { - debugLogA("CToxProto::FileAllow: failed to start the transfer of file (%d)", transfer->fileNumber); - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + debugLogA("CToxProto::FileAllow: failed to start the transfer (%d)", error); + tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); } } @@ -70,7 +87,7 @@ HANDLE __cdecl CToxProto::FileAllow(MCONTACT hContact, HANDLE hTransfer, const P } // if file is exists -int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR **szFilename) +int CToxProto::OnFileResume(HANDLE hTransfer, int *action, const PROTOCHAR **szFilename) { bool result = false; FileTransferParam *transfer = (FileTransferParam*)hTransfer; @@ -92,20 +109,21 @@ int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR break; } + TOX_ERR_FILE_CONTROL error; if (result) { debugLogA("CToxProto::FileResume: start receiving file (%d)", transfer->fileNumber); transfer->status = STARTED; - if (tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0) == TOX_ERROR) + if (!tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_RESUME, &error)) { - debugLogA("CToxProto::FileResume: failed to start the transfer of file (%d)", transfer->fileNumber); - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + debugLogA("CToxProto::FileResume: failed to start the transfer (%d)", error); + tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, &error); } } else { transfer->status = CANCELED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, &error); transfers.Remove(transfer); } ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, result ? ACKRESULT_CONNECTED : ACKRESULT_DENIED, (HANDLE)transfer, 0); @@ -114,50 +132,60 @@ int __cdecl CToxProto::FileResume(HANDLE hTransfer, int *action, const PROTOCHAR } // getting the file data -void CToxProto::OnFileData(Tox *tox, int32_t friendNumber, uint8_t fileNumber, const uint8_t *data, uint16_t size, void *arg) +void CToxProto::OnFileReceiveData(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, const uint8_t *data, size_t length, void *arg) { CToxProto *proto = (CToxProto*)arg; - MCONTACT hContact = proto->GetContact(friendNumber); - if (hContact == NULL) + FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber); + if (transfer == NULL) { - proto->debugLogA("CToxProto::OnFileData: cannot find contact by number (%d)", friendNumber); - tox_file_send_control(tox, friendNumber, 1, fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); return; } - FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber); - if (transfer == NULL) + if (length == 0 || (length == 0 && position == UINT64_MAX)) { - proto->debugLogA("CToxProto::OnFileData: cannot find transfer by number (%d)", fileNumber); - transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + //receiving is finished + proto->debugLogA(__FUNCTION__": finised the transfer of file (%d)", fileNumber); + bool isFileFullyTransfered = transfer->pfts.currentFileProgress == transfer->pfts.currentFileSize; + transfer->status = isFileFullyTransfered ? FINISHED : FAILED; + if (!isFileFullyTransfered) + { + proto->debugLogA(__FUNCTION__": file (%d) is transferred not completely", fileNumber); + } + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, isFileFullyTransfered ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)transfer, 0); + proto->transfers.Remove(transfer); + } + + MCONTACT hContact = proto->GetContact(friendNumber); + if (hContact == NULL) + { + proto->debugLogA("CToxProto::OnFileData: cannot find contact by number (%d)", friendNumber); + tox_file_control(proto->tox, friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); return; } - if (fwrite(data, sizeof(uint8_t), size, transfer->hFile) != size) + if (fwrite(data, sizeof(uint8_t), length, transfer->hFile) != length) { - proto->debugLogA("CToxProto::OnFileData: cannot write to file (%d)", fileNumber); + proto->debugLogA(__FUNCTION__": failed write to file (%d)", fileNumber); proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + tox_file_control(proto->tox, friendNumber, fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); return; } - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += size; + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress += length; proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); } /* FILE SENDING */ // outcoming file flow -HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHAR **ppszFiles) +HANDLE CToxProto::OnSendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHAR **ppszFiles) { int32_t friendNumber = GetToxFriendNumber(hContact); - if (friendNumber == TOX_ERROR) - { + if (friendNumber == UINT32_MAX) return NULL; - } TCHAR *fileName = _tcsrchr(ppszFiles[0], '\\') + 1; @@ -169,7 +197,7 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHA FILE *hFile = _tfopen(ppszFiles[0], _T("rb")); if (hFile == NULL) { - debugLogA("CToxProto::SendFilesAsync: cannot open file"); + debugLogA(__FUNCTION__": cannot open file"); return NULL; } @@ -178,10 +206,11 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHA rewind(hFile); char *name = mir_utf8encodeW(fileName); - int fileNumber = tox_new_file_sender(tox, friendNumber, fileSize, (uint8_t*)name, (uint16_t)mir_strlen(name)); - if (fileNumber == TOX_ERROR) + TOX_ERR_FILE_SEND sendError; + uint32_t fileNumber = tox_file_send(tox, friendNumber, TOX_FILE_KIND_DATA, fileSize, NULL, (uint8_t*)name, mir_strlen(name), &sendError); + if (sendError != TOX_ERR_FILE_SEND_OK) { - debugLogA("CToxProto::SendFilesAsync: cannot send file"); + debugLogA(__FUNCTION__": failed to send file (%d)", sendError); return NULL; } @@ -195,85 +224,76 @@ HANDLE __cdecl CToxProto::SendFile(MCONTACT hContact, const PROTOCHAR*, PROTOCHA return (HANDLE)transfer; } -// start sending -void CToxProto::SendFileAsync(void *arg) +void CToxProto::OnFileSendData(Tox*, uint32_t friendNumber, uint32_t fileNumber, uint64_t position, size_t length, void *arg) { - FileTransferParam *transfer = (FileTransferParam*)arg; - transfer->status = STARTED; + CToxProto *proto = (CToxProto*)arg; - size_t dataSize = 0; - uint64_t fileProgress = transfer->pfts.currentFileProgress; - uint64_t fileSize = transfer->pfts.currentFileSize; - int chunkSize = min(tox_file_data_size(tox, transfer->friendNumber), fileSize); - uint8_t *data = (uint8_t*)mir_alloc(chunkSize); + FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber); + if (transfer == NULL) + { + tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); + return; + } - while (transfer->status == STARTED && transfer->hFile != NULL && fileProgress < fileSize) + if (length == 0) { - if (dataSize == 0) + // file sending is finished + proto->debugLogA(__FUNCTION__": finised the transfer of file (%d)", fileNumber); + bool isFileFullyTransfered = transfer->pfts.currentFileProgress == transfer->pfts.currentFileSize; + transfer->status = isFileFullyTransfered ? FINISHED : FAILED; + if (!isFileFullyTransfered) { - dataSize = min(chunkSize, fileSize - fileProgress); - size_t read = fread(data, sizeof(uint8_t), dataSize, transfer->hFile); - if (read != dataSize) - { - debugLogA("CToxProto::SendFileAsync: failed to read from file (%d)", transfer->fileNumber); - debugLogA("CToxProto::SendFileAsync: read %d of %d (%d)", read, dataSize, transfer->fileNumber); - debugLogA("CToxProto::SendFileAsync: sent %llu of %llu of file (%d)", transfer->pfts.currentFileProgress, transfer->pfts.currentFileSize, transfer->fileNumber); - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); - transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - return; - } + proto->debugLogA(__FUNCTION__": file (%d) is transferred not completely", fileNumber); } + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, isFileFullyTransfered ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)transfer, 0); + proto->transfers.Remove(transfer); + return; + } - int sendResult = TOX_ERROR; - { - mir_cslock lock(toxLock); - sendResult = tox_file_send_data(tox, transfer->friendNumber, transfer->fileNumber, data, (uint16_t)dataSize); - } - if (sendResult == TOX_ERROR) - { - Sleep(100); - continue; - } + uint64_t sentBytes = _ftelli64(transfer->hFile); + if (sentBytes != position) + _fseeki64(transfer->hFile, position, SEEK_SET); - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = fileProgress += dataSize; - ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DATA, (HANDLE)transfer, (LPARAM)&transfer->pfts); - dataSize = 0; + uint8_t *data = (uint8_t*)mir_alloc(length); + if (fread(data, sizeof(uint8_t), length, transfer->hFile) != length) + { + proto->debugLogA(__FUNCTION__": failed to read from file (%d)", transfer->fileNumber); + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + transfer->status = FAILED; + tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); + return; } - mir_free(data); - - if (transfer->status == STARTED && fileProgress == fileSize) + TOX_ERR_FILE_SEND_CHUNK error; + if (!tox_file_send_chunk(proto->tox, friendNumber, fileNumber, position, data, length, &error)) { - transfer->status = FINISHED; - if (tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_FINISHED, NULL, 0) == TOX_ERROR) - { - debugLogA("CToxProto::SendFileAsync: failed to finish the transfer of file (%d)", transfer->fileNumber); - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - } + proto->debugLogA(__FUNCTION__": failed to send file chunk (%d)", error); + proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); + transfer->status = FAILED; + tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); + mir_free(data); + return; } + + transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = length; + + mir_free(data); } /* COMMON */ // file request is cancelled -int __cdecl CToxProto::FileCancel(MCONTACT, HANDLE hTransfer) +int CToxProto::OnFileCancel(MCONTACT, HANDLE hTransfer) { FileTransferParam *transfer = (FileTransferParam*)hTransfer; transfer->status = CANCELED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + tox_file_control(tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); transfers.Remove(transfer); return 0; } -// file request is denied -int __cdecl CToxProto::FileDeny(MCONTACT hContact, HANDLE hTransfer, const PROTOCHAR*) -{ - return FileCancel(hContact, hTransfer); -} - -void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_send, uint8_t fileNumber, uint8_t type, const uint8_t *data, uint16_t length, void *arg) +void CToxProto::OnFileRequest(Tox*, uint32_t friendNumber, uint32_t fileNumber, TOX_FILE_CONTROL control, void *arg) { CToxProto *proto = (CToxProto*)arg; @@ -283,81 +303,26 @@ void CToxProto::OnFileRequest(Tox *tox, int32_t friendNumber, uint8_t receive_se FileTransferParam *transfer = proto->transfers.Get(friendNumber, fileNumber); if (transfer == NULL) { - tox_file_send_control(tox, friendNumber, receive_send, fileNumber, TOX_FILECONTROL_KILL, NULL, 0); + tox_file_control(proto->tox, transfer->friendNumber, transfer->fileNumber, TOX_FILE_CONTROL_CANCEL, NULL); return; } - switch (type) + switch (control) { - case TOX_FILECONTROL_ACCEPT: - // receiver allowed the transfer - if (receive_send == 1) - { - proto->debugLogA("CToxProto::OnFileRequest: start the transfer of file (%d)", transfer->fileNumber); - // start file sending - proto->ForkThread(&CToxProto::SendFileAsync, transfer); - } - break; - - case TOX_FILECONTROL_PAUSE: + case TOX_FILE_CONTROL_PAUSE: transfer->status = PAUSED; break; - case TOX_FILECONTROL_RESUME_BROKEN: - // receiver asked to resume transfer - if (receive_send == 1) - { - uint64_t progress = *(uint64_t*)data; - if (progress >= transfer->pfts.currentFileSize || length != sizeof(uint64_t)) - { - transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - } - if (tox_file_send_control(tox, friendNumber, transfer->GetDirection(), fileNumber, TOX_FILECONTROL_ACCEPT, NULL, 0) == TOX_ERROR) - { - proto->debugLogA("CToxProto::OnFileRequest: failed to resume the transfer of file (%d)", transfer->fileNumber); - proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_FAILED, (HANDLE)transfer, 0); - transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - break; - } - if (transfer->pfts.currentFileProgress != progress) - { - transfer->pfts.totalProgress = transfer->pfts.currentFileProgress = progress; - if (_fseeki64(transfer->hFile, progress, SEEK_SET)) - { - proto->debugLogA("CToxProto::OnFileRequest: failed to change file position from %llu to %llu of file (%d)", - transfer->pfts.currentFileProgress, progress, transfer->fileNumber); - transfer->status = FAILED; - tox_file_send_control(tox, transfer->friendNumber, transfer->GetDirection(), transfer->fileNumber, TOX_FILECONTROL_KILL, NULL, 0); - } - } - proto->debugLogA("CToxProto::SendFileAsync: resume the transfer of file (%d)", transfer->fileNumber); - // resume file sending - proto->ForkThread(&CToxProto::SendFileAsync, transfer); - } + case TOX_FILE_CONTROL_RESUME: + transfer->status = STARTED; + proto->debugLogA("CToxProto::OnFileRequest: start/resume the transfer of file (%d)", transfer->fileNumber); break; - case TOX_FILECONTROL_KILL: + case TOX_FILE_CONTROL_CANCEL: transfer->status = CANCELED; proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, ACKRESULT_DENIED, (HANDLE)transfer, 0); proto->transfers.Remove(transfer); break; - - case TOX_FILECONTROL_FINISHED: - { - proto->debugLogA("CToxProto::SendFileAsync: finish the transfer of file (%d)", transfer->fileNumber); - bool isFileFullyTransfered = transfer->pfts.currentFileProgress == transfer->pfts.currentFileSize; - transfer->status = isFileFullyTransfered ? FINISHED : FAILED; - if (!isFileFullyTransfered) - { - proto->debugLogA("CToxProto::SendFileAsync: file (%d) is transferred not completely", transfer->fileNumber); - } - tox_file_send_control(tox, friendNumber, transfer->GetDirection(), fileNumber, isFileFullyTransfered ? TOX_FILECONTROL_FINISHED : TOX_FILECONTROL_KILL, NULL, 0); - proto->ProtoBroadcastAck(transfer->pfts.hContact, ACKTYPE_FILE, isFileFullyTransfered ? ACKRESULT_SUCCESS : ACKRESULT_FAILED, (HANDLE)transfer, 0); - proto->transfers.Remove(transfer); - } - break; } } } \ No newline at end of file diff --git a/protocols/Tox/src/tox_transfer.h b/protocols/Tox/src/tox_transfer.h index 41c6e1a4c6..c185209091 100644 --- a/protocols/Tox/src/tox_transfer.h +++ b/protocols/Tox/src/tox_transfer.h @@ -18,11 +18,11 @@ struct FileTransferParam PROTOFILETRANSFERSTATUS pfts; FILE_TRANSFER_STATUS status; FILE *hFile; - int32_t friendNumber; - uint8_t fileNumber; - int64_t transferNumber; + uint32_t friendNumber; + uint32_t fileNumber; + uint64_t transferNumber; - FileTransferParam(int32_t friendNumber, uint8_t fileNumber, const TCHAR *fileName, uint64_t fileSize) + FileTransferParam(uint32_t friendNumber, uint32_t fileNumber, const TCHAR *fileName, uint64_t fileSize) { status = NONE; hFile = NULL; @@ -94,7 +94,7 @@ public: } } - FileTransferParam* Get(int32_t friendNumber, uint8_t fileNumber) + FileTransferParam* Get(uint32_t friendNumber, uint32_t fileNumber) { int64_t transferNumber = (((int64_t)friendNumber) << 32) | ((int64_t)fileNumber); if (transfers.find(transferNumber) != transfers.end()) @@ -115,7 +115,7 @@ public: return NULL; } - void Remove(int32_t friendNumber, uint8_t fileNumber) + void Remove(uint32_t friendNumber, uint32_t fileNumber) { int64_t transferNumber = (((int64_t)friendNumber) << 32) | ((int64_t)fileNumber); if (transfers.find(transferNumber) != transfers.end()) diff --git a/protocols/Tox/src/tox_utils.cpp b/protocols/Tox/src/tox_utils.cpp index ccbb41effd..29e43d425b 100644 --- a/protocols/Tox/src/tox_utils.cpp +++ b/protocols/Tox/src/tox_utils.cpp @@ -1,32 +1,32 @@ #include "common.h" -TOX_USERSTATUS CToxProto::MirandaToToxStatus(int status) +TOX_USER_STATUS CToxProto::MirandaToToxStatus(int status) { - TOX_USERSTATUS userstatus = TOX_USERSTATUS_NONE; + TOX_USER_STATUS userstatus = TOX_USER_STATUS_NONE; switch (status) { case ID_STATUS_AWAY: - userstatus = TOX_USERSTATUS_AWAY; + userstatus = TOX_USER_STATUS_AWAY; break; case ID_STATUS_OCCUPIED: - userstatus = TOX_USERSTATUS_BUSY; + userstatus = TOX_USER_STATUS_BUSY; break; } return userstatus; } -int CToxProto::ToxToMirandaStatus(TOX_USERSTATUS userstatus) +int CToxProto::ToxToMirandaStatus(TOX_USER_STATUS userstatus) { int status = ID_STATUS_OFFLINE; switch (userstatus) { - case TOX_USERSTATUS_NONE: + case TOX_USER_STATUS_NONE: status = ID_STATUS_ONLINE; break; - case TOX_USERSTATUS_AWAY: + case TOX_USER_STATUS_AWAY: status = ID_STATUS_AWAY; break; - case TOX_USERSTATUS_BUSY: + case TOX_USER_STATUS_BUSY: status = ID_STATUS_OCCUPIED; break; } @@ -62,13 +62,5 @@ void CToxProto::ShowNotification(const TCHAR *message, int flags, MCONTACT hCont bool CToxProto::IsFileExists(std::tstring path) { - //return ::GetFileAttributes(fileName) != DWORD(-1) - WIN32_FIND_DATA wfd; - HANDLE hFind = FindFirstFile(path.c_str(), &wfd); - if (INVALID_HANDLE_VALUE != hFind) - { - FindClose(hFind); - return true; - } - return false; + return _taccess(path.c_str(), 0) == 0; } \ No newline at end of file diff --git a/protocols/Tox/src/version.h b/protocols/Tox/src/version.h index e3ec1bf9d5..d9040b8af6 100644 --- a/protocols/Tox/src/version.h +++ b/protocols/Tox/src/version.h @@ -1,7 +1,7 @@ #define __MAJOR_VERSION 0 #define __MINOR_VERSION 11 -#define __RELEASE_NUM 0 -#define __BUILD_NUM 8 +#define __RELEASE_NUM 1 +#define __BUILD_NUM 0 #include -- cgit v1.2.3