Пример #1
0
static void _qq_send_file_progess(PurpleConnection *gc)
{
	qq_data *qd = (qq_data *) gc->proto_data;
	PurpleXfer *xfer = qd->xfer;
	ft_info *info = (ft_info *) xfer->data;
	guint32 mask;
	guint8 *buffer;
	guint i;
	gint readbytes;

	if (purple_xfer_get_bytes_remaining(xfer) <= 0) return;
	if (info->window == 0 && info->max_fragment_index == 0)
	{
		if (_qq_xfer_open_file(purple_xfer_get_local_filename(xfer), "rb", xfer) == -1) {
			purple_xfer_cancel_local(xfer);
			return;
		}
	}
	buffer = g_newa(guint8, info->fragment_len);
	mask = 0x1 << (info->max_fragment_index % sizeof(info->window));
	for (i = 0; i < sizeof(info->window); i++) {
		if ((info->window & mask) == 0) {
			readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + i, info->fragment_len, xfer);
			if (readbytes > 0)
				_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,
						info->max_fragment_index + i + 1, 0, buffer, readbytes);
		}
		if (mask & 0x8000) mask = 0x0001;
		else mask = mask << 1;
	}
}
Пример #2
0
static void ggp_edisc_xfer_recv_done(PurpleHttpConnection *hc,
	PurpleHttpResponse *response, gpointer _xfer)
{
	PurpleXfer *xfer = _xfer;
	ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer);

	if (purple_xfer_is_cancelled(xfer))
		return;

	g_return_if_fail(edisc_xfer != NULL);

	edisc_xfer->hc = NULL;

	if (!purple_http_response_is_successful(response)) {
		ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
		return;
	}

	if (purple_xfer_get_bytes_remaining(xfer) == 0) {
		purple_xfer_set_completed(xfer, TRUE);
		purple_xfer_end(xfer);
		ggp_edisc_xfer_free(xfer);
	} else {
		purple_debug_warning("gg", "ggp_edisc_xfer_recv_done: didn't "
			"received everything\n");
		ggp_edisc_xfer_error(xfer, _("Error while receiving a file"));
	}
}
Пример #3
0
/*------------------------------------------------------------------------
 * Start the file transfer.
 *
 *  @param xfer			The file transfer object
 */
static void mxit_xfer_start( PurpleXfer* xfer )
{
	goffset			filesize;
	unsigned char*	buffer;
	int				wrote;

	purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_start\n" );

	if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
		/*
		 * the user wants to send a file to one of his contacts. we need to create
		 * a buffer and copy the file data into memory and then we can send it to
		 * the contact. we will send the whole file with one go.
		 */
		filesize = purple_xfer_get_bytes_remaining( xfer );
		buffer = g_malloc( filesize );

		if ( fread( buffer, filesize, 1, xfer->dest_fp ) > 0 ) {
			/* send data */
			wrote = purple_xfer_write( xfer, buffer, filesize );
			if ( wrote > 0 )
				purple_xfer_set_bytes_sent( xfer, wrote );
		}
		else {
			/* file read error */
			purple_xfer_error( purple_xfer_get_type( xfer ), purple_xfer_get_account( xfer ), purple_xfer_get_remote_user( xfer ), _( "Unable to access the local file" ) );
			purple_xfer_cancel_local( xfer );
		}

		/* free the buffer */
		g_free( buffer );
		buffer = NULL;
	}
}
Пример #4
0
static gssize
tftp_read(guchar **buffer, PurpleXfer *xfer)
{
	return sipe_core_tftp_read(PURPLE_XFER_TO_SIPE_FILE_TRANSFER,
				   buffer,
				   purple_xfer_get_bytes_remaining(xfer),
				   xfer->current_buffer_size);
}
Пример #5
0
static void _qq_update_send_progess(PurpleConnection *gc, guint32 fragment_index)
{
	guint32 mask;
	guint8 *buffer;
	gint readbytes;
	qq_data *qd = (qq_data *) gc->proto_data;
	PurpleXfer *xfer = qd->xfer;
	ft_info *info = (ft_info *) xfer->data;

	purple_debug_info("QQ",
			"receiving %dth fragment ack, slide window status %o, max_fragment_index %d\n",
			fragment_index, info->window, info->max_fragment_index);
	if (fragment_index < info->max_fragment_index ||
			fragment_index >= info->max_fragment_index + sizeof(info->window)) {
		purple_debug_info("QQ", "duplicate %dth fragment, drop it!\n", fragment_index+1);
		return;
	}
	mask = 0x1 << (fragment_index % sizeof(info->window));
	if ((info->window & mask) == 0)
	{
		info->window |= mask;
		if (fragment_index + 1 != info->fragment_num) {
			xfer->bytes_sent += info->fragment_len;
		} else {
			xfer->bytes_sent += purple_xfer_get_size(xfer) % info->fragment_len;
		}
		xfer->bytes_remaining = purple_xfer_get_size(xfer) - purple_xfer_get_bytes_sent(xfer);
		purple_xfer_update_progress(xfer);
		if (purple_xfer_get_bytes_remaining(xfer) <= 0) {
			/* We have finished sending the file */
			purple_xfer_set_completed(xfer, TRUE);
			return;
		}
		mask = 0x1 << (info->max_fragment_index % sizeof(info->window));
		while (info->window & mask)
		{
			/* move the slide window */
			info->window &= ~mask;

			buffer = g_newa(guint8, info->fragment_len);
			readbytes = _qq_xfer_read_file(buffer, info->max_fragment_index + sizeof(info->window),
					info->fragment_len, xfer);
			if (readbytes > 0)
				_qq_send_file_data_packet(gc, QQ_FILE_CMD_FILE_OP, QQ_FILE_DATA_INFO,
						info->max_fragment_index + sizeof(info->window) + 1, 0, buffer, readbytes);

			info->max_fragment_index ++;
			if (mask & 0x8000) mask = 0x0001;
			else mask = mask << 1;
		}
	}
	purple_debug_info("QQ",
			"procceed %dth fragment ack, slide window status %o, max_fragment_index %d\n",
			fragment_index, info->window, info->max_fragment_index);
}
Пример #6
0
static gboolean ggp_edisc_xfer_recv_writer(PurpleHttpConnection *http_conn,
	PurpleHttpResponse *response, const gchar *buffer, size_t offset,
	size_t length, gpointer _xfer)
{
	PurpleXfer *xfer = _xfer;
	ggp_edisc_xfer *edisc_xfer;
	gssize stored;

	g_return_val_if_fail(xfer != NULL, FALSE);
	edisc_xfer = purple_xfer_get_protocol_data(xfer);
	g_return_val_if_fail(edisc_xfer != NULL, FALSE);

	stored = purple_xfer_write_file(xfer, (guchar *)buffer, length) ?
			(gssize)length : -1;

	if (stored < 0 || (gsize)stored != length) {
		purple_debug_error("gg", "ggp_edisc_xfer_recv_writer: "
			"saved too less\n");
		return FALSE;
	}

	if (stored > purple_xfer_get_bytes_remaining(xfer)) {
		purple_debug_error("gg", "ggp_edisc_xfer_recv_writer: "
			"saved too much (%" G_GSSIZE_FORMAT " > %" G_GOFFSET_FORMAT ")\n",
			stored, purple_xfer_get_bytes_remaining(xfer));
		return FALSE;
	}

	/* May look redundant with ggp_edisc_xfer_progress_watcher,
	 * but it isn't!
	 */
	purple_xfer_set_bytes_sent(xfer,
		purple_xfer_get_bytes_sent(xfer) + stored);

	return TRUE;
}
Пример #7
0
static gssize irc_dccsend_send_write(const guchar *buffer, size_t size, PurpleXfer *xfer)
{
	gssize s;
	int ret;

	s = MIN(purple_xfer_get_bytes_remaining(xfer), size);
	if (!s)
		return 0;

	ret = write(xfer->fd, buffer, s);

	if (ret < 0 && errno == EAGAIN)
		ret = 0;

	return ret;
}
static void
yahoo_process_filetrans_15_reader(PurpleHttpConnection *hc,
	gchar *buffer, size_t offset, size_t length, gpointer _xfer,
	PurpleHttpContentReaderCb cb)
{
	PurpleXfer *xfer = _xfer;
	gssize stored;

	if ((goffset)offset != purple_xfer_get_bytes_sent(xfer)) {
		purple_debug_warning("yahoo",
			"offset != purple_xfer_get_bytes_sent(xfer)\n");
	}

	stored = purple_xfer_read_file(xfer, (guchar*)buffer, length);

	cb(hc, (stored >= 0), (purple_xfer_get_bytes_remaining(xfer) == 0),
		stored);
}
Пример #9
0
void
finch_xfer_dialog_add_xfer(PurpleXfer *xfer)
{
	PurpleGntXferUiData *data;
	PurpleXferType type;
	char *size_str, *remaining_str;
	char *lfilename, *utf8;

	g_return_if_fail(xfer_dialog != NULL);
	g_return_if_fail(xfer != NULL);

	purple_xfer_ref(xfer);

	data = FINCHXFER(xfer);
	data->in_list = TRUE;

	finch_xfer_dialog_show();

	data->last_updated_time = 0;

	type = purple_xfer_get_type(xfer);

	size_str      = purple_str_size_to_units(purple_xfer_get_size(xfer));
	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));

	lfilename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
	utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL);
	g_free(lfilename);
	lfilename = utf8;
	gnt_tree_add_row_last(GNT_TREE(xfer_dialog->tree), xfer,
		gnt_tree_create_row(GNT_TREE(xfer_dialog->tree),
			"0.0", (type == PURPLE_XFER_RECEIVE) ? purple_xfer_get_filename(xfer) : lfilename,
			size_str, "0.0", "",_("Waiting for transfer to begin")), NULL);
	g_free(lfilename);

	g_free(size_str);
	g_free(remaining_str);

	xfer_dialog->num_transfers++;

	update_title_progress();
}
Пример #10
0
gssize
purple_xfer_read(PurpleXfer *xfer, guchar **buffer)
{
	gssize s, r;

	g_return_val_if_fail(xfer   != NULL, 0);
	g_return_val_if_fail(buffer != NULL, 0);

	if (purple_xfer_get_size(xfer) == 0)
		s = xfer->current_buffer_size;
	else
		s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);

	if (xfer->ops.read != NULL)	{
		r = (xfer->ops.read)(buffer, xfer);
	}
	else {
		*buffer = g_malloc0(s);

		r = read(xfer->fd, *buffer, s);
		if (r < 0 && errno == EAGAIN)
			r = 0;
		else if (r < 0)
			r = -1;
		else if (r == 0)
			r = -1;
	}

	if (r == xfer->current_buffer_size)
		/*
		 * We managed to read the entire buffer.  This means our this
		 * network is fast and our buffer is too small, so make it
		 * bigger.
		 */
		purple_xfer_increase_buffer_size(xfer);

	return r;
}
Пример #11
0
gssize
purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size)
{
	gssize r, s;

	g_return_val_if_fail(xfer   != NULL, 0);
	g_return_val_if_fail(buffer != NULL, 0);
	g_return_val_if_fail(size   != 0,    0);

	s = MIN(purple_xfer_get_bytes_remaining(xfer), size);

	if (xfer->ops.write != NULL) {
		r = (xfer->ops.write)(buffer, s, xfer);
	} else {
		r = write(xfer->fd, buffer, s);
		if (r < 0 && errno == EAGAIN)
			r = 0;
		if ((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer))
			purple_xfer_set_completed(xfer, TRUE);
	}

	return r;
}
Пример #12
0
static void
yahoo_process_filetrans_15_downloaded(PurpleHttpConnection *hc,
	PurpleHttpResponse *response, gpointer _xfer)
{
	PurpleXfer *xfer = _xfer;
	struct yahoo_xfer_data *xd;

	xd = purple_xfer_get_protocol_data(xfer);

	xd->hc = NULL;

	if (purple_xfer_is_cancelled(xfer))
		return;

	if (!purple_http_response_is_successful(response) ||
		purple_xfer_get_bytes_remaining(xfer) > 0)
	{
		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
		purple_xfer_end(xfer);
	} else {
		purple_xfer_set_completed(xfer, TRUE);
		purple_xfer_end(xfer);
	}
}
Пример #13
0
void
pidgin_xfer_dialog_update_xfer(PidginXferDialog *dialog,
								PurpleXfer *xfer)
{
	PidginXferUiData *data;
	char *size_str, *remaining_str;
	GtkTreeSelection *selection;
	time_t current_time;
	GtkTreeIter iter;
	gboolean valid;

	g_return_if_fail(dialog != NULL);
	g_return_if_fail(xfer != NULL);

	if ((data = PIDGINXFER(xfer)) == NULL)
		return;

	if (data->in_list == FALSE)
		return;

	current_time = time(NULL);
	if (((current_time - data->last_updated_time) == 0) &&
		(!purple_xfer_is_completed(xfer)))
	{
		/* Don't update the window more than once per second */
		return;
	}
	data->last_updated_time = current_time;

	size_str      = purple_str_size_to_units(purple_xfer_get_size(xfer));
	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));

	gtk_list_store_set(xfer_dialog->model, &data->iter,
					   COLUMN_PROGRESS, purple_xfer_get_progress(xfer),
					   COLUMN_SIZE, size_str,
					   COLUMN_REMAINING, remaining_str,
					   -1);

	g_free(size_str);
	g_free(remaining_str);

	if (purple_xfer_is_completed(xfer))
	{
		GdkPixbuf *pixbuf;

		pixbuf = gtk_widget_render_icon(dialog->window,
										PIDGIN_STOCK_FILE_DONE,
										GTK_ICON_SIZE_MENU, NULL);

		gtk_list_store_set(GTK_LIST_STORE(xfer_dialog->model), &data->iter,
						   COLUMN_STATUS, pixbuf,
						   COLUMN_REMAINING, _("Finished"),
						   -1);

		g_object_unref(pixbuf);
	}

	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(xfer_dialog->tree));

	update_title_progress(dialog);
	if (xfer == dialog->selected_xfer)
		update_detailed_info(xfer_dialog, xfer);

	if (purple_xfer_is_completed(xfer) && dialog->auto_clear)
		pidgin_xfer_dialog_remove_xfer(dialog, xfer);
	else
		update_buttons(dialog, xfer);

	/*
	 * If all transfers are finished, and the pref is set, then
	 * close the dialog.  Otherwise just exit this function.
	 */
	if (dialog->keep_open)
		return;

	valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(dialog->model), &iter);
	while (valid)
	{
		GValue val;
		PurpleXfer *next;

		val.g_type = 0;
		gtk_tree_model_get_value(GTK_TREE_MODEL(dialog->model),
				&iter, COLUMN_DATA, &val);

		next = g_value_get_pointer(&val);
		if (!purple_xfer_is_completed(next))
			return;

		valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(dialog->model), &iter);
	}

	/* If we got to this point then we know everything is finished */
	pidgin_xfer_dialog_hide(dialog);
}
Пример #14
0
void
finch_xfer_dialog_update_xfer(PurpleXfer *xfer)
{
	PurpleGntXferUiData *data;
	char *size_str, *remaining_str;
	time_t current_time;
	char prog_str[5];
	double kb_sent;
	double kbps = 0.0;
	time_t elapsed, now;
	char *kbsec;
	gboolean send;

	if ((now = purple_xfer_get_end_time(xfer)) == 0)
		now = time(NULL);

	kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0;
	elapsed = (purple_xfer_get_start_time(xfer) > 0 ? now - purple_xfer_get_start_time(xfer) : 0);
	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);

	g_return_if_fail(xfer_dialog != NULL);
	g_return_if_fail(xfer != NULL);

	if ((data = FINCHXFER(xfer)) == NULL)
		return;

	if (data->in_list == FALSE || data->notified)
		return;

	current_time = time(NULL);
	if (((current_time - data->last_updated_time) == 0) &&
		(!purple_xfer_is_completed(xfer))) {
		/* Don't update the window more than once per second */
		return;
	}
	data->last_updated_time = current_time;

	send = (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND);
	size_str      = purple_str_size_to_units(purple_xfer_get_size(xfer));
	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));
	kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps);

	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS,
			g_ascii_dtostr(prog_str, sizeof(prog_str), purple_xfer_get_progress(xfer) * 100.));
	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SIZE, size_str);
	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, remaining_str);
	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_SPEED, kbsec);
	g_free(size_str);
	g_free(remaining_str);
	g_free(kbsec);
	if (purple_xfer_is_completed(xfer)) {
		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS, send ? _("Sent") : _("Received"));
		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_REMAINING, _("Finished"));
		if (!send) {
			char *msg = g_strdup_printf(_("The file was saved as %s."), purple_xfer_get_local_filename(xfer));
			purple_xfer_conversation_write(xfer, msg, FALSE);
			g_free(msg);
		}
		data->notified = TRUE;
	} else {
		gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_STATUS,
				send ? _("Sending") : _("Receiving"));
	}

	update_title_progress();

	if (purple_xfer_is_completed(xfer) && xfer_dialog->auto_clear)
		finch_xfer_dialog_remove_xfer(xfer);
}
Пример #15
0
void
pidgin_xfer_dialog_add_xfer(PidginXferDialog *dialog, PurpleXfer *xfer)
{
	PidginXferUiData *data;
	PurpleXferType type;
	GdkPixbuf *pixbuf;
	char *size_str, *remaining_str;
	char *lfilename, *utf8;

	g_return_if_fail(dialog != NULL);
	g_return_if_fail(xfer != NULL);

	purple_xfer_ref(xfer);

	data = PIDGINXFER(xfer);
	data->in_list = TRUE;

	pidgin_xfer_dialog_show(dialog);

	data->last_updated_time = 0;

	type = purple_xfer_get_type(xfer);

	size_str      = purple_str_size_to_units(purple_xfer_get_size(xfer));
	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));

	pixbuf = gtk_widget_render_icon(dialog->window,
									(type == PURPLE_XFER_RECEIVE
									 ? PIDGIN_STOCK_DOWNLOAD
									 : PIDGIN_STOCK_UPLOAD),
									GTK_ICON_SIZE_MENU, NULL);

	gtk_list_store_append(dialog->model, &data->iter);
	lfilename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
	utf8 = g_filename_to_utf8(lfilename, -1, NULL, NULL, NULL);
	g_free(lfilename);
	lfilename = utf8;
	gtk_list_store_set(dialog->model, &data->iter,
					   COLUMN_STATUS, pixbuf,
					   COLUMN_PROGRESS, 0.0,
					   COLUMN_FILENAME, (type == PURPLE_XFER_RECEIVE)
					                     ? purple_xfer_get_filename(xfer)
							     : lfilename,
					   COLUMN_SIZE, size_str,
					   COLUMN_REMAINING, _("Waiting for transfer to begin"),
					   COLUMN_DATA, xfer,
					   -1);
	g_free(lfilename);

	gtk_tree_view_columns_autosize(GTK_TREE_VIEW(dialog->tree));

	g_object_unref(pixbuf);

	g_free(size_str);
	g_free(remaining_str);

	dialog->num_transfers++;

	ensure_row_selected(dialog);
	update_title_progress(dialog);
}
Пример #16
0
/**************************************************************************
 * Utility Functions
 **************************************************************************/
static void
get_xfer_info_strings(PurpleXfer *xfer, char **kbsec, char **time_elapsed,
					  char **time_remaining)
{
	PidginXferUiData *data;
	double kb_sent, kb_rem;
	double kbps = 0.0;
	time_t elapsed, now;

	data = PIDGINXFER(xfer);

	if (xfer->end_time != 0)
		now = xfer->end_time;
	else
		now = time(NULL);

	kb_sent = purple_xfer_get_bytes_sent(xfer) / 1024.0;
	kb_rem  = purple_xfer_get_bytes_remaining(xfer) / 1024.0;
	elapsed = (xfer->start_time > 0 ? now - xfer->start_time : 0);
	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);

	if (kbsec != NULL) {
		*kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps);
	}

	if (time_elapsed != NULL)
	{
		int h, m, s;
		int secs_elapsed;

		if (xfer->start_time > 0)
		{
			secs_elapsed = now - xfer->start_time;

			h = secs_elapsed / 3600;
			m = (secs_elapsed % 3600) / 60;
			s = secs_elapsed % 60;

			*time_elapsed = g_strdup_printf("%d:%02d:%02d", h, m, s);
		}
		else
		{
			*time_elapsed = g_strdup(_("Not started"));
		}
	}

	if (time_remaining != NULL) {
		if (purple_xfer_is_completed(xfer)) {
			*time_remaining = g_strdup(_("Finished"));
		}
		else if (purple_xfer_is_canceled(xfer)) {
			*time_remaining = g_strdup(_("Canceled"));
		}
		else if (purple_xfer_get_size(xfer) == 0 || (kb_sent > 0 && kbps == 0)) {
			*time_remaining = g_strdup(_("Unknown"));
		}
		else if (kb_sent <= 0) {
			*time_remaining = g_strdup(_("Waiting for transfer to begin"));
		}
		else {
			int h, m, s;
			int secs_remaining;

			secs_remaining = (int)(kb_rem / kbps);

			h = secs_remaining / 3600;
			m = (secs_remaining % 3600) / 60;
			s = secs_remaining % 60;

			*time_remaining = g_strdup_printf("%d:%02d:%02d", h, m, s);
		}
	}
}
Пример #17
0
static void
do_transfer(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;
	guchar *buffer = NULL;
	gssize r = 0;

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (xfer->type == PURPLE_XFER_RECEIVE) {
		r = purple_xfer_read(xfer, &buffer);
		if (r > 0) {
			size_t wc;
			if (ui_ops && ui_ops->ui_write)
				wc = ui_ops->ui_write(xfer, buffer, r);
			else
				wc = fwrite(buffer, 1, r, xfer->dest_fp);

			if (wc != r) {
				purple_debug_error("filetransfer", "Unable to write whole buffer.\n");
				purple_xfer_cancel_local(xfer);
				g_free(buffer);
				return;
			}

			if ((purple_xfer_get_size(xfer) > 0) &&
				((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer)))
				purple_xfer_set_completed(xfer, TRUE);
		} else if(r < 0) {
			purple_xfer_cancel_remote(xfer);
			g_free(buffer);
			return;
		}
	} else if (xfer->type == PURPLE_XFER_SEND) {
		size_t result = 0;
		size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);
		PurpleXferPrivData *priv = g_hash_table_lookup(xfers_data, xfer);
		gboolean read = TRUE;

		/* this is so the prpl can keep the connection open
		   if it needs to for some odd reason. */
		if (s == 0) {
			if (xfer->watcher) {
				purple_input_remove(xfer->watcher);
				xfer->watcher = 0;
			}
			return;
		}

		if (priv->buffer) {
			if (priv->buffer->len < s) {
				s -= priv->buffer->len;
				read = TRUE;
			} else {
				read = FALSE;
			}
		}

		if (read) {
			if (ui_ops && ui_ops->ui_read) {
				gssize tmp = ui_ops->ui_read(xfer, &buffer, s);
				if (tmp == 0) {
					/*
					 * The UI claimed it was ready, but didn't have any data for
					 * us...  It will call purple_xfer_ui_ready when ready, which
					 * sets back up this watcher.
					 */
					if (xfer->watcher != 0) {
						purple_input_remove(xfer->watcher);
						xfer->watcher = 0;
					}

					/* Need to indicate the prpl is still ready... */
					priv->ready |= PURPLE_XFER_READY_PRPL;

					g_return_if_reached();
				} else if (tmp < 0) {
					purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
					purple_xfer_cancel_local(xfer);
					return;
				}

				result = tmp;
			} else {
				buffer = g_malloc(s);
				result = fread(buffer, 1, s, xfer->dest_fp);
				if (result != s) {
					purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
					purple_xfer_cancel_local(xfer);
					g_free(buffer);
					return;
				}
			}
		}

		if (priv->buffer) {
			g_byte_array_append(priv->buffer, buffer, result);
			g_free(buffer);
			buffer = priv->buffer->data;
			result = priv->buffer->len;
		}

		r = purple_xfer_write(xfer, buffer, result);

		if (r == -1) {
			purple_xfer_cancel_remote(xfer);
			if (!priv->buffer)
				/* We don't free buffer if priv->buffer is set, because in
				   that case buffer doesn't belong to us. */
				g_free(buffer);
			return;
		} else if (r == result) {
			/*
			 * We managed to write the entire buffer.  This means our
			 * network is fast and our buffer is too small, so make it
			 * bigger.
			 */
			purple_xfer_increase_buffer_size(xfer);
		} else {
			if (ui_ops && ui_ops->data_not_sent)
				ui_ops->data_not_sent(xfer, buffer + r, result - r);
		}

		if (priv->buffer) {
			/*
			 * Remove what we wrote
			 * If we wrote the whole buffer the byte array will be empty
			 * Otherwise we'll keep what wasn't sent for next time.
			 */
			buffer = NULL;
			g_byte_array_remove_range(priv->buffer, 0, r);
		}
	}

	if (r > 0) {
		if (purple_xfer_get_size(xfer) > 0)
			xfer->bytes_remaining -= r;

		xfer->bytes_sent += r;

		if (xfer->ops.ack != NULL)
			xfer->ops.ack(xfer, buffer, r);

		g_free(buffer);

		if (ui_ops != NULL && ui_ops->update_progress != NULL)
			ui_ops->update_progress(xfer,
				purple_xfer_get_progress(xfer));
	}

	if (purple_xfer_is_completed(xfer))
		purple_xfer_end(xfer);
}
Пример #18
0
static void
do_transfer(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;
	guchar *buffer = NULL;
	gssize r = 0;

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (xfer->type == PURPLE_XFER_RECEIVE) {
		r = purple_xfer_read(xfer, &buffer);
		if (r > 0) {
			size_t wc;
			if (ui_ops && ui_ops->ui_write)
				wc = ui_ops->ui_write(xfer, buffer, r);
			else
				wc = fwrite(buffer, 1, r, xfer->dest_fp);

			if (wc != r) {
				purple_debug_error("filetransfer", "Unable to write whole buffer.\n");
				purple_xfer_cancel_local(xfer);
				g_free(buffer);
				return;
			}

			if ((purple_xfer_get_size(xfer) > 0) &&
				((purple_xfer_get_bytes_sent(xfer)+r) >= purple_xfer_get_size(xfer)))
				purple_xfer_set_completed(xfer, TRUE);
		} else if(r < 0) {
			purple_xfer_cancel_remote(xfer);
			g_free(buffer);
			return;
		}
	} else if (xfer->type == PURPLE_XFER_SEND) {
		size_t result;
		size_t s = MIN(purple_xfer_get_bytes_remaining(xfer), xfer->current_buffer_size);

		/* this is so the prpl can keep the connection open
		   if it needs to for some odd reason. */
		if (s == 0) {
			if (xfer->watcher) {
				purple_input_remove(xfer->watcher);
				xfer->watcher = 0;
			}
			return;
		}

		if (ui_ops && ui_ops->ui_read) {
			gssize tmp = ui_ops->ui_read(xfer, &buffer, s);
			if (tmp == 0) {
				/*
				 * UI isn't ready to send data. It will call
				 * purple_xfer_ui_ready when ready, which sets back up this
				 * watcher.
				 */
				if (xfer->watcher != 0) {
					purple_timeout_remove(xfer->watcher);
					xfer->watcher = 0;
				}

				return;
			} else if (tmp < 0) {
				purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
				purple_xfer_cancel_local(xfer);
				return;
			}

			result = tmp;
		} else {
			buffer = g_malloc0(s);
			result = fread(buffer, 1, s, xfer->dest_fp);
			if (result != s) {
				purple_debug_error("filetransfer", "Unable to read whole buffer.\n");
				purple_xfer_cancel_local(xfer);
				g_free(buffer);
				return;
			}
		}

		/* Write as much as we're allowed to. */
		r = purple_xfer_write(xfer, buffer, result);

		if (r == -1) {
			purple_xfer_cancel_remote(xfer);
			g_free(buffer);
			return;
		} else if (r < result) {
			if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
				/* We have to seek back in the file now. */
				fseek(xfer->dest_fp, r - s, SEEK_CUR);
			}
			else {
				ui_ops->data_not_sent(xfer, buffer + r, result - r);
			}
		} else {
			/*
			 * We managed to write the entire buffer.  This means our
			 * network is fast and our buffer is too small, so make it
			 * bigger.
			 */
			purple_xfer_increase_buffer_size(xfer);
		}
	}

	if (r > 0) {
		if (purple_xfer_get_size(xfer) > 0)
			xfer->bytes_remaining -= r;

		xfer->bytes_sent += r;

		if (xfer->ops.ack != NULL)
			xfer->ops.ack(xfer, buffer, r);

		g_free(buffer);

		if (ui_ops != NULL && ui_ops->update_progress != NULL)
			ui_ops->update_progress(xfer,
				purple_xfer_get_progress(xfer));
	}

	if (purple_xfer_is_completed(xfer))
		purple_xfer_end(xfer);
}