Mercurial > pidgin
annotate libgaim/ft.c @ 20392:9ba7dee775e1
The first msn-p13-merge-head.diff.gz from SF Patch #1621854 from Ka-Hing Cheung.
"uploaded a diff, this diff is unchanged from the last tarball that I
previously uploaded, except that it's against HEAD. This should be a little
easier for most people."
(This was apparently msn-p13-merge-head.diff, which SourceForge didn't allow to
be uploaded.)
PLUS
"Updated the diff with basically no change, except with simom's icon fix.
The previous diff was broken because some of the files were not added"
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Sun, 15 Apr 2007 03:01:41 +0000 |
parents | 5176a9f30ba3 |
children |
rev | line source |
---|---|
14192 | 1 /** |
2 * @file ft.c File Transfer API | |
3 * | |
4 * gaim | |
5 * | |
6 * Gaim is the legal property of its developers, whose names are too numerous | |
7 * to list here. Please refer to the COPYRIGHT file distributed with this | |
8 * source distribution. | |
9 * | |
10 * This program is free software; you can redistribute it and/or modify | |
11 * it under the terms of the GNU General Public License as published by | |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
15 * This program is distributed in the hope that it will be useful, | |
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
20 * You should have received a copy of the GNU General Public License | |
21 * along with this program; if not, write to the Free Software | |
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
23 * | |
24 */ | |
25 #include "internal.h" | |
26 #include "ft.h" | |
27 #include "network.h" | |
28 #include "notify.h" | |
29 #include "prefs.h" | |
30 #include "proxy.h" | |
31 #include "request.h" | |
32 #include "util.h" | |
33 | |
15218 | 34 #define FT_INITIAL_BUFFER_SIZE 4096 |
35 #define FT_MAX_BUFFER_SIZE 65535 | |
36 | |
14192 | 37 static GaimXferUiOps *xfer_ui_ops = NULL; |
38 | |
14905 | 39 static int gaim_xfer_choose_file(GaimXfer *xfer); |
40 | |
14192 | 41 GaimXfer * |
42 gaim_xfer_new(GaimAccount *account, GaimXferType type, const char *who) | |
43 { | |
44 GaimXfer *xfer; | |
45 GaimXferUiOps *ui_ops; | |
46 | |
47 g_return_val_if_fail(type != GAIM_XFER_UNKNOWN, NULL); | |
48 g_return_val_if_fail(account != NULL, NULL); | |
49 g_return_val_if_fail(who != NULL, NULL); | |
50 | |
51 xfer = g_new0(GaimXfer, 1); | |
52 | |
53 xfer->ref = 1; | |
54 xfer->type = type; | |
55 xfer->account = account; | |
56 xfer->who = g_strdup(who); | |
57 xfer->ui_ops = gaim_xfers_get_ui_ops(); | |
58 xfer->message = NULL; | |
15218 | 59 xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE; |
14192 | 60 |
61 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
62 | |
63 if (ui_ops != NULL && ui_ops->new_xfer != NULL) | |
64 ui_ops->new_xfer(xfer); | |
65 | |
66 return xfer; | |
67 } | |
68 | |
69 static void | |
70 gaim_xfer_destroy(GaimXfer *xfer) | |
71 { | |
72 GaimXferUiOps *ui_ops; | |
73 | |
74 g_return_if_fail(xfer != NULL); | |
75 | |
76 /* Close the file browser, if it's open */ | |
77 gaim_request_close_with_handle(xfer); | |
78 | |
79 if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_STARTED) | |
80 gaim_xfer_cancel_local(xfer); | |
81 | |
82 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
83 | |
84 if (ui_ops != NULL && ui_ops->destroy != NULL) | |
85 ui_ops->destroy(xfer); | |
86 | |
87 g_free(xfer->who); | |
88 g_free(xfer->filename); | |
89 g_free(xfer->remote_ip); | |
90 g_free(xfer->local_filename); | |
91 | |
92 g_free(xfer); | |
93 } | |
94 | |
95 void | |
96 gaim_xfer_ref(GaimXfer *xfer) | |
97 { | |
98 g_return_if_fail(xfer != NULL); | |
99 | |
100 xfer->ref++; | |
101 } | |
102 | |
103 void | |
104 gaim_xfer_unref(GaimXfer *xfer) | |
105 { | |
106 g_return_if_fail(xfer != NULL); | |
107 g_return_if_fail(xfer->ref > 0); | |
108 | |
109 xfer->ref--; | |
110 | |
111 if (xfer->ref == 0) | |
112 gaim_xfer_destroy(xfer); | |
113 } | |
114 | |
115 static void | |
116 gaim_xfer_set_status(GaimXfer *xfer, GaimXferStatusType status) | |
117 { | |
118 g_return_if_fail(xfer != NULL); | |
119 | |
120 if(xfer->type == GAIM_XFER_SEND) { | |
121 switch(status) { | |
122 case GAIM_XFER_STATUS_ACCEPTED: | |
123 gaim_signal_emit(gaim_xfers_get_handle(), "file-send-accept", xfer); | |
124 break; | |
125 case GAIM_XFER_STATUS_STARTED: | |
126 gaim_signal_emit(gaim_xfers_get_handle(), "file-send-start", xfer); | |
127 break; | |
128 case GAIM_XFER_STATUS_DONE: | |
129 gaim_signal_emit(gaim_xfers_get_handle(), "file-send-complete", xfer); | |
130 break; | |
131 case GAIM_XFER_STATUS_CANCEL_LOCAL: | |
132 case GAIM_XFER_STATUS_CANCEL_REMOTE: | |
133 gaim_signal_emit(gaim_xfers_get_handle(), "file-send-cancel", xfer); | |
134 break; | |
135 default: | |
136 break; | |
137 } | |
138 } else if(xfer->type == GAIM_XFER_RECEIVE) { | |
139 switch(status) { | |
140 case GAIM_XFER_STATUS_ACCEPTED: | |
141 gaim_signal_emit(gaim_xfers_get_handle(), "file-recv-accept", xfer); | |
142 break; | |
143 case GAIM_XFER_STATUS_STARTED: | |
144 gaim_signal_emit(gaim_xfers_get_handle(), "file-recv-start", xfer); | |
145 break; | |
146 case GAIM_XFER_STATUS_DONE: | |
147 gaim_signal_emit(gaim_xfers_get_handle(), "file-recv-complete", xfer); | |
148 break; | |
149 case GAIM_XFER_STATUS_CANCEL_LOCAL: | |
150 case GAIM_XFER_STATUS_CANCEL_REMOTE: | |
151 gaim_signal_emit(gaim_xfers_get_handle(), "file-recv-cancel", xfer); | |
152 break; | |
153 default: | |
154 break; | |
155 } | |
156 } | |
157 | |
158 xfer->status = status; | |
159 } | |
160 | |
161 void gaim_xfer_conversation_write(GaimXfer *xfer, char *message, gboolean is_error) | |
162 { | |
163 GaimConversation *conv = NULL; | |
164 GaimMessageFlags flags = GAIM_MESSAGE_SYSTEM; | |
165 char *escaped; | |
166 | |
167 g_return_if_fail(xfer != NULL); | |
168 g_return_if_fail(message != NULL); | |
169 | |
170 conv = gaim_find_conversation_with_account(GAIM_CONV_TYPE_IM, xfer->who, | |
171 gaim_xfer_get_account(xfer)); | |
172 | |
173 if (conv == NULL) | |
174 return; | |
175 | |
176 escaped = g_markup_escape_text(message, -1); | |
177 | |
178 if (is_error) | |
179 flags = GAIM_MESSAGE_ERROR; | |
180 | |
181 gaim_conversation_write(conv, NULL, escaped, flags, time(NULL)); | |
182 g_free(escaped); | |
183 } | |
184 | |
185 static void gaim_xfer_show_file_error(GaimXfer *xfer, const char *filename) | |
186 { | |
187 int err = errno; | |
188 gchar *msg = NULL, *utf8; | |
189 GaimXferType xfer_type = gaim_xfer_get_type(xfer); | |
190 GaimAccount *account = gaim_xfer_get_account(xfer); | |
191 | |
192 utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); | |
193 switch(xfer_type) { | |
194 case GAIM_XFER_SEND: | |
195 msg = g_strdup_printf(_("Error reading %s: \n%s.\n"), | |
196 utf8, strerror(err)); | |
197 break; | |
198 case GAIM_XFER_RECEIVE: | |
199 msg = g_strdup_printf(_("Error writing %s: \n%s.\n"), | |
200 utf8, strerror(err)); | |
201 break; | |
202 default: | |
203 msg = g_strdup_printf(_("Error accessing %s: \n%s.\n"), | |
204 utf8, strerror(err)); | |
205 break; | |
206 } | |
207 g_free(utf8); | |
208 | |
209 gaim_xfer_conversation_write(xfer, msg, TRUE); | |
210 gaim_xfer_error(xfer_type, account, xfer->who, msg); | |
211 g_free(msg); | |
212 } | |
213 | |
214 static void | |
215 gaim_xfer_choose_file_ok_cb(void *user_data, const char *filename) | |
216 { | |
217 GaimXfer *xfer; | |
218 struct stat st; | |
14905 | 219 gchar *dir; |
14192 | 220 |
221 xfer = (GaimXfer *)user_data; | |
222 | |
223 if (g_stat(filename, &st) != 0) { | |
224 /* File not found. */ | |
225 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) { | |
15099
59189ce09f10
[gaim-migrate @ 17885]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14905
diff
changeset
|
226 #ifndef _WIN32 |
59189ce09f10
[gaim-migrate @ 17885]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14905
diff
changeset
|
227 int mode = W_OK; |
59189ce09f10
[gaim-migrate @ 17885]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14905
diff
changeset
|
228 #else |
59189ce09f10
[gaim-migrate @ 17885]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14905
diff
changeset
|
229 int mode = F_OK; |
59189ce09f10
[gaim-migrate @ 17885]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14905
diff
changeset
|
230 #endif |
14905 | 231 dir = g_path_get_dirname(filename); |
232 | |
15099
59189ce09f10
[gaim-migrate @ 17885]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
14905
diff
changeset
|
233 if (g_access(dir, mode) == 0) { |
14905 | 234 gaim_xfer_request_accepted(xfer, filename); |
235 } else { | |
236 gaim_xfer_ref(xfer); | |
237 gaim_notify_message( | |
238 NULL, GAIM_NOTIFY_MSG_ERROR, NULL, | |
239 _("Directory is not writable."), NULL, | |
240 (GaimNotifyCloseCallback)gaim_xfer_choose_file, xfer); | |
241 } | |
242 | |
243 g_free(dir); | |
14192 | 244 } |
245 else { | |
246 gaim_xfer_show_file_error(xfer, filename); | |
247 gaim_xfer_request_denied(xfer); | |
248 } | |
249 } | |
250 else if ((gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) && | |
251 (st.st_size == 0)) { | |
252 | |
253 gaim_notify_error(NULL, NULL, | |
254 _("Cannot send a file of 0 bytes."), NULL); | |
255 | |
256 gaim_xfer_request_denied(xfer); | |
257 } | |
258 else if ((gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) && | |
259 S_ISDIR(st.st_mode)) { | |
260 /* | |
261 * XXX - Sending a directory should be valid for some protocols. | |
262 */ | |
263 gaim_notify_error(NULL, NULL, | |
264 _("Cannot send a directory."), NULL); | |
265 | |
266 gaim_xfer_request_denied(xfer); | |
267 } | |
268 else if ((gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) && | |
269 S_ISDIR(st.st_mode)) { | |
270 char *msg, *utf8; | |
271 utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); | |
272 msg = g_strdup_printf( | |
273 _("%s is not a regular file. Cowardly refusing to overwrite it.\n"), utf8); | |
274 g_free(utf8); | |
275 gaim_notify_error(NULL, NULL, msg, NULL); | |
276 g_free(msg); | |
277 gaim_xfer_request_denied(xfer); | |
278 } | |
279 else { | |
280 gaim_xfer_request_accepted(xfer, filename); | |
281 } | |
282 | |
283 gaim_xfer_unref(xfer); | |
284 } | |
285 | |
286 static void | |
287 gaim_xfer_choose_file_cancel_cb(void *user_data, const char *filename) | |
288 { | |
289 GaimXfer *xfer = (GaimXfer *)user_data; | |
290 | |
291 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_CANCEL_LOCAL); | |
292 gaim_xfer_request_denied(xfer); | |
293 } | |
294 | |
295 static int | |
296 gaim_xfer_choose_file(GaimXfer *xfer) | |
297 { | |
298 gaim_request_file(xfer, NULL, gaim_xfer_get_filename(xfer), | |
299 (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE), | |
300 G_CALLBACK(gaim_xfer_choose_file_ok_cb), | |
301 G_CALLBACK(gaim_xfer_choose_file_cancel_cb), xfer); | |
302 | |
303 return 0; | |
304 } | |
305 | |
306 static int | |
307 cancel_recv_cb(GaimXfer *xfer) | |
308 { | |
309 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_CANCEL_LOCAL); | |
310 gaim_xfer_request_denied(xfer); | |
311 gaim_xfer_unref(xfer); | |
312 | |
313 return 0; | |
314 } | |
315 | |
316 static void | |
317 gaim_xfer_ask_recv(GaimXfer *xfer) | |
318 { | |
319 char *buf, *size_buf; | |
320 size_t size; | |
321 | |
322 /* If we have already accepted the request, ask the destination file | |
323 name directly */ | |
324 if (gaim_xfer_get_status(xfer) != GAIM_XFER_STATUS_ACCEPTED) { | |
325 GaimBuddy *buddy = gaim_find_buddy(xfer->account, xfer->who); | |
326 | |
327 if (gaim_xfer_get_filename(xfer) != NULL) | |
328 { | |
329 size = gaim_xfer_get_size(xfer); | |
330 size_buf = gaim_str_size_to_units(size); | |
331 buf = g_strdup_printf(_("%s wants to send you %s (%s)"), | |
332 buddy ? gaim_buddy_get_alias(buddy) : xfer->who, | |
333 gaim_xfer_get_filename(xfer), size_buf); | |
334 g_free(size_buf); | |
335 } | |
336 else | |
337 { | |
338 buf = g_strdup_printf(_("%s wants to send you a file"), | |
339 buddy ? gaim_buddy_get_alias(buddy) : xfer->who); | |
340 } | |
341 | |
342 if (xfer->message != NULL) | |
343 serv_got_im(gaim_account_get_connection(xfer->account), | |
344 xfer->who, xfer->message, 0, time(NULL)); | |
345 | |
346 gaim_request_accept_cancel(xfer, NULL, buf, NULL, | |
347 GAIM_DEFAULT_ACTION_NONE, xfer, | |
348 G_CALLBACK(gaim_xfer_choose_file), | |
349 G_CALLBACK(cancel_recv_cb)); | |
350 | |
351 g_free(buf); | |
352 } else | |
353 gaim_xfer_choose_file(xfer); | |
354 } | |
355 | |
356 static int | |
357 ask_accept_ok(GaimXfer *xfer) | |
358 { | |
359 gaim_xfer_request_accepted(xfer, NULL); | |
360 | |
361 return 0; | |
362 } | |
363 | |
364 static int | |
365 ask_accept_cancel(GaimXfer *xfer) | |
366 { | |
367 gaim_xfer_request_denied(xfer); | |
368 gaim_xfer_unref(xfer); | |
369 | |
370 return 0; | |
371 } | |
372 | |
373 static void | |
374 gaim_xfer_ask_accept(GaimXfer *xfer) | |
375 { | |
376 char *buf, *buf2 = NULL; | |
377 GaimBuddy *buddy = gaim_find_buddy(xfer->account, xfer->who); | |
378 | |
379 buf = g_strdup_printf(_("Accept file transfer request from %s?"), | |
380 buddy ? gaim_buddy_get_alias(buddy) : xfer->who); | |
381 if (gaim_xfer_get_remote_ip(xfer) && | |
382 gaim_xfer_get_remote_port(xfer)) | |
383 buf2 = g_strdup_printf(_("A file is available for download from:\n" | |
384 "Remote host: %s\nRemote port: %d"), | |
385 gaim_xfer_get_remote_ip(xfer), | |
386 gaim_xfer_get_remote_port(xfer)); | |
387 gaim_request_accept_cancel(xfer, NULL, buf, buf2, | |
388 GAIM_DEFAULT_ACTION_NONE, xfer, | |
389 G_CALLBACK(ask_accept_ok), | |
390 G_CALLBACK(ask_accept_cancel)); | |
391 g_free(buf); | |
392 g_free(buf2); | |
393 } | |
394 | |
395 void | |
396 gaim_xfer_request(GaimXfer *xfer) | |
397 { | |
398 g_return_if_fail(xfer != NULL); | |
399 g_return_if_fail(xfer->ops.init != NULL); | |
400 | |
401 gaim_xfer_ref(xfer); | |
402 | |
403 if (gaim_xfer_get_type(xfer) == GAIM_XFER_RECEIVE) | |
404 { | |
405 gaim_signal_emit(gaim_xfers_get_handle(), "file-recv-request", xfer); | |
406 if (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) | |
407 { | |
408 /* The file-transfer was cancelled by a plugin */ | |
409 gaim_xfer_cancel_local(xfer); | |
410 } | |
411 else if (gaim_xfer_get_filename(xfer) || | |
412 gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_ACCEPTED) | |
413 { | |
414 gchar* message = NULL; | |
415 GaimBuddy *buddy = gaim_find_buddy(xfer->account, xfer->who); | |
416 message = g_strdup_printf(_("%s is offering to send file %s"), | |
417 buddy ? gaim_buddy_get_alias(buddy) : xfer->who, gaim_xfer_get_filename(xfer)); | |
418 gaim_xfer_conversation_write(xfer, message, FALSE); | |
419 g_free(message); | |
420 /* Ask for a filename to save to if it's not already given by a plugin */ | |
421 if (xfer->local_filename == NULL) | |
422 gaim_xfer_ask_recv(xfer); | |
423 } | |
424 else | |
425 { | |
426 gaim_xfer_ask_accept(xfer); | |
427 } | |
428 } | |
429 else | |
430 { | |
431 gaim_xfer_choose_file(xfer); | |
432 } | |
433 } | |
434 | |
435 void | |
436 gaim_xfer_request_accepted(GaimXfer *xfer, const char *filename) | |
437 { | |
438 GaimXferType type; | |
439 struct stat st; | |
440 char *msg, *utf8; | |
441 GaimAccount *account; | |
442 GaimBuddy *buddy; | |
443 | |
444 if (xfer == NULL) | |
445 return; | |
446 | |
447 type = gaim_xfer_get_type(xfer); | |
448 account = gaim_xfer_get_account(xfer); | |
449 | |
450 if (!filename && type == GAIM_XFER_RECEIVE) { | |
451 xfer->status = GAIM_XFER_STATUS_ACCEPTED; | |
452 xfer->ops.init(xfer); | |
453 return; | |
454 } | |
455 | |
456 buddy = gaim_find_buddy(account, xfer->who); | |
457 | |
458 if (type == GAIM_XFER_SEND) { | |
459 /* Sending a file */ | |
460 /* Check the filename. */ | |
461 #ifdef _WIN32 | |
462 if (g_strrstr(filename, "../") || g_strrstr(filename, "..\\")) { | |
463 #else | |
464 if (g_strrstr(filename, "../")) { | |
465 #endif | |
466 char *utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); | |
467 | |
468 msg = g_strdup_printf(_("%s is not a valid filename.\n"), utf8); | |
469 gaim_xfer_error(type, account, xfer->who, msg); | |
470 g_free(utf8); | |
471 g_free(msg); | |
472 | |
473 gaim_xfer_unref(xfer); | |
474 return; | |
475 } | |
476 | |
477 if (g_stat(filename, &st) == -1) { | |
478 gaim_xfer_show_file_error(xfer, filename); | |
479 gaim_xfer_unref(xfer); | |
480 return; | |
481 } | |
482 | |
483 gaim_xfer_set_local_filename(xfer, filename); | |
484 gaim_xfer_set_size(xfer, st.st_size); | |
485 | |
486 utf8 = g_filename_to_utf8(g_basename(filename), -1, NULL, NULL, NULL); | |
487 gaim_xfer_set_filename(xfer, utf8); | |
488 | |
489 msg = g_strdup_printf(_("Offering to send %s to %s"), | |
490 utf8, buddy ? gaim_buddy_get_alias(buddy) : xfer->who); | |
491 g_free(utf8); | |
492 | |
493 gaim_xfer_conversation_write(xfer, msg, FALSE); | |
494 g_free(msg); | |
495 } | |
496 else { | |
497 /* Receiving a file */ | |
498 xfer->status = GAIM_XFER_STATUS_ACCEPTED; | |
499 gaim_xfer_set_local_filename(xfer, filename); | |
500 | |
501 msg = g_strdup_printf(_("Starting transfer of %s from %s"), | |
502 xfer->filename, buddy ? gaim_buddy_get_alias(buddy) : xfer->who); | |
503 gaim_xfer_conversation_write(xfer, msg, FALSE); | |
504 g_free(msg); | |
505 } | |
506 | |
507 gaim_xfer_add(xfer); | |
508 xfer->ops.init(xfer); | |
509 | |
510 } | |
511 | |
512 void | |
513 gaim_xfer_request_denied(GaimXfer *xfer) | |
514 { | |
515 g_return_if_fail(xfer != NULL); | |
516 | |
517 if (xfer->ops.request_denied != NULL) | |
518 xfer->ops.request_denied(xfer); | |
519 | |
520 gaim_xfer_unref(xfer); | |
521 } | |
522 | |
523 GaimXferType | |
524 gaim_xfer_get_type(const GaimXfer *xfer) | |
525 { | |
526 g_return_val_if_fail(xfer != NULL, GAIM_XFER_UNKNOWN); | |
527 | |
528 return xfer->type; | |
529 } | |
530 | |
531 GaimAccount * | |
532 gaim_xfer_get_account(const GaimXfer *xfer) | |
533 { | |
534 g_return_val_if_fail(xfer != NULL, NULL); | |
535 | |
536 return xfer->account; | |
537 } | |
538 | |
539 GaimXferStatusType | |
540 gaim_xfer_get_status(const GaimXfer *xfer) | |
541 { | |
542 g_return_val_if_fail(xfer != NULL, GAIM_XFER_STATUS_UNKNOWN); | |
543 | |
544 return xfer->status; | |
545 } | |
546 | |
547 gboolean | |
548 gaim_xfer_is_canceled(const GaimXfer *xfer) | |
549 { | |
550 g_return_val_if_fail(xfer != NULL, TRUE); | |
551 | |
552 if ((gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_LOCAL) || | |
553 (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_CANCEL_REMOTE)) | |
554 return TRUE; | |
555 else | |
556 return FALSE; | |
557 } | |
558 | |
559 gboolean | |
560 gaim_xfer_is_completed(const GaimXfer *xfer) | |
561 { | |
562 g_return_val_if_fail(xfer != NULL, TRUE); | |
563 | |
564 return (gaim_xfer_get_status(xfer) == GAIM_XFER_STATUS_DONE); | |
565 } | |
566 | |
567 const char * | |
568 gaim_xfer_get_filename(const GaimXfer *xfer) | |
569 { | |
570 g_return_val_if_fail(xfer != NULL, NULL); | |
571 | |
572 return xfer->filename; | |
573 } | |
574 | |
575 const char * | |
576 gaim_xfer_get_local_filename(const GaimXfer *xfer) | |
577 { | |
578 g_return_val_if_fail(xfer != NULL, NULL); | |
579 | |
580 return xfer->local_filename; | |
581 } | |
582 | |
583 size_t | |
584 gaim_xfer_get_bytes_sent(const GaimXfer *xfer) | |
585 { | |
586 g_return_val_if_fail(xfer != NULL, 0); | |
587 | |
588 return xfer->bytes_sent; | |
589 } | |
590 | |
591 size_t | |
592 gaim_xfer_get_bytes_remaining(const GaimXfer *xfer) | |
593 { | |
594 g_return_val_if_fail(xfer != NULL, 0); | |
595 | |
596 return xfer->bytes_remaining; | |
597 } | |
598 | |
599 size_t | |
600 gaim_xfer_get_size(const GaimXfer *xfer) | |
601 { | |
602 g_return_val_if_fail(xfer != NULL, 0); | |
603 | |
604 return xfer->size; | |
605 } | |
606 | |
607 double | |
608 gaim_xfer_get_progress(const GaimXfer *xfer) | |
609 { | |
610 g_return_val_if_fail(xfer != NULL, 0.0); | |
611 | |
612 if (gaim_xfer_get_size(xfer) == 0) | |
613 return 0.0; | |
614 | |
615 return ((double)gaim_xfer_get_bytes_sent(xfer) / | |
616 (double)gaim_xfer_get_size(xfer)); | |
617 } | |
618 | |
619 unsigned int | |
620 gaim_xfer_get_local_port(const GaimXfer *xfer) | |
621 { | |
622 g_return_val_if_fail(xfer != NULL, -1); | |
623 | |
624 return xfer->local_port; | |
625 } | |
626 | |
627 const char * | |
628 gaim_xfer_get_remote_ip(const GaimXfer *xfer) | |
629 { | |
630 g_return_val_if_fail(xfer != NULL, NULL); | |
631 | |
632 return xfer->remote_ip; | |
633 } | |
634 | |
635 unsigned int | |
636 gaim_xfer_get_remote_port(const GaimXfer *xfer) | |
637 { | |
638 g_return_val_if_fail(xfer != NULL, -1); | |
639 | |
640 return xfer->remote_port; | |
641 } | |
642 | |
643 void | |
644 gaim_xfer_set_completed(GaimXfer *xfer, gboolean completed) | |
645 { | |
646 GaimXferUiOps *ui_ops; | |
647 | |
648 g_return_if_fail(xfer != NULL); | |
649 | |
650 if (completed == TRUE) { | |
651 char *msg = NULL; | |
652 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_DONE); | |
653 | |
654 if (gaim_xfer_get_filename(xfer) != NULL) | |
655 msg = g_strdup_printf(_("Transfer of file %s complete"), | |
656 gaim_xfer_get_filename(xfer)); | |
657 else | |
658 msg = g_strdup_printf(_("File transfer complete")); | |
659 gaim_xfer_conversation_write(xfer, msg, FALSE); | |
660 g_free(msg); | |
661 } | |
662 | |
663 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
664 | |
665 if (ui_ops != NULL && ui_ops->update_progress != NULL) | |
666 ui_ops->update_progress(xfer, gaim_xfer_get_progress(xfer)); | |
667 } | |
668 | |
669 void | |
670 gaim_xfer_set_message(GaimXfer *xfer, const char *message) | |
671 { | |
672 g_return_if_fail(xfer != NULL); | |
673 | |
674 g_free(xfer->message); | |
675 xfer->message = g_strdup(message); | |
676 } | |
677 | |
678 void | |
679 gaim_xfer_set_filename(GaimXfer *xfer, const char *filename) | |
680 { | |
681 g_return_if_fail(xfer != NULL); | |
682 | |
683 g_free(xfer->filename); | |
684 xfer->filename = g_strdup(filename); | |
685 } | |
686 | |
687 void | |
688 gaim_xfer_set_local_filename(GaimXfer *xfer, const char *filename) | |
689 { | |
690 g_return_if_fail(xfer != NULL); | |
691 | |
692 g_free(xfer->local_filename); | |
693 xfer->local_filename = g_strdup(filename); | |
694 } | |
695 | |
696 void | |
697 gaim_xfer_set_size(GaimXfer *xfer, size_t size) | |
698 { | |
699 g_return_if_fail(xfer != NULL); | |
700 | |
15260 | 701 xfer->size = size; |
702 xfer->bytes_remaining = xfer->size - gaim_xfer_get_bytes_sent(xfer); | |
703 } | |
14192 | 704 |
15260 | 705 void |
706 gaim_xfer_set_bytes_sent(GaimXfer *xfer, size_t bytes_sent) | |
707 { | |
708 g_return_if_fail(xfer != NULL); | |
709 | |
710 xfer->bytes_sent = bytes_sent; | |
711 xfer->bytes_remaining = gaim_xfer_get_size(xfer) - bytes_sent; | |
14192 | 712 } |
713 | |
714 GaimXferUiOps * | |
715 gaim_xfer_get_ui_ops(const GaimXfer *xfer) | |
716 { | |
717 g_return_val_if_fail(xfer != NULL, NULL); | |
718 | |
719 return xfer->ui_ops; | |
720 } | |
721 | |
722 void | |
723 gaim_xfer_set_init_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *)) | |
724 { | |
725 g_return_if_fail(xfer != NULL); | |
726 | |
727 xfer->ops.init = fnc; | |
728 } | |
729 | |
730 void gaim_xfer_set_request_denied_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *)) | |
731 { | |
732 g_return_if_fail(xfer != NULL); | |
733 | |
734 xfer->ops.request_denied = fnc; | |
735 } | |
736 | |
737 void | |
738 gaim_xfer_set_read_fnc(GaimXfer *xfer, gssize (*fnc)(guchar **, GaimXfer *)) | |
739 { | |
740 g_return_if_fail(xfer != NULL); | |
741 | |
742 xfer->ops.read = fnc; | |
743 } | |
744 | |
745 void | |
746 gaim_xfer_set_write_fnc(GaimXfer *xfer, | |
747 gssize (*fnc)(const guchar *, size_t, GaimXfer *)) | |
748 { | |
749 g_return_if_fail(xfer != NULL); | |
750 | |
751 xfer->ops.write = fnc; | |
752 } | |
753 | |
754 void | |
755 gaim_xfer_set_ack_fnc(GaimXfer *xfer, | |
756 void (*fnc)(GaimXfer *, const guchar *, size_t)) | |
757 { | |
758 g_return_if_fail(xfer != NULL); | |
759 | |
760 xfer->ops.ack = fnc; | |
761 } | |
762 | |
763 void | |
764 gaim_xfer_set_start_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *)) | |
765 { | |
766 g_return_if_fail(xfer != NULL); | |
767 | |
768 xfer->ops.start = fnc; | |
769 } | |
770 | |
771 void | |
772 gaim_xfer_set_end_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *)) | |
773 { | |
774 g_return_if_fail(xfer != NULL); | |
775 | |
776 xfer->ops.end = fnc; | |
777 } | |
778 | |
779 void | |
780 gaim_xfer_set_cancel_send_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *)) | |
781 { | |
782 g_return_if_fail(xfer != NULL); | |
783 | |
784 xfer->ops.cancel_send = fnc; | |
785 } | |
786 | |
787 void | |
788 gaim_xfer_set_cancel_recv_fnc(GaimXfer *xfer, void (*fnc)(GaimXfer *)) | |
789 { | |
790 g_return_if_fail(xfer != NULL); | |
791 | |
792 xfer->ops.cancel_recv = fnc; | |
793 } | |
794 | |
15218 | 795 static void |
796 gaim_xfer_increase_buffer_size(GaimXfer *xfer) | |
797 { | |
798 xfer->current_buffer_size = MIN(xfer->current_buffer_size * 1.5, | |
799 FT_MAX_BUFFER_SIZE); | |
800 } | |
801 | |
14192 | 802 gssize |
803 gaim_xfer_read(GaimXfer *xfer, guchar **buffer) | |
804 { | |
805 gssize s, r; | |
806 | |
807 g_return_val_if_fail(xfer != NULL, 0); | |
808 g_return_val_if_fail(buffer != NULL, 0); | |
809 | |
810 if (gaim_xfer_get_size(xfer) == 0) | |
15218 | 811 s = xfer->current_buffer_size; |
14192 | 812 else |
15218 | 813 s = MIN(gaim_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size); |
14192 | 814 |
815 if (xfer->ops.read != NULL) | |
816 r = (xfer->ops.read)(buffer, xfer); | |
817 else { | |
818 *buffer = g_malloc0(s); | |
819 | |
820 r = read(xfer->fd, *buffer, s); | |
821 if (r < 0 && errno == EAGAIN) | |
822 r = 0; | |
823 else if (r < 0) | |
824 r = -1; | |
825 else if ((gaim_xfer_get_size(xfer) > 0) && | |
826 ((gaim_xfer_get_bytes_sent(xfer)+r) >= gaim_xfer_get_size(xfer))) | |
827 gaim_xfer_set_completed(xfer, TRUE); | |
828 else if (r == 0) | |
829 r = -1; | |
830 } | |
831 | |
15218 | 832 if (r == xfer->current_buffer_size) |
833 /* | |
834 * We managed to read the entire buffer. This means our this | |
835 * network is fast and our buffer is too small, so make it | |
836 * bigger. | |
837 */ | |
838 gaim_xfer_increase_buffer_size(xfer); | |
839 | |
14192 | 840 return r; |
841 } | |
842 | |
843 gssize | |
844 gaim_xfer_write(GaimXfer *xfer, const guchar *buffer, gsize size) | |
845 { | |
846 gssize r, s; | |
847 | |
848 g_return_val_if_fail(xfer != NULL, 0); | |
849 g_return_val_if_fail(buffer != NULL, 0); | |
850 g_return_val_if_fail(size != 0, 0); | |
851 | |
852 s = MIN(gaim_xfer_get_bytes_remaining(xfer), size); | |
853 | |
854 if (xfer->ops.write != NULL) { | |
855 r = (xfer->ops.write)(buffer, s, xfer); | |
856 } else { | |
857 r = write(xfer->fd, buffer, s); | |
858 if (r < 0 && errno == EAGAIN) | |
859 r = 0; | |
860 if ((gaim_xfer_get_bytes_sent(xfer)+r) >= gaim_xfer_get_size(xfer)) | |
861 gaim_xfer_set_completed(xfer, TRUE); | |
862 } | |
863 | |
864 return r; | |
865 } | |
866 | |
867 static void | |
868 transfer_cb(gpointer data, gint source, GaimInputCondition condition) | |
869 { | |
870 GaimXferUiOps *ui_ops; | |
871 GaimXfer *xfer = (GaimXfer *)data; | |
872 guchar *buffer = NULL; | |
873 gssize r = 0; | |
874 | |
875 if (condition & GAIM_INPUT_READ) { | |
876 r = gaim_xfer_read(xfer, &buffer); | |
877 if (r > 0) { | |
878 fwrite(buffer, 1, r, xfer->dest_fp); | |
879 } else if(r <= 0) { | |
880 gaim_xfer_cancel_remote(xfer); | |
881 return; | |
882 } | |
883 } | |
884 | |
885 if (condition & GAIM_INPUT_WRITE) { | |
15218 | 886 size_t s = MIN(gaim_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size); |
14192 | 887 |
888 /* this is so the prpl can keep the connection open | |
889 if it needs to for some odd reason. */ | |
890 if (s == 0) { | |
891 if (xfer->watcher) { | |
892 gaim_input_remove(xfer->watcher); | |
893 xfer->watcher = 0; | |
894 } | |
895 return; | |
896 } | |
897 | |
898 buffer = g_malloc0(s); | |
899 | |
900 fread(buffer, 1, s, xfer->dest_fp); | |
901 | |
902 /* Write as much as we're allowed to. */ | |
903 r = gaim_xfer_write(xfer, buffer, s); | |
904 | |
905 if (r == -1) { | |
906 gaim_xfer_cancel_remote(xfer); | |
907 g_free(buffer); | |
908 return; | |
909 } else if (r < s) { | |
910 /* We have to seek back in the file now. */ | |
911 fseek(xfer->dest_fp, r - s, SEEK_CUR); | |
15218 | 912 } else { |
913 /* | |
914 * We managed to write the entire buffer. This means our | |
915 * network is fast and our buffer is too small, so make it | |
916 * bigger. | |
917 */ | |
918 gaim_xfer_increase_buffer_size(xfer); | |
14192 | 919 } |
920 } | |
921 | |
922 if (r > 0) { | |
923 if (gaim_xfer_get_size(xfer) > 0) | |
924 xfer->bytes_remaining -= r; | |
925 | |
926 xfer->bytes_sent += r; | |
927 | |
928 if (xfer->ops.ack != NULL) | |
929 xfer->ops.ack(xfer, buffer, r); | |
930 | |
931 g_free(buffer); | |
932 | |
933 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
934 | |
935 if (ui_ops != NULL && ui_ops->update_progress != NULL) | |
936 ui_ops->update_progress(xfer, | |
937 gaim_xfer_get_progress(xfer)); | |
938 } | |
939 | |
940 if (gaim_xfer_is_completed(xfer)) | |
941 gaim_xfer_end(xfer); | |
942 } | |
943 | |
944 static void | |
945 begin_transfer(GaimXfer *xfer, GaimInputCondition cond) | |
946 { | |
947 GaimXferType type = gaim_xfer_get_type(xfer); | |
948 | |
949 xfer->dest_fp = g_fopen(gaim_xfer_get_local_filename(xfer), | |
950 type == GAIM_XFER_RECEIVE ? "wb" : "rb"); | |
951 | |
952 if (xfer->dest_fp == NULL) { | |
953 gaim_xfer_show_file_error(xfer, gaim_xfer_get_local_filename(xfer)); | |
954 gaim_xfer_cancel_local(xfer); | |
955 return; | |
956 } | |
957 | |
15260 | 958 fseek(xfer->dest_fp, xfer->bytes_sent, SEEK_SET); |
959 | |
14192 | 960 xfer->watcher = gaim_input_add(xfer->fd, cond, transfer_cb, xfer); |
961 | |
962 xfer->start_time = time(NULL); | |
963 | |
964 if (xfer->ops.start != NULL) | |
965 xfer->ops.start(xfer); | |
966 } | |
967 | |
968 static void | |
969 connect_cb(gpointer data, gint source, const gchar *error_message) | |
970 { | |
971 GaimXfer *xfer = (GaimXfer *)data; | |
972 | |
973 xfer->fd = source; | |
974 | |
975 begin_transfer(xfer, GAIM_INPUT_READ); | |
976 } | |
977 | |
978 void | |
979 gaim_xfer_start(GaimXfer *xfer, int fd, const char *ip, | |
980 unsigned int port) | |
981 { | |
982 GaimInputCondition cond; | |
983 GaimXferType type; | |
984 | |
985 g_return_if_fail(xfer != NULL); | |
986 g_return_if_fail(gaim_xfer_get_type(xfer) != GAIM_XFER_UNKNOWN); | |
987 | |
988 type = gaim_xfer_get_type(xfer); | |
989 | |
990 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_STARTED); | |
991 | |
992 if (type == GAIM_XFER_RECEIVE) { | |
993 cond = GAIM_INPUT_READ; | |
994 | |
995 if (ip != NULL) { | |
996 xfer->remote_ip = g_strdup(ip); | |
997 xfer->remote_port = port; | |
998 | |
999 /* Establish a file descriptor. */ | |
14837 | 1000 gaim_proxy_connect(NULL, xfer->account, xfer->remote_ip, |
14192 | 1001 xfer->remote_port, connect_cb, xfer); |
1002 | |
1003 return; | |
1004 } | |
1005 else { | |
1006 xfer->fd = fd; | |
1007 } | |
1008 } | |
1009 else { | |
1010 cond = GAIM_INPUT_WRITE; | |
1011 | |
1012 xfer->fd = fd; | |
1013 } | |
1014 | |
1015 begin_transfer(xfer, cond); | |
1016 } | |
1017 | |
1018 void | |
1019 gaim_xfer_end(GaimXfer *xfer) | |
1020 { | |
1021 g_return_if_fail(xfer != NULL); | |
1022 | |
1023 /* See if we are actually trying to cancel this. */ | |
1024 if (!gaim_xfer_is_completed(xfer)) { | |
1025 gaim_xfer_cancel_local(xfer); | |
1026 return; | |
1027 } | |
1028 | |
1029 xfer->end_time = time(NULL); | |
1030 if (xfer->ops.end != NULL) | |
1031 xfer->ops.end(xfer); | |
1032 | |
1033 if (xfer->watcher != 0) { | |
1034 gaim_input_remove(xfer->watcher); | |
1035 xfer->watcher = 0; | |
1036 } | |
1037 | |
1038 if (xfer->fd != 0) | |
1039 close(xfer->fd); | |
1040 | |
1041 if (xfer->dest_fp != NULL) { | |
1042 fclose(xfer->dest_fp); | |
1043 xfer->dest_fp = NULL; | |
1044 } | |
1045 | |
1046 gaim_xfer_unref(xfer); | |
1047 } | |
1048 | |
1049 void | |
1050 gaim_xfer_add(GaimXfer *xfer) | |
1051 { | |
1052 GaimXferUiOps *ui_ops; | |
1053 | |
1054 g_return_if_fail(xfer != NULL); | |
1055 | |
1056 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
1057 | |
1058 if (ui_ops != NULL && ui_ops->add_xfer != NULL) | |
1059 ui_ops->add_xfer(xfer); | |
1060 } | |
1061 | |
1062 void | |
1063 gaim_xfer_cancel_local(GaimXfer *xfer) | |
1064 { | |
1065 GaimXferUiOps *ui_ops; | |
1066 char *msg = NULL; | |
1067 | |
1068 g_return_if_fail(xfer != NULL); | |
1069 | |
1070 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_CANCEL_LOCAL); | |
1071 xfer->end_time = time(NULL); | |
1072 | |
1073 if (gaim_xfer_get_filename(xfer) != NULL) | |
1074 { | |
1075 msg = g_strdup_printf(_("You canceled the transfer of %s"), | |
1076 gaim_xfer_get_filename(xfer)); | |
1077 } | |
1078 else | |
1079 { | |
1080 msg = g_strdup_printf(_("File transfer cancelled")); | |
1081 } | |
1082 gaim_xfer_conversation_write(xfer, msg, FALSE); | |
1083 g_free(msg); | |
1084 | |
1085 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) | |
1086 { | |
1087 if (xfer->ops.cancel_send != NULL) | |
1088 xfer->ops.cancel_send(xfer); | |
1089 } | |
1090 else | |
1091 { | |
1092 if (xfer->ops.cancel_recv != NULL) | |
1093 xfer->ops.cancel_recv(xfer); | |
1094 } | |
1095 | |
1096 if (xfer->watcher != 0) { | |
1097 gaim_input_remove(xfer->watcher); | |
1098 xfer->watcher = 0; | |
1099 } | |
1100 | |
1101 if (xfer->fd != 0) | |
1102 close(xfer->fd); | |
1103 | |
1104 if (xfer->dest_fp != NULL) { | |
1105 fclose(xfer->dest_fp); | |
1106 xfer->dest_fp = NULL; | |
1107 } | |
1108 | |
1109 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
1110 | |
1111 if (ui_ops != NULL && ui_ops->cancel_local != NULL) | |
1112 ui_ops->cancel_local(xfer); | |
1113 | |
1114 xfer->bytes_remaining = 0; | |
1115 | |
1116 gaim_xfer_unref(xfer); | |
1117 } | |
1118 | |
1119 void | |
1120 gaim_xfer_cancel_remote(GaimXfer *xfer) | |
1121 { | |
1122 GaimXferUiOps *ui_ops; | |
1123 gchar *msg; | |
1124 GaimAccount *account; | |
1125 GaimBuddy *buddy; | |
1126 | |
1127 g_return_if_fail(xfer != NULL); | |
1128 | |
1129 gaim_request_close_with_handle(xfer); | |
1130 gaim_xfer_set_status(xfer, GAIM_XFER_STATUS_CANCEL_REMOTE); | |
1131 xfer->end_time = time(NULL); | |
1132 | |
1133 account = gaim_xfer_get_account(xfer); | |
1134 buddy = gaim_find_buddy(account, xfer->who); | |
1135 | |
1136 if (gaim_xfer_get_filename(xfer) != NULL) | |
1137 { | |
1138 msg = g_strdup_printf(_("%s canceled the transfer of %s"), | |
1139 buddy ? gaim_buddy_get_alias(buddy) : xfer->who, gaim_xfer_get_filename(xfer)); | |
1140 } | |
1141 else | |
1142 { | |
1143 msg = g_strdup_printf(_("%s canceled the file transfer"), | |
1144 buddy ? gaim_buddy_get_alias(buddy) : xfer->who); | |
1145 } | |
1146 gaim_xfer_conversation_write(xfer, msg, TRUE); | |
1147 gaim_xfer_error(gaim_xfer_get_type(xfer), account, xfer->who, msg); | |
1148 g_free(msg); | |
1149 | |
1150 if (gaim_xfer_get_type(xfer) == GAIM_XFER_SEND) | |
1151 { | |
1152 if (xfer->ops.cancel_send != NULL) | |
1153 xfer->ops.cancel_send(xfer); | |
1154 } | |
1155 else | |
1156 { | |
1157 if (xfer->ops.cancel_recv != NULL) | |
1158 xfer->ops.cancel_recv(xfer); | |
1159 } | |
1160 | |
1161 if (xfer->watcher != 0) { | |
1162 gaim_input_remove(xfer->watcher); | |
1163 xfer->watcher = 0; | |
1164 } | |
1165 | |
1166 if (xfer->fd != 0) | |
1167 close(xfer->fd); | |
1168 | |
1169 if (xfer->dest_fp != NULL) { | |
1170 fclose(xfer->dest_fp); | |
1171 xfer->dest_fp = NULL; | |
1172 } | |
1173 | |
1174 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
1175 | |
1176 if (ui_ops != NULL && ui_ops->cancel_remote != NULL) | |
1177 ui_ops->cancel_remote(xfer); | |
1178 | |
1179 xfer->bytes_remaining = 0; | |
1180 | |
1181 gaim_xfer_unref(xfer); | |
1182 } | |
1183 | |
1184 void | |
1185 gaim_xfer_error(GaimXferType type, GaimAccount *account, const char *who, const char *msg) | |
1186 { | |
1187 char *title; | |
1188 | |
1189 g_return_if_fail(msg != NULL); | |
1190 g_return_if_fail(type != GAIM_XFER_UNKNOWN); | |
1191 | |
1192 if (account) { | |
1193 GaimBuddy *buddy; | |
1194 buddy = gaim_find_buddy(account, who); | |
1195 if (buddy) | |
1196 who = gaim_buddy_get_alias(buddy); | |
1197 } | |
1198 | |
1199 if (type == GAIM_XFER_SEND) | |
1200 title = g_strdup_printf(_("File transfer to %s failed."), who); | |
1201 else | |
1202 title = g_strdup_printf(_("File transfer from %s failed."), who); | |
1203 | |
1204 gaim_notify_error(NULL, NULL, title, msg); | |
1205 | |
1206 g_free(title); | |
1207 } | |
1208 | |
1209 void | |
1210 gaim_xfer_update_progress(GaimXfer *xfer) | |
1211 { | |
1212 GaimXferUiOps *ui_ops; | |
1213 | |
1214 g_return_if_fail(xfer != NULL); | |
1215 | |
1216 ui_ops = gaim_xfer_get_ui_ops(xfer); | |
1217 if (ui_ops != NULL && ui_ops->update_progress != NULL) | |
1218 ui_ops->update_progress(xfer, gaim_xfer_get_progress(xfer)); | |
1219 } | |
1220 | |
1221 | |
1222 /************************************************************************** | |
1223 * File Transfer Subsystem API | |
1224 **************************************************************************/ | |
1225 void * | |
1226 gaim_xfers_get_handle(void) { | |
1227 static int handle = 0; | |
1228 | |
1229 return &handle; | |
1230 } | |
1231 | |
1232 void | |
1233 gaim_xfers_init(void) { | |
1234 void *handle = gaim_xfers_get_handle(); | |
1235 | |
1236 /* register signals */ | |
1237 gaim_signal_register(handle, "file-recv-accept", | |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1238 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1239 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1240 GAIM_SUBTYPE_XFER)); |
14192 | 1241 gaim_signal_register(handle, "file-send-accept", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1242 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1243 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1244 GAIM_SUBTYPE_XFER)); |
14192 | 1245 gaim_signal_register(handle, "file-recv-start", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1246 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1247 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1248 GAIM_SUBTYPE_XFER)); |
14192 | 1249 gaim_signal_register(handle, "file-send-start", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1250 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1251 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1252 GAIM_SUBTYPE_XFER)); |
14192 | 1253 gaim_signal_register(handle, "file-send-cancel", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1254 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1255 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1256 GAIM_SUBTYPE_XFER)); |
14192 | 1257 gaim_signal_register(handle, "file-recv-cancel", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1258 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1259 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1260 GAIM_SUBTYPE_XFER)); |
14192 | 1261 gaim_signal_register(handle, "file-send-complete", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1262 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1263 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1264 GAIM_SUBTYPE_XFER)); |
14192 | 1265 gaim_signal_register(handle, "file-recv-complete", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1266 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1267 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1268 GAIM_SUBTYPE_XFER)); |
14192 | 1269 gaim_signal_register(handle, "file-recv-request", |
14618
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1270 gaim_marshal_VOID__POINTER, NULL, 1, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1271 gaim_value_new(GAIM_TYPE_SUBTYPE, |
2f0b4d0de5bb
[gaim-migrate @ 17346]
Etan Reisner <pidgin@unreliablesource.net>
parents:
14192
diff
changeset
|
1272 GAIM_SUBTYPE_XFER)); |
14192 | 1273 } |
1274 | |
1275 void | |
1276 gaim_xfers_uninit(void) { | |
1277 gaim_signals_disconnect_by_handle(gaim_xfers_get_handle()); | |
1278 } | |
1279 | |
1280 void | |
1281 gaim_xfers_set_ui_ops(GaimXferUiOps *ops) { | |
1282 xfer_ui_ops = ops; | |
1283 } | |
1284 | |
1285 GaimXferUiOps * | |
1286 gaim_xfers_get_ui_ops(void) { | |
1287 return xfer_ui_ops; | |
1288 } |