source: protocols/purple/ft-direct.c @ a880e34

Last change on this file since a880e34 was 5ebff60, checked in by dequis <dx@…>, at 2015-02-20T22:50:54Z

Reindent everything to K&R style with tabs

Used uncrustify, with the configuration file in ./doc/uncrustify.cfg

Commit author set to "Indent <please@…>" so that it's easier to
skip while doing git blame.

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/***************************************************************************\
2*                                                                           *
3*  BitlBee - An IRC to IM gateway                                           *
4*  libpurple module - File transfer stuff                                   *
5*                                                                           *
6*  Copyright 2009-2010 Wilmer van der Gaast <wilmer@gaast.net>              *
7*                                                                           *
8*  This program is free software; you can redistribute it and/or modify     *
9*  it under the terms of the GNU General Public License as published by     *
10*  the Free Software Foundation; either version 2 of the License, or        *
11*  (at your option) any later version.                                      *
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*  You should have received a copy of the GNU General Public License along  *
19*  with this program; if not, write to the Free Software Foundation, Inc.,  *
20*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
21*                                                                           *
22\***************************************************************************/
23
24/* This code tries to do direct file transfers, i.e. without caching the file
25   locally on disk first. Since libpurple can only do this since version 2.6.0
26   and even then very unreliably (and not with all IM modules), I'm canning
27   this code for now. */
28
29#include "bitlbee.h"
30
31#include <stdarg.h>
32
33#include <glib.h>
34#include <purple.h>
35
36struct prpl_xfer_data {
37        PurpleXfer *xfer;
38        file_transfer_t *ft;
39        gint ready_timer;
40        char *buf;
41        int buf_len;
42};
43
44static file_transfer_t *next_ft;
45
46struct im_connection *purple_ic_by_pa(PurpleAccount *pa);
47
48/* Glorious hack: We seem to have to remind at least some libpurple plugins
49   that we're ready because this info may get lost if we give it too early.
50   So just do it ten times a second. :-/ */
51static gboolean prplcb_xfer_write_request_cb(gpointer data, gint fd, b_input_condition cond)
52{
53        struct prpl_xfer_data *px = data;
54
55        purple_xfer_ui_ready(px->xfer);
56
57        return purple_xfer_get_type(px->xfer) == PURPLE_XFER_RECEIVE;
58}
59
60static gboolean prpl_xfer_write_request(struct file_transfer *ft)
61{
62        struct prpl_xfer_data *px = ft->data;
63
64        px->ready_timer = b_timeout_add(100, prplcb_xfer_write_request_cb, px);
65        return TRUE;
66}
67
68static gboolean prpl_xfer_write(struct file_transfer *ft, char *buffer, unsigned int len)
69{
70        struct prpl_xfer_data *px = ft->data;
71
72        px->buf = g_memdup(buffer, len);
73        px->buf_len = len;
74
75        //purple_xfer_ui_ready( px->xfer );
76        px->ready_timer = b_timeout_add(0, prplcb_xfer_write_request_cb, px);
77
78        return TRUE;
79}
80
81static void prpl_xfer_accept(struct file_transfer *ft)
82{
83        struct prpl_xfer_data *px = ft->data;
84
85        purple_xfer_request_accepted(px->xfer, NULL);
86        prpl_xfer_write_request(ft);
87}
88
89static void prpl_xfer_canceled(struct file_transfer *ft, char *reason)
90{
91        struct prpl_xfer_data *px = ft->data;
92
93        purple_xfer_request_denied(px->xfer);
94}
95
96static gboolean prplcb_xfer_new_send_cb(gpointer data, gint fd, b_input_condition cond)
97{
98        PurpleXfer *xfer = data;
99        struct im_connection *ic = purple_ic_by_pa(xfer->account);
100        struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
101        PurpleBuddy *buddy;
102        const char *who;
103
104        buddy = purple_find_buddy(xfer->account, xfer->who);
105        who = buddy ? purple_buddy_get_name(buddy) : xfer->who;
106
107        /* TODO(wilmer): After spreading some more const goodness in BitlBee,
108           remove the evil cast below. */
109        px->ft = imcb_file_send_start(ic, (char *) who, xfer->filename, xfer->size);
110        px->ft->data = px;
111        px->xfer = data;
112        px->xfer->ui_data = px;
113
114        px->ft->accept = prpl_xfer_accept;
115        px->ft->canceled = prpl_xfer_canceled;
116        px->ft->write_request = prpl_xfer_write_request;
117
118        return FALSE;
119}
120
121static void prplcb_xfer_new(PurpleXfer *xfer)
122{
123        if (purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE) {
124                /* This should suppress the stupid file dialog. */
125                purple_xfer_set_local_filename(xfer, "/tmp/wtf123");
126
127                /* Sadly the xfer struct is still empty ATM so come back after
128                   the caller is done. */
129                b_timeout_add(0, prplcb_xfer_new_send_cb, xfer);
130        } else {
131                struct prpl_xfer_data *px = g_new0(struct prpl_xfer_data, 1);
132
133                px->ft = next_ft;
134                px->ft->data = px;
135                px->xfer = xfer;
136                px->xfer->ui_data = px;
137
138                purple_xfer_set_filename(xfer, px->ft->file_name);
139                purple_xfer_set_size(xfer, px->ft->file_size);
140
141                next_ft = NULL;
142        }
143}
144
145static void prplcb_xfer_progress(PurpleXfer *xfer, double percent)
146{
147        fprintf(stderr, "prplcb_xfer_dbg 0x%p %f\n", xfer, percent);
148}
149
150static void prplcb_xfer_dbg(PurpleXfer *xfer)
151{
152        fprintf(stderr, "prplcb_xfer_dbg 0x%p\n", xfer);
153}
154
155static gssize prplcb_xfer_write(PurpleXfer *xfer, const guchar *buffer, gssize size)
156{
157        struct prpl_xfer_data *px = xfer->ui_data;
158        gboolean st;
159
160        fprintf(stderr, "xfer_write %d %d\n", size, px->buf_len);
161
162        b_event_remove(px->ready_timer);
163        px->ready_timer = 0;
164
165        st = px->ft->write(px->ft, (char *) buffer, size);
166
167        if (st && xfer->bytes_remaining == size) {
168                imcb_file_finished(px->ft);
169        }
170
171        return st ? size : 0;
172}
173
174gssize prplcb_xfer_read(PurpleXfer *xfer, guchar **buffer, gssize size)
175{
176        struct prpl_xfer_data *px = xfer->ui_data;
177
178        fprintf(stderr, "xfer_read %d %d\n", size, px->buf_len);
179
180        if (px->buf) {
181                *buffer = px->buf;
182                px->buf = NULL;
183
184                px->ft->write_request(px->ft);
185
186                return px->buf_len;
187        }
188
189        return 0;
190}
191
192PurpleXferUiOps bee_xfer_uiops =
193{
194        prplcb_xfer_new,
195        prplcb_xfer_dbg,
196        prplcb_xfer_dbg,
197        prplcb_xfer_progress,
198        prplcb_xfer_dbg,
199        prplcb_xfer_dbg,
200        prplcb_xfer_write,
201        prplcb_xfer_read,
202        prplcb_xfer_dbg,
203};
204
205static gboolean prplcb_xfer_send_cb(gpointer data, gint fd, b_input_condition cond);
206
207void purple_transfer_request(struct im_connection *ic, file_transfer_t *ft, char *handle)
208{
209        PurpleAccount *pa = ic->proto_data;
210        struct prpl_xfer_data *px;
211
212        /* xfer_new() will pick up this variable. It's a hack but we're not
213           multi-threaded anyway. */
214        next_ft = ft;
215        serv_send_file(purple_account_get_connection(pa), handle, ft->file_name);
216
217        ft->write = prpl_xfer_write;
218
219        px = ft->data;
220        imcb_file_recv_start(ft);
221
222        px->ready_timer = b_timeout_add(100, prplcb_xfer_send_cb, px);
223}
224
225static gboolean prplcb_xfer_send_cb(gpointer data, gint fd, b_input_condition cond)
226{
227        struct prpl_xfer_data *px = data;
228
229        if (px->ft->status & FT_STATUS_TRANSFERRING) {
230                fprintf(stderr, "The ft, it is ready...\n");
231                px->ft->write_request(px->ft);
232
233                return FALSE;
234        }
235
236        return TRUE;
237}
Note: See TracBrowser for help on using the repository browser.