1 /*
2 * SkypeWeb Plugin for libpurple/Pidgin
3 * Copyright (c) 2014-2020 Eion Robb
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "libskypeweb.h"
20 #include "skypeweb_connection.h"
21 #include "skypeweb_contacts.h"
22 #include "skypeweb_login.h"
23 #include "skypeweb_messages.h"
24 #include "skypeweb_util.h"
25
26 void
skypeweb_do_all_the_things(SkypeWebAccount * sa)27 skypeweb_do_all_the_things(SkypeWebAccount *sa)
28 {
29 skypeweb_get_vdms_token(sa);
30
31 if (!sa->username) {
32 skypeweb_get_self_details(sa);
33 } else
34 if (sa->registration_token) {
35 skypeweb_get_self_details(sa);
36
37 if (sa->authcheck_timeout)
38 g_source_remove(sa->authcheck_timeout);
39 skypeweb_check_authrequests(sa);
40 sa->authcheck_timeout = g_timeout_add_seconds(120, (GSourceFunc)skypeweb_check_authrequests, sa);
41 purple_connection_set_state(sa->pc, PURPLE_CONNECTION_CONNECTED);
42
43 skypeweb_get_friend_list(sa);
44 skypeweb_poll(sa);
45
46 skype_web_get_offline_history(sa);
47
48 skypeweb_set_status(sa->account, purple_account_get_active_status(sa->account));
49 } else {
50 //Too soon!
51 skypeweb_get_registration_token(sa);
52 }
53
54
55 }
56
57
58 /******************************************************************************/
59 /* PRPL functions */
60 /******************************************************************************/
61
62 static const char *
skypeweb_list_icon(PurpleAccount * account,PurpleBuddy * buddy)63 skypeweb_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
64 {
65
66 if (buddy != NULL) {
67 const gchar *buddy_name = purple_buddy_get_name(buddy);
68 if (buddy_name && SKYPEWEB_BUDDY_IS_MSN(buddy_name)) {
69 return "msn";
70 }
71 }
72 return "skype";
73 }
74
75 static gchar *
skypeweb_status_text(PurpleBuddy * buddy)76 skypeweb_status_text(PurpleBuddy *buddy)
77 {
78 SkypeWebBuddy *sbuddy = purple_buddy_get_protocol_data(buddy);
79
80 if (sbuddy && sbuddy->mood && *(sbuddy->mood))
81 {
82 gchar *stripped = purple_markup_strip_html(sbuddy->mood);
83 gchar *escaped = g_markup_printf_escaped("%s", stripped);
84
85 g_free(stripped);
86
87 return escaped;
88 }
89
90 return NULL;
91 }
92
93 void
skypeweb_tooltip_text(PurpleBuddy * buddy,PurpleNotifyUserInfo * user_info,gboolean full)94 skypeweb_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full)
95 {
96 SkypeWebBuddy *sbuddy = purple_buddy_get_protocol_data(buddy);
97
98 if (sbuddy)
99 {
100 PurplePresence *presence;
101 PurpleStatus *status;
102 SkypeWebBuddy *sbuddy = purple_buddy_get_protocol_data(buddy);
103
104 presence = purple_buddy_get_presence(buddy);
105 status = purple_presence_get_active_status(presence);
106 purple_notify_user_info_add_pair_html(user_info, _("Status"), purple_status_get_name(status));
107 if (sbuddy->mood && *sbuddy->mood) {
108 gchar *stripped = purple_markup_strip_html(sbuddy->mood);
109 gchar *escaped = g_markup_printf_escaped("%s", stripped);
110
111 purple_notify_user_info_add_pair_html(user_info, _("Message"), escaped);
112
113 g_free(stripped);
114 g_free(escaped);
115 }
116
117 if (sbuddy->display_name && *sbuddy->display_name) {
118 gchar *escaped = g_markup_printf_escaped("%s", sbuddy->display_name);
119 purple_notify_user_info_add_pair_html(user_info, "Alias", escaped);
120 g_free(escaped);
121 }
122 if (sbuddy->fullname && *sbuddy->fullname) {
123 gchar *escaped = g_markup_printf_escaped("%s", sbuddy->fullname);
124 purple_notify_user_info_add_pair_html(user_info, "Full Name", escaped);
125 g_free(escaped);
126 }
127 }
128 }
129
130 const gchar *
skypeweb_list_emblem(PurpleBuddy * buddy)131 skypeweb_list_emblem(PurpleBuddy *buddy)
132 {
133 if (buddy != NULL) {
134 //SkypeWebBuddy *sbuddy = purple_buddy_get_protocol_data(buddy);
135 const gchar *buddy_name = purple_buddy_get_name(buddy);
136
137 if (buddy_name && SKYPEWEB_BUDDY_IS_BOT(buddy_name)) {
138 return "bot";
139 }
140 }
141 return NULL;
142 }
143
144 GList *
skypeweb_status_types(PurpleAccount * account)145 skypeweb_status_types(PurpleAccount *account)
146 {
147 GList *types = NULL;
148 PurpleStatusType *status;
149
150 status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, FALSE, FALSE, FALSE);
151 types = g_list_append(types, status);
152
153 status = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, SKYPEWEB_STATUS_ONLINE, _("Online"), TRUE, TRUE, FALSE, "message", "Mood", purple_value_new(PURPLE_TYPE_STRING), NULL);
154 types = g_list_append(types, status);
155 status = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, SKYPEWEB_STATUS_AWAY, _("Away"), TRUE, TRUE, FALSE, "message", "Mood", purple_value_new(PURPLE_TYPE_STRING), NULL);
156 types = g_list_append(types, status);
157 // status = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY, SKYPEWEB_STATUS_AWAY, _("Not Available"), TRUE, TRUE, FALSE, "message", "Mood", purple_value_new(PURPLE_TYPE_STRING), NULL);
158 // types = g_list_append(types, status);
159 status = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, SKYPEWEB_STATUS_BUSY, _("Do Not Disturb"), TRUE, TRUE, FALSE, "message", "Mood", purple_value_new(PURPLE_TYPE_STRING), NULL);
160 types = g_list_append(types, status);
161 status = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE, SKYPEWEB_STATUS_HIDDEN, _("Invisible"), TRUE, TRUE, FALSE, "message", "Mood", purple_value_new(PURPLE_TYPE_STRING), NULL);
162 types = g_list_append(types, status);
163 status = purple_status_type_new_with_attrs(PURPLE_STATUS_OFFLINE, SKYPEWEB_STATUS_OFFLINE, _("Offline"), TRUE, TRUE, FALSE, "message", "Mood", purple_value_new(PURPLE_TYPE_STRING), NULL);
164 types = g_list_append(types, status);
165
166 return types;
167 }
168
169
170 static GList *
skypeweb_chat_info(PurpleConnection * gc)171 skypeweb_chat_info(PurpleConnection *gc)
172 {
173 GList *m = NULL;
174 PurpleProtocolChatEntry *pce;
175
176 pce = g_new0(PurpleProtocolChatEntry, 1);
177 pce->label = _("Skype Name");
178 pce->identifier = "chatname";
179 pce->required = TRUE;
180 m = g_list_append(m, pce);
181
182 /*pce = g_new0(PurpleProtocolChatEntry, 1);
183 pce->label = _("Password");
184 pce->identifier = "password";
185 pce->required = FALSE;
186 m = g_list_append(m, pce);*/
187
188 return m;
189 }
190
191 static GHashTable *
skypeweb_chat_info_defaults(PurpleConnection * gc,const char * chatname)192 skypeweb_chat_info_defaults(PurpleConnection *gc, const char *chatname)
193 {
194 GHashTable *defaults;
195 defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
196 if (chatname != NULL)
197 {
198 g_hash_table_insert(defaults, "chatname", g_strdup(chatname));
199 }
200 return defaults;
201 }
202
203 static gchar *
skypeweb_get_chat_name(GHashTable * data)204 skypeweb_get_chat_name(GHashTable *data)
205 {
206 gchar *temp;
207
208 if (data == NULL)
209 return NULL;
210
211 temp = g_hash_table_lookup(data, "chatname");
212
213 if (temp == NULL)
214 return NULL;
215
216 return g_strdup(temp);
217 }
218
219
220 static void
skypeweb_join_chat(PurpleConnection * pc,GHashTable * data)221 skypeweb_join_chat(PurpleConnection *pc, GHashTable *data)
222 {
223 SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
224 gchar *chatname;
225 gchar *post;
226 GString *url;
227 PurpleChatConversation *chatconv;
228
229 chatname = (gchar *)g_hash_table_lookup(data, "chatname");
230 if (chatname == NULL)
231 {
232 return;
233 }
234
235 chatconv = purple_conversations_find_chat_with_account(chatname, sa->account);
236 if (chatconv != NULL && !purple_chat_conversation_has_left(chatconv)) {
237 purple_conversation_present(PURPLE_CONVERSATION(chatconv));
238 return;
239 }
240
241 url = g_string_new("/v1/threads/");
242 g_string_append_printf(url, "%s", purple_url_encode(chatname));
243 g_string_append(url, "/members/");
244 g_string_append_printf(url, "8:%s", purple_url_encode(sa->username));
245
246 /* Specifying the role does not seem to be required and often result in a users role being
247 * downgraded from admin to user
248 * post = "{\"role\":\"User\"}"; */
249 post = "{}";
250
251 skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, sa->messages_host, url->str, post, NULL, NULL, TRUE);
252
253 g_string_free(url, TRUE);
254
255 skypeweb_get_conversation_history(sa, chatname);
256 skypeweb_get_thread_users(sa, chatname);
257
258 chatconv = purple_serv_got_joined_chat(pc, g_str_hash(chatname), chatname);
259 purple_conversation_set_data(PURPLE_CONVERSATION(chatconv), "chatname", g_strdup(chatname));
260
261 purple_conversation_present(PURPLE_CONVERSATION(chatconv));
262 }
263
264 void
skypeweb_buddy_free(PurpleBuddy * buddy)265 skypeweb_buddy_free(PurpleBuddy *buddy)
266 {
267 SkypeWebBuddy *sbuddy = purple_buddy_get_protocol_data(buddy);
268 if (sbuddy != NULL)
269 {
270 purple_buddy_set_protocol_data(buddy, NULL);
271
272 g_free(sbuddy->skypename);
273 g_free(sbuddy->fullname);
274 g_free(sbuddy->display_name);
275 g_free(sbuddy->avatar_url);
276 g_free(sbuddy->mood);
277
278 g_free(sbuddy);
279 }
280 }
281
282 void
skypeweb_fake_group_buddy(PurpleConnection * pc,const char * who,const char * old_group,const char * new_group)283 skypeweb_fake_group_buddy(PurpleConnection *pc, const char *who, const char *old_group, const char *new_group)
284 {
285 // Do nothing to stop the remove+add behaviour
286 }
287 void
skypeweb_fake_group_rename(PurpleConnection * pc,const char * old_name,PurpleGroup * group,GList * moved_buddies)288 skypeweb_fake_group_rename(PurpleConnection *pc, const char *old_name, PurpleGroup *group, GList *moved_buddies)
289 {
290 // Do nothing to stop the remove+add behaviour
291 }
292
293 static GList *
skypeweb_node_menu(PurpleBlistNode * node)294 skypeweb_node_menu(PurpleBlistNode *node)
295 {
296 GList *m = NULL;
297 PurpleMenuAction *act;
298 PurpleBuddy *buddy;
299 SkypeWebAccount *sa = NULL;
300
301 if(PURPLE_IS_BUDDY(node))
302 {
303 buddy = PURPLE_BUDDY(node);
304 if (purple_buddy_get_protocol_data(buddy)) {
305 SkypeWebBuddy *sbuddy = purple_buddy_get_protocol_data(buddy);
306 sa = sbuddy->sa;
307 }
308 if (sa == NULL) {
309 PurpleConnection *pc = purple_account_get_connection(purple_buddy_get_account(buddy));
310 sa = purple_connection_get_protocol_data(pc);
311 }
312
313 if (sa != NULL) {
314 act = purple_menu_action_new(_("Initiate _Chat"),
315 PURPLE_CALLBACK(skypeweb_initiate_chat_from_node),
316 sa, NULL);
317 m = g_list_append(m, act);
318 }
319 }
320
321 return m;
322 }
323
324 static gulong conversation_updated_signal = 0;
325 static gulong chat_conversation_typing_signal = 0;
326
327 static void
skypeweb_login(PurpleAccount * account)328 skypeweb_login(PurpleAccount *account)
329 {
330 PurpleConnection *pc = purple_account_get_connection(account);
331 SkypeWebAccount *sa = g_new0(SkypeWebAccount, 1);
332 PurpleConnectionFlags flags;
333
334 purple_connection_set_protocol_data(pc, sa);
335
336 flags = purple_connection_get_flags(pc);
337 flags |= PURPLE_CONNECTION_FLAG_HTML | PURPLE_CONNECTION_FLAG_NO_BGCOLOR | PURPLE_CONNECTION_FLAG_NO_FONTSIZE;
338 purple_connection_set_flags(pc, flags);
339
340 if (!SKYPEWEB_BUDDY_IS_MSN(purple_account_get_username(account))) {
341 sa->username = g_ascii_strdown(purple_account_get_username(account), -1);
342 }
343 sa->account = account;
344 sa->pc = pc;
345 sa->cookie_jar = purple_http_cookie_jar_new();
346 sa->sent_messages_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
347 sa->messages_host = g_strdup(SKYPEWEB_DEFAULT_MESSAGES_HOST);
348 sa->keepalive_pool = purple_http_keepalive_pool_new();
349 purple_http_keepalive_pool_set_limit_per_host(sa->keepalive_pool, SKYPEWEB_MAX_CONNECTIONS);
350 sa->conns = purple_http_connection_set_new();
351
352 if (purple_account_get_bool(account, "alt-login", FALSE)) {
353 skypeweb_begin_soapy_login(sa);
354 } else {
355 if (purple_account_get_string(account, "refresh-token", NULL) && purple_account_get_remember_password(account)) {
356 skypeweb_refresh_token_login(sa);
357 } else {
358 skypeweb_begin_oauth_login(sa);
359 }
360 }
361
362 if (!conversation_updated_signal) {
363 conversation_updated_signal = purple_signal_connect(purple_conversations_get_handle(), "conversation-updated", purple_connection_get_protocol(pc), PURPLE_CALLBACK(skypeweb_mark_conv_seen), NULL);
364 }
365 if (!chat_conversation_typing_signal) {
366 chat_conversation_typing_signal = purple_signal_connect(purple_conversations_get_handle(), "chat-conversation-typing", purple_connection_get_protocol(pc), PURPLE_CALLBACK(skypeweb_conv_send_typing), NULL);
367 }
368 }
369
370 static void
skypeweb_close(PurpleConnection * pc)371 skypeweb_close(PurpleConnection *pc)
372 {
373 SkypeWebAccount *sa;
374 GSList *buddies;
375
376 g_return_if_fail(pc != NULL);
377 #if !PURPLE_VERSION_CHECK(3, 0, 0)
378 purple_connection_set_state(pc, PURPLE_CONNECTION_DISCONNECTING);
379 #endif
380
381 sa = purple_connection_get_protocol_data(pc);
382 g_return_if_fail(sa != NULL);
383
384 g_source_remove(sa->authcheck_timeout);
385 g_source_remove(sa->poll_timeout);
386 g_source_remove(sa->watchdog_timeout);
387
388 skypeweb_logout(sa);
389
390 purple_debug_info("skypeweb", "destroying incomplete connections\n");
391
392 purple_http_connection_set_destroy(sa->conns);
393 purple_http_conn_cancel_all(pc);
394 purple_http_keepalive_pool_unref(sa->keepalive_pool);
395 purple_http_cookie_jar_unref(sa->cookie_jar);
396
397 buddies = purple_blist_find_buddies(sa->account, NULL);
398 while (buddies != NULL) {
399 PurpleBuddy *buddy = buddies->data;
400 skypeweb_buddy_free(buddy);
401 purple_buddy_set_protocol_data(buddy, NULL);
402 buddies = g_slist_delete_link(buddies, buddies);
403 }
404
405 g_hash_table_destroy(sa->sent_messages_hash);
406
407 g_free(sa->vdms_token);
408 g_free(sa->messages_host);
409 g_free(sa->skype_token);
410 g_free(sa->registration_token);
411 g_free(sa->endpoint);
412 g_free(sa->primary_member_name);
413 g_free(sa->self_display_name);
414 g_free(sa->username);
415 g_free(sa);
416 }
417
418 gboolean
skypeweb_offline_message(const PurpleBuddy * buddy)419 skypeweb_offline_message(const PurpleBuddy *buddy)
420 {
421 return TRUE;
422 }
423
424 static PurpleCmdRet
skypeweb_cmd_list(PurpleConversation * conv,const gchar * cmd,gchar ** args,gchar ** error,void * data)425 skypeweb_cmd_list(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
426 {
427 purple_roomlist_show_with_account(purple_conversation_get_account(conv));
428
429 return PURPLE_CMD_RET_OK;
430 }
431
432 static PurpleCmdRet
skypeweb_cmd_leave(PurpleConversation * conv,const gchar * cmd,gchar ** args,gchar ** error,void * data)433 skypeweb_cmd_leave(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
434 {
435 PurpleConnection *pc = NULL;
436 int id = -1;
437 SkypeWebAccount *sa;
438
439 pc = purple_conversation_get_connection(conv);
440 id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv));
441
442 if (pc == NULL || id == -1)
443 return PURPLE_CMD_RET_FAILED;
444
445 sa = purple_connection_get_protocol_data(pc);
446 if (sa == NULL)
447 return PURPLE_CMD_RET_FAILED;
448
449 skypeweb_chat_kick(pc, id, sa->username);
450
451 return PURPLE_CMD_RET_OK;
452 }
453
454 static PurpleCmdRet
skypeweb_cmd_kick(PurpleConversation * conv,const gchar * cmd,gchar ** args,gchar ** error,void * data)455 skypeweb_cmd_kick(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
456 {
457 PurpleConnection *pc = NULL;
458 int id = -1;
459
460 pc = purple_conversation_get_connection(conv);
461 id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv));
462
463 if (pc == NULL || id == -1)
464 return PURPLE_CMD_RET_FAILED;
465
466 skypeweb_chat_kick(pc, id, args[0]);
467
468 return PURPLE_CMD_RET_OK;
469 }
470
471 static PurpleCmdRet
skypeweb_cmd_invite(PurpleConversation * conv,const gchar * cmd,gchar ** args,gchar ** error,void * data)472 skypeweb_cmd_invite(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
473 {
474 PurpleConnection *pc = NULL;
475 int id = -1;
476
477 pc = purple_conversation_get_connection(conv);
478 id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv));
479
480 if (pc == NULL || id == -1)
481 return PURPLE_CMD_RET_FAILED;
482
483 skypeweb_chat_invite(pc, id, NULL, args[0]);
484
485 return PURPLE_CMD_RET_OK;
486 }
487
488 static PurpleCmdRet
skypeweb_cmd_topic(PurpleConversation * conv,const gchar * cmd,gchar ** args,gchar ** error,void * data)489 skypeweb_cmd_topic(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
490 {
491 PurpleConnection *pc = NULL;
492 PurpleChatConversation *chat;
493 int id = -1;
494
495 pc = purple_conversation_get_connection(conv);
496 chat = PURPLE_CHAT_CONVERSATION(conv);
497 id = purple_chat_conversation_get_id(chat);
498
499 if (pc == NULL || id == -1)
500 return PURPLE_CMD_RET_FAILED;
501
502 if (!args || !args[0]) {
503 gchar *buf;
504 const gchar *topic = purple_chat_conversation_get_topic(chat);
505
506 if (topic) {
507 gchar *tmp, *tmp2;
508 tmp = g_markup_escape_text(topic, -1);
509 tmp2 = purple_markup_linkify(tmp);
510 buf = g_strdup_printf(_("current topic is: %s"), tmp2);
511 g_free(tmp);
512 g_free(tmp2);
513 } else {
514 buf = g_strdup(_("No topic is set"));
515 }
516
517 purple_conversation_write_system_message(conv, buf, PURPLE_MESSAGE_NO_LOG);
518
519 g_free(buf);
520 return PURPLE_CMD_RET_OK;
521 }
522
523 skypeweb_chat_set_topic(pc, id, args[0]);
524
525 return PURPLE_CMD_RET_OK;
526 }
527
528 /******************************************************************************/
529 /* Plugin functions */
530 /******************************************************************************/
531
532 static gboolean
skypeweb_uri_handler(const char * proto,const char * cmd,GHashTable * params)533 skypeweb_uri_handler(const char *proto, const char *cmd, GHashTable *params)
534 {
535 PurpleAccount *account;
536 PurpleConnection *pc;
537
538 if (!g_str_equal(proto, "skype"))
539 return FALSE;
540
541 /*skype uri's:
542
543 skype: //does nothing
544 skype:{buddyname} //open im with {buddyname}
545 skype:{buddynames}?chat //open multi-user chat with {buddynames}
546 skype:?chat&blob={blob id} //open public multi-user chat with the blob id of {blob id}
547 skype:?chat&id={chat id} //open multi-user chat with the id of {chat id}
548 skype:{buddyname}?add //add user to buddy list
549 skype:{buddyname}?userinfo //get buddy's info
550
551 skype:{buddynames}?call //call {buddynames}
552 skype:{buddyname}?voicemail //send a voice mail message
553 skype:{buddyname}?sendfile //send a file
554 */
555
556 account = find_acct(SKYPEWEB_PLUGIN_ID, g_hash_table_lookup(params, "account"));
557 pc = purple_account_get_connection(account);
558
559 if (g_hash_table_lookup(params, "chat")) {
560 if (cmd && *cmd) {
561 //there'll be a bunch of usernames, seperated by semi-colon
562 if (strchr(cmd, ';')) {
563 gchar **users = g_strsplit_set(cmd, ";", -1);
564 skypeweb_initiate_chat(purple_connection_get_protocol_data(pc), users[0]);
565 //TODO the other users
566 g_strfreev(users);
567 } else {
568 PurpleIMConversation *imconv;
569 imconv = purple_conversations_find_im_with_account(cmd, account);
570 if (!imconv) {
571 imconv = purple_im_conversation_new(account, cmd);
572 }
573 purple_conversation_present(PURPLE_CONVERSATION(imconv));
574 }
575 } else {
576 //probably a public multi-user chat?
577 GHashTable *chatinfo = NULL;
578 if (g_hash_table_lookup(params, "id")) {
579 chatinfo = skypeweb_chat_info_defaults(pc, g_hash_table_lookup(params, "id"));
580 } else if (g_hash_table_lookup(params, "blob")) {
581 chatinfo = skypeweb_chat_info_defaults(pc, g_hash_table_lookup(params, "blob"));
582 }
583
584 if (chatinfo != NULL) {
585 skypeweb_join_chat(pc, chatinfo);
586 g_hash_table_destroy(chatinfo);
587 }
588 }
589 } else if (g_hash_table_lookup(params, "add")) {
590 purple_blist_request_add_buddy(account, cmd, "Skype", g_hash_table_lookup(params, "displayname"));
591 return TRUE;
592 } else if (g_hash_table_lookup(params, "call")) {
593
594 } else if (g_hash_table_lookup(params, "userinfo")) {
595 skypeweb_get_info(pc, cmd);
596 return TRUE;
597 } else if (g_hash_table_lookup(params, "voicemail")) {
598
599 } else if (g_hash_table_lookup(params, "sendfile")) {
600
601 } else if (strlen(cmd)) {
602 //supposed to be the same as call?
603 }
604
605 //we don't know how to handle this
606 return FALSE;
607 }
608
609 #if PURPLE_VERSION_CHECK(3, 0, 0)
610 typedef struct _SkypeWebProtocol
611 {
612 PurpleProtocol parent;
613 } SkypeWebProtocol;
614
615 typedef struct _SkypeWebProtocolClass
616 {
617 PurpleProtocolClass parent_class;
618 } SkypeWebProtocolClass;
619
620 G_MODULE_EXPORT GType skypeweb_protocol_get_type(void);
621 #define SKYPEWEB_TYPE_PROTOCOL (skypeweb_protocol_get_type())
622 #define SKYPEWEB_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SKYPEWEB_TYPE_PROTOCOL, SkypeWebProtocol))
623 #define SKYPEWEB_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SKYPEWEB_TYPE_PROTOCOL, SkypeWebProtocolClass))
624 #define SKYPEWEB_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), SKYPEWEB_TYPE_PROTOCOL))
625 #define SKYPEWEB_IS_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), SKYPEWEB_TYPE_PROTOCOL))
626 #define SKYPEWEB_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), SKYPEWEB_TYPE_PROTOCOL, SkypeWebProtocolClass))
627
628 static PurpleProtocol *skypeweb_protocol;
629 #else
630
631 // Normally set in core.c in purple3
632 void _purple_socket_init(void);
633 void _purple_socket_uninit(void);
634
635 #endif
636
637
638 static gboolean
plugin_load(PurplePlugin * plugin,GError ** error)639 plugin_load(PurplePlugin *plugin
640 #if PURPLE_VERSION_CHECK(3, 0, 0)
641 , GError **error
642 #endif
643 )
644 {
645
646 #if !PURPLE_VERSION_CHECK(3, 0, 0)
647 _purple_socket_init();
648 purple_http_init();
649 #endif
650
651
652 //leave
653 purple_cmd_register("leave", "", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
654 PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
655 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_leave,
656 _("leave: Leave the group chat"), NULL);
657 //kick
658 purple_cmd_register("kick", "s", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
659 PURPLE_CMD_FLAG_PROTOCOL_ONLY,
660 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_kick,
661 _("kick <user>: Kick a user from the group chat."),
662 NULL);
663 //add
664 purple_cmd_register("add", "s", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
665 PURPLE_CMD_FLAG_PROTOCOL_ONLY,
666 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_invite,
667 _("add <user>: Add a user to the group chat."),
668 NULL);
669 //topic
670 purple_cmd_register("topic", "s", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
671 PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_ALLOW_WRONG_ARGS,
672 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_topic,
673 _("topic [<new topic>]: View or change the topic"),
674 NULL);
675 /*
676 //call, as in call person
677 //kickban
678 purple_cmd_register("kickban", "s", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
679 PURPLE_CMD_FLAG_PROTOCOL_ONLY,
680 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_kickban,
681 _("kickban <user> [room]: Kick and ban a user from the room."),
682 NULL);
683 //setrole
684 purple_cmd_register("setrole", "ss", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
685 PURPLE_CMD_FLAG_PROTOCOL_ONLY,
686 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_setrole,
687 _("setrole <user> <MASTER | USER | ADMIN>: Change the role of a user."),
688 NULL);
689 */
690
691 purple_cmd_register("list", "", PURPLE_CMD_P_PLUGIN, PURPLE_CMD_FLAG_CHAT |
692 PURPLE_CMD_FLAG_PROTOCOL_ONLY | PURPLE_CMD_FLAG_IM,
693 SKYPEWEB_PLUGIN_ID, skypeweb_cmd_list,
694 _("list: Display a list of multi-chat group chats you are in."),
695 NULL);
696
697 purple_signal_connect(purple_get_core(), "uri-handler", plugin, PURPLE_CALLBACK(skypeweb_uri_handler), NULL);
698
699 return TRUE;
700 }
701
702 static gboolean
plugin_unload(PurplePlugin * plugin,GError ** error)703 plugin_unload(PurplePlugin *plugin
704 #if PURPLE_VERSION_CHECK(3, 0, 0)
705 , GError **error
706 #endif
707 )
708 {
709 #if !PURPLE_VERSION_CHECK(3, 0, 0)
710 _purple_socket_uninit();
711 purple_http_uninit();
712 #endif
713 purple_signals_disconnect_by_handle(plugin);
714
715 return TRUE;
716 }
717
718 static GList *
skypeweb_actions(PurplePlugin * plugin,gpointer context)719 skypeweb_actions(
720 #if !PURPLE_VERSION_CHECK(3, 0, 0)
721 PurplePlugin *plugin, gpointer context
722 #else
723 PurpleConnection *pc
724 #endif
725 )
726 {
727 GList *m = NULL;
728 PurpleProtocolAction *act;
729
730 act = purple_protocol_action_new(_("Search for friends..."), skypeweb_search_users);
731 m = g_list_append(m, act);
732
733 act = purple_protocol_action_new(_("People you might know..."), skypeweb_contact_suggestions);
734 m = g_list_append(m, act);
735
736 return m;
737 }
738
739 #if !PURPLE_VERSION_CHECK(2, 8, 0)
740 # define OPT_PROTO_INVITE_MESSAGE 0x00000800
741 #endif
742
743 #if !PURPLE_VERSION_CHECK(3, 0, 0)
744 static void
plugin_init(PurplePlugin * plugin)745 plugin_init(PurplePlugin *plugin)
746 {
747 PurplePluginInfo *info = g_new0(PurplePluginInfo, 1);
748 PurplePluginProtocolInfo *prpl_info = g_new0(PurplePluginProtocolInfo, 1);
749 #endif
750
751 #if PURPLE_VERSION_CHECK(3, 0, 0)
752 static void
753 skypeweb_protocol_init(PurpleProtocol *prpl_info)
754 {
755 PurpleProtocol *info = prpl_info;
756 #endif
757 PurpleAccountOption *typing_type1, *typing_type2, *alt_login;
758 PurpleBuddyIconSpec icon_spec = {"jpeg", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY};
759
760 //PurpleProtocol
761 info->id = SKYPEWEB_PLUGIN_ID;
762 info->name = "Skype (HTTP)";
763 prpl_info->options = OPT_PROTO_CHAT_TOPIC | OPT_PROTO_INVITE_MESSAGE /*| OPT_PROTO_IM_IMAGE*/;
764 typing_type1 = purple_account_option_bool_new(N_("Show 'Typing' status as system message in chat window."), "show-typing-as-text", FALSE);
765 typing_type2 = purple_account_option_bool_new(N_("Show 'Typing' status with 'Voice' icon near buddy name."), "show-typing-as-icon", FALSE);
766 alt_login = purple_account_option_bool_new(N_("Use alternative login method"), "alt-login", TRUE);
767
768 #if !PURPLE_VERSION_CHECK(3, 0, 0)
769 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, typing_type1);
770 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, typing_type2);
771 prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, alt_login);
772 prpl_info->icon_spec = icon_spec;
773 #else
774 prpl_info->account_options = g_list_append(prpl_info->account_options, typing_type1);
775 prpl_info->account_options = g_list_append(prpl_info->account_options, typing_type2);
776 prpl_info->account_options = g_list_append(prpl_info->account_options, alt_login);
777 prpl_info->icon_spec = &icon_spec;
778 #endif
779
780 #if PURPLE_VERSION_CHECK(3, 0, 0)
781 }
782
783 static void
784 skypeweb_protocol_class_init(PurpleProtocolClass *prpl_info)
785 {
786 #endif
787 //PurpleProtocolClass
788 prpl_info->login = skypeweb_login;
789 prpl_info->close = skypeweb_close;
790 prpl_info->status_types = skypeweb_status_types;
791 prpl_info->list_icon = skypeweb_list_icon;
792 #if PURPLE_VERSION_CHECK(3, 0, 0)
793 }
794
795 static void
796 skypeweb_protocol_client_iface_init(PurpleProtocolClientIface *prpl_info)
797 {
798 PurpleProtocolClientIface *info = prpl_info;
799 #endif
800
801 //PurpleProtocolClientIface
802 #if !PURPLE_VERSION_CHECK(3, 0, 0)
803 info->actions = skypeweb_actions;
804 #else
805 info->get_actions = skypeweb_actions;
806 #endif
807 prpl_info->list_emblem = skypeweb_list_emblem;
808 prpl_info->status_text = skypeweb_status_text;
809 prpl_info->tooltip_text = skypeweb_tooltip_text;
810 prpl_info->blist_node_menu = skypeweb_node_menu;
811 prpl_info->buddy_free = skypeweb_buddy_free;
812 prpl_info->normalize = purple_normalize_nocase;
813 prpl_info->offline_message = skypeweb_offline_message;
814 prpl_info->get_account_text_table = NULL; // skypeweb_get_account_text_table;
815 #if PURPLE_VERSION_CHECK(3, 0, 0)
816 }
817
818 static void
819 skypeweb_protocol_server_iface_init(PurpleProtocolServerIface *prpl_info)
820 {
821 #endif
822
823 //PurpleProtocolServerIface
824 prpl_info->get_info = skypeweb_get_info;
825 prpl_info->set_status = skypeweb_set_status;
826 prpl_info->set_idle = skypeweb_set_idle;
827 #if !PURPLE_VERSION_CHECK(3, 0, 0)
828 prpl_info->add_buddy = skypeweb_add_buddy;
829 #else
830 prpl_info->add_buddy = skypeweb_add_buddy_with_invite;
831 #endif
832 prpl_info->remove_buddy = skypeweb_buddy_remove;
833 prpl_info->group_buddy = skypeweb_fake_group_buddy;
834 prpl_info->rename_group = skypeweb_fake_group_rename;
835 #if PURPLE_VERSION_CHECK(3, 0, 0)
836 }
837
838 static void
839 skypeweb_protocol_im_iface_init(PurpleProtocolIMIface *prpl_info)
840 {
841 #endif
842
843 //PurpleProtocolIMIface
844 #if !PURPLE_VERSION_CHECK(3, 0, 0)
845 prpl_info->send_im = skypeweb_send_im;
846 #else
847 prpl_info->send = skypeweb_send_im;
848 #endif
849 prpl_info->send_typing = skypeweb_send_typing;
850 #if PURPLE_VERSION_CHECK(3, 0, 0)
851 }
852
853 static void
854 skypeweb_protocol_chat_iface_init(PurpleProtocolChatIface *prpl_info)
855 {
856 #endif
857
858 //PurpleProtocolChatIface
859 #if !PURPLE_VERSION_CHECK(3, 0, 0)
860 prpl_info->chat_info = skypeweb_chat_info;
861 prpl_info->chat_info_defaults = skypeweb_chat_info_defaults;
862 prpl_info->join_chat = skypeweb_join_chat;
863 prpl_info->get_chat_name = skypeweb_get_chat_name;
864 prpl_info->chat_invite = skypeweb_chat_invite;
865 prpl_info->chat_leave = NULL; //skypeweb_chat_fake_leave;
866 prpl_info->chat_send = skypeweb_chat_send;
867 prpl_info->set_chat_topic = skypeweb_chat_set_topic;
868 #else
869 prpl_info->info = skypeweb_chat_info;
870 prpl_info->info_defaults = skypeweb_chat_info_defaults;
871 prpl_info->join = skypeweb_join_chat;
872 prpl_info->get_name = skypeweb_get_chat_name;
873 prpl_info->invite = skypeweb_chat_invite;
874 prpl_info->leave = NULL; //skypeweb_chat_fake_leave;
875 prpl_info->send = skypeweb_chat_send;
876 prpl_info->set_topic = skypeweb_chat_set_topic;
877 #endif
878 #if PURPLE_VERSION_CHECK(3, 0, 0)
879 }
880
881 static void
882 skypeweb_protocol_privacy_iface_init(PurpleProtocolPrivacyIface *prpl_info)
883 {
884 #endif
885
886 //PurpleProtocolPrivacyIface
887 prpl_info->add_deny = skypeweb_buddy_block;
888 prpl_info->rem_deny = skypeweb_buddy_unblock;
889 #if PURPLE_VERSION_CHECK(3, 0, 0)
890 }
891
892 static void
893 skypeweb_protocol_xfer_iface_init(PurpleProtocolXferInterface *prpl_info)
894 {
895 #endif
896
897 //PurpleProtocolXferInterface
898 prpl_info->new_xfer = skypeweb_new_xfer;
899 prpl_info->send_file = skypeweb_send_file;
900 #if !PURPLE_VERSION_CHECK(3, 0, 0)
901 prpl_info->can_receive_file = skypeweb_can_receive_file;
902 #else
903 prpl_info->can_receive = skypeweb_can_receive_file;
904 #endif
905
906 #if PURPLE_VERSION_CHECK(3, 0, 0)
907 }
908
909 static void
910 skypeweb_protocol_roomlist_iface_init(PurpleProtocolRoomlistIface *prpl_info)
911 {
912 #endif
913
914 //PurpleProtocolRoomlistIface
915 #if !PURPLE_VERSION_CHECK(3, 0, 0)
916 prpl_info->roomlist_get_list = skypeweb_roomlist_get_list;
917 #else
918 prpl_info->get_list = skypeweb_roomlist_get_list;
919 #endif
920
921 #if !PURPLE_VERSION_CHECK(3, 0, 0)
922 // Plugin info
923 info->magic = PURPLE_PLUGIN_MAGIC;
924 info->major_version = 2;
925 info->minor_version = MIN(PURPLE_MINOR_VERSION, 8);
926 info->type = PURPLE_PLUGIN_PROTOCOL;
927 info->priority = PURPLE_PRIORITY_DEFAULT;
928 info->version = SKYPEWEB_PLUGIN_VERSION;
929 info->summary = N_("Skype for Web Protocol Plugin");
930 info->description = N_("Skype for Web Protocol Plugin");
931 info->author = "Eion Robb <eionrobb@gmail.com>";
932 info->homepage = "http://github.com/EionRobb/skype4pidgin";
933 info->load = plugin_load;
934 info->unload = plugin_unload;
935 info->extra_info = prpl_info;
936
937 // Protocol info
938 #if PURPLE_MINOR_VERSION >= 5
939 prpl_info->struct_size = sizeof(PurplePluginProtocolInfo);
940 #endif
941 #if PURPLE_MINOR_VERSION >= 8
942 prpl_info->add_buddy_with_invite = skypeweb_add_buddy_with_invite;
943 #endif
944
945 plugin->info = info;
946 #endif
947
948 }
949
950 #if PURPLE_VERSION_CHECK(3, 0, 0)
951
952
953 PURPLE_DEFINE_TYPE_EXTENDED(
954 SkypeWebProtocol, skypeweb_protocol, PURPLE_TYPE_PROTOCOL, 0,
955
956 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CLIENT_IFACE,
957 skypeweb_protocol_client_iface_init)
958
959 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_SERVER_IFACE,
960 skypeweb_protocol_server_iface_init)
961
962 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_IM_IFACE,
963 skypeweb_protocol_im_iface_init)
964
965 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CHAT_IFACE,
966 skypeweb_protocol_chat_iface_init)
967
968 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_PRIVACY_IFACE,
969 skypeweb_protocol_privacy_iface_init)
970
971 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_ROOMLIST_IFACE,
972 skypeweb_protocol_roomlist_iface_init)
973
974 PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER,
975 skypeweb_protocol_xfer_iface_init)
976 );
977
978 static gboolean
979 libpurple3_plugin_load(PurplePlugin *plugin, GError **error)
980 {
981 skypeweb_protocol_register_type(plugin);
982 skypeweb_protocol = purple_protocols_add(SKYPEWEB_TYPE_PROTOCOL, error);
983 if (!skypeweb_protocol)
984 return FALSE;
985
986 return plugin_load(plugin, error);
987 }
988
989 static gboolean
990 libpurple3_plugin_unload(PurplePlugin *plugin, GError **error)
991 {
992 if (!plugin_unload(plugin, error))
993 return FALSE;
994
995 if (!purple_protocols_remove(skypeweb_protocol, error))
996 return FALSE;
997
998 return TRUE;
999 }
1000
1001 static PurplePluginInfo *
1002 plugin_query(GError **error)
1003 {
1004 return purple_plugin_info_new(
1005 "id", SKYPEWEB_PLUGIN_ID,
1006 "name", "SkypeWeb Protocol",
1007 "version", SKYPEWEB_PLUGIN_VERSION,
1008 "category", N_("Protocol"),
1009 "summary", N_("SkypeWeb Protocol Plugin"),
1010 "description", N_("SkypeWeb Protocol Plugin"),
1011 "website", "http://github.com/EionRobb/skype4pidgin",
1012 "abi-version", PURPLE_ABI_VERSION,
1013 "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
1014 PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
1015 NULL
1016 );
1017 }
1018
1019
1020 PURPLE_PLUGIN_INIT(skypeweb, plugin_query, libpurple3_plugin_load, libpurple3_plugin_unload);
1021 #else
1022
1023 static PurplePluginInfo aLovelyBunchOfCoconuts;
1024 PURPLE_INIT_PLUGIN(skypeweb, plugin_init, aLovelyBunchOfCoconuts);
1025 #endif
1026
1027