1 #include "internal.h" 2 3 #include <string.h> 4 #include <ctype.h> 5 6 #include <gdk/gdk.h> 7 #include <gtk/gtkplug.h> 8 9 #include <gtkplugin.h> 10 11 #include <debug.h> 12 #include <util.h> 13 #include <conversation.h> 14 15 #include "pe_blist.h" 16 #include "state_ui.h" 17 #include "state.h" 18 19 GHashTable *encryption_state_table; /* name -> EncryptionState */ 20 21 /* Helper function: */ 22 static void reset_state_struct(const PurpleAccount* account, 23 const gchar* name, 24 EncryptionState* state); 25 26 void PE_state_init() { 27 encryption_state_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); 28 } 29 30 void PE_state_delete() { 31 g_hash_table_destroy(encryption_state_table); 32 } 33 34 EncryptionState* PE_get_state(PurpleConversation* conv) { 35 if (conv == NULL) return NULL; 36 37 EncryptionState *state = purple_conversation_get_data(conv, "PE_state"); 38 39 if (state == NULL) { 40 state = g_malloc(sizeof(EncryptionState)); 41 purple_conversation_set_data(conv, "PE_state", state); 42 43 // should probably change this to use some prefs info rather than our buddy list stuff 44 state->outgoing_encrypted = 45 PE_get_buddy_default_autoencrypt(purple_conversation_get_account(conv), 46 purple_conversation_get_name(conv)); 47 48 if (conv == NULL) { 49 return NULL; 50 } 51 52 state->has_been_notified = 53 PE_get_default_notified(purple_conversation_get_account(conv), 54 purple_conversation_get_name(conv)); 55 56 state->incoming_encrypted = FALSE; 57 state->is_capable = FALSE; 58 } 59 return state; 60 } 61 62 void PE_reset_state(PurpleConversation* conv) { 63 EncryptionState *state; 64 65 if (conv == NULL) return; 66 67 state = PE_get_state(conv); 68 69 reset_state_struct(purple_conversation_get_account(conv), purple_conversation_get_name(conv), state); 70 } 71 72 void PE_free_state(PurpleConversation* conv) { 73 EncryptionState *state; 74 75 if (conv == NULL) return; 76 77 state = PE_get_state(conv); 78 79 if (state) { 80 g_free(state); 81 } 82 } 83 84 static void reset_state_struct(const PurpleAccount* account, const gchar* name, 85 EncryptionState* state) { 86 87 state->outgoing_encrypted = PE_get_buddy_default_autoencrypt(account, name); 88 state->has_been_notified = PE_get_default_notified(account, name); 89 90 state->incoming_encrypted = FALSE; 91 state->is_capable = FALSE; 92 } 93 94 void PE_set_tx_encryption(PurpleConversation* conv, gboolean do_encrypt) { 95 EncryptionState *state; 96 97 if (conv == NULL) return; 98 99 state = PE_get_state(conv); 100 101 if (state->outgoing_encrypted != do_encrypt) { 102 state->outgoing_encrypted = do_encrypt; 103 PE_sync_state(conv); 104 } 105 } 106 107 void PE_set_capable(PurpleConversation* conv, gboolean cap) { 108 EncryptionState *state; 109 110 if (conv == NULL) return; 111 112 state = PE_get_state(conv); 113 114 if (state->is_capable != cap) { 115 state->is_capable = cap; 116 if (state->outgoing_encrypted == FALSE) { 117 PE_sync_state(conv); 118 } 119 } 120 } 121 122 void PE_set_rx_encryption(PurpleConversation *conv, gboolean incoming_encrypted) { 123 EncryptionState *state; 124 125 if (conv == NULL) return; 126 127 state = PE_get_state(conv); 128 129 if (state->incoming_encrypted != incoming_encrypted) { 130 state->incoming_encrypted = incoming_encrypted; 131 PE_set_rx_encryption_icon(conv, incoming_encrypted); 132 } 133 } 134 135 gboolean PE_get_tx_encryption(PurpleConversation *conv) { 136 EncryptionState *state = PE_get_state(conv); 137 138 if (state == NULL) return FALSE; 139 140 return state->outgoing_encrypted; 141 } 142 143 void PE_sync_state(PurpleConversation *conv) { 144 EncryptionState *state; 145 146 if (conv == NULL) return; 147 148 state = PE_get_state(conv); 149 PE_set_rx_encryption_icon(conv, state->incoming_encrypted); 150 PE_set_tx_encryption_icon(conv, state->outgoing_encrypted, state->is_capable); 151 } 152 153 gboolean PE_has_been_notified(PurpleConversation *conv) { 154 EncryptionState *state = PE_get_state(conv); 155 156 if (state == NULL) return TRUE; 157 158 return state->has_been_notified; 159 } 160 161 void PE_set_notified(PurpleConversation *conv, gboolean new_state) { 162 EncryptionState *state; 163 164 if (conv == NULL) return; 165 166 state = PE_get_state(conv); 167 168 state->has_been_notified = new_state; 169 } 170 171 172 gboolean PE_get_default_notified(const PurpleAccount *account, const gchar* name) { 173 /* Most protocols no longer have a notify message, since they don't do HTML */ 174 175 /* The only special case here is Oscar/TOC: If the other user's name is all */ 176 /* digits, then they're ICQ, so we pretend that we already notified them */ 177 178 const char* protocol_id = purple_account_get_protocol_id(account); 179 180 if (strcmp(protocol_id, "prpl-toc") == 0 || strcmp(protocol_id, "prpl-oscar") == 0) { 181 182 while(*name != 0) { 183 if (!isdigit(*name++)) { 184 /* not ICQ */ 185 return FALSE; 186 } 187 } 188 /* Hrm. must be ICQ */ 189 return TRUE; 190 } 191 192 /* default to notifying next time, if protocol allows it */ 193 194 return FALSE; 195 } 196 197 198