Mercurial > pidgin
comparison plugins/napster.c @ 1323:4cbb78f05e4b
[gaim-migrate @ 1333]
I am on some serious crack :-)
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Wed, 20 Dec 2000 04:05:15 +0000 |
parents | |
children | 08aa745310f6 |
comparison
equal
deleted
inserted
replaced
1322:c72b2eed92cb | 1323:4cbb78f05e4b |
---|---|
1 /* | |
2 * gaim - Napster Protocol Plugin | |
3 * | |
4 * Copyright (C) 2000, Rob Flynn <rob@tgflinux.com> | |
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 */ | |
21 | |
22 #include "../config.h" | |
23 | |
24 #include <netdb.h> | |
25 #include <gtk/gtk.h> | |
26 #include <unistd.h> | |
27 #include <errno.h> | |
28 #include <netinet/in.h> | |
29 #include <arpa/inet.h> | |
30 #include <time.h> | |
31 #include <string.h> | |
32 #include <stdlib.h> | |
33 #include <stdio.h> | |
34 #include <time.h> | |
35 #include <sys/socket.h> | |
36 #include <sys/stat.h> | |
37 #include "multi.h" | |
38 #include "prpl.h" | |
39 #include "gaim.h" | |
40 | |
41 #define NAP_BUF_LEN 4096 | |
42 | |
43 GSList *nap_connections = NULL; | |
44 | |
45 static unsigned int chat_id = 0; | |
46 | |
47 struct nap_channel { | |
48 unsigned int id; | |
49 gchar *name; | |
50 }; | |
51 | |
52 struct nap_data { | |
53 int fd; | |
54 int inpa; | |
55 | |
56 gchar *email; | |
57 GSList *channels; | |
58 }; | |
59 | |
60 static char *nap_name() | |
61 { | |
62 return "Napster"; | |
63 } | |
64 | |
65 char *name() | |
66 { | |
67 return "Napster"; | |
68 } | |
69 | |
70 char *description() | |
71 { | |
72 return "Allows gaim to use the Napster protocol. Yes, kids, drugs are bad."; | |
73 } | |
74 | |
75 | |
76 /* FIXME: Make this use va_arg stuff */ | |
77 void nap_write_packet(struct gaim_connection *gc, unsigned short command, char *message) | |
78 { | |
79 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
80 unsigned short size; | |
81 | |
82 size = strlen(message); | |
83 | |
84 write(ndata->fd, &size, 2); | |
85 write(ndata->fd, &command, 2); | |
86 write(ndata->fd, message, size); | |
87 } | |
88 | |
89 static void nap_send_im(struct gaim_connection *gc, char *who, char *message, int away) | |
90 { | |
91 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
92 gchar buf[NAP_BUF_LEN]; | |
93 | |
94 g_snprintf(buf, NAP_BUF_LEN, "%s %s", who, message); | |
95 nap_write_packet(gc, 0xCD, buf); | |
96 } | |
97 | |
98 static struct nap_channel *find_channel_by_name(struct gaim_connection *gc, char *name) | |
99 { | |
100 struct nap_channel *channel; | |
101 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
102 GSList *channels; | |
103 | |
104 channels = ndata->channels; | |
105 | |
106 while (channels) { | |
107 channel = (struct nap_channel *)channels->data; | |
108 if (!g_strcasecmp(name, channel->name)) { | |
109 return channel; | |
110 } | |
111 | |
112 channels = g_slist_next(channels); | |
113 } | |
114 | |
115 return NULL; | |
116 } | |
117 | |
118 static struct nap_channel *find_channel_by_id(struct gaim_connection *gc, int id) | |
119 { | |
120 struct nap_channel *channel; | |
121 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
122 GSList *channels; | |
123 | |
124 channels = ndata->channels; | |
125 | |
126 while (channels) { | |
127 channel = (struct nap_channel *)channels->data; | |
128 if (id == channel->id) { | |
129 return channel; | |
130 } | |
131 | |
132 channels = g_slist_next(channels); | |
133 } | |
134 | |
135 return NULL; | |
136 } | |
137 | |
138 static struct conversation *find_conversation_by_id(struct gaim_connection *gc, int id) | |
139 { | |
140 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
141 GSList *bc = gc->buddy_chats; | |
142 struct conversation *b = NULL; | |
143 | |
144 while (bc) { | |
145 b = (struct conversation *)bc->data; | |
146 if (id == b->id) { | |
147 break; | |
148 } | |
149 bc = bc->next; | |
150 b = NULL; | |
151 } | |
152 | |
153 if (!b) { | |
154 return NULL; | |
155 } | |
156 | |
157 return b; | |
158 } | |
159 | |
160 static void nap_callback(gpointer data, gint source, GdkInputCondition condition) | |
161 { | |
162 struct gaim_connection *gc = data; | |
163 struct nap_data *ndata = gc->proto_data; | |
164 gchar *buf; | |
165 unsigned short header[2]; | |
166 int i = 0; | |
167 int len; | |
168 int command; | |
169 gchar **res; | |
170 | |
171 read(source, header, 4); | |
172 len = header[0]; | |
173 command = header[1]; | |
174 | |
175 buf = (gchar *)g_malloc(sizeof(gchar) * (len + 1)); | |
176 | |
177 read(source, buf, len); | |
178 | |
179 buf[len] = 0; | |
180 | |
181 if (command == 0xd6) { | |
182 res = g_strsplit(buf, " ", 0); | |
183 /* Do we want to report what the users are doing? */ | |
184 printf("users: %s, files: %s, size: %sGB\n", res[0], res[1], res[2]); | |
185 g_strfreev(res); | |
186 free(buf); | |
187 return; | |
188 } | |
189 | |
190 if (command == 0x26d) { | |
191 /* Do we want to use the MOTD? */ | |
192 free(buf); | |
193 return; | |
194 } | |
195 | |
196 if (command == 0xCD) { | |
197 res = g_strsplit(buf, " ", 1); | |
198 serv_got_im(gc, res[0], res[1], 0); | |
199 g_strfreev(res); | |
200 free(buf); | |
201 return; | |
202 } | |
203 | |
204 if (command == 0x195) { | |
205 struct nap_channel *channel; | |
206 int id; | |
207 | |
208 channel = find_channel_by_name(gc, buf); | |
209 | |
210 if (!channel) { | |
211 chat_id++; | |
212 | |
213 channel = g_new0(struct nap_channel, 1); | |
214 | |
215 channel->id = chat_id; | |
216 channel->name = g_strdup(buf); | |
217 | |
218 ndata->channels = g_slist_append(ndata->channels, channel); | |
219 | |
220 serv_got_joined_chat(gc, chat_id, buf); | |
221 } | |
222 | |
223 free(buf); | |
224 return; | |
225 } | |
226 | |
227 if (command == 0x198 || command == 0x196) { | |
228 struct nap_channel *channel; | |
229 struct conversation *convo; | |
230 gchar **res; | |
231 | |
232 res = g_strsplit(buf, " ", 0); | |
233 | |
234 channel = find_channel_by_name(gc, res[0]); | |
235 convo = find_conversation_by_id(gc, channel->id); | |
236 | |
237 add_chat_buddy(convo, res[1]); | |
238 | |
239 g_strfreev(res); | |
240 | |
241 free(buf); | |
242 return; | |
243 } | |
244 | |
245 if (command == 0x193) { | |
246 gchar **res; | |
247 struct nap_channel *channel; | |
248 | |
249 res = g_strsplit(buf, " ", 2); | |
250 | |
251 channel = find_channel_by_name(gc, res[0]); | |
252 | |
253 if (channel) | |
254 serv_got_chat_in(gc, channel->id, res[1], 0, res[2]); | |
255 | |
256 g_strfreev(res); | |
257 free(buf); | |
258 return; | |
259 } | |
260 | |
261 if (command == 0x194) { | |
262 do_error_dialog(buf, "Gaim: Napster Error"); | |
263 free(buf); | |
264 return; | |
265 } | |
266 | |
267 if (command == 0x12e) { | |
268 gchar buf2[NAP_BUF_LEN]; | |
269 | |
270 g_snprintf(buf2, NAP_BUF_LEN, "Unable to add '%s' to your hotlist", buf); | |
271 do_error_dialog(buf2, "Gaim: Napster Error"); | |
272 | |
273 free(buf); | |
274 return; | |
275 | |
276 } | |
277 | |
278 if (command == 0x191) { | |
279 struct nap_channel *channel; | |
280 | |
281 channel = find_channel_by_name(gc, buf); | |
282 | |
283 if (!channel) /* I'm not sure how this would happen =) */ | |
284 return; | |
285 | |
286 serv_got_chat_left(gc, channel->id); | |
287 ndata->channels = g_slist_remove(ndata->channels, channel); | |
288 | |
289 free(buf); | |
290 return; | |
291 | |
292 } | |
293 | |
294 if (command == 0xd1) { | |
295 gchar **res; | |
296 | |
297 res = g_strsplit(buf, " ", 0); | |
298 | |
299 serv_got_update(gc, res[0], 1, 0, time((time_t *)NULL), 0, 0, 0); | |
300 | |
301 g_strfreev(res); | |
302 free(buf); | |
303 return; | |
304 } | |
305 | |
306 if (command == 0xd2) { | |
307 serv_got_update(gc, buf, 0, 0, 0, 0, 0, 0); | |
308 free(buf); | |
309 return; | |
310 } | |
311 | |
312 if (command == 0x12d) { | |
313 /* Our buddy was added successfully */ | |
314 free(buf); | |
315 return; | |
316 } | |
317 | |
318 printf("NAP: [COMMAND: 0x%04x] %s\n", command, buf); | |
319 } | |
320 | |
321 | |
322 static void nap_login_callback(gpointer data, gint source, GdkInputCondition condition) | |
323 { | |
324 struct gaim_connection *gc = data; | |
325 struct nap_data *ndata = gc->proto_data; | |
326 gchar buf[NAP_BUF_LEN]; | |
327 unsigned short header[2]; | |
328 int i = 0; | |
329 int len; | |
330 int command; | |
331 | |
332 read(source, header, 4); | |
333 len = header[0]; | |
334 command = header[1]; | |
335 | |
336 read(source, buf, len); | |
337 buf[len] = 0; | |
338 | |
339 if (command == 0x03) { | |
340 printf("Registered with E-Mail address of: %s\n", buf); | |
341 ndata->email = g_strdup(buf); | |
342 | |
343 /* Remove old inpa, add new one */ | |
344 gdk_input_remove(ndata->inpa); | |
345 ndata->inpa = 0; | |
346 gc->inpa = gdk_input_add(ndata->fd, GDK_INPUT_READ, nap_callback, gc); | |
347 | |
348 /* Our signon is complete */ | |
349 account_online(gc); | |
350 serv_finish_login(gc); | |
351 | |
352 if (bud_list_cache_exists(gc)) | |
353 do_import(NULL, gc); | |
354 | |
355 return; | |
356 } | |
357 } | |
358 | |
359 | |
360 | |
361 static void nap_login(struct aim_user *user) | |
362 { | |
363 int fd; | |
364 struct hostent *host; | |
365 struct sockaddr_in site; | |
366 struct gaim_connection *gc = new_gaim_conn(user); | |
367 struct nap_data *ndata = gc->proto_data = g_new0(struct nap_data, 1); | |
368 char buf[NAP_BUF_LEN]; | |
369 char c; | |
370 char z[4]; | |
371 int i; | |
372 int status; | |
373 | |
374 host = gethostbyname("64.124.41.184"); | |
375 | |
376 if (!host) { | |
377 hide_login_progress(gc, "Unable to resolve hostname"); | |
378 signoff(gc); | |
379 return; | |
380 } | |
381 | |
382 site.sin_family = AF_INET; | |
383 site.sin_addr.s_addr = *(long *)(host->h_addr); | |
384 | |
385 site.sin_port = htons(8888); | |
386 | |
387 fd = socket(AF_INET, SOCK_STREAM, 0); | |
388 if (fd < 0) { | |
389 hide_login_progress(gc, "Unable to create socket"); | |
390 signoff(gc); | |
391 return; | |
392 } | |
393 | |
394 /* Make a connection with the server */ | |
395 if (connect(fd, (struct sockaddr *)&site, sizeof(site)) < 0) { | |
396 hide_login_progress(gc, "Unable to connect."); | |
397 signoff(gc); | |
398 return; | |
399 } | |
400 | |
401 ndata->fd = fd; | |
402 | |
403 /* And write our signon data */ | |
404 g_snprintf(buf, NAP_BUF_LEN, "%s %s 0 \"Gnapster 1.4.1a\" 0", gc->username, gc->password); | |
405 nap_write_packet(gc, 0x02, buf); | |
406 | |
407 /* And set up the input watcher */ | |
408 ndata->inpa = gdk_input_add(ndata->fd, GDK_INPUT_READ, nap_login_callback, gc); | |
409 | |
410 } | |
411 | |
412 static void nap_join_chat(struct gaim_connection *gc, int id, char *name) | |
413 { | |
414 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
415 gchar buf[NAP_BUF_LEN]; | |
416 | |
417 /* Make sure the name has a # preceeding it */ | |
418 if (name[0] != '#') | |
419 g_snprintf(buf, NAP_BUF_LEN, "#%s", name); | |
420 else | |
421 g_snprintf(buf, NAP_BUF_LEN, "%s", name); | |
422 | |
423 nap_write_packet(gc, 0x190, buf); | |
424 } | |
425 | |
426 static void nap_chat_leave(struct gaim_connection *gc, int id) | |
427 { | |
428 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
429 struct nap_channel *channel = NULL; | |
430 GSList *channels = ndata->channels; | |
431 | |
432 channel = find_channel_by_id(gc, id); | |
433 | |
434 if (!channel) /* Again, I'm not sure how this would happen */ | |
435 return; | |
436 | |
437 nap_write_packet(gc, 0x191, channel->name); | |
438 | |
439 channels = g_slist_remove(channels, channel); | |
440 g_free(channel->name); | |
441 g_free(channel); | |
442 | |
443 } | |
444 | |
445 static void nap_chat_send(struct gaim_connection *gc, int id, char *message) | |
446 { | |
447 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
448 struct nap_channel *channel = NULL; | |
449 gchar buf[NAP_BUF_LEN]; | |
450 | |
451 channel = find_channel_by_id(gc, id); | |
452 | |
453 if (!channel) { | |
454 /* This shouldn't happen */ | |
455 return; | |
456 } | |
457 | |
458 g_snprintf(buf, NAP_BUF_LEN, "%s %s", channel->name, message); | |
459 nap_write_packet(gc, 0x192, buf); | |
460 | |
461 } | |
462 | |
463 static void nap_add_buddy(struct gaim_connection *gc, char *name) | |
464 { | |
465 nap_write_packet(gc, 0xCF, name); | |
466 } | |
467 | |
468 static void nap_remove_buddy(struct gaim_connection *gc, char *name) | |
469 { | |
470 nap_write_packet(gc, 0x12F, name); | |
471 } | |
472 | |
473 static void nap_close(struct gaim_connection *gc) | |
474 { | |
475 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
476 gchar buf[NAP_BUF_LEN]; | |
477 struct nap_channel *channel; | |
478 GSList *channels = ndata->channels; | |
479 | |
480 if (gc->inpa) | |
481 gdk_input_remove(gc->inpa); | |
482 | |
483 while (channels) { | |
484 channel = (struct nap_channel *)channels->data; | |
485 g_free(channel->name); | |
486 channels = g_slist_remove(channels, channel); | |
487 g_free(channel); | |
488 } | |
489 | |
490 } | |
491 | |
492 static void nap_add_buddies(struct gaim_connection *gc, GList *buddies) | |
493 { | |
494 struct nap_data *ndata = (struct nap_data *)gc->proto_data; | |
495 gchar buf[NAP_BUF_LEN]; | |
496 int n = 0; | |
497 | |
498 while (buddies) { | |
499 nap_write_packet(gc, 0xd0, (char *)buddies->data); | |
500 buddies = buddies -> next; | |
501 } | |
502 } | |
503 | |
504 static struct prpl *my_protocol = NULL; | |
505 | |
506 void nap_init(struct prpl *ret) | |
507 { | |
508 ret->protocol = PROTO_NAPSTER; | |
509 ret->name = nap_name; | |
510 ret->list_icon = NULL; | |
511 ret->action_menu = NULL; | |
512 ret->user_opts = NULL; | |
513 ret->login = nap_login; | |
514 ret->close = nap_close; | |
515 ret->send_im = nap_send_im; | |
516 ret->set_info = NULL; | |
517 ret->get_info = NULL; | |
518 ret->set_away = NULL; | |
519 ret->get_away_msg = NULL; | |
520 ret->set_dir = NULL; | |
521 ret->get_dir = NULL; | |
522 ret->dir_search = NULL; | |
523 ret->set_idle = NULL; | |
524 ret->change_passwd = NULL; | |
525 ret->add_buddy = nap_add_buddy; | |
526 ret->add_buddies = nap_add_buddies; | |
527 ret->remove_buddy = nap_remove_buddy; | |
528 ret->add_permit = NULL; | |
529 ret->rem_permit = NULL; | |
530 ret->add_deny = NULL; | |
531 ret->rem_deny = NULL; | |
532 ret->warn = NULL; | |
533 ret->accept_chat = NULL; | |
534 ret->join_chat = nap_join_chat; | |
535 ret->chat_invite = NULL; | |
536 ret->chat_leave = nap_chat_leave; | |
537 ret->chat_whisper = NULL; | |
538 ret->chat_send = nap_chat_send; | |
539 ret->keepalive = NULL; | |
540 | |
541 my_protocol = ret; | |
542 } | |
543 | |
544 char *gaim_plugin_init(GModule * handle) | |
545 { | |
546 load_protocol(nap_init); | |
547 return NULL; | |
548 } | |
549 | |
550 void gaim_plugin_remove() | |
551 { | |
552 struct prpl *p = find_prpl(PROTO_NAPSTER); | |
553 if (p == my_protocol) | |
554 unload_protocol(p); | |
555 } |