| 23 #include <glib/gi18n-lib.h> |
23 #include <glib/gi18n-lib.h> |
| 24 |
24 |
| 25 #include "purpleircv3messagehandlers.h" |
25 #include "purpleircv3messagehandlers.h" |
| 26 |
26 |
| 27 #include "purpleircv3connection.h" |
27 #include "purpleircv3connection.h" |
| 28 #include "purpleircv3constants.h" |
|
| 29 #include "purpleircv3core.h" |
28 #include "purpleircv3core.h" |
| 30 #include "purpleircv3ctcp.h" |
|
| 31 #include "purpleircv3formatting.h" |
|
| 32 #include "purpleircv3source.h" |
|
| 33 |
|
| 34 /****************************************************************************** |
|
| 35 * Fallback |
|
| 36 *****************************************************************************/ |
|
| 37 gboolean |
|
| 38 purple_ircv3_message_handler_fallback(PurpleIRCv3Message *message, |
|
| 39 G_GNUC_UNUSED GError **error, |
|
| 40 gpointer data) |
|
| 41 { |
|
| 42 PurpleIRCv3Connection *connection = data; |
|
| 43 char *new_command = NULL; |
|
| 44 const char *command = NULL; |
|
| 45 |
|
| 46 command = purple_ircv3_message_get_command(message); |
|
| 47 |
|
| 48 new_command = g_strdup_printf(_("unknown command '%s'"), command); |
|
| 49 purple_ircv3_message_set_command(message, new_command); |
|
| 50 purple_ircv3_connection_add_status_message(connection, message); |
|
| 51 |
|
| 52 g_clear_pointer(&new_command, g_free); |
|
| 53 |
|
| 54 return TRUE; |
|
| 55 } |
|
| 56 |
|
| 57 /****************************************************************************** |
|
| 58 * Status Messages |
|
| 59 *****************************************************************************/ |
|
| 60 gboolean |
|
| 61 purple_ircv3_message_handler_status(PurpleIRCv3Message *message, |
|
| 62 G_GNUC_UNUSED GError **error, |
|
| 63 gpointer data) |
|
| 64 { |
|
| 65 purple_ircv3_connection_add_status_message(data, message); |
|
| 66 |
|
| 67 return TRUE; |
|
| 68 } |
|
| 69 |
|
| 70 gboolean |
|
| 71 purple_ircv3_message_handler_status_ignore_param0(PurpleIRCv3Message *message, |
|
| 72 GError **error, |
|
| 73 gpointer data) |
|
| 74 { |
|
| 75 GStrv params = NULL; |
|
| 76 GStrv new_params = NULL; |
|
| 77 guint n_params = 0; |
|
| 78 |
|
| 79 params = purple_ircv3_message_get_params(message); |
|
| 80 if(params != NULL) { |
|
| 81 n_params = g_strv_length(params); |
|
| 82 } |
|
| 83 |
|
| 84 if(n_params <= 1) { |
|
| 85 g_set_error(error, PURPLE_IRCV3_DOMAIN, 0, |
|
| 86 "expected n_params > 1, got %u", n_params); |
|
| 87 |
|
| 88 return FALSE; |
|
| 89 } |
|
| 90 |
|
| 91 /* We need to make a copy because otherwise we'd get a use after free in |
|
| 92 * set_params. |
|
| 93 */ |
|
| 94 new_params = g_strdupv(params + 1); |
|
| 95 purple_ircv3_message_set_params(message, new_params); |
|
| 96 g_clear_pointer(&new_params, g_strfreev); |
|
| 97 |
|
| 98 purple_ircv3_connection_add_status_message(data, message); |
|
| 99 |
|
| 100 return TRUE; |
|
| 101 } |
|
| 102 |
29 |
| 103 /****************************************************************************** |
30 /****************************************************************************** |
| 104 * General Commands |
31 * General Commands |
| 105 *****************************************************************************/ |
32 *****************************************************************************/ |
| 106 gboolean |
33 gboolean |
| 107 purple_ircv3_message_handler_ping(PurpleIRCv3Message *message, |
34 purple_ircv3_message_handler_privmsg(G_GNUC_UNUSED IbisClient *client, |
| 108 G_GNUC_UNUSED GError **error, |
35 const char *command, |
| 109 gpointer data) |
36 IbisMessage *ibis_message, gpointer data) |
| 110 { |
|
| 111 PurpleIRCv3Connection *connection = data; |
|
| 112 GStrv params = NULL; |
|
| 113 |
|
| 114 params = purple_ircv3_message_get_params(message); |
|
| 115 |
|
| 116 if(params != NULL && g_strv_length(params) == 1) { |
|
| 117 purple_ircv3_connection_writef(connection, "PONG %s", params[0]); |
|
| 118 } else { |
|
| 119 purple_ircv3_connection_writef(connection, "PONG"); |
|
| 120 } |
|
| 121 |
|
| 122 return TRUE; |
|
| 123 } |
|
| 124 |
|
| 125 gboolean |
|
| 126 purple_ircv3_message_handler_privmsg(PurpleIRCv3Message *v3_message, |
|
| 127 G_GNUC_UNUSED GError **error, |
|
| 128 gpointer data) |
|
| 129 { |
37 { |
| 130 PurpleIRCv3Connection *connection = data; |
38 PurpleIRCv3Connection *connection = data; |
| 131 PurpleContact *contact = NULL; |
39 PurpleContact *contact = NULL; |
| 132 PurpleConversation *conversation = NULL; |
40 PurpleConversation *conversation = NULL; |
| 133 PurpleMessage *message = NULL; |
41 PurpleMessage *message = NULL; |
| 134 PurpleMessageFlags flags = PURPLE_MESSAGE_RECV; |
42 PurpleMessageFlags flags = PURPLE_MESSAGE_RECV; |
| 135 GDateTime *dt = NULL; |
43 GDateTime *dt = NULL; |
| 136 GHashTable *tags = NULL; |
44 IbisTags *tags = NULL; |
| 137 GStrv params = NULL; |
45 GStrv params = NULL; |
| 138 gpointer raw_id = NULL; |
|
| 139 gpointer raw_timestamp = NULL; |
|
| 140 char *nick = NULL; |
46 char *nick = NULL; |
| 141 char *stripped = NULL; |
47 char *stripped = NULL; |
| 142 const char *command = NULL; |
|
| 143 const char *id = NULL; |
48 const char *id = NULL; |
| |
49 const char *raw_tag = NULL; |
| 144 const char *source = NULL; |
50 const char *source = NULL; |
| 145 const char *target = NULL; |
51 const char *target = NULL; |
| 146 |
52 |
| 147 command = purple_ircv3_message_get_command(v3_message); |
53 params = ibis_message_get_params(ibis_message); |
| 148 params = purple_ircv3_message_get_params(v3_message); |
54 source = ibis_message_get_source(ibis_message); |
| 149 source = purple_ircv3_message_get_source(v3_message); |
55 tags = ibis_message_get_tags(ibis_message); |
| 150 tags = purple_ircv3_message_get_tags(v3_message); |
|
| 151 |
56 |
| 152 if(params == NULL) { |
57 if(params == NULL) { |
| 153 g_warning("privmsg received with no parameters"); |
58 g_warning("privmsg received with no parameters"); |
| 154 |
59 |
| 155 return FALSE; |
60 return FALSE; |
| 188 PURPLE_CONTACT_INFO(contact), |
93 PURPLE_CONTACT_INFO(contact), |
| 189 FALSE, NULL); |
94 FALSE, NULL); |
| 190 } |
95 } |
| 191 } |
96 } |
| 192 |
97 |
| |
98 if(purple_strequal(command, IBIS_MSG_NOTICE)) { |
| |
99 flags |= PURPLE_MESSAGE_NOTIFY; |
| |
100 } |
| |
101 |
| 193 /* Grab the msgid if one was provided. */ |
102 /* Grab the msgid if one was provided. */ |
| 194 if(g_hash_table_lookup_extended(tags, "msgid", NULL, &raw_id)) { |
103 raw_tag = ibis_tags_lookup(tags, "msgid"); |
| 195 if(!purple_strempty(raw_id)) { |
104 if(!purple_strempty(raw_tag)) { |
| 196 id = raw_id; |
105 id = raw_tag; |
| 197 } |
|
| 198 } |
|
| 199 |
|
| 200 if(purple_strequal(command, PURPLE_IRCV3_MSG_NOTICE)) { |
|
| 201 flags |= PURPLE_MESSAGE_NOTIFY; |
|
| 202 } |
106 } |
| 203 |
107 |
| 204 /* Determine the timestamp of the message. */ |
108 /* Determine the timestamp of the message. */ |
| 205 if(g_hash_table_lookup_extended(tags, "time", NULL, &raw_timestamp)) { |
109 raw_tag = ibis_tags_lookup(tags, "time"); |
| 206 const char *timestamp = raw_timestamp; |
110 if(!purple_strempty(raw_tag)) { |
| 207 |
111 GTimeZone *tz = g_time_zone_new_utc(); |
| 208 if(!purple_strempty(timestamp)) { |
112 |
| 209 GTimeZone *tz = g_time_zone_new_utc(); |
113 dt = g_date_time_new_from_iso8601(raw_tag, tz); |
| 210 |
114 |
| 211 dt = g_date_time_new_from_iso8601(timestamp, tz); |
115 g_time_zone_unref(tz); |
| 212 |
|
| 213 g_time_zone_unref(tz); |
|
| 214 } |
|
| 215 } |
116 } |
| 216 |
117 |
| 217 /* If the server didn't provide a time, use the current local time. */ |
118 /* If the server didn't provide a time, use the current local time. */ |
| 218 if(dt == NULL) { |
119 if(dt == NULL) { |
| 219 dt = g_date_time_new_now_local(); |
120 dt = g_date_time_new_now_local(); |
| 220 } |
121 } |
| 221 |
122 |
| 222 stripped = purple_ircv3_formatting_strip(params[1]); |
123 stripped = ibis_formatting_strip(params[1]); |
| 223 message = g_object_new( |
124 message = g_object_new( |
| 224 PURPLE_TYPE_MESSAGE, |
125 PURPLE_TYPE_MESSAGE, |
| 225 "author", source, |
126 "author", source, |
| 226 "contents", stripped, |
127 "contents", stripped, |
| 227 "flags", flags, |
128 "flags", flags, |
| 231 g_free(stripped); |
132 g_free(stripped); |
| 232 |
133 |
| 233 g_date_time_unref(dt); |
134 g_date_time_unref(dt); |
| 234 |
135 |
| 235 /* Check if this is a CTCP message. */ |
136 /* Check if this is a CTCP message. */ |
| 236 if(!purple_ircv3_ctcp_handle(connection, conversation, message)) { |
137 if(ibis_message_get_ctcp(ibis_message)) { |
| 237 purple_conversation_write_message(conversation, message); |
138 /* TODO: later... */ |
| 238 } |
139 } |
| |
140 |
| |
141 purple_conversation_write_message(conversation, message); |
| 239 |
142 |
| 240 g_clear_pointer(&nick, g_free); |
143 g_clear_pointer(&nick, g_free); |
| 241 g_clear_object(&message); |
144 g_clear_object(&message); |
| 242 |
145 |
| 243 return TRUE; |
146 return TRUE; |
| 244 } |
147 } |
| 245 |
148 |
| 246 gboolean |
149 gboolean |
| 247 purple_ircv3_message_handler_topic(PurpleIRCv3Message *message, |
150 purple_ircv3_message_handler_topic(G_GNUC_UNUSED IbisClient *client, |
| 248 GError **error, |
151 const char *command, IbisMessage *message, |
| 249 gpointer data) |
152 gpointer data) |
| 250 { |
153 { |
| 251 PurpleIRCv3Connection *connection = data; |
154 PurpleIRCv3Connection *connection = data; |
| 252 PurpleConversation *conversation = NULL; |
155 PurpleConversation *conversation = NULL; |
| 253 GStrv params = NULL; |
156 GStrv params = NULL; |
| 254 const char *channel = NULL; |
157 const char *channel = NULL; |
| 255 const char *command = NULL; |
|
| 256 const char *topic = NULL; |
158 const char *topic = NULL; |
| 257 guint n_params = 0; |
159 guint n_params = 0; |
| 258 |
160 |
| 259 command = purple_ircv3_message_get_command(message); |
161 params = ibis_message_get_params(message); |
| 260 params = purple_ircv3_message_get_params(message); |
|
| 261 n_params = g_strv_length(params); |
162 n_params = g_strv_length(params); |
| 262 |
163 |
| 263 if(purple_strequal(command, PURPLE_IRCV3_MSG_TOPIC)) { |
164 if(purple_strequal(command, IBIS_MSG_TOPIC)) { |
| 264 if(n_params != 2) { |
165 if(n_params != 2) { |
| 265 g_set_error(error, PURPLE_IRCV3_DOMAIN, 0, |
166 g_message("received TOPIC with %u parameters, expected 2", |
| 266 "received TOPIC with %u parameters, expected 2", |
167 n_params); |
| 267 n_params); |
|
| 268 |
168 |
| 269 return FALSE; |
169 return FALSE; |
| 270 } |
170 } |
| 271 |
171 |
| 272 channel = params[0]; |
172 channel = params[0]; |
| 273 topic = params[1]; |
173 topic = params[1]; |
| 274 } else if(purple_strequal(command, PURPLE_IRCV3_RPL_NOTOPIC)) { |
174 } else if(purple_strequal(command, IBIS_RPL_NOTOPIC)) { |
| 275 if(n_params != 3) { |
175 if(n_params != 3) { |
| 276 g_set_error(error, PURPLE_IRCV3_DOMAIN, 0, |
176 g_message("received RPL_NOTOPIC with %u parameters, expected 3", |
| 277 "received RPL_NOTOPIC with %u parameters, expected 3", |
177 n_params); |
| 278 n_params); |
|
| 279 |
178 |
| 280 return FALSE; |
179 return FALSE; |
| 281 } |
180 } |
| 282 |
181 |
| 283 channel = params[1]; |
182 channel = params[1]; |
| 284 topic = ""; |
183 topic = ""; |
| 285 } else if(purple_strequal(command, PURPLE_IRCV3_RPL_TOPIC)) { |
184 } else if(purple_strequal(command, IBIS_RPL_TOPIC)) { |
| 286 if(n_params != 3) { |
185 if(n_params != 3) { |
| 287 g_set_error(error, PURPLE_IRCV3_DOMAIN, 0, |
186 g_message("received RPL_TOPIC with %u parameters, expected 3", |
| 288 "received RPL_TOPIC with %u parameters, expected 3", |
187 n_params); |
| 289 n_params); |
|
| 290 |
188 |
| 291 return FALSE; |
189 return FALSE; |
| 292 } |
190 } |
| 293 |
191 |
| 294 channel = params[1]; |
192 channel = params[1]; |
| 295 topic = params[2]; |
193 topic = params[2]; |
| 296 } else { |
194 } else { |
| 297 g_set_error(error, PURPLE_IRCV3_DOMAIN, 0, "unexpected command %s", |
195 g_message("unexpected command %s", command); |
| 298 command); |
|
| 299 |
196 |
| 300 return FALSE; |
197 return FALSE; |
| 301 } |
198 } |
| 302 |
199 |
| 303 conversation = purple_ircv3_connection_find_or_create_conversation(connection, |
200 conversation = purple_ircv3_connection_find_or_create_conversation(connection, |
| 304 channel); |
201 channel); |
| 305 if(!PURPLE_IS_CONVERSATION(conversation)) { |
202 if(!PURPLE_IS_CONVERSATION(conversation)) { |
| 306 g_set_error(error, PURPLE_IRCV3_DOMAIN, 0, |
203 g_message("failed to find or create channel '%s'", channel); |
| 307 "failed to find or create channel '%s'", channel); |
|
| 308 |
204 |
| 309 return FALSE; |
205 return FALSE; |
| 310 } |
206 } |
| 311 |
207 |
| 312 purple_conversation_set_topic(conversation, topic); |
208 purple_conversation_set_topic(conversation, topic); |