40
40
static PurpleXferUiOps *xfer_ui_ops = NULL;
41
41
static GList *xfers;
44
* A hack to store more data since we can't extend the size of PurpleXfer
47
static GHashTable *xfers_data = NULL;
49
typedef struct _PurpleXferPrivData {
51
* Used to moderate the file transfer when either the read/write ui_ops are
52
* set or fd is not set. In those cases, the UI/prpl call the respective
53
* function, which is somewhat akin to a fd watch being triggered.
56
PURPLE_XFER_READY_NONE = 0x0,
57
PURPLE_XFER_READY_UI = 0x1,
58
PURPLE_XFER_READY_PRPL = 0x2,
43
62
static int purple_xfer_choose_file(PurpleXfer *xfer);
65
purple_xfer_priv_data_destroy(gpointer data)
67
PurpleXferPrivData *priv = data;
46
73
purple_xfers_get_all()
70
98
xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
101
priv = g_new0(PurpleXferPrivData, 1);
102
priv->ready = PURPLE_XFER_READY_NONE;
104
g_hash_table_insert(xfers_data, xfer, priv);
73
106
ui_ops = purple_xfer_get_ui_ops(xfer);
75
108
if (ui_ops != NULL && ui_ops->new_xfer != NULL)
102
135
g_free(xfer->remote_ip);
103
136
g_free(xfer->local_filename);
138
g_hash_table_remove(xfers_data, xfer);
105
140
PURPLE_DBUS_UNREGISTER_POINTER(xfer);
141
xfers = g_list_remove(xfers, xfer);
107
xfers = g_list_remove(xfers, xfer);
479
517
if (type == PURPLE_XFER_SEND) {
480
518
/* Sending a file */
481
519
/* Check the filename. */
520
PurpleXferUiOps *ui_ops;
521
ui_ops = purple_xfer_get_ui_ops(xfer);
483
524
if (g_strrstr(filename, "../") || g_strrstr(filename, "..\\"))
485
526
if (g_strrstr(filename, "../"))
488
char *utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
529
utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
490
531
msg = g_strdup_printf(_("%s is not a valid filename.\n"), utf8);
491
532
purple_xfer_error(type, account, xfer->who, msg);
499
if (g_stat(filename, &st) == -1) {
500
purple_xfer_show_file_error(xfer, filename);
501
purple_xfer_unref(xfer);
540
if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
541
if (g_stat(filename, &st) == -1) {
542
purple_xfer_show_file_error(xfer, filename);
543
purple_xfer_unref(xfer);
547
purple_xfer_set_local_filename(xfer, filename);
548
purple_xfer_set_size(xfer, st.st_size);
550
utf8 = g_strdup(filename);
551
purple_xfer_set_local_filename(xfer, filename);
505
purple_xfer_set_local_filename(xfer, filename);
506
purple_xfer_set_size(xfer, st.st_size);
508
utf8 = g_filename_to_utf8(g_basename(filename), -1, NULL, NULL, NULL);
554
base = g_path_get_basename(filename);
555
utf8 = g_filename_to_utf8(base, -1, NULL, NULL, NULL);
509
557
purple_xfer_set_filename(xfer, utf8);
511
559
msg = g_strdup_printf(_("Offering to send %s to %s"),
512
560
utf8, buddy ? purple_buddy_get_alias(buddy) : xfer->who);
515
562
purple_xfer_conversation_write(xfer, msg, FALSE);
695
742
if (completed == TRUE) {
696
743
char *msg = NULL;
744
PurpleConversation *conv;
697
746
purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_DONE);
699
748
if (purple_xfer_get_filename(xfer) != NULL)
700
msg = g_strdup_printf(_("Transfer of file %s complete"),
701
purple_xfer_get_filename(xfer));
750
char *filename = g_markup_escape_text(purple_xfer_get_filename(xfer), -1);
751
if (purple_xfer_get_local_filename(xfer)
752
&& purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
754
char *local = g_markup_escape_text(purple_xfer_get_local_filename(xfer), -1);
755
msg = g_strdup_printf(_("Transfer of file <A HREF=\"file://%s\">%s</A> complete"),
760
msg = g_strdup_printf(_("Transfer of file %s complete"),
703
765
msg = g_strdup(_("File transfer complete"));
704
purple_xfer_conversation_write(xfer, msg, FALSE);
767
conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who,
768
purple_xfer_get_account(xfer));
771
purple_conversation_write(conv, NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
858
925
s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
860
if (xfer->ops.read != NULL)
927
if (xfer->ops.read != NULL) {
861
928
r = (xfer->ops.read)(buffer, xfer);
863
931
*buffer = g_malloc0(s);
913
transfer_cb(gpointer data, gint source, PurpleInputCondition condition)
978
do_transfer(PurpleXfer *xfer)
915
980
PurpleXferUiOps *ui_ops;
916
PurpleXfer *xfer = (PurpleXfer *)data;
917
981
guchar *buffer = NULL;
920
if (condition & PURPLE_INPUT_READ) {
984
ui_ops = purple_xfer_get_ui_ops(xfer);
986
if (xfer->type == PURPLE_XFER_RECEIVE) {
921
987
r = purple_xfer_read(xfer, &buffer);
923
const size_t wc = fwrite(buffer, 1, r, xfer->dest_fp);
990
if (ui_ops && ui_ops->ui_write)
991
wc = ui_ops->ui_write(xfer, buffer, r);
993
wc = fwrite(buffer, 1, r, xfer->dest_fp);
925
996
purple_debug_error("filetransfer", "Unable to write whole buffer.\n");
926
purple_xfer_cancel_remote(xfer);
997
purple_xfer_cancel_local(xfer);
1002
if ((purple_xfer_get_size(xfer) > 0) &&
1003
((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer)))
1004
purple_xfer_set_completed(xfer, TRUE);
929
1005
} else if(r < 0) {
930
1006
purple_xfer_cancel_remote(xfer);
935
if (condition & PURPLE_INPUT_WRITE) {
1010
} else if (xfer->type == PURPLE_XFER_SEND) {
937
1012
size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
949
buffer = g_malloc0(s);
951
result = fread(buffer, 1, s, xfer->dest_fp);
953
purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
954
purple_xfer_cancel_remote(xfer);
1024
if (ui_ops && ui_ops->ui_read) {
1025
gssize tmp = ui_ops->ui_read(xfer, &buffer, s);
1028
* UI isn't ready to send data. It will call
1029
* purple_xfer_ui_ready when ready, which sets back up this
1032
if (xfer->watcher != 0) {
1033
purple_timeout_remove(xfer->watcher);
1038
} else if (tmp < 0) {
1039
purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
1040
purple_xfer_cancel_local(xfer);
1046
buffer = g_malloc0(s);
1047
result = fread(buffer, 1, s, xfer->dest_fp);
1049
purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
1050
purple_xfer_cancel_local(xfer);
959
1056
/* Write as much as we're allowed to. */
960
r = purple_xfer_write(xfer, buffer, s);
1057
r = purple_xfer_write(xfer, buffer, result);
963
1060
purple_xfer_cancel_remote(xfer);
967
/* We have to seek back in the file now. */
968
fseek(xfer->dest_fp, r - s, SEEK_CUR);
1063
} else if (r < result) {
1064
if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
1065
/* We have to seek back in the file now. */
1066
fseek(xfer->dest_fp, r - s, SEEK_CUR);
1069
ui_ops->data_not_sent(xfer, buffer + r, result - r);
971
1073
* We managed to write the entire buffer. This means our
990
ui_ops = purple_xfer_get_ui_ops(xfer);
992
1092
if (ui_ops != NULL && ui_ops->update_progress != NULL)
993
1093
ui_ops->update_progress(xfer,
994
1094
purple_xfer_get_progress(xfer));
1102
transfer_cb(gpointer data, gint source, PurpleInputCondition condition)
1104
PurpleXfer *xfer = data;
1106
if (xfer->dest_fp == NULL) {
1107
/* The UI is moderating its side manually */
1108
PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
1109
if (0 == (priv->ready & PURPLE_XFER_READY_UI)) {
1110
priv->ready |= PURPLE_XFER_READY_PRPL;
1112
purple_input_remove(xfer->watcher);
1002
1122
begin_transfer(PurpleXfer *xfer, PurpleInputCondition cond)
1004
1124
PurpleXferType type = purple_xfer_get_type(xfer);
1006
xfer->dest_fp = g_fopen(purple_xfer_get_local_filename(xfer),
1007
type == PURPLE_XFER_RECEIVE ? "wb" : "rb");
1009
if (xfer->dest_fp == NULL) {
1010
purple_xfer_show_file_error(xfer, purple_xfer_get_local_filename(xfer));
1011
purple_xfer_cancel_local(xfer);
1125
PurpleXferUiOps *ui_ops = purple_xfer_get_ui_ops(xfer);
1127
if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
1128
xfer->dest_fp = g_fopen(purple_xfer_get_local_filename(xfer),
1129
type == PURPLE_XFER_RECEIVE ? "wb" : "rb");
1131
if (xfer->dest_fp == NULL) {
1132
purple_xfer_show_file_error(xfer, purple_xfer_get_local_filename(xfer));
1133
purple_xfer_cancel_local(xfer);
1137
fseek(xfer->dest_fp, xfer->bytes_sent, SEEK_SET);
1015
fseek(xfer->dest_fp, xfer->bytes_sent, SEEK_SET);
1018
1141
xfer->watcher = purple_input_add(xfer->fd, cond, transfer_cb, xfer);
1020
1143
xfer->start_time = time(NULL);
1165
purple_xfer_ui_ready(PurpleXfer *xfer)
1167
PurpleInputCondition cond;
1168
PurpleXferType type;
1169
PurpleXferPrivData *priv;
1171
g_return_if_fail(xfer != NULL);
1173
priv = g_hash_table_lookup(xfers_data, xfer);
1174
priv->ready |= PURPLE_XFER_READY_UI;
1176
if (0 == (priv->ready & PURPLE_XFER_READY_PRPL))
1179
type = purple_xfer_get_type(xfer);
1180
if (type == PURPLE_XFER_SEND)
1181
cond = PURPLE_INPUT_WRITE;
1182
else /* if (type == PURPLE_XFER_RECEIVE) */
1183
cond = PURPLE_INPUT_READ;
1185
if (xfer->watcher == 0 && xfer->fd != -1)
1186
xfer->watcher = purple_input_add(xfer->fd, cond, transfer_cb, xfer);
1188
priv->ready = PURPLE_XFER_READY_NONE;
1194
purple_xfer_prpl_ready(PurpleXfer *xfer)
1196
PurpleXferPrivData *priv;
1198
g_return_if_fail(xfer != NULL);
1200
priv = g_hash_table_lookup(xfers_data, xfer);
1201
priv->ready |= PURPLE_XFER_READY_PRPL;
1203
/* I don't think fwrite/fread are ever *not* ready */
1204
if (xfer->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI))
1207
priv->ready = PURPLE_XFER_READY_NONE;
1042
1213
purple_xfer_start(PurpleXfer *xfer, int fd, const char *ip,
1043
1214
unsigned int port)
1053
1224
purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_STARTED);
1227
* FIXME 3.0.0 -- there's too much broken code depending on fd == 0
1228
* meaning "don't use a real fd"
1055
1233
if (type == PURPLE_XFER_RECEIVE) {
1056
1234
cond = PURPLE_INPUT_READ;
1136
1314
if (purple_xfer_get_filename(xfer) != NULL)
1138
msg = g_strdup_printf(_("You canceled the transfer of %s"),
1316
msg = g_strdup_printf(_("You cancelled the transfer of %s"),
1139
1317
purple_xfer_get_filename(xfer));
1199
1377
if (purple_xfer_get_filename(xfer) != NULL)
1201
msg = g_strdup_printf(_("%s canceled the transfer of %s"),
1379
msg = g_strdup_printf(_("%s cancelled the transfer of %s"),
1202
1380
buddy ? purple_buddy_get_alias(buddy) : xfer->who, purple_xfer_get_filename(xfer));
1206
msg = g_strdup_printf(_("%s canceled the file transfer"),
1384
msg = g_strdup_printf(_("%s cancelled the file transfer"),
1207
1385
buddy ? purple_buddy_get_alias(buddy) : xfer->who);
1209
1387
purple_xfer_conversation_write(xfer, msg, TRUE);
1296
1474
purple_xfers_init(void) {
1297
1475
void *handle = purple_xfers_get_handle();
1477
xfers_data = g_hash_table_new_full(g_direct_hash, g_direct_equal,
1478
NULL, purple_xfer_priv_data_destroy);
1299
1480
/* register signals */
1300
1481
purple_signal_register(handle, "file-recv-accept",
1301
1482
purple_marshal_VOID__POINTER, NULL, 1,