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