コード例 #1
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
static void
purple_xfer_destroy(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;

	g_return_if_fail(xfer != NULL);

	if (purple_debug_is_verbose())
		purple_debug_info("xfer", "destroyed %p [%d]\n", xfer, xfer->ref);

	/* Close the file browser, if it's open */
	purple_request_close_with_handle(xfer);

	if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_STARTED)
		purple_xfer_cancel_local(xfer);

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->destroy != NULL)
		ui_ops->destroy(xfer);

	g_free(xfer->who);
	g_free(xfer->filename);
	g_free(xfer->remote_ip);
	g_free(xfer->local_filename);

	g_hash_table_remove(xfers_data, xfer);

	PURPLE_DBUS_UNREGISTER_POINTER(xfer);
	xfers = g_list_remove(xfers, xfer);
	g_free(xfer);
}
コード例 #2
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
static void
begin_transfer(PurpleXfer *xfer, PurpleInputCondition cond)
{
	PurpleXferType type = purple_xfer_get_type(xfer);
	PurpleXferUiOps *ui_ops = purple_xfer_get_ui_ops(xfer);

	if (xfer->start_time != 0) {
		purple_debug_error("xfer", "Transfer is being started multiple times\n");
		g_return_if_reached();
	}

	if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
		xfer->dest_fp = g_fopen(purple_xfer_get_local_filename(xfer),
		                        type == PURPLE_XFER_RECEIVE ? "wb" : "rb");

		if (xfer->dest_fp == NULL) {
			purple_xfer_show_file_error(xfer, purple_xfer_get_local_filename(xfer));
			purple_xfer_cancel_local(xfer);
			return;
		}

		fseek(xfer->dest_fp, xfer->bytes_sent, SEEK_SET);
	}

	if (xfer->fd != -1)
		xfer->watcher = purple_input_add(xfer->fd, cond, transfer_cb, xfer);

	xfer->start_time = time(NULL);

	if (xfer->ops.start != NULL)
		xfer->ops.start(xfer);
}
コード例 #3
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
void
purple_xfer_cancel_local(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;
	char *msg = NULL;

	g_return_if_fail(xfer != NULL);

	purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
	xfer->end_time = time(NULL);

	if (purple_xfer_get_filename(xfer) != NULL)
	{
		msg = g_strdup_printf(_("You cancelled the transfer of %s"),
							  purple_xfer_get_filename(xfer));
	}
	else
	{
		msg = g_strdup(_("File transfer cancelled"));
	}
	purple_xfer_conversation_write(xfer, msg, FALSE);
	g_free(msg);

	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
	{
		if (xfer->ops.cancel_send != NULL)
			xfer->ops.cancel_send(xfer);
	}
	else
	{
		if (xfer->ops.cancel_recv != NULL)
			xfer->ops.cancel_recv(xfer);
	}

	if (xfer->watcher != 0) {
		purple_input_remove(xfer->watcher);
		xfer->watcher = 0;
	}

	if (xfer->fd != -1)
		close(xfer->fd);

	if (xfer->dest_fp != NULL) {
		fclose(xfer->dest_fp);
		xfer->dest_fp = NULL;
	}

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->cancel_local != NULL)
		ui_ops->cancel_local(xfer);

	xfer->bytes_remaining = 0;

	purple_xfer_unref(xfer);
}
コード例 #4
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
void
purple_xfer_update_progress(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;

	g_return_if_fail(xfer != NULL);

	ui_ops = purple_xfer_get_ui_ops(xfer);
	if (ui_ops != NULL && ui_ops->update_progress != NULL)
		ui_ops->update_progress(xfer, purple_xfer_get_progress(xfer));
}
コード例 #5
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
void
purple_xfer_add(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;

	g_return_if_fail(xfer != NULL);

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->add_xfer != NULL)
		ui_ops->add_xfer(xfer);
}
コード例 #6
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
PurpleXfer *
purple_xfer_new(PurpleAccount *account, PurpleXferType type, const char *who)
{
	PurpleXfer *xfer;
	PurpleXferUiOps *ui_ops;
	PurpleXferPrivData *priv;

	g_return_val_if_fail(type    != PURPLE_XFER_UNKNOWN, NULL);
	g_return_val_if_fail(account != NULL,              NULL);
	g_return_val_if_fail(who     != NULL,              NULL);

	xfer = g_new0(PurpleXfer, 1);
	PURPLE_DBUS_REGISTER_POINTER(xfer, PurpleXfer);

	xfer->ref = 1;
	xfer->type    = type;
	xfer->account = account;
	xfer->who     = g_strdup(who);
	xfer->ui_ops  = ui_ops = purple_xfers_get_ui_ops();
	xfer->message = NULL;
	xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
	xfer->fd = -1;

	priv = g_new0(PurpleXferPrivData, 1);
	priv->ready = PURPLE_XFER_READY_NONE;

	if (ui_ops && ui_ops->data_not_sent) {
		/* If the ui will handle unsent data no need for buffer */
		priv->buffer = NULL;
	} else {
		priv->buffer = g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE);
	}

	g_hash_table_insert(xfers_data, xfer, priv);

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->new_xfer != NULL)
		ui_ops->new_xfer(xfer);

	xfers = g_list_prepend(xfers, xfer);

	if (purple_debug_is_verbose())
		purple_debug_info("xfer", "new %p [%d]\n", xfer, xfer->ref);

	return xfer;
}
コード例 #7
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
void
purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed)
{
	PurpleXferUiOps *ui_ops;

	g_return_if_fail(xfer != NULL);

	if (completed == TRUE) {
		char *msg = NULL;
		PurpleConversation *conv;

		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_DONE);

		if (purple_xfer_get_filename(xfer) != NULL)
		{
			char *filename = g_markup_escape_text(purple_xfer_get_filename(xfer), -1);
			if (purple_xfer_get_local_filename(xfer)
			 && purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
			{
				char *local = g_markup_escape_text(purple_xfer_get_local_filename(xfer), -1);
				msg = g_strdup_printf(_("Transfer of file <A HREF=\"file://%s\">%s</A> complete"),
				                      local, filename);
				g_free(local);
			}
			else
				msg = g_strdup_printf(_("Transfer of file %s complete"),
				                      filename);
			g_free(filename);
		}
		else
			msg = g_strdup(_("File transfer complete"));

		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who,
		                                             purple_xfer_get_account(xfer));

		if (conv != NULL)
			purple_conversation_write(conv, NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
		g_free(msg);
	}

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->update_progress != NULL)
		ui_ops->update_progress(xfer, purple_xfer_get_progress(xfer));
}
コード例 #8
0
ファイル: ft.c プロジェクト: wosigh/messaging-plugins
PurpleXfer *
purple_xfer_new(PurpleAccount *account, PurpleXferType type, const char *who)
{
	PurpleXfer *xfer;
	PurpleXferUiOps *ui_ops;
	PurpleXferPrivData *priv;

	g_return_val_if_fail(type    != PURPLE_XFER_UNKNOWN, NULL);
	g_return_val_if_fail(account != NULL,              NULL);
	g_return_val_if_fail(who     != NULL,              NULL);

	xfer = g_new0(PurpleXfer, 1);
	PURPLE_DBUS_REGISTER_POINTER(xfer, PurpleXfer);

	xfer->ref = 1;
	xfer->type    = type;
	xfer->account = account;
	xfer->who     = g_strdup(who);
	xfer->ui_ops  = purple_xfers_get_ui_ops();
	xfer->message = NULL;
	xfer->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
	xfer->fd = -1;

	priv = g_new0(PurpleXferPrivData, 1);
	priv->ready = PURPLE_XFER_READY_NONE;

	g_hash_table_insert(xfers_data, xfer, priv);

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->new_xfer != NULL)
		ui_ops->new_xfer(xfer);

	xfers = g_list_prepend(xfers, xfer);
	return xfer;
}
コード例 #9
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
void
purple_xfer_request_accepted(PurpleXfer *xfer, const char *filename)
{
	PurpleXferType type;
	struct stat st;
	char *msg, *utf8, *base;
	PurpleAccount *account;
	PurpleBuddy *buddy;

	if (xfer == NULL)
		return;

	type = purple_xfer_get_type(xfer);
	account = purple_xfer_get_account(xfer);

	purple_debug_misc("xfer", "request accepted for %p\n", xfer);

	if (!filename && type == PURPLE_XFER_RECEIVE) {
		xfer->status = PURPLE_XFER_STATUS_ACCEPTED;
		xfer->ops.init(xfer);
		return;
	}

	buddy = purple_find_buddy(account, xfer->who);

	if (type == PURPLE_XFER_SEND) {
		/* Sending a file */
		/* Check the filename. */
		PurpleXferUiOps *ui_ops;
		ui_ops = purple_xfer_get_ui_ops(xfer);

#ifdef _WIN32
		if (g_strrstr(filename, "../") || g_strrstr(filename, "..\\"))
#else
		if (g_strrstr(filename, "../"))
#endif
		{
			utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);

			msg = g_strdup_printf(_("%s is not a valid filename.\n"), utf8);
			purple_xfer_error(type, account, xfer->who, msg);
			g_free(utf8);
			g_free(msg);

			purple_xfer_unref(xfer);
			return;
		}

		if (ui_ops == NULL || (ui_ops->ui_read == NULL && ui_ops->ui_write == NULL)) {
			if (g_stat(filename, &st) == -1) {
				purple_xfer_show_file_error(xfer, filename);
				purple_xfer_unref(xfer);
				return;
			}

			purple_xfer_set_local_filename(xfer, filename);
			purple_xfer_set_size(xfer, st.st_size);
		} else {
			utf8 = g_strdup(filename);
			purple_xfer_set_local_filename(xfer, filename);
		}

		base = g_path_get_basename(filename);
		utf8 = g_filename_to_utf8(base, -1, NULL, NULL, NULL);
		g_free(base);
		purple_xfer_set_filename(xfer, utf8);

		msg = g_strdup_printf(_("Offering to send %s to %s"),
				utf8, buddy ? purple_buddy_get_alias(buddy) : xfer->who);
		g_free(utf8);
		purple_xfer_conversation_write(xfer, msg, FALSE);
		g_free(msg);
	}
	else {
		/* Receiving a file */
		xfer->status = PURPLE_XFER_STATUS_ACCEPTED;
		purple_xfer_set_local_filename(xfer, filename);

		msg = g_strdup_printf(_("Starting transfer of %s from %s"),
				xfer->filename, buddy ? purple_buddy_get_alias(buddy) : xfer->who);
		purple_xfer_conversation_write(xfer, msg, FALSE);
		g_free(msg);
	}

	purple_xfer_add(xfer);
	xfer->ops.init(xfer);

}
コード例 #10
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
void
purple_xfer_cancel_remote(PurpleXfer *xfer)
{
	PurpleXferUiOps *ui_ops;
	gchar *msg;
	PurpleAccount *account;
	PurpleBuddy *buddy;

	g_return_if_fail(xfer != NULL);

	purple_request_close_with_handle(xfer);
	purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
	xfer->end_time = time(NULL);

	account = purple_xfer_get_account(xfer);
	buddy = purple_find_buddy(account, xfer->who);

	if (purple_xfer_get_filename(xfer) != NULL)
	{
		msg = g_strdup_printf(_("%s cancelled the transfer of %s"),
				buddy ? purple_buddy_get_alias(buddy) : xfer->who, purple_xfer_get_filename(xfer));
	}
	else
	{
		msg = g_strdup_printf(_("%s cancelled the file transfer"),
				buddy ? purple_buddy_get_alias(buddy) : xfer->who);
	}
	purple_xfer_conversation_write(xfer, msg, TRUE);
	purple_xfer_error(purple_xfer_get_type(xfer), account, xfer->who, msg);
	g_free(msg);

	if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
	{
		if (xfer->ops.cancel_send != NULL)
			xfer->ops.cancel_send(xfer);
	}
	else
	{
		if (xfer->ops.cancel_recv != NULL)
			xfer->ops.cancel_recv(xfer);
	}

	if (xfer->watcher != 0) {
		purple_input_remove(xfer->watcher);
		xfer->watcher = 0;
	}

	if (xfer->fd != -1)
		close(xfer->fd);

	if (xfer->dest_fp != NULL) {
		fclose(xfer->dest_fp);
		xfer->dest_fp = NULL;
	}

	ui_ops = purple_xfer_get_ui_ops(xfer);

	if (ui_ops != NULL && ui_ops->cancel_remote != NULL)
		ui_ops->cancel_remote(xfer);

	xfer->bytes_remaining = 0;

	purple_xfer_unref(xfer);
}
コード例 #11
0
ファイル: ft.c プロジェクト: crodjer/pidgin_whiteboard
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);
}
コード例 #12
0
ファイル: ft.c プロジェクト: wosigh/messaging-plugins
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);
}