| 761 purple_connection_set_id(connection, uuid); |
827 purple_connection_set_id(connection, uuid); |
| 762 |
828 |
| 763 g_free(uuid); |
829 g_free(uuid); |
| 764 } |
830 } |
| 765 |
831 |
| 766 purple_account_set_connection(priv->account, connection); |
|
| 767 |
|
| 768 purple_signal_emit(purple_connections_get_handle(), "signing-on", |
832 purple_signal_emit(purple_connections_get_handle(), "signing-on", |
| 769 connection); |
833 connection); |
| |
834 } |
| |
835 |
| |
836 static void |
| |
837 purple_connection_dispose(GObject *obj) { |
| |
838 PurpleConnection *connection = PURPLE_CONNECTION(obj); |
| |
839 PurpleConnectionPrivate *priv = NULL; |
| |
840 |
| |
841 priv = purple_connection_get_instance_private(connection); |
| |
842 |
| |
843 g_clear_object(&priv->account); |
| |
844 |
| |
845 if(priv->disconnect_timeout > 0) { |
| |
846 g_source_remove(priv->disconnect_timeout); |
| |
847 priv->disconnect_timeout = 0; |
| |
848 } |
| |
849 |
| |
850 G_OBJECT_CLASS(purple_connection_parent_class)->dispose(obj); |
| 770 } |
851 } |
| 771 |
852 |
| 772 static void |
853 static void |
| 773 purple_connection_finalize(GObject *object) { |
854 purple_connection_finalize(GObject *object) { |
| 774 PurpleConnection *connection = PURPLE_CONNECTION(object); |
855 PurpleConnection *connection = PURPLE_CONNECTION(object); |
| 775 PurpleConnectionPrivate *priv = NULL; |
856 PurpleConnectionPrivate *priv = NULL; |
| 776 GSList *buddies; |
857 |
| |
858 priv = purple_connection_get_instance_private(connection); |
| |
859 |
| |
860 g_clear_pointer(&priv->error_info, purple_connection_error_info_free); |
| |
861 |
| |
862 purple_str_wipe(priv->password); |
| |
863 g_free(priv->display_name); |
| |
864 g_free(priv->id); |
| |
865 |
| |
866 G_OBJECT_CLASS(purple_connection_parent_class)->finalize(object); |
| |
867 } |
| |
868 |
| |
869 static void |
| |
870 purple_connection_class_init(PurpleConnectionClass *klass) { |
| |
871 GObjectClass *obj_class = G_OBJECT_CLASS(klass); |
| |
872 |
| |
873 obj_class->get_property = purple_connection_get_property; |
| |
874 obj_class->set_property = purple_connection_set_property; |
| |
875 obj_class->dispose = purple_connection_dispose; |
| |
876 obj_class->finalize = purple_connection_finalize; |
| |
877 obj_class->constructed = purple_connection_constructed; |
| |
878 |
| |
879 klass->connect = purple_connection_default_connect; |
| |
880 klass->disconnect = purple_connection_default_disconnect; |
| |
881 |
| |
882 properties[PROP_ID] = g_param_spec_string( |
| |
883 "id", "id", |
| |
884 "The identifier of the account", |
| |
885 NULL, |
| |
886 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
| |
887 |
| |
888 properties[PROP_PROTOCOL] = g_param_spec_object( |
| |
889 "protocol", "Protocol", |
| |
890 "The protocol that the connection is using.", |
| |
891 PURPLE_TYPE_PROTOCOL, |
| |
892 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
| |
893 |
| |
894 properties[PROP_FLAGS] = g_param_spec_flags( |
| |
895 "flags", "Connection flags", |
| |
896 "The flags of the connection.", |
| |
897 PURPLE_TYPE_CONNECTION_FLAGS, 0, |
| |
898 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
| |
899 |
| |
900 properties[PROP_STATE] = g_param_spec_enum( |
| |
901 "state", "Connection state", |
| |
902 "The current state of the connection.", |
| |
903 PURPLE_TYPE_CONNECTION_STATE, PURPLE_CONNECTION_STATE_DISCONNECTED, |
| |
904 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
| |
905 |
| |
906 properties[PROP_ACCOUNT] = g_param_spec_object( |
| |
907 "account", "Account", |
| |
908 "The account using the connection.", PURPLE_TYPE_ACCOUNT, |
| |
909 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
| |
910 |
| |
911 properties[PROP_PASSWORD] = g_param_spec_string( |
| |
912 "password", "Password", |
| |
913 "The password used for connection.", NULL, |
| |
914 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
| |
915 |
| |
916 properties[PROP_DISPLAY_NAME] = g_param_spec_string( |
| |
917 "display-name", "Display name", |
| |
918 "Your name that appears to other people.", NULL, |
| |
919 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
| |
920 |
| |
921 g_object_class_install_properties(obj_class, PROP_LAST, properties); |
| |
922 } |
| |
923 |
| |
924 void |
| |
925 _purple_connection_new_unregister(PurpleAccount *account, const char *password, |
| |
926 PurpleAccountUnregistrationCb cb, |
| |
927 gpointer user_data) |
| |
928 { |
| |
929 PurpleConnection *gc; |
| |
930 PurpleProtocol *protocol; |
| |
931 |
| |
932 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
| |
933 |
| |
934 protocol = purple_account_get_protocol(account); |
| |
935 |
| |
936 if(protocol == NULL) { |
| |
937 gchar *message; |
| |
938 |
| |
939 message = g_strdup_printf(_("Missing protocol for %s"), |
| |
940 purple_account_get_username(account)); |
| |
941 purple_notify_error(NULL, _("Unregistration Error"), message, |
| |
942 NULL, purple_request_cpar_from_account(account)); |
| |
943 g_free(message); |
| |
944 return; |
| |
945 } |
| |
946 |
| |
947 if(!purple_account_is_disconnected(account)) { |
| |
948 purple_protocol_server_unregister_user(PURPLE_PROTOCOL_SERVER(protocol), |
| |
949 account, cb, user_data); |
| |
950 return; |
| |
951 } |
| |
952 |
| |
953 if(((password == NULL) || (*password == '\0')) && |
| |
954 !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) && |
| |
955 !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) |
| |
956 { |
| |
957 purple_debug_error("connection", "Cannot connect to account %s " |
| |
958 "without a password.", |
| |
959 purple_account_get_username(account)); |
| |
960 |
| |
961 return; |
| |
962 } |
| |
963 |
| |
964 gc = g_object_new( |
| |
965 PURPLE_TYPE_CONNECTION, |
| |
966 "protocol", protocol, |
| |
967 "account", account, |
| |
968 "password", password, |
| |
969 NULL); |
| |
970 |
| |
971 g_return_if_fail(gc != NULL); |
| |
972 |
| |
973 purple_debug_info("connection", "Unregistering. gc = %p", gc); |
| |
974 |
| |
975 purple_protocol_server_unregister_user(PURPLE_PROTOCOL_SERVER(protocol), |
| |
976 account, cb, user_data); |
| |
977 } |
| |
978 |
| |
979 gboolean |
| |
980 purple_connection_connect(PurpleConnection *connection, GError **error) { |
| |
981 PurpleConnectionClass *klass = NULL; |
| |
982 PurpleConnectionPrivate *priv = NULL; |
| |
983 |
| |
984 g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), FALSE); |
| |
985 |
| |
986 priv = purple_connection_get_instance_private(connection); |
| |
987 |
| |
988 if(!purple_account_is_disconnected(priv->account)) { |
| |
989 g_set_error(error, PURPLE_CONNECTION_ERROR, 0, |
| |
990 "account %s is not disconnected", |
| |
991 purple_account_get_username(priv->account)); |
| |
992 |
| |
993 return TRUE; |
| |
994 } |
| |
995 |
| |
996 if(((priv->password == NULL) || (*priv->password == '\0')) && |
| |
997 !(purple_protocol_get_options(priv->protocol) & OPT_PROTO_NO_PASSWORD) && |
| |
998 !(purple_protocol_get_options(priv->protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) |
| |
999 { |
| |
1000 g_set_error(error, PURPLE_CONNECTION_ERROR, 0, |
| |
1001 "Cannot connect to account %s without a password.", |
| |
1002 purple_account_get_username(priv->account)); |
| |
1003 |
| |
1004 return FALSE; |
| |
1005 } |
| |
1006 |
| |
1007 purple_debug_info("connection", "Connecting. connection = %p", |
| |
1008 connection); |
| |
1009 |
| |
1010 klass = PURPLE_CONNECTION_GET_CLASS(connection); |
| |
1011 if(klass != NULL && klass->connect != NULL) { |
| |
1012 return klass->connect(connection, error); |
| |
1013 } |
| |
1014 |
| |
1015 g_set_error(error, PURPLE_CONNECTION_ERROR, 0, |
| |
1016 "The connection for %s did not implement the connect method", |
| |
1017 purple_account_get_username(priv->account)); |
| |
1018 |
| |
1019 return FALSE; |
| |
1020 } |
| |
1021 |
| |
1022 gboolean |
| |
1023 purple_connection_disconnect(PurpleConnection *connection, GError **error) { |
| |
1024 PurpleConnectionClass *klass = NULL; |
| |
1025 PurpleConnectionPrivate *priv = NULL; |
| |
1026 GSList *buddies = NULL; |
| 777 gboolean remove = FALSE; |
1027 gboolean remove = FALSE; |
| 778 gpointer handle; |
1028 gboolean ret = TRUE; |
| 779 |
1029 gpointer handle = NULL; |
| 780 priv = purple_connection_get_instance_private(connection); |
1030 |
| 781 |
1031 g_return_val_if_fail(PURPLE_IS_CONNECTION(connection), FALSE); |
| 782 priv->is_finalizing = TRUE; |
1032 |
| 783 |
1033 /* We don't check if the connection's state is connected as everything |
| 784 handle = purple_connections_get_handle(); |
1034 * should be idempotent when doing cleanup. |
| 785 |
1035 */ |
| 786 purple_debug_info("connection", "Disconnecting connection %p", connection); |
1036 |
| 787 |
1037 priv = purple_connection_get_instance_private(connection); |
| |
1038 |
| |
1039 /* If we're not connecting, we'll need to remove stuff from our contacts |
| |
1040 * from the buddy list. |
| |
1041 */ |
| 788 if(priv->state != PURPLE_CONNECTION_STATE_CONNECTING) { |
1042 if(priv->state != PURPLE_CONNECTION_STATE_CONNECTING) { |
| 789 remove = TRUE; |
1043 remove = TRUE; |
| 790 } |
1044 } |
| 791 |
1045 |
| |
1046 handle = purple_connections_get_handle(); |
| |
1047 |
| |
1048 purple_debug_info("connection", "Disconnecting connection %p", connection); |
| |
1049 purple_connection_set_state(connection, |
| |
1050 PURPLE_CONNECTION_STATE_DISCONNECTING); |
| 792 purple_signal_emit(handle, "signing-off", connection); |
1051 purple_signal_emit(handle, "signing-off", connection); |
| 793 |
1052 |
| 794 g_slist_free_full(priv->active_chats, |
1053 g_slist_free_full(priv->active_chats, |
| 795 (GDestroyNotify)purple_chat_conversation_leave); |
1054 (GDestroyNotify)purple_chat_conversation_leave); |
| 796 |
1055 |
| 797 update_keepalive(connection, FALSE); |
1056 update_keepalive(connection, FALSE); |
| 798 |
1057 |
| 799 purple_protocol_close(priv->protocol, connection); |
1058 /* Dispatch to the connection's disconnect method. */ |
| |
1059 klass = PURPLE_CONNECTION_GET_CLASS(connection); |
| |
1060 if(klass != NULL && klass->disconnect != NULL) { |
| |
1061 ret = klass->disconnect(connection, error); |
| |
1062 } |
| 800 |
1063 |
| 801 /* Clear out the proto data that was freed in the protocol's close method */ |
1064 /* Clear out the proto data that was freed in the protocol's close method */ |
| 802 buddies = purple_blist_find_buddies(priv->account, NULL); |
1065 buddies = purple_blist_find_buddies(priv->account, NULL); |
| 803 while (buddies != NULL) { |
1066 while (buddies != NULL) { |
| 804 PurpleBuddy *buddy = buddies->data; |
1067 PurpleBuddy *buddy = buddies->data; |
| 805 purple_buddy_set_protocol_data(buddy, NULL); |
1068 purple_buddy_set_protocol_data(buddy, NULL); |
| 806 buddies = g_slist_delete_link(buddies, buddies); |
1069 buddies = g_slist_delete_link(buddies, buddies); |
| 807 } |
1070 } |
| 808 |
1071 |
| |
1072 /* Do the rest of our cleanup. */ |
| 809 connections = g_list_remove(connections, connection); |
1073 connections = g_list_remove(connections, connection); |
| 810 |
1074 |
| 811 purple_connection_set_state(connection, PURPLE_CONNECTION_STATE_DISCONNECTED); |
1075 purple_connection_set_state(connection, |
| |
1076 PURPLE_CONNECTION_STATE_DISCONNECTED); |
| 812 |
1077 |
| 813 if(remove) { |
1078 if(remove) { |
| 814 purple_blist_remove_account(priv->account); |
1079 purple_blist_remove_account(priv->account); |
| 815 } |
1080 } |
| 816 |
1081 |
| 825 purple_signal_emit(handle, "offline"); |
1090 purple_signal_emit(handle, "offline"); |
| 826 } |
1091 } |
| 827 |
1092 |
| 828 purple_debug_info("connection", "Destroying connection %p", connection); |
1093 purple_debug_info("connection", "Destroying connection %p", connection); |
| 829 |
1094 |
| 830 purple_account_set_connection(priv->account, NULL); |
1095 return ret; |
| 831 |
|
| 832 g_clear_pointer(&priv->error_info, purple_connection_error_info_free); |
|
| 833 |
|
| 834 if(priv->disconnect_timeout > 0) { |
|
| 835 g_source_remove(priv->disconnect_timeout); |
|
| 836 } |
|
| 837 |
|
| 838 purple_str_wipe(priv->password); |
|
| 839 g_free(priv->display_name); |
|
| 840 g_free(priv->id); |
|
| 841 |
|
| 842 G_OBJECT_CLASS(purple_connection_parent_class)->finalize(object); |
|
| 843 } |
|
| 844 |
|
| 845 static void |
|
| 846 purple_connection_class_init(PurpleConnectionClass *klass) { |
|
| 847 GObjectClass *obj_class = G_OBJECT_CLASS(klass); |
|
| 848 |
|
| 849 obj_class->get_property = purple_connection_get_property; |
|
| 850 obj_class->set_property = purple_connection_set_property; |
|
| 851 obj_class->finalize = purple_connection_finalize; |
|
| 852 obj_class->constructed = purple_connection_constructed; |
|
| 853 |
|
| 854 properties[PROP_ID] = g_param_spec_string( |
|
| 855 "id", "id", |
|
| 856 "The identifier of the account", |
|
| 857 NULL, |
|
| 858 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
|
| 859 |
|
| 860 properties[PROP_PROTOCOL] = g_param_spec_object( |
|
| 861 "protocol", "Protocol", |
|
| 862 "The protocol that the connection is using.", |
|
| 863 PURPLE_TYPE_PROTOCOL, |
|
| 864 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
|
| 865 |
|
| 866 properties[PROP_FLAGS] = g_param_spec_flags( |
|
| 867 "flags", "Connection flags", |
|
| 868 "The flags of the connection.", |
|
| 869 PURPLE_TYPE_CONNECTION_FLAGS, 0, |
|
| 870 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
|
| 871 |
|
| 872 properties[PROP_STATE] = g_param_spec_enum( |
|
| 873 "state", "Connection state", |
|
| 874 "The current state of the connection.", |
|
| 875 PURPLE_TYPE_CONNECTION_STATE, PURPLE_CONNECTION_STATE_DISCONNECTED, |
|
| 876 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
|
| 877 |
|
| 878 properties[PROP_ACCOUNT] = g_param_spec_object( |
|
| 879 "account", "Account", |
|
| 880 "The account using the connection.", PURPLE_TYPE_ACCOUNT, |
|
| 881 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); |
|
| 882 |
|
| 883 properties[PROP_PASSWORD] = g_param_spec_string( |
|
| 884 "password", "Password", |
|
| 885 "The password used for connection.", NULL, |
|
| 886 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
|
| 887 |
|
| 888 properties[PROP_DISPLAY_NAME] = g_param_spec_string( |
|
| 889 "display-name", "Display name", |
|
| 890 "Your name that appears to other people.", NULL, |
|
| 891 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); |
|
| 892 |
|
| 893 g_object_class_install_properties(obj_class, PROP_LAST, properties); |
|
| 894 } |
|
| 895 |
|
| 896 void |
|
| 897 _purple_connection_new(PurpleAccount *account, gboolean is_registration, |
|
| 898 const gchar *password) |
|
| 899 { |
|
| 900 PurpleConnection *connection = NULL; |
|
| 901 PurpleConnectionPrivate *priv = NULL; |
|
| 902 PurpleProtocol *protocol = NULL; |
|
| 903 |
|
| 904 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
|
| 905 |
|
| 906 if(!purple_account_is_disconnected(account)) { |
|
| 907 return; |
|
| 908 } |
|
| 909 |
|
| 910 protocol = purple_account_get_protocol(account); |
|
| 911 |
|
| 912 if(protocol == NULL) { |
|
| 913 gchar *message; |
|
| 914 |
|
| 915 message = g_strdup_printf(_("Missing protocol for %s"), |
|
| 916 purple_account_get_username(account)); |
|
| 917 purple_notify_error(NULL, is_registration ? _("Registration Error") : |
|
| 918 _("Connection Error"), message, NULL, |
|
| 919 purple_request_cpar_from_account(account)); |
|
| 920 g_free(message); |
|
| 921 |
|
| 922 return; |
|
| 923 } |
|
| 924 |
|
| 925 if(is_registration) { |
|
| 926 if(!PURPLE_PROTOCOL_IMPLEMENTS(protocol, SERVER, register_user)) { |
|
| 927 return; |
|
| 928 } |
|
| 929 } else { |
|
| 930 if(((password == NULL) || (*password == '\0')) && |
|
| 931 !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) && |
|
| 932 !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) |
|
| 933 { |
|
| 934 purple_debug_error("connection", "Cannot connect to account %s " |
|
| 935 "without a password.", |
|
| 936 purple_account_get_username(account)); |
|
| 937 |
|
| 938 return; |
|
| 939 } |
|
| 940 } |
|
| 941 |
|
| 942 connection = g_object_new( |
|
| 943 PURPLE_TYPE_CONNECTION, |
|
| 944 "protocol", protocol, |
|
| 945 "account", account, |
|
| 946 "password", password, |
|
| 947 NULL); |
|
| 948 |
|
| 949 g_return_if_fail(connection != NULL); |
|
| 950 |
|
| 951 priv = purple_connection_get_instance_private(connection); |
|
| 952 |
|
| 953 if(is_registration) { |
|
| 954 purple_debug_info("connection", "Registering. connection = %p", |
|
| 955 connection); |
|
| 956 |
|
| 957 /* set this so we don't auto-reconnect after registering */ |
|
| 958 priv->wants_to_die = TRUE; |
|
| 959 |
|
| 960 purple_protocol_server_register_user(PURPLE_PROTOCOL_SERVER(protocol), |
|
| 961 account); |
|
| 962 } else { |
|
| 963 purple_debug_info("connection", "Connecting. connection = %p", |
|
| 964 connection); |
|
| 965 |
|
| 966 purple_protocol_login(protocol, account); |
|
| 967 } |
|
| 968 } |
|
| 969 |
|
| 970 void |
|
| 971 _purple_connection_new_unregister(PurpleAccount *account, const char *password, |
|
| 972 PurpleAccountUnregistrationCb cb, |
|
| 973 gpointer user_data) |
|
| 974 { |
|
| 975 /* Lots of copy/pasted code to avoid API changes. You might want to integrate that into the previous function when possible. */ |
|
| 976 PurpleConnection *gc; |
|
| 977 PurpleProtocol *protocol; |
|
| 978 |
|
| 979 g_return_if_fail(PURPLE_IS_ACCOUNT(account)); |
|
| 980 |
|
| 981 protocol = purple_account_get_protocol(account); |
|
| 982 |
|
| 983 if(protocol == NULL) { |
|
| 984 gchar *message; |
|
| 985 |
|
| 986 message = g_strdup_printf(_("Missing protocol for %s"), |
|
| 987 purple_account_get_username(account)); |
|
| 988 purple_notify_error(NULL, _("Unregistration Error"), message, |
|
| 989 NULL, purple_request_cpar_from_account(account)); |
|
| 990 g_free(message); |
|
| 991 return; |
|
| 992 } |
|
| 993 |
|
| 994 if(!purple_account_is_disconnected(account)) { |
|
| 995 purple_protocol_server_unregister_user(PURPLE_PROTOCOL_SERVER(protocol), |
|
| 996 account, cb, user_data); |
|
| 997 return; |
|
| 998 } |
|
| 999 |
|
| 1000 if(((password == NULL) || (*password == '\0')) && |
|
| 1001 !(purple_protocol_get_options(protocol) & OPT_PROTO_NO_PASSWORD) && |
|
| 1002 !(purple_protocol_get_options(protocol) & OPT_PROTO_PASSWORD_OPTIONAL)) |
|
| 1003 { |
|
| 1004 purple_debug_error("connection", "Cannot connect to account %s without " |
|
| 1005 "a password.\n", purple_account_get_username(account)); |
|
| 1006 |
|
| 1007 return; |
|
| 1008 } |
|
| 1009 |
|
| 1010 gc = g_object_new( |
|
| 1011 PURPLE_TYPE_CONNECTION, |
|
| 1012 "protocol", protocol, |
|
| 1013 "account", account, |
|
| 1014 "password", password, |
|
| 1015 NULL); |
|
| 1016 |
|
| 1017 g_return_if_fail(gc != NULL); |
|
| 1018 |
|
| 1019 purple_debug_info("connection", "Unregistering. gc = %p\n", gc); |
|
| 1020 |
|
| 1021 purple_protocol_server_unregister_user(PURPLE_PROTOCOL_SERVER(protocol), |
|
| 1022 account, cb, user_data); |
|
| 1023 } |
1096 } |
| 1024 |
1097 |
| 1025 /************************************************************************** |
1098 /************************************************************************** |
| 1026 * Connections API |
1099 * Connections API |
| 1027 **************************************************************************/ |
1100 **************************************************************************/ |