Wed, 12 Nov 2008 05:14:03 +0000
merge of '77693555855fe9cd3215414f79964dba346cc5fa'
and '19a87e98e5857ad0289f2c760d460f7f1dbbb42d'
| 8849 | 1 | /* |
| 2 | ||
| 3 | silcgaim_ft.c | |
| 4 | ||
| 5 | Author: Pekka Riikonen <priikone@silcnet.org> | |
| 6 | ||
| 7 | Copyright (C) 2004 Pekka Riikonen | |
| 8 | ||
| 9 | This program is free software; you can redistribute it and/or modify | |
| 10 | it under the terms of the GNU General Public License as published by | |
| 11 | the Free Software Foundation; version 2 of the License. | |
| 12 | ||
| 13 | This program is distributed in the hope that it will be useful, | |
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 16 | GNU General Public License for more details. | |
| 17 | ||
| 18 | */ | |
| 19 | ||
| 20 | #include "silcincludes.h" | |
| 21 | #include "silcclient.h" | |
| 22 | #include "silcgaim.h" | |
| 23 | ||
| 24 | /****************************** File Transfer ********************************/ | |
| 25 | ||
| 26 | /* This implements the secure file transfer protocol (SFTP) using the SILC | |
| 27 | SFTP library implementation. The API we use from the SILC Toolkit is the | |
| 28 | SILC Client file transfer API, as it provides a simple file transfer we | |
| 29 | need in this case. We could use the SILC SFTP API directly, but it would | |
| 30 | be an overkill since we'd effectively re-implement the file transfer what | |
| 31 | the SILC Client's file transfer API already provides. | |
| 32 | ||
| 33 | From Gaim we do NOT use the FT API to do the transfer as it is very limiting. | |
| 34 | In fact it does not suite to file transfers like SFTP at all. For example, | |
| 35 | it assumes that read operations are synchronous what they are not in SFTP. | |
| 36 | It also assumes that the file transfer socket is to be handled by the Gaim | |
| 37 | eventloop, and this naturally is something we don't want to do in case of | |
| 38 | SILC Toolkit. The FT API suites well to purely stream based file transfers | |
| 39 | like HTTP GET and similar. | |
| 40 | ||
| 41 | For this reason, we directly access the Gaim GKT FT API and hack the FT | |
| 42 | API to merely provide the user interface experience and all the magic | |
| 43 | is done in the SILC Toolkit. Ie. we update the statistics information in | |
| 44 | the FT API for user interface, and that's it. A bit dirty but until the | |
| 45 | FT API gets better this is the way to go. Good thing that FT API allowed | |
| 46 | us to do this. */ | |
| 47 | ||
| 48 | typedef struct { | |
| 49 | SilcGaim sg; | |
| 50 | SilcClientEntry client_entry; | |
| 51 | SilcUInt32 session_id; | |
| 52 | char *hostname; | |
| 53 | SilcUInt16 port; | |
| 54 | GaimXfer *xfer; | |
| 55 | ||
| 56 | SilcClientFileName completion; | |
| 57 | void *completion_context; | |
| 58 | } *SilcGaimXfer; | |
| 59 | ||
| 60 | static void | |
| 61 | silcgaim_ftp_monitor(SilcClient client, | |
| 62 | SilcClientConnection conn, | |
| 63 | SilcClientMonitorStatus status, | |
| 64 | SilcClientFileError error, | |
| 65 | SilcUInt64 offset, | |
| 66 | SilcUInt64 filesize, | |
| 67 | SilcClientEntry client_entry, | |
| 68 | SilcUInt32 session_id, | |
| 69 | const char *filepath, | |
| 70 | void *context) | |
| 71 | { | |
| 72 | SilcGaimXfer xfer = context; | |
| 73 | GaimConnection *gc = xfer->sg->gc; | |
| 74 | char tmp[256]; | |
| 75 | ||
| 76 | if (status == SILC_CLIENT_FILE_MONITOR_CLOSED) { | |
| 77 | gaim_xfer_unref(xfer->xfer); | |
| 78 | silc_free(xfer); | |
| 79 | return; | |
| 80 | } | |
| 81 | ||
| 82 | if (status == SILC_CLIENT_FILE_MONITOR_KEY_AGREEMENT) | |
| 83 | return; | |
| 84 | ||
| 85 | if (status == SILC_CLIENT_FILE_MONITOR_ERROR) { | |
| 86 | if (error == SILC_CLIENT_FILE_NO_SUCH_FILE) { | |
| 87 | g_snprintf(tmp, sizeof(tmp), "No such file %s", | |
| 88 | filepath ? filepath : "[N/A]"); | |
| 89 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 90 | _("Error during file transfer"), tmp); | |
| 91 | } else if (error == SILC_CLIENT_FILE_PERMISSION_DENIED) { | |
| 92 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 93 | _("Error during file transfer"), | |
| 94 | _("Permission denied")); | |
| 95 | } else if (error == SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED) { | |
| 96 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 97 | _("Error during file transfer"), | |
| 98 | _("Key agreement failed")); | |
| 99 | } else if (error == SILC_CLIENT_FILE_UNKNOWN_SESSION) { | |
| 100 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 101 | _("Error during file transfer"), | |
|
10254
e7938826d550
[gaim-migrate @ 11394]
Mark Doliner <markdoliner@pidgin.im>
parents:
9788
diff
changeset
|
102 | _("File transfer session does not exist")); |
| 8849 | 103 | } else { |
| 104 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 105 | _("Error during file transfer"), NULL); | |
| 106 | } | |
| 107 | silc_client_file_close(client, conn, session_id); | |
| 108 | gaim_xfer_unref(xfer->xfer); | |
| 109 | silc_free(xfer); | |
| 110 | return; | |
| 111 | } | |
| 112 | ||
| 113 | /* Update file transfer UI */ | |
| 114 | if (!offset && filesize) | |
| 115 | gaim_xfer_set_size(xfer->xfer, filesize); | |
| 116 | if (offset && filesize) { | |
| 117 | xfer->xfer->bytes_sent = offset; | |
| 118 | xfer->xfer->bytes_remaining = filesize - offset; | |
| 119 | } | |
| 120 | gaim_xfer_update_progress(xfer->xfer); | |
| 121 | ||
| 122 | if (status == SILC_CLIENT_FILE_MONITOR_SEND || | |
| 123 | status == SILC_CLIENT_FILE_MONITOR_RECEIVE) { | |
| 124 | if (offset == filesize) { | |
| 125 | /* Download finished */ | |
| 126 | gaim_xfer_set_completed(xfer->xfer, TRUE); | |
| 127 | silc_client_file_close(client, conn, session_id); | |
| 128 | } | |
| 129 | } | |
| 130 | } | |
| 131 | ||
| 132 | static void | |
| 133 | silcgaim_ftp_cancel(GaimXfer *x) | |
| 134 | { | |
| 135 | SilcGaimXfer xfer = x->data; | |
| 136 | xfer->xfer->status = GAIM_XFER_STATUS_CANCEL_LOCAL; | |
| 137 | gaim_xfer_update_progress(xfer->xfer); | |
| 138 | silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); | |
| 139 | } | |
| 140 | ||
| 141 | static void | |
| 142 | silcgaim_ftp_ask_name_cancel(GaimXfer *x) | |
| 143 | { | |
| 144 | SilcGaimXfer xfer = x->data; | |
| 145 | ||
| 146 | /* Cancel the transmission */ | |
| 147 | xfer->completion(NULL, xfer->completion_context); | |
| 148 | silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); | |
| 149 | } | |
| 150 | ||
| 151 | static void | |
| 152 | silcgaim_ftp_ask_name_ok(GaimXfer *x) | |
| 153 | { | |
| 154 | SilcGaimXfer xfer = x->data; | |
| 155 | const char *name; | |
| 156 | ||
| 157 | name = gaim_xfer_get_local_filename(x); | |
|
10589
4e10236e06d4
[gaim-migrate @ 11994]
Daniel Atallah <datallah@pidgin.im>
parents:
10254
diff
changeset
|
158 | g_unlink(name); |
| 8849 | 159 | xfer->completion(name, xfer->completion_context); |
| 160 | } | |
| 161 | ||
| 162 | static void | |
| 163 | silcgaim_ftp_ask_name(SilcClient client, | |
| 164 | SilcClientConnection conn, | |
| 165 | SilcUInt32 session_id, | |
| 166 | const char *remote_filename, | |
| 167 | SilcClientFileName completion, | |
| 168 | void *completion_context, | |
| 169 | void *context) | |
| 170 | { | |
| 171 | SilcGaimXfer xfer = context; | |
| 172 | ||
| 173 | xfer->completion = completion; | |
| 174 | xfer->completion_context = completion_context; | |
| 175 | ||
| 176 | gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_ask_name_ok); | |
| 177 | gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_ask_name_cancel); | |
| 178 | ||
| 179 | /* Request to save the file */ | |
| 180 | gaim_xfer_set_filename(xfer->xfer, remote_filename); | |
| 181 | gaim_xfer_request(xfer->xfer); | |
| 182 | } | |
| 183 | ||
| 184 | static void | |
| 185 | silcgaim_ftp_request_result(GaimXfer *x) | |
| 186 | { | |
| 187 | SilcGaimXfer xfer = x->data; | |
| 188 | SilcClientFileError status; | |
| 189 | GaimConnection *gc = xfer->sg->gc; | |
| 190 | ||
| 191 | if (gaim_xfer_get_status(x) != GAIM_XFER_STATUS_ACCEPTED) | |
| 192 | return; | |
| 193 | ||
| 194 | /* Start the file transfer */ | |
| 195 | status = silc_client_file_receive(xfer->sg->client, xfer->sg->conn, | |
| 196 | silcgaim_ftp_monitor, xfer, | |
| 197 | NULL, xfer->session_id, | |
| 198 | silcgaim_ftp_ask_name, xfer); | |
| 199 | switch (status) { | |
| 200 | case SILC_CLIENT_FILE_OK: | |
| 201 | return; | |
| 202 | break; | |
| 203 | ||
| 204 | case SILC_CLIENT_FILE_UNKNOWN_SESSION: | |
| 205 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 206 | _("No file transfer session active"), NULL); | |
| 207 | break; | |
| 208 | ||
| 209 | case SILC_CLIENT_FILE_ALREADY_STARTED: | |
| 210 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 211 | _("File transfer already started"), NULL); | |
| 212 | break; | |
| 213 | ||
| 214 | case SILC_CLIENT_FILE_KEY_AGREEMENT_FAILED: | |
| 215 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 216 | _("Could not perform key agreement for file transfer"), | |
| 217 | NULL); | |
| 218 | break; | |
| 219 | ||
| 220 | default: | |
| 221 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 222 | _("Could not start the file transfer"), NULL); | |
| 223 | break; | |
| 224 | } | |
| 225 | ||
| 226 | /* Error */ | |
| 227 | gaim_xfer_unref(xfer->xfer); | |
| 228 | g_free(xfer->hostname); | |
| 229 | silc_free(xfer); | |
| 230 | } | |
| 231 | ||
| 232 | static void | |
| 233 | silcgaim_ftp_request_denied(GaimXfer *x) | |
| 234 | { | |
| 235 | ||
| 236 | } | |
| 237 | ||
| 238 | void silcgaim_ftp_request(SilcClient client, SilcClientConnection conn, | |
| 239 | SilcClientEntry client_entry, SilcUInt32 session_id, | |
| 240 | const char *hostname, SilcUInt16 port) | |
| 241 | { | |
| 242 | GaimConnection *gc = client->application; | |
| 243 | SilcGaim sg = gc->proto_data; | |
| 244 | SilcGaimXfer xfer; | |
| 245 | ||
| 246 | xfer = silc_calloc(1, sizeof(*xfer)); | |
| 247 | if (!xfer) { | |
|
13453
4000a28ae1f5
[gaim-migrate @ 15827]
Stu Tomlinson <nosnilmot@pidgin.im>
parents:
12149
diff
changeset
|
248 | silc_client_file_close(sg->client, sg->conn, session_id); |
| 8849 | 249 | return; |
| 250 | } | |
| 251 | ||
| 252 | xfer->sg = sg; | |
| 253 | xfer->client_entry = client_entry; | |
| 254 | xfer->session_id = session_id; | |
| 255 | xfer->hostname = g_strdup(hostname); | |
| 256 | xfer->port = port; | |
| 257 | xfer->xfer = gaim_xfer_new(xfer->sg->account, GAIM_XFER_RECEIVE, | |
| 258 | xfer->client_entry->nickname); | |
| 259 | if (!xfer->xfer) { | |
| 260 | silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); | |
| 261 | g_free(xfer->hostname); | |
| 262 | silc_free(xfer); | |
| 263 | return; | |
| 264 | } | |
| 265 | gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_request_result); | |
| 266 | gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_request_denied); | |
| 267 | gaim_xfer_set_cancel_recv_fnc(xfer->xfer, silcgaim_ftp_cancel); | |
| 268 | xfer->xfer->remote_ip = g_strdup(hostname); | |
| 269 | xfer->xfer->remote_port = port; | |
| 270 | xfer->xfer->data = xfer; | |
| 271 | ||
| 272 | /* File transfer request */ | |
| 273 | gaim_xfer_request(xfer->xfer); | |
| 274 | } | |
| 275 | ||
| 276 | static void | |
| 277 | silcgaim_ftp_send_cancel(GaimXfer *x) | |
| 278 | { | |
| 279 | SilcGaimXfer xfer = x->data; | |
| 280 | silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); | |
| 281 | gaim_xfer_unref(xfer->xfer); | |
| 282 | g_free(xfer->hostname); | |
| 283 | silc_free(xfer); | |
| 284 | } | |
| 285 | ||
| 286 | static void | |
| 287 | silcgaim_ftp_send(GaimXfer *x) | |
| 288 | { | |
| 289 | SilcGaimXfer xfer = x->data; | |
| 290 | const char *name; | |
| 8910 | 291 | char *local_ip = NULL, *remote_ip = NULL; |
| 8849 | 292 | gboolean local = TRUE; |
| 293 | ||
| 294 | name = gaim_xfer_get_local_filename(x); | |
| 295 | ||
| 296 | /* Do the same magic what we do with key agreement (see silcgaim_buddy.c) | |
| 297 | to see if we are behind NAT. */ | |
| 298 | if (silc_net_check_local_by_sock(xfer->sg->conn->sock->sock, | |
| 299 | NULL, &local_ip)) { | |
| 300 | /* Check if the IP is private */ | |
| 301 | if (silcgaim_ip_is_private(local_ip)) { | |
| 302 | local = FALSE; | |
| 303 | /* Local IP is private, resolve the remote server IP to see whether | |
| 304 | we are talking to Internet or just on LAN. */ | |
| 305 | if (silc_net_check_host_by_sock(xfer->sg->conn->sock->sock, NULL, | |
| 306 | &remote_ip)) | |
| 307 | if (silcgaim_ip_is_private(remote_ip)) | |
| 308 | /* We assume we are in LAN. Let's provide the connection point. */ | |
| 309 | local = TRUE; | |
| 310 | } | |
| 311 | } | |
| 312 | ||
| 313 | if (local && !local_ip) | |
| 314 | local_ip = silc_net_localip(); | |
| 315 | ||
| 316 | /* Send the file */ | |
| 317 | silc_client_file_send(xfer->sg->client, xfer->sg->conn, | |
| 318 | silcgaim_ftp_monitor, xfer, | |
| 319 | local_ip, 0, !local, xfer->client_entry, | |
| 320 | name, &xfer->session_id); | |
| 321 | ||
| 322 | silc_free(local_ip); | |
| 323 | silc_free(remote_ip); | |
| 324 | } | |
| 325 | ||
| 326 | static void | |
| 327 | silcgaim_ftp_send_file_resolved(SilcClient client, | |
| 328 | SilcClientConnection conn, | |
| 329 | SilcClientEntry *clients, | |
| 330 | SilcUInt32 clients_count, | |
| 331 | void *context) | |
| 332 | { | |
| 333 | GaimConnection *gc = client->application; | |
| 334 | char tmp[256]; | |
| 335 | ||
| 336 | if (!clients) { | |
| 337 | g_snprintf(tmp, sizeof(tmp), | |
| 338 | _("User %s is not present in the network"), | |
| 339 | (const char *)context); | |
| 340 | gaim_notify_error(gc, _("Secure File Transfer"), | |
| 341 | _("Cannot send file"), tmp); | |
| 342 | silc_free(context); | |
| 343 | return; | |
| 344 | } | |
| 345 | ||
|
9466
b6425eab60ca
[gaim-migrate @ 10291]
Daniel Atallah <datallah@pidgin.im>
parents:
9353
diff
changeset
|
346 | silcgaim_ftp_send_file(client->application, (const char *)context, NULL); |
| 8849 | 347 | silc_free(context); |
| 348 | } | |
| 349 | ||
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
350 | GaimXfer *silcgaim_ftp_new_xfer(GaimConnection *gc, const char *name) |
| 8849 | 351 | { |
| 352 | SilcGaim sg = gc->proto_data; | |
| 353 | SilcClient client = sg->client; | |
| 354 | SilcClientConnection conn = sg->conn; | |
| 355 | SilcClientEntry *clients; | |
| 356 | SilcUInt32 clients_count; | |
| 357 | SilcGaimXfer xfer; | |
| 358 | char *nickname; | |
| 359 | ||
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
360 | g_return_val_if_fail(name != NULL, NULL); |
| 8849 | 361 | |
| 362 | if (!silc_parse_userfqdn(name, &nickname, NULL)) | |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
363 | return NULL; |
| 8849 | 364 | |
| 365 | /* Find client entry */ | |
| 366 | clients = silc_client_get_clients_local(client, conn, nickname, name, | |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
367 | &clients_count); |
| 8849 | 368 | if (!clients) { |
| 369 | silc_client_get_clients(client, conn, nickname, NULL, | |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
370 | silcgaim_ftp_send_file_resolved, |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
371 | strdup(name)); |
| 8849 | 372 | silc_free(nickname); |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
373 | return NULL; |
| 8849 | 374 | } |
| 375 | ||
| 376 | xfer = silc_calloc(1, sizeof(*xfer)); | |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
377 | |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
378 | g_return_val_if_fail(xfer != NULL, NULL); |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
379 | |
| 8849 | 380 | xfer->sg = sg; |
| 381 | xfer->client_entry = clients[0]; | |
| 382 | xfer->xfer = gaim_xfer_new(xfer->sg->account, GAIM_XFER_SEND, | |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
383 | xfer->client_entry->nickname); |
| 8849 | 384 | if (!xfer->xfer) { |
| 385 | silc_client_file_close(xfer->sg->client, xfer->sg->conn, xfer->session_id); | |
| 386 | g_free(xfer->hostname); | |
| 387 | silc_free(xfer); | |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
388 | return NULL; |
| 8849 | 389 | } |
| 390 | gaim_xfer_set_init_fnc(xfer->xfer, silcgaim_ftp_send); | |
| 391 | gaim_xfer_set_request_denied_fnc(xfer->xfer, silcgaim_ftp_request_denied); | |
| 392 | gaim_xfer_set_cancel_send_fnc(xfer->xfer, silcgaim_ftp_send_cancel); | |
| 393 | xfer->xfer->data = xfer; | |
| 394 | ||
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
395 | silc_free(clients); |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
396 | silc_free(nickname); |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
397 | |
|
12149
9706e9a4fad3
[gaim-migrate @ 14450]
Richard Laager <rlaager@pidgin.im>
parents:
12143
diff
changeset
|
398 | return xfer->xfer; |
|
12143
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
399 | } |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
400 | |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
401 | void silcgaim_ftp_send_file(GaimConnection *gc, const char *name, const char *file) |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
402 | { |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
403 | GaimXfer *xfer = silcgaim_ftp_new_xfer(gc, name); |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
404 | |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
405 | g_return_if_fail(xfer != NULL); |
|
09f216663302
[gaim-migrate @ 14444]
Evan Schoenberg <evands@pidgin.im>
parents:
11015
diff
changeset
|
406 | |
| 8849 | 407 | /* Choose file to send */ |
|
9466
b6425eab60ca
[gaim-migrate @ 10291]
Daniel Atallah <datallah@pidgin.im>
parents:
9353
diff
changeset
|
408 | if (file) |
|
12149
9706e9a4fad3
[gaim-migrate @ 14450]
Richard Laager <rlaager@pidgin.im>
parents:
12143
diff
changeset
|
409 | gaim_xfer_request_accepted(xfer, file); |
|
9466
b6425eab60ca
[gaim-migrate @ 10291]
Daniel Atallah <datallah@pidgin.im>
parents:
9353
diff
changeset
|
410 | else |
|
12149
9706e9a4fad3
[gaim-migrate @ 14450]
Richard Laager <rlaager@pidgin.im>
parents:
12143
diff
changeset
|
411 | gaim_xfer_request(xfer); |
| 8849 | 412 | } |