| 1 /* |
|
| 2 * gaim - Napster Protocol Plugin |
|
| 3 * |
|
| 4 * Copyright (C) 2000-2001, Rob Flynn <rob@marko.net> |
|
| 5 * |
|
| 6 * This program is free software; you can redistribute it and/or modify |
|
| 7 * it under the terms of the GNU General Public License as published by |
|
| 8 * the Free Software Foundation; either version 2 of the License, or |
|
| 9 * (at your option) any later version. |
|
| 10 * |
|
| 11 * This program is distributed in the hope that it will be useful, |
|
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 14 * GNU General Public License for more details. |
|
| 15 * |
|
| 16 * You should have received a copy of the GNU General Public License |
|
| 17 * along with this program; if not, write to the Free Software |
|
| 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
| 19 */ |
|
| 20 #include "internal.h" |
|
| 21 |
|
| 22 #include "account.h" |
|
| 23 #include "accountopt.h" |
|
| 24 #include "blist.h" |
|
| 25 #include "conversation.h" |
|
| 26 #include "debug.h" |
|
| 27 #include "notify.h" |
|
| 28 #include "prpl.h" |
|
| 29 #include "proxy.h" |
|
| 30 #include "util.h" |
|
| 31 #include "version.h" |
|
| 32 |
|
| 33 #define NAP_SERVER "64.124.41.187" |
|
| 34 #define NAP_PORT 8888 |
|
| 35 |
|
| 36 #define NAPSTER_CONNECT_STEPS 2 |
|
| 37 |
|
| 38 GSList *nap_connections = NULL; |
|
| 39 |
|
| 40 struct nap_data { |
|
| 41 int fd; |
|
| 42 gchar *email; |
|
| 43 }; |
|
| 44 |
|
| 45 static GaimConversation *nap_find_chat(GaimConnection *gc, const char *name) |
|
| 46 { |
|
| 47 GSList *bcs = gc->buddy_chats; |
|
| 48 |
|
| 49 while (bcs) { |
|
| 50 GaimConversation *b = bcs->data; |
|
| 51 if (!gaim_utf8_strcasecmp(b->name, name)) |
|
| 52 return b; |
|
| 53 bcs = bcs->next; |
|
| 54 } |
|
| 55 |
|
| 56 return NULL; |
|
| 57 } |
|
| 58 |
|
| 59 static void nap_write_packet(GaimConnection *gc, unsigned short command, const char *format, ...) |
|
| 60 { |
|
| 61 struct nap_data *ndata = (struct nap_data *)gc->proto_data; |
|
| 62 va_list ap; |
|
| 63 gchar *message; |
|
| 64 unsigned short size; |
|
| 65 |
|
| 66 va_start(ap, format); |
|
| 67 message = g_strdup_vprintf(format, ap); |
|
| 68 va_end(ap); |
|
| 69 |
|
| 70 size = strlen(message); |
|
| 71 gaim_debug(GAIM_DEBUG_MISC, "napster", "S %3hd: %s\n", command, message); |
|
| 72 |
|
| 73 write(ndata->fd, &size, 2); |
|
| 74 write(ndata->fd, &command, 2); |
|
| 75 write(ndata->fd, message, size); |
|
| 76 |
|
| 77 g_free(message); |
|
| 78 } |
|
| 79 |
|
| 80 static int nap_do_irc_style(GaimConnection *gc, const char *message, const char *name) |
|
| 81 { |
|
| 82 gchar **res; |
|
| 83 |
|
| 84 gaim_debug(GAIM_DEBUG_MISC, "napster", "C %s\n", message); |
|
| 85 |
|
| 86 res = g_strsplit(message, " ", 2); |
|
| 87 |
|
| 88 if (!g_ascii_strcasecmp(res[0], "/ME")) { /* MSG_CLIENT_PUBLIC */ |
|
| 89 nap_write_packet(gc, 824, "%s \"%s\"", name, res[1]); |
|
| 90 |
|
| 91 } else if (!g_ascii_strcasecmp(res[0], "/MSG")) { /* MSG_CLIENT_PUBLIC */ |
|
| 92 nap_write_packet(gc, 205, "%s", res[1]); |
|
| 93 |
|
| 94 } else if (!g_ascii_strcasecmp(res[0], "/JOIN")) { /* join chatroom MSG_CLIENT_JOIN */ |
|
| 95 if (!res[1]) { |
|
| 96 g_strfreev(res); |
|
| 97 return 1; |
|
| 98 } |
|
| 99 if (res[1][0] != '#') |
|
| 100 nap_write_packet(gc, 400, "#%s", res[1]); |
|
| 101 else |
|
| 102 nap_write_packet(gc, 400, "%s", res[1]); |
|
| 103 |
|
| 104 } else if (!g_ascii_strcasecmp(res[0], "/PART")) { /* partchatroom MSG_CLIENT_PART */ |
|
| 105 nap_write_packet(gc, 401, "%s", res[1] ? res[1] : name); |
|
| 106 |
|
| 107 } else if (!g_ascii_strcasecmp(res[0], "/TOPIC")) { /* set topic MSG_SERVER_TOPIC */ |
|
| 108 nap_write_packet(gc, 410, "%s", res[1] ? res[1] : name); |
|
| 109 |
|
| 110 } else if (!g_ascii_strcasecmp(res[0], "/WHOIS")) { /* whois request MSG_CLIENT_WHOIS */ |
|
| 111 nap_write_packet(gc, 603, "%s", res[1]); |
|
| 112 |
|
| 113 } else if (!g_ascii_strcasecmp(res[0], "/PING")) { /* send ping MSG_CLIENT_PING */ |
|
| 114 nap_write_packet(gc, 751, "%s", res[1]); |
|
| 115 |
|
| 116 } else if (!g_ascii_strcasecmp(res[0], "/KICK")) { /* kick asswipe MSG_CLIENT_KICK */ |
|
| 117 nap_write_packet(gc, 829, "%s", res[1]); |
|
| 118 |
|
| 119 } else { |
|
| 120 g_strfreev(res); |
|
| 121 return 1; |
|
| 122 } |
|
| 123 |
|
| 124 g_strfreev(res); |
|
| 125 return 0; |
|
| 126 } |
|
| 127 |
|
| 128 /* 205 - MSG_CLIENT_PRIVMSG */ |
|
| 129 static int nap_send_im(GaimConnection *gc, const char *who, const char *message, GaimMessageFlags flags) |
|
| 130 { |
|
| 131 char *tmp = gaim_unescape_html(message); |
|
| 132 |
|
| 133 if ((strlen(tmp) < 2) || (tmp[0] != '/' ) || (tmp[1] == '/')) { |
|
| 134 /* Actually send a chat message */ |
|
| 135 nap_write_packet(gc, 205, "%s %s", who, tmp); |
|
| 136 } else { |
|
| 137 /* user typed an IRC-style command */ |
|
| 138 nap_do_irc_style(gc, tmp, who); |
|
| 139 } |
|
| 140 |
|
| 141 g_free(tmp); |
|
| 142 |
|
| 143 return 1; |
|
| 144 } |
|
| 145 |
|
| 146 /* 207 - MSG_CLIENT_ADD_HOTLIST */ |
|
| 147 static void nap_add_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) |
|
| 148 { |
|
| 149 nap_write_packet(gc, 207, "%s", buddy->name); |
|
| 150 } |
|
| 151 |
|
| 152 /* 208 - MSG_CLIENT_ADD_HOTLIST_SEQ */ |
|
| 153 static void nap_send_buddylist(GaimConnection *gc) |
|
| 154 { |
|
| 155 GaimBuddyList *blist; |
|
| 156 GaimBlistNode *gnode, *cnode, *bnode; |
|
| 157 GaimBuddy *buddy; |
|
| 158 |
|
| 159 if ((blist = gaim_get_blist()) != NULL) |
|
| 160 { |
|
| 161 for (gnode = blist->root; gnode != NULL; gnode = gnode->next) |
|
| 162 { |
|
| 163 if (!GAIM_BLIST_NODE_IS_GROUP(gnode)) |
|
| 164 continue; |
|
| 165 for (cnode = gnode->child; cnode != NULL; cnode = cnode->next) |
|
| 166 { |
|
| 167 if (!GAIM_BLIST_NODE_IS_CONTACT(cnode)) |
|
| 168 continue; |
|
| 169 for (bnode = cnode->child; bnode != NULL; bnode = bnode->next) |
|
| 170 { |
|
| 171 if (!GAIM_BLIST_NODE_IS_BUDDY(bnode)) |
|
| 172 continue; |
|
| 173 buddy = (GaimBuddy *)bnode; |
|
| 174 nap_write_packet(gc, 208, "%s", buddy->name); |
|
| 175 } |
|
| 176 } |
|
| 177 } |
|
| 178 } |
|
| 179 } |
|
| 180 |
|
| 181 /* 303 - MSG_CLIENT_REMOVE_HOTLIST */ |
|
| 182 static void nap_remove_buddy(GaimConnection *gc, GaimBuddy *buddy, GaimGroup *group) |
|
| 183 { |
|
| 184 nap_write_packet(gc, 303, "%s", buddy->name); |
|
| 185 } |
|
| 186 |
|
| 187 static char *nap_get_chat_name(GHashTable *data) { |
|
| 188 char *name = g_hash_table_lookup(data, "group"); |
|
| 189 |
|
| 190 /* Make sure the name has a # preceding it */ |
|
| 191 if (name[0] != '#') { |
|
| 192 return g_strdup_printf("#%s", name); |
|
| 193 } |
|
| 194 |
|
| 195 return g_strdup(name); |
|
| 196 } |
|
| 197 |
|
| 198 /* 400 - MSG_CLIENT_JOIN */ |
|
| 199 static void nap_join_chat(GaimConnection *gc, GHashTable *data) |
|
| 200 { |
|
| 201 char *name; |
|
| 202 |
|
| 203 if (!data) |
|
| 204 return; |
|
| 205 |
|
| 206 name = nap_get_chat_name(data); |
|
| 207 |
|
| 208 if (name) { |
|
| 209 nap_write_packet(gc, 400, "%s", name); |
|
| 210 g_free(name); |
|
| 211 } |
|
| 212 } |
|
| 213 |
|
| 214 /* 401 - MSG_CLIENT_PART */ |
|
| 215 static void nap_chat_leave(GaimConnection *gc, int id) |
|
| 216 { |
|
| 217 GaimConversation *c = gaim_find_chat(gc, id); |
|
| 218 |
|
| 219 if (!c) |
|
| 220 return; |
|
| 221 |
|
| 222 nap_write_packet(gc, 401, "%s", c->name); |
|
| 223 } |
|
| 224 |
|
| 225 /* 402 - MSG_CLIENT_PUBLIC */ |
|
| 226 static int nap_chat_send(GaimConnection *gc, int id, const char *message, GaimMessageFlags flags) |
|
| 227 { |
|
| 228 GaimConversation *c = gaim_find_chat(gc, id); |
|
| 229 char *tmp = gaim_unescape_html(message); |
|
| 230 |
|
| 231 if (!c) |
|
| 232 return -EINVAL; |
|
| 233 |
|
| 234 if ((strlen(tmp) < 2) || (tmp[0] != '/' ) || (tmp[1] == '/')) { |
|
| 235 /* Actually send a chat message */ |
|
| 236 nap_write_packet(gc, 402, "%s %s", c->name, tmp); |
|
| 237 } else { |
|
| 238 /* user typed an IRC-style command */ |
|
| 239 nap_do_irc_style(gc, tmp, c->name); |
|
| 240 } |
|
| 241 |
|
| 242 g_free(tmp); |
|
| 243 |
|
| 244 return 0; |
|
| 245 } |
|
| 246 |
|
| 247 /* 603 - MSG_CLIENT_WHOIS */ |
|
| 248 static void nap_get_info(GaimConnection *gc, const char *who) |
|
| 249 { |
|
| 250 nap_write_packet(gc, 603, "%s", who); |
|
| 251 } |
|
| 252 |
|
| 253 static void nap_callback(gpointer data, gint source, GaimInputCondition condition) |
|
| 254 { |
|
| 255 GaimConnection *gc = data; |
|
| 256 struct nap_data *ndata = gc->proto_data; |
|
| 257 GaimAccount *account = gaim_connection_get_account(gc); |
|
| 258 GaimConversation *c; |
|
| 259 gchar *buf, *buf2, *buf3, **res; |
|
| 260 unsigned short header[2]; |
|
| 261 int len; |
|
| 262 int command; |
|
| 263 int i; |
|
| 264 |
|
| 265 if (read(source, (void*)header, 4) != 4) { |
|
| 266 gaim_connection_error(gc, _("Unable to read header from server")); |
|
| 267 return; |
|
| 268 } |
|
| 269 |
|
| 270 len = header[0]; |
|
| 271 command = header[1]; |
|
| 272 buf = (gchar *)g_malloc((len + 1) * sizeof(gchar)); |
|
| 273 buf[len] = '\0'; |
|
| 274 |
|
| 275 i = 0; |
|
| 276 do { |
|
| 277 int tmp = read(source, buf + i, len - i); |
|
| 278 if (tmp <= 0) { |
|
| 279 g_free(buf); |
|
| 280 buf = g_strdup_printf(_("Unable to read message from server: %s. Command is %hd, length is %hd."), strerror(errno), len, command); |
|
| 281 gaim_connection_error(gc, buf); |
|
| 282 g_free(buf); |
|
| 283 return; |
|
| 284 } |
|
| 285 i += tmp; |
|
| 286 } while (i != len); |
|
| 287 |
|
| 288 gaim_debug(GAIM_DEBUG_MISC, "napster", "R %3hd: %s\n", command, buf); |
|
| 289 |
|
| 290 switch (command) { |
|
| 291 case 000: /* MSG_SERVER_ERROR */ |
|
| 292 gaim_notify_error(gc, NULL, buf, NULL); |
|
| 293 gaim_input_remove(gc->inpa); |
|
| 294 gc->inpa = 0; |
|
| 295 close(source); |
|
| 296 gaim_connection_error(gc, _("Unknown server error.")); |
|
| 297 break; |
|
| 298 |
|
| 299 case 003: /* MSG_SERVER_EMAIL */ |
|
| 300 gaim_debug(GAIM_DEBUG_MISC, "napster", "Registered with e-mail address: %s\n", buf); |
|
| 301 ndata->email = g_strdup(buf); |
|
| 302 |
|
| 303 /* Our signon is complete */ |
|
| 304 gaim_connection_set_state(gc, GAIM_CONNECTED); |
|
| 305 |
|
| 306 /* Send the server our buddy list */ |
|
| 307 nap_send_buddylist(gc); |
|
| 308 |
|
| 309 break; |
|
| 310 |
|
| 311 case 201: /* MSG_SERVER_SEARCH_RESULT */ |
|
| 312 res = g_strsplit(buf, " ", 0); |
|
| 313 gaim_prpl_got_user_status(account, res[0], "available", NULL); |
|
| 314 g_strfreev(res); |
|
| 315 break; |
|
| 316 |
|
| 317 case 202: /* MSG_SERVER_SEARCH_END */ |
|
| 318 gaim_prpl_got_user_status(account, buf, "offline", NULL); |
|
| 319 break; |
|
| 320 |
|
| 321 case 205: /* MSG_CLIENT_PRIVMSG */ |
|
| 322 res = g_strsplit(buf, " ", 2); |
|
| 323 buf2 = g_markup_escape_text(res[1], -1); |
|
| 324 serv_got_im(gc, res[0], buf2, 0, time(NULL)); |
|
| 325 g_free(buf2); |
|
| 326 g_strfreev(res); |
|
| 327 break; |
|
| 328 |
|
| 329 case 209: /* MSG_SERVER_USER_SIGNON */ |
|
| 330 /* USERNAME SPEED */ |
|
| 331 res = g_strsplit(buf, " ", 2); |
|
| 332 gaim_prpl_got_user_status(account, res[0], "available", NULL); |
|
| 333 g_strfreev(res); |
|
| 334 break; |
|
| 335 |
|
| 336 case 210: /* MSG_SERVER_USER_SIGNOFF */ |
|
| 337 /* USERNAME SPEED */ |
|
| 338 res = g_strsplit(buf, " ", 2); |
|
| 339 gaim_prpl_got_user_status(account, res[0], "offline", NULL); |
|
| 340 g_strfreev(res); |
|
| 341 break; |
|
| 342 |
|
| 343 case 214: /* MSG_SERVER_STATS */ |
|
| 344 res = g_strsplit(buf, " ", 3); |
|
| 345 buf2 = g_strdup_printf(_("users: %s, files: %s, size: %sGB"), res[0], res[1], res[2]); |
|
| 346 serv_got_im(gc, "server", buf2, 0, time(NULL)); |
|
| 347 g_free(buf2); |
|
| 348 g_strfreev(res); |
|
| 349 break; |
|
| 350 |
|
| 351 case 301: /* MSG_SERVER_HOTLIST_ACK */ |
|
| 352 /* Our buddy was added successfully */ |
|
| 353 break; |
|
| 354 |
|
| 355 case 302: /* MSG_SERVER_HOTLIST_ERROR */ |
|
| 356 buf2 = g_strdup_printf(_("Unable to add \"%s\" to your Napster hotlist"), buf); |
|
| 357 gaim_notify_error(gc, NULL, buf2, NULL); |
|
| 358 g_free(buf2); |
|
| 359 break; |
|
| 360 |
|
| 361 case 316: /* MSG_SERVER_DISCONNECTING */ |
|
| 362 /* we have been kicked off =^( */ |
|
| 363 gaim_connection_error(gc, _("You were disconnected from the server.")); |
|
| 364 break; |
|
| 365 |
|
| 366 case 401: /* MSG_CLIENT_PART */ |
|
| 367 c = nap_find_chat(gc, buf); |
|
| 368 if (c) |
|
| 369 serv_got_chat_left(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c))); |
|
| 370 break; |
|
| 371 |
|
| 372 case 403: /* MSG_SERVER_PUBLIC */ |
|
| 373 res = g_strsplit(buf, " ", 3); |
|
| 374 c = nap_find_chat(gc, res[0]); |
|
| 375 if (c) |
|
| 376 serv_got_chat_in(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c)), res[1], 0, res[2], time((time_t)NULL)); |
|
| 377 g_strfreev(res); |
|
| 378 break; |
|
| 379 |
|
| 380 case 404: /* MSG_SERVER_NOSUCH */ |
|
| 381 /* abused by opennap servers to broadcast stuff */ |
|
| 382 buf2 = g_markup_escape_text(buf, -1); |
|
| 383 serv_got_im(gc, "server", buf2, 0, time(NULL)); |
|
| 384 g_free(buf2); |
|
| 385 break; |
|
| 386 |
|
| 387 case 405: /* MSG_SERVER_JOIN_ACK */ |
|
| 388 c = nap_find_chat(gc, buf); |
|
| 389 if (!c) |
|
| 390 serv_got_joined_chat(gc, gaim_conv_chat_get_id(GAIM_CONV_CHAT(c)), buf); |
|
| 391 break; |
|
| 392 |
|
| 393 case 407: /* MSG_SERVER_PART */ |
|
| 394 res = g_strsplit(buf, " ", 0); |
|
| 395 c = nap_find_chat(gc, res[0]); |
|
| 396 gaim_conv_chat_remove_user(GAIM_CONV_CHAT(c), res[1], NULL); |
|
| 397 g_strfreev(res); |
|
| 398 break; |
|
| 399 |
|
| 400 case 406: /* MSG_SERVER_JOIN */ |
|
| 401 case 408: /* MSG_SERVER_CHANNEL_USER_LIST */ |
|
| 402 res = g_strsplit(buf, " ", 4); |
|
| 403 c = nap_find_chat(gc, res[0]); |
|
| 404 gaim_conv_chat_add_user(GAIM_CONV_CHAT(c), res[1], NULL, GAIM_CBFLAGS_NONE, TRUE); |
|
| 405 g_strfreev(res); |
|
| 406 break; |
|
| 407 |
|
| 408 case 409: /* MSG_SERVER_CHANNEL_USER_LIST_END */ |
|
| 409 break; |
|
| 410 |
|
| 411 case 410: /* MSG_SERVER_TOPIC */ |
|
| 412 /* display the topic in the channel */ |
|
| 413 res = g_strsplit(buf, " ", 2); |
|
| 414 c = nap_find_chat(gc, res[0]); |
|
| 415 gaim_conv_chat_set_topic(GAIM_CONV_CHAT(c), res[0], res[1]); |
|
| 416 g_strfreev(res); |
|
| 417 break; |
|
| 418 |
|
| 419 case 603: /* MSG_CLIENT_WHOIS */ |
|
| 420 buf2 = g_strdup_printf(_("%s requested your information"), buf); |
|
| 421 serv_got_im(gc, "server", buf2, 0, time(NULL)); |
|
| 422 g_free(buf2); |
|
| 423 break; |
|
| 424 |
|
| 425 case 604: /* MSG_SERVER_WHOIS_RESPONSE */ |
|
| 426 /* XXX - Format is: "Elite" 37 " " "Active" 0 0 0 0 "gaim 0.63cvs" 0 0 192.168.1.41 32798 0 unknown flounder */ |
|
| 427 res = g_strsplit(buf, " ", 2); |
|
| 428 /* res[0] == username */ |
|
| 429 gaim_notify_userinfo(gc, res[0], res[1], NULL, NULL); |
|
| 430 g_strfreev(res); |
|
| 431 break; |
|
| 432 |
|
| 433 case 621: |
|
| 434 case 622: /* MSG_CLIENT_MOTD */ |
|
| 435 /* also replaces MSG_SERVER_MOTD, so we should display it */ |
|
| 436 buf2 = g_markup_escape_text(buf, -1); |
|
| 437 serv_got_im(gc, "motd", buf2, 0, time(NULL)); |
|
| 438 g_free(buf2); |
|
| 439 break; |
|
| 440 |
|
| 441 case 627: /* MSG_CLIENT_WALLOP */ |
|
| 442 /* abused by opennap server maintainers to broadcast stuff */ |
|
| 443 buf2 = g_markup_escape_text(buf, -1); |
|
| 444 serv_got_im(gc, "wallop", buf2, 0, time(NULL)); |
|
| 445 g_free(buf2); |
|
| 446 break; |
|
| 447 |
|
| 448 case 628: /* MSG_CLIENT_ANNOUNCE */ |
|
| 449 buf2 = g_markup_escape_text(buf, -1); |
|
| 450 serv_got_im(gc, "announce", buf2, 0, time(NULL)); |
|
| 451 g_free(buf); |
|
| 452 break; |
|
| 453 |
|
| 454 case 748: /* MSG_SERVER_GHOST */ |
|
| 455 /* Looks like someone logged in as us! =-O */ |
|
| 456 gaim_connection_error(gc, _("You have signed on from another location.")); |
|
| 457 break; |
|
| 458 |
|
| 459 case 751: /* MSG_CLIENT_PING */ |
|
| 460 buf2 = g_strdup_printf(_("%s requested a PING"), buf); |
|
| 461 serv_got_im(gc, "server", buf2, 0, time(NULL)); |
|
| 462 g_free(buf2); |
|
| 463 /* send back a pong */ |
|
| 464 /* MSG_CLIENT_PONG */ |
|
| 465 nap_write_packet(gc, 752, "%s", buf); |
|
| 466 break; |
|
| 467 |
|
| 468 case 752: /* MSG_CLIENT_PONG */ |
|
| 469 buf2 = g_strdup_printf("Received pong from %s", buf); |
|
| 470 gaim_notify_info(gc, NULL, buf2, NULL); |
|
| 471 g_free(buf2); |
|
| 472 break; |
|
| 473 |
|
| 474 case 824: /* MSG_CLIENT_EMOTE */ |
|
| 475 res = g_strsplit(buf, " ", 3); |
|
| 476 buf2 = g_strndup(res[2]+1, strlen(res[2]) - 2); /* chomp off the surround quotes */ |
|
| 477 buf3 = g_strdup_printf("/me %s", buf2); |
|
| 478 g_free(buf2); |
|
| 479 if ((c = nap_find_chat(gc, res[0]))) { |
|
| 480 gaim_conv_chat_write(GAIM_CONV_CHAT(c), res[1], buf3, GAIM_MESSAGE_NICK, time(NULL)); |
|
| 481 } |
|
| 482 g_free(buf3); |
|
| 483 g_strfreev(res); |
|
| 484 break; |
|
| 485 |
|
| 486 default: |
|
| 487 gaim_debug(GAIM_DEBUG_MISC, "napster", "Unknown packet %hd: %s\n", command, buf); |
|
| 488 break; |
|
| 489 } |
|
| 490 |
|
| 491 g_free(buf); |
|
| 492 } |
|
| 493 |
|
| 494 /* 002 - MSG_CLIENT_LOGIN */ |
|
| 495 static void nap_login_connect(gpointer data, gint source, GaimInputCondition cond) |
|
| 496 { |
|
| 497 GaimConnection *gc = data; |
|
| 498 struct nap_data *ndata = (struct nap_data *)gc->proto_data; |
|
| 499 gchar *buf; |
|
| 500 |
|
| 501 if (!g_list_find(gaim_connections_get_all(), gc)) { |
|
| 502 close(source); |
|
| 503 return; |
|
| 504 } |
|
| 505 |
|
| 506 if (source < 0) { |
|
| 507 gaim_connection_error(gc, _("Unable to connect.")); |
|
| 508 return; |
|
| 509 } |
|
| 510 |
|
| 511 ndata->fd = source; |
|
| 512 |
|
| 513 /* Update the login progress status display */ |
|
| 514 buf = g_strdup_printf("Logging in: %s", gaim_account_get_username(gc->account)); |
|
| 515 gaim_connection_update_progress(gc, buf, 1, NAPSTER_CONNECT_STEPS); |
|
| 516 g_free(buf); |
|
| 517 |
|
| 518 /* Write our signon data */ |
|
| 519 nap_write_packet(gc, 2, "%s %s 0 \"gaim %s\" 0", |
|
| 520 gaim_account_get_username(gc->account), |
|
| 521 gaim_connection_get_password(gc), VERSION); |
|
| 522 |
|
| 523 /* And set up the input watcher */ |
|
| 524 gc->inpa = gaim_input_add(ndata->fd, GAIM_INPUT_READ, nap_callback, gc); |
|
| 525 } |
|
| 526 |
|
| 527 static void nap_login(GaimAccount *account) |
|
| 528 { |
|
| 529 GaimConnection *gc = gaim_account_get_connection(account); |
|
| 530 |
|
| 531 gaim_connection_update_progress(gc, _("Connecting"), 0, NAPSTER_CONNECT_STEPS); |
|
| 532 |
|
| 533 gc->proto_data = g_new0(struct nap_data, 1); |
|
| 534 if (gaim_proxy_connect(account, |
|
| 535 gaim_account_get_string(account, "server", NAP_SERVER), |
|
| 536 gaim_account_get_int(account, "port", NAP_PORT), |
|
| 537 nap_login_connect, gc) != 0) { |
|
| 538 gaim_connection_error(gc, _("Unable to connect.")); |
|
| 539 } |
|
| 540 } |
|
| 541 |
|
| 542 static void nap_close(GaimConnection *gc) |
|
| 543 { |
|
| 544 struct nap_data *ndata = (struct nap_data *)gc->proto_data; |
|
| 545 |
|
| 546 if (gc->inpa) |
|
| 547 gaim_input_remove(gc->inpa); |
|
| 548 |
|
| 549 if (!ndata) |
|
| 550 return; |
|
| 551 |
|
| 552 close(ndata->fd); |
|
| 553 |
|
| 554 g_free(ndata->email); |
|
| 555 g_free(ndata); |
|
| 556 } |
|
| 557 |
|
| 558 static const char* nap_list_icon(GaimAccount *a, GaimBuddy *b) |
|
| 559 { |
|
| 560 return "napster"; |
|
| 561 } |
|
| 562 |
|
| 563 static void nap_list_emblems(GaimBuddy *b, const char **se, const char **sw, |
|
| 564 const char **nw, const char **ne) |
|
| 565 { |
|
| 566 if(!GAIM_BUDDY_IS_ONLINE(b)) |
|
| 567 *se = "offline"; |
|
| 568 } |
|
| 569 |
|
| 570 static GList *nap_status_types(GaimAccount *account) |
|
| 571 { |
|
| 572 GList *types = NULL; |
|
| 573 GaimStatusType *type; |
|
| 574 |
|
| 575 g_return_val_if_fail(account != NULL, NULL); |
|
| 576 |
|
| 577 type = gaim_status_type_new_full(GAIM_STATUS_AVAILABLE, |
|
| 578 NULL, NULL, TRUE, TRUE, FALSE); |
|
| 579 types = g_list_append(types, type); |
|
| 580 |
|
| 581 type = gaim_status_type_new_full(GAIM_STATUS_OFFLINE, |
|
| 582 NULL, NULL, TRUE, TRUE, FALSE); |
|
| 583 types = g_list_append(types, type); |
|
| 584 |
|
| 585 return types; |
|
| 586 } |
|
| 587 |
|
| 588 static GList *nap_chat_info(GaimConnection *gc) |
|
| 589 { |
|
| 590 GList *m = NULL; |
|
| 591 struct proto_chat_entry *pce; |
|
| 592 |
|
| 593 pce = g_new0(struct proto_chat_entry, 1); |
|
| 594 pce->label = _("_Group:"); |
|
| 595 pce->identifier = "group"; |
|
| 596 m = g_list_append(m, pce); |
|
| 597 |
|
| 598 return m; |
|
| 599 } |
|
| 600 |
|
| 601 GHashTable *nap_chat_info_defaults(GaimConnection *gc, const char *chat_name) |
|
| 602 { |
|
| 603 GHashTable *defaults; |
|
| 604 |
|
| 605 defaults = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free); |
|
| 606 |
|
| 607 if (chat_name != NULL) |
|
| 608 g_hash_table_insert(defaults, "group", g_strdup(chat_name)); |
|
| 609 |
|
| 610 return defaults; |
|
| 611 } |
|
| 612 |
|
| 613 static GaimPlugin *my_protocol = NULL; |
|
| 614 |
|
| 615 static GaimPluginProtocolInfo prpl_info = |
|
| 616 { |
|
| 617 OPT_PROTO_CHAT_TOPIC, |
|
| 618 NULL, /* user_splits */ |
|
| 619 NULL, /* protocol_options */ |
|
| 620 NO_BUDDY_ICONS, /* icon_spec */ |
|
| 621 nap_list_icon, /* list_icon */ |
|
| 622 nap_list_emblems, /* list_emblems */ |
|
| 623 NULL, /* status_text */ |
|
| 624 NULL, /* tooltip_text */ |
|
| 625 nap_status_types, /* status_types */ |
|
| 626 NULL, /* blist_node_menu */ |
|
| 627 nap_chat_info, /* chat_info */ |
|
| 628 nap_chat_info_defaults, /* chat_info_defaults */ |
|
| 629 nap_login, /* login */ |
|
| 630 nap_close, /* close */ |
|
| 631 nap_send_im, /* send_im */ |
|
| 632 NULL, /* set_info */ |
|
| 633 NULL, /* send_typing */ |
|
| 634 nap_get_info, /* get_info */ |
|
| 635 NULL, /* set_away */ |
|
| 636 NULL, /* set_idle */ |
|
| 637 NULL, /* change_passwd */ |
|
| 638 nap_add_buddy, /* add_buddy */ |
|
| 639 NULL, /* add_buddies */ |
|
| 640 nap_remove_buddy, /* remove_buddy */ |
|
| 641 NULL, /* remove_buddies */ |
|
| 642 NULL, /* add_permit */ |
|
| 643 NULL, /* add_deny */ |
|
| 644 NULL, /* rem_permit */ |
|
| 645 NULL, /* rem_deny */ |
|
| 646 NULL, /* set_permit_deny */ |
|
| 647 nap_join_chat, /* join_chat */ |
|
| 648 NULL, /* reject chat invite */ |
|
| 649 nap_get_chat_name, /* get_chat_name */ |
|
| 650 NULL, /* chat_invite */ |
|
| 651 nap_chat_leave, /* chat_leave */ |
|
| 652 NULL, /* chat_whisper */ |
|
| 653 nap_chat_send, /* chat_send */ |
|
| 654 NULL, /* keepalive */ |
|
| 655 NULL, /* register_user */ |
|
| 656 NULL, /* get_cb_info */ |
|
| 657 NULL, /* get_cb_away */ |
|
| 658 NULL, /* alias_buddy */ |
|
| 659 NULL, /* group_buddy */ |
|
| 660 NULL, /* rename_group */ |
|
| 661 NULL, /* buddy_free */ |
|
| 662 NULL, /* convo_closed */ |
|
| 663 NULL, /* normalize */ |
|
| 664 NULL, /* set_buddy_icon */ |
|
| 665 NULL, /* remove_group */ |
|
| 666 NULL, /* get_cb_real_name */ |
|
| 667 NULL, /* set_chat_topic */ |
|
| 668 NULL, /* find_blist_chat */ |
|
| 669 NULL, /* roomlist_get_list */ |
|
| 670 NULL, /* roomlist_cancel */ |
|
| 671 NULL, /* roomlist_expand_category */ |
|
| 672 NULL, /* can_receive_file */ |
|
| 673 NULL, /* send_file */ |
|
| 674 NULL, /* new_xfer */ |
|
| 675 NULL, /* offline_message */ |
|
| 676 NULL, /* whiteboard_prpl_ops */ |
|
| 677 NULL, /* media_prpl_ops */ |
|
| 678 }; |
|
| 679 |
|
| 680 static GaimPluginInfo info = |
|
| 681 { |
|
| 682 GAIM_PLUGIN_MAGIC, |
|
| 683 GAIM_MAJOR_VERSION, |
|
| 684 GAIM_MINOR_VERSION, |
|
| 685 GAIM_PLUGIN_PROTOCOL, /**< type */ |
|
| 686 NULL, /**< ui_requirement */ |
|
| 687 0, /**< flags */ |
|
| 688 NULL, /**< dependencies */ |
|
| 689 GAIM_PRIORITY_DEFAULT, /**< priority */ |
|
| 690 |
|
| 691 "prpl-napster", /**< id */ |
|
| 692 "Napster", /**< name */ |
|
| 693 VERSION, /**< version */ |
|
| 694 /** summary */ |
|
| 695 N_("NAPSTER Protocol Plugin"), |
|
| 696 /** description */ |
|
| 697 N_("NAPSTER Protocol Plugin"), |
|
| 698 NULL, /**< author */ |
|
| 699 GAIM_WEBSITE, /**< homepage */ |
|
| 700 |
|
| 701 NULL, /**< load */ |
|
| 702 NULL, /**< unload */ |
|
| 703 NULL, /**< destroy */ |
|
| 704 |
|
| 705 NULL, /**< ui_info */ |
|
| 706 &prpl_info, /**< extra_info */ |
|
| 707 NULL, |
|
| 708 NULL |
|
| 709 }; |
|
| 710 |
|
| 711 static void init_plugin(GaimPlugin *plugin) |
|
| 712 { |
|
| 713 GaimAccountOption *option; |
|
| 714 |
|
| 715 option = gaim_account_option_string_new(_("Server"), "server", |
|
| 716 NAP_SERVER); |
|
| 717 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, |
|
| 718 option); |
|
| 719 |
|
| 720 option = gaim_account_option_int_new(_("Port"), "port", 8888); |
|
| 721 prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, |
|
| 722 option); |
|
| 723 |
|
| 724 my_protocol = plugin; |
|
| 725 } |
|
| 726 |
|
| 727 GAIM_INIT_PLUGIN(napster, init_plugin, info); |
|