pidgin/pidgin

Remove PurpleXfer

2 weeks ago, Gary Kramlich
b632ff7a7936
Parents 1f52237ebd7a
Children d921cd91924f
Remove PurpleXfer

the autoaccept plugin has been left for now, but no longer builds by default
because we haven't ported it to the new PurpleFileTransfer API yet.

Testing Done:
Hung out with the turtles.

Reviewed at https://reviews.imfreedom.org/r/3086/
--- a/ChangeLog.API Thu Apr 11 04:02:16 2024 -0500
+++ b/ChangeLog.API Thu Apr 11 20:34:07 2024 -0500
@@ -205,26 +205,11 @@
* Signal registration now uses GTypes instead of PurpleValues. See
SIGNAL-HOWTO for more information.
* purple_whiteboard_create renamed to purple_whiteboard_new
- * purple_xfer_get_bytes_remaining now returns a goffset
- * purple_xfer_get_bytes_sent now returns a goffset
- * purple_xfer_get_size now returns a goffset
- * purple_xfer_is_canceled renamed to purple_xfer_is_cancelled
- * PurpleXfer is now a GObject. Please see the documentation for details.
- * purple_xfer_get_type renamed to purple_xfer_get_xfer_type
- * PurpleXferStatusType renamed to PurpleXferStatus
- * PURPLE_XFER_* prefix of PurpleXferType enums changed to
- PURPLE_XFER_TYPE_*
- * purple_xfer_set_bytes_sent now takes a goffset as the bytes_sent
- parameter
- * purple_xfer_set_size now takes a goffset as the size parameter
* PurpleCertificateVerificationStatus enumeration is now merged with
internal flags, thus removing PURPLE_CERTIFICATE_INVALID and
replacing it with more precise errors.
* PurpleConnectionUiOps.report_disconnect now passes a
PurpleConnectionError as the second parameter
- * PurpleXfer.bytes_remaining is now a goffset
- * PurpleXfer.bytes_sent is now a goffset
- * PurpleXfer.size is now a goffset
* PurpleCertificateScheme.get_times now uses gint64 instead of
time_t to represent times
* purple_certificate_get_times now uses gint64 instead of
@@ -829,20 +814,55 @@
* PurpleValue, use GValue instead.
* purple_whiteboard_get_ui_data and purple_whiteboard_set_ui_data, use
g_object_set_data instead.
- * PurpleXferUiOps.add_thumbnail. Use PurpleXfer::add-thumbnail
- instead.
- * PurpleXferUiOps.add_xfer. Use notify::visible on #PurpleXfer
- objects instead.
- * PurpleXferUiOps.cancel_local and
- PurpleXferUiOps.cancel_remote. Use notify::status on
- #PurpleXfer objects instead.
- * PurpleXferUiOps.data_not_sent. Use PurpleXfer::data-not-sent
- instead.
- * PurpleXferUiOps.destroy
- * PurpleXferUiOps.ui_read. Use PurpleXfer::read-local instead.
- * PurpleXferUiOps.ui_write. Use PurpleXfer::write-local instead.
- * PurpleXferUiOps.update_progress. Use notify::progress on
- #PurpleXfer objects instead.
+ * PurpleXfer
+ * PurpleXferUiOps
+ * purple_xfer_cancel_local
+ * purple_xfer_cancel_remote
+ * purple_xfer_conversation_write
+ * purple_xfer_end
+ * purple_xfer_error
+ * purple_xfer_get_account
+ * purple_xfer_get_bytes_remaining
+ * purple_xfer_get_bytes_sent
+ * purple_xfer_get_end_time
+ * purple_xfer_get_filename
+ * purple_xfer_get_local_filename
+ * purple_xfer_get_local_port
+ * purple_xfer_get_progress
+ * purple_xfer_get_remote_ip
+ * purple_xfer_get_remote_port
+ * purple_xfer_get_remote_user
+ * purple_xfer_get_size
+ * purple_xfer_get_start_time
+ * purple_xfer_get_status
+ * purple_xfer_get_thumbnail
+ * purple_xfer_get_thumbnail_mimetype
+ * purple_xfer_get_ui_ops
+ * purple_xfer_is_completed
+ * purple_xfer_new
+ * purple_xfer_prepare_thumbnail
+ * purple_xfer_read
+ * purple_xfer_read_file
+ * purple_xfer_request
+ * purple_xfer_request_accepted
+ * purple_xfer_request_denied
+ * purple_xfer_set_bytes_sent
+ * purple_xfer_set_completed
+ * purple_xfer_set_filename
+ * purple_xfer_set_local_filename
+ * purple_xfer_set_message
+ * purple_xfer_set_size
+ * purple_xfer_set_thumbnail
+ * purple_xfer_start
+ * purple_xfer_ui_ready
+ * purple_xfer_write
+ * purple_xfer_write_file
+ * purple_xfers_get_all
+ * purple_xfers_get_handle
+ * purple_xfers_get_ui_ops
+ * purple_xfers_init
+ * purple_xfers_set_ui_ops
+ * purple_xfers_uninit
* quitting signal
* serv_got_attention
* serv_send_attention
--- a/doc/reference/libpurple/libpurple.toml.in Thu Apr 11 04:02:16 2024 -0500
+++ b/doc/reference/libpurple/libpurple.toml.in Thu Apr 11 20:34:07 2024 -0500
@@ -48,7 +48,6 @@
"signals_core.md",
"signals_jabber.md",
"signals_savedstatus.md",
- "signals_xfer.md",
"tut_c_plugins.md",
]
content_images = [
--- a/doc/reference/libpurple/meson.build Thu Apr 11 04:02:16 2024 -0500
+++ b/doc/reference/libpurple/meson.build Thu Apr 11 20:34:07 2024 -0500
@@ -10,7 +10,6 @@
'signals_core.md',
'signals_jabber.md',
'signals_savedstatus.md',
- 'signals_xfer.md',
'tut_c_plugins.md',
]
--- a/doc/reference/libpurple/signals_xfer.md Thu Apr 11 04:02:16 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-Title: File Transfer Signals
-Slug: file-transfer-signals
-
-## File Transfer Signals
-
-### Signal List
-
-* [file-recv-request](#file-recv-request)
-
-### Signal Detail
-
-#### file-recv-request
-
-```c
-void user_function(PurpleXfer *xfer, gpointer data);
-```
-
-Emitted before the user is prompted for an incoming file-transfer. Plugins can intercept the signal to auto-accept/auto-reject the requests. To auto-accept the file transfer, use purple_xfer_request_accepted(). To auto-reject, set the status of the xfer to PURPLE_XFER_STATUS_CANCEL_LOCAL.
-
-**Parameters:**
-
-**xfer**
-: The file transfer.
-
-**data**
-: User data.
--- a/libpurple/core.c Thu Apr 11 04:02:16 2024 -0500
+++ b/libpurple/core.c Thu Apr 11 20:34:07 2024 -0500
@@ -31,7 +31,6 @@
#include "conversations.h"
#include "core.h"
#include "debug.h"
-#include "xfer.h"
#include "idle.h"
#include "image-store.h"
#include "network.h"
@@ -181,7 +180,6 @@
purple_network_init();
purple_proxy_init();
- purple_xfers_init();
purple_idle_init();
purple_idle_manager_startup();
@@ -253,7 +251,6 @@
purple_savedstatuses_uninit();
purple_statuses_uninit();
purple_accounts_uninit();
- purple_xfers_uninit();
purple_proxy_uninit();
_purple_image_store_uninit();
purple_network_uninit();
--- a/libpurple/meson.build Thu Apr 11 04:02:16 2024 -0500
+++ b/libpurple/meson.build Thu Apr 11 20:34:07 2024 -0500
@@ -124,7 +124,6 @@
'signals.c',
'status.c',
'util.c',
- 'xfer.c',
'xmlnode.c'
]
@@ -241,7 +240,6 @@
'signals.h',
'status.h',
'util.h',
- 'xfer.h',
'xmlnode.h',
]
@@ -330,7 +328,6 @@
'purpletyping.h',
'roomlist.h',
'status.h',
- 'xfer.h',
'xmlnode.h'
]
--- a/libpurple/plugins/autoaccept/meson.build Thu Apr 11 04:02:16 2024 -0500
+++ b/libpurple/plugins/autoaccept/meson.build Thu Apr 11 20:34:07 2024 -0500
@@ -3,7 +3,9 @@
gnu_symbol_visibility : 'hidden',
dependencies : [libpurple_dep, glib],
name_prefix : '',
- install : true, install_dir : PURPLE_PLUGINDIR)
+ install : true,
+ install_dir : PURPLE_PLUGINDIR,
+ build_by_default : false)
settings_schemas = [
'im.pidgin.Purple.plugin.AutoAccept.gschema.xml',
--- a/libpurple/server.c Thu Apr 11 04:02:16 2024 -0500
+++ b/libpurple/server.c Thu Apr 11 20:34:07 2024 -0500
@@ -41,7 +41,6 @@
#include "server.h"
#include "status.h"
#include "util.h"
-#include "xfer.h"
unsigned int
purple_serv_send_typing(PurpleConnection *gc, const char *name, PurpleIMTypingState state)
--- a/libpurple/xfer.c Thu Apr 11 04:02:16 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,2608 +0,0 @@
-/*
- * Purple - Internet Messaging Library
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this library; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#include <glib/gi18n-lib.h>
-
-#include "glibcompat.h" /* for purple_g_stat on win32 */
-
-#include <glib/gstdio.h>
-
-#include "debug.h"
-#include "eventloop.h"
-#include "glibcompat.h"
-#include "image-store.h"
-#include "network.h"
-#include "notify.h"
-#include "prefs.h"
-#include "proxy.h"
-#include "purpleconversationmanager.h"
-#include "purpleenums.h"
-#include "purplegio.h"
-#include "request.h"
-#include "server.h"
-#include "util.h"
-#include "xfer.h"
-
-#ifdef _WIN32
-# include "win32/libc_interface.h"
-#endif
-
-#define FT_INITIAL_BUFFER_SIZE 4096
-#define FT_MAX_BUFFER_SIZE 65535
-
-typedef struct _PurpleXferPrivate PurpleXferPrivate;
-
-static PurpleXferUiOps *xfer_ui_ops = NULL;
-static GList *xfers;
-
-/* Private data for a file transfer */
-struct _PurpleXferPrivate {
- PurpleXferType type; /* The type of transfer. */
-
- PurpleAccount *account; /* The account. */
-
- char *who; /* The person on the other end of the
- transfer. */
-
- char *message; /* A message sent with the request */
- char *filename; /* The name sent over the network. */
- char *local_filename; /* The name on the local hard drive. */
- goffset size; /* The size of the file. */
-
- FILE *dest_fp; /* The destination file pointer. */
-
- char *remote_ip; /* The remote IP address. */
- guint16 local_port; /* The local port. */
- guint16 remote_port; /* The remote port. */
-
- GSocketConnection *conn; /* The socket connection. */
- int fd; /* The socket file descriptor. */
- int watcher; /* Watcher. */
-
- goffset bytes_sent; /* The number of bytes sent. */
- gint64 start_time; /* When the transfer of data began. */
- gint64 end_time; /* When the transfer of data ended. */
-
- size_t current_buffer_size; /* This gradually increases for fast
- network connections. */
-
- PurpleXferStatus status; /* File Transfer's status. */
-
- gboolean visible; /* Hint the UI that the transfer should
- be visible or not. */
- PurpleXferUiOps *ui_ops; /* UI-specific operations. */
-
- /*
- * Used to moderate the file transfer when either the read/write ui_ops are
- * set or fd is not set. In those cases, the UI/protocol call the respective
- * function, which is somewhat akin to a fd watch being triggered.
- */
- enum {
- PURPLE_XFER_READY_NONE = 0x0,
- PURPLE_XFER_READY_UI = 0x1,
- PURPLE_XFER_READY_PROTOCOL = 0x2,
- } ready;
-
- /* TODO: Should really use a PurpleCircBuffer for this. */
- GByteArray *buffer;
-
- gpointer thumbnail_data; /* thumbnail image */
- gsize thumbnail_size;
- gchar *thumbnail_mimetype;
-};
-
-/* GObject property enums */
-enum
-{
- PROP_0,
- PROP_TYPE,
- PROP_ACCOUNT,
- PROP_REMOTE_USER,
- PROP_MESSAGE,
- PROP_FILENAME,
- PROP_LOCAL_FILENAME,
- PROP_FILE_SIZE,
- PROP_REMOTE_IP,
- PROP_LOCAL_PORT,
- PROP_REMOTE_PORT,
- PROP_FD,
- PROP_WATCHER,
- PROP_BYTES_SENT,
- PROP_START_TIME,
- PROP_END_TIME,
- PROP_STATUS,
- PROP_PROGRESS,
- PROP_VISIBLE,
- N_PROPERTIES,
-};
-
-static GParamSpec *properties[N_PROPERTIES] = {NULL, };
-
-/* GObject signal enums */
-enum
-{
- SIG_OPEN_LOCAL,
- SIG_QUERY_LOCAL,
- SIG_READ_LOCAL,
- SIG_WRITE_LOCAL,
- SIG_DATA_NOT_SENT,
- SIG_ADD_THUMBNAIL,
- N_SIGNALS,
-};
-static guint signals[N_SIGNALS] = {0, };
-
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleXfer, purple_xfer, G_TYPE_OBJECT);
-
-static void purple_xfer_choose_file(PurpleXfer *xfer);
-
-static const gchar *
-purple_xfer_status_type_to_string(PurpleXferStatus type)
-{
- static const struct {
- PurpleXferStatus type;
- const char *name;
- } type_names[] = {
- { PURPLE_XFER_STATUS_UNKNOWN, "unknown" },
- { PURPLE_XFER_STATUS_NOT_STARTED, "not started" },
- { PURPLE_XFER_STATUS_ACCEPTED, "accepted" },
- { PURPLE_XFER_STATUS_STARTED, "started" },
- { PURPLE_XFER_STATUS_DONE, "done" },
- { PURPLE_XFER_STATUS_CANCEL_LOCAL, "cancelled locally" },
- { PURPLE_XFER_STATUS_CANCEL_REMOTE, "cancelled remotely" }
- };
- gsize i;
-
- for (i = 0; i < G_N_ELEMENTS(type_names); ++i)
- if (type_names[i].type == type)
- return type_names[i].name;
-
- return "invalid state";
-}
-
-void
-purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatus status)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (purple_debug_is_verbose())
- purple_debug_info("xfer", "Changing status of xfer %p from %s to %s\n",
- xfer, purple_xfer_status_type_to_string(priv->status),
- purple_xfer_status_type_to_string(status));
-
- if (priv->status == status)
- return;
-
- priv->status = status;
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_STATUS]);
-}
-
-void
-purple_xfer_set_visible(PurpleXfer *xfer, gboolean visible)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- priv->visible = visible;
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_VISIBLE]);
-}
-
-static void
-purple_xfer_conversation_write_internal(PurpleXfer *xfer,
- const char *message, gboolean is_error, gboolean print_thumbnail)
-{
- PurpleConversation *im = NULL;
- PurpleConversationManager *manager = NULL;
- PurpleMessageFlags flags = PURPLE_MESSAGE_SYSTEM;
- char *escaped;
- gconstpointer thumbnail_data;
- gsize size;
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- thumbnail_data = purple_xfer_get_thumbnail(xfer, &size);
-
- manager = purple_conversation_manager_get_default();
- im = purple_conversation_manager_find_im(manager,
- purple_xfer_get_account(xfer),
- priv->who);
- if(PURPLE_IS_IM_CONVERSATION(im)) {
- return;
- }
-
- escaped = g_markup_escape_text(message, -1);
-
- if (is_error)
- flags |= PURPLE_MESSAGE_ERROR;
-
- if (print_thumbnail && thumbnail_data) {
- gchar *message_with_img;
- PurpleImage *img;
- guint id;
-
- img = purple_image_new_from_data(thumbnail_data, size);
- id = purple_image_store_add(img);
- g_object_unref(img);
-
- message_with_img = g_strdup_printf("<img src=\""
- PURPLE_IMAGE_STORE_PROTOCOL "%u\"> %s", id, escaped);
- purple_conversation_write_system_message(
- im, message_with_img, flags);
- g_free(message_with_img);
- } else {
- purple_conversation_write_system_message(
- im, escaped, flags);
- }
- g_free(escaped);
-}
-
-void
-purple_xfer_conversation_write(PurpleXfer *xfer, const gchar *message,
- gboolean is_error)
-{
- g_return_if_fail(PURPLE_IS_XFER(xfer));
- g_return_if_fail(message != NULL);
-
- purple_xfer_conversation_write_internal(xfer, message, is_error, FALSE);
-}
-
-/* maybe this one should be exported publicly? */
-static void
-purple_xfer_conversation_write_with_thumbnail(PurpleXfer *xfer,
- const gchar *message)
-{
- purple_xfer_conversation_write_internal(xfer, message, FALSE, TRUE);
-}
-
-
-static void purple_xfer_show_file_error(PurpleXfer *xfer, const char *filename)
-{
- int err = errno;
- gchar *msg = NULL, *utf8;
- PurpleXferType xfer_type = purple_xfer_get_xfer_type(xfer);
- PurpleAccount *account = purple_xfer_get_account(xfer);
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
- switch(xfer_type) {
- case PURPLE_XFER_TYPE_SEND:
- msg = g_strdup_printf(_("Error reading %s: \n%s.\n"),
- utf8, g_strerror(err));
- break;
- case PURPLE_XFER_TYPE_RECEIVE:
- msg = g_strdup_printf(_("Error writing %s: \n%s.\n"),
- utf8, g_strerror(err));
- break;
- default:
- msg = g_strdup_printf(_("Error accessing %s: \n%s.\n"),
- utf8, g_strerror(err));
- break;
- }
- g_free(utf8);
-
- purple_xfer_conversation_write(xfer, msg, TRUE);
- purple_xfer_error(xfer_type, account, priv->who, msg);
- g_free(msg);
-}
-
-static void
-purple_xfer_choose_file_ok_cb(void *user_data, const char *filename)
-{
- PurpleXfer *xfer;
- PurpleXferType type;
- GStatBuf st;
- gchar *dir;
-
- xfer = (PurpleXfer *)user_data;
- type = purple_xfer_get_xfer_type(xfer);
-
- if (g_stat(filename, &st) != 0) {
- /* File not found. */
- if (type == PURPLE_XFER_TYPE_RECEIVE) {
-#ifndef _WIN32
- int mode = W_OK;
-#else
- int mode = F_OK;
-#endif
- dir = g_path_get_dirname(filename);
-
- if (g_access(dir, mode) == 0) {
- purple_xfer_request_accepted(xfer, filename);
- } else {
- g_object_ref(xfer);
- purple_notify_message(
- NULL, PURPLE_NOTIFY_MSG_ERROR, NULL,
- _("Directory is not writable."), NULL,
- purple_request_cpar_from_account(
- purple_xfer_get_account(xfer)),
- (PurpleNotifyCloseCallback)purple_xfer_choose_file, xfer);
- }
-
- g_free(dir);
- }
- else {
- purple_xfer_show_file_error(xfer, filename);
- purple_xfer_cancel_local(xfer);
- }
- }
- else if ((type == PURPLE_XFER_TYPE_SEND) && (st.st_size == 0)) {
-
- purple_notify_error(NULL, NULL,
- _("Cannot send a file of 0 bytes."), NULL,
- purple_request_cpar_from_account(
- purple_xfer_get_account(xfer)));
-
- purple_xfer_cancel_local(xfer);
- }
- else if ((type == PURPLE_XFER_TYPE_SEND) && S_ISDIR(st.st_mode)) {
- /*
- * XXX - Sending a directory should be valid for some protocols.
- */
- purple_notify_error(NULL, NULL, _("Cannot send a directory."),
- NULL, purple_request_cpar_from_account(
- purple_xfer_get_account(xfer)));
-
- purple_xfer_cancel_local(xfer);
- }
- else if ((type == PURPLE_XFER_TYPE_RECEIVE) && S_ISDIR(st.st_mode)) {
- char *msg, *utf8;
- utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL);
- msg = g_strdup_printf(
- _("%s is not a regular file. Cowardly refusing to overwrite it.\n"), utf8);
- g_free(utf8);
- purple_notify_error(NULL, NULL, msg, NULL,
- purple_request_cpar_from_account(
- purple_xfer_get_account(xfer)));
- g_free(msg);
- purple_xfer_request_denied(xfer);
- }
- else if (type == PURPLE_XFER_TYPE_SEND) {
-#ifndef _WIN32
- int mode = R_OK;
-#else
- int mode = F_OK;
-#endif
-
- if (g_access(filename, mode) == 0) {
- purple_xfer_request_accepted(xfer, filename);
- } else {
- g_object_ref(xfer);
- purple_notify_message(
- NULL, PURPLE_NOTIFY_MSG_ERROR, NULL,
- _("File is not readable."), NULL,
- purple_request_cpar_from_account(
- purple_xfer_get_account(xfer)),
- (PurpleNotifyCloseCallback)purple_xfer_choose_file, xfer);
- }
- }
- else {
- purple_xfer_request_accepted(xfer, filename);
- }
-
- g_object_unref(xfer);
-}
-
-static void
-purple_xfer_choose_file_cancel_cb(void *user_data,
- G_GNUC_UNUSED const char *filename)
-{
- PurpleXfer *xfer = (PurpleXfer *)user_data;
-
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
- if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND)
- purple_xfer_cancel_local(xfer);
- else
- purple_xfer_request_denied(xfer);
- g_object_unref(xfer);
-}
-
-static void
-purple_xfer_choose_file(PurpleXfer *xfer)
-{
- purple_request_file(xfer, NULL, purple_xfer_get_filename(xfer),
- (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE),
- G_CALLBACK(purple_xfer_choose_file_ok_cb),
- G_CALLBACK(purple_xfer_choose_file_cancel_cb),
- purple_request_cpar_from_account(purple_xfer_get_account(xfer)),
- xfer);
-}
-
-static int
-cancel_recv_cb(PurpleXfer *xfer)
-{
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
- purple_xfer_request_denied(xfer);
- g_object_unref(xfer);
-
- return 0;
-}
-
-static void
-purple_xfer_ask_recv(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
- char *buf, *size_buf;
- goffset size;
- gconstpointer thumb;
- gsize thumb_size;
-
- /* If we have already accepted the request, ask the destination file
- name directly */
- if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_ACCEPTED) {
- PurpleRequestCommonParameters *cpar;
- PurpleBuddy *buddy = purple_blist_find_buddy(priv->account, priv->who);
-
- if (purple_xfer_get_filename(xfer) != NULL)
- {
- size = purple_xfer_get_size(xfer);
- size_buf = g_format_size_full(size, G_FORMAT_SIZE_LONG_FORMAT);
- buf = g_strdup_printf(_("%s wants to send you %s (%s)"),
- buddy ? purple_buddy_get_alias(buddy) : priv->who,
- purple_xfer_get_filename(xfer), size_buf);
- g_free(size_buf);
- }
- else
- {
- buf = g_strdup_printf(_("%s wants to send you a file"),
- buddy ? purple_buddy_get_alias(buddy) : priv->who);
- }
-
- if (priv->message != NULL)
- purple_serv_got_im(purple_account_get_connection(priv->account),
- priv->who, priv->message, 0, time(NULL));
-
- cpar = purple_request_cpar_from_account(priv->account);
- if ((thumb = purple_xfer_get_thumbnail(xfer, &thumb_size))) {
- purple_request_cpar_set_custom_icon(cpar, thumb,
- thumb_size);
- }
-
- purple_request_accept_cancel(xfer, NULL, buf, NULL,
- PURPLE_DEFAULT_ACTION_NONE, cpar, xfer,
- G_CALLBACK(purple_xfer_choose_file),
- G_CALLBACK(cancel_recv_cb));
-
- g_free(buf);
- } else
- purple_xfer_choose_file(xfer);
-}
-
-static int
-ask_accept_ok(PurpleXfer *xfer)
-{
- purple_xfer_request_accepted(xfer, NULL);
-
- return 0;
-}
-
-static int
-ask_accept_cancel(PurpleXfer *xfer)
-{
- purple_xfer_request_denied(xfer);
- g_object_unref(xfer);
-
- return 0;
-}
-
-static void
-purple_xfer_ask_accept(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
- char *buf, *buf2 = NULL;
- PurpleBuddy *buddy = purple_blist_find_buddy(priv->account, priv->who);
-
- buf = g_strdup_printf(_("Accept file transfer request from %s?"),
- buddy ? purple_buddy_get_alias(buddy) : priv->who);
- if (purple_xfer_get_remote_ip(xfer) &&
- purple_xfer_get_remote_port(xfer))
- buf2 = g_strdup_printf(_("A file is available for download from:\n"
- "Remote host: %s\nRemote port: %d"),
- purple_xfer_get_remote_ip(xfer),
- purple_xfer_get_remote_port(xfer));
- purple_request_accept_cancel(xfer, NULL, buf, buf2,
- PURPLE_DEFAULT_ACTION_NONE,
- purple_request_cpar_from_account(priv->account), xfer,
- G_CALLBACK(ask_accept_ok), G_CALLBACK(ask_accept_cancel));
- g_free(buf);
- g_free(buf2);
-}
-
-void
-purple_xfer_request(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- /* this is unref'd in the finishers, like cancel and stop */
- g_object_ref(xfer);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (priv->type == PURPLE_XFER_TYPE_RECEIVE)
- {
- purple_signal_emit(purple_xfers_get_handle(), "file-recv-request", xfer);
- if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
- {
- /* The file-transfer was cancelled by a plugin */
- purple_xfer_cancel_local(xfer);
- }
- else if (priv->filename || priv->status == PURPLE_XFER_STATUS_ACCEPTED)
- {
- gchar* message = NULL;
- PurpleBuddy *buddy = purple_blist_find_buddy(priv->account, priv->who);
-
- message = g_strdup_printf(_("%s is offering to send file %s"),
- buddy ? purple_buddy_get_alias(buddy) : priv->who, purple_xfer_get_filename(xfer));
- purple_xfer_conversation_write_with_thumbnail(xfer, message);
- g_free(message);
-
- /* Ask for a filename to save to if it's not already given by a plugin */
- if (priv->local_filename == NULL)
- purple_xfer_ask_recv(xfer);
- }
- else
- {
- purple_xfer_ask_accept(xfer);
- }
- }
- else
- {
- purple_xfer_choose_file(xfer);
- }
-}
-
-static gboolean
-do_query_local(PurpleXfer *xfer, const gchar *filename)
-{
- GStatBuf st;
-
- if (g_stat(filename, &st) == -1) {
- purple_xfer_show_file_error(xfer, filename);
- return FALSE;
- }
-
- purple_xfer_set_size(xfer, st.st_size);
- return TRUE;
-}
-
-void
-purple_xfer_request_accepted(PurpleXfer *xfer, const gchar *filename)
-{
- PurpleXferClass *klass = NULL;
- PurpleXferPrivate *priv = NULL;
- gchar *msg, *utf8, *base;
- PurpleBuddy *buddy;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
- priv = purple_xfer_get_instance_private(xfer);
-
- purple_debug_misc("xfer", "request accepted for %p\n", xfer);
-
- if(filename == NULL) {
- if(priv->type == PURPLE_XFER_TYPE_RECEIVE) {
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_ACCEPTED);
- klass->init(xfer);
- } else {
- purple_debug_warning(
- "xfer",
- "can not set file transfer without a file name"
- );
- }
-
- return;
- }
-
- buddy = purple_blist_find_buddy(priv->account, priv->who);
-
- if (priv->type == PURPLE_XFER_TYPE_SEND) {
- /* Sending a file */
- /* Check the filename. */
- gboolean query_status;
-
-#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(priv->type, priv->account, priv->who, msg);
- g_free(utf8);
- g_free(msg);
-
- g_object_unref(xfer);
- return;
- }
-
- g_signal_emit(xfer, signals[SIG_QUERY_LOCAL], 0, filename,
- &query_status);
- if (!query_status) {
- g_object_unref(xfer);
- return;
- }
- 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) : priv->who);
- g_free(utf8);
- purple_xfer_conversation_write(xfer, msg, FALSE);
- g_free(msg);
- }
- else {
- /* Receiving a file */
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_ACCEPTED);
- purple_xfer_set_local_filename(xfer, filename);
-
- msg = g_strdup_printf(_("Starting transfer of %s from %s"),
- priv->filename, buddy ? purple_buddy_get_alias(buddy) : priv->who);
- purple_xfer_conversation_write(xfer, msg, FALSE);
- g_free(msg);
- }
-
- purple_xfer_set_visible(xfer, TRUE);
-
- klass->init(xfer);
-}
-
-void
-purple_xfer_request_denied(PurpleXfer *xfer)
-{
- PurpleXferClass *klass = NULL;
-
- g_return_if_fail(PURPLE_XFER(xfer));
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
-
- purple_debug_misc("xfer", "xfer %p denied\n", xfer);
-
- if(klass && klass->request_denied) {
- klass->request_denied(xfer);
- }
-
- g_object_unref(xfer);
-}
-
-int purple_xfer_get_fd(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->fd;
-}
-
-int purple_xfer_get_watcher(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->watcher;
-}
-
-PurpleXferType
-purple_xfer_get_xfer_type(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), PURPLE_XFER_TYPE_UNKNOWN);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->type;
-}
-
-PurpleAccount *
-purple_xfer_get_account(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->account;
-}
-
-void
-purple_xfer_set_remote_user(PurpleXfer *xfer, const char *who)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- g_free(priv->who);
- priv->who = g_strdup(who);
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_REMOTE_USER]);
-}
-
-const char *
-purple_xfer_get_remote_user(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->who;
-}
-
-PurpleXferStatus
-purple_xfer_get_status(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), PURPLE_XFER_STATUS_UNKNOWN);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->status;
-}
-
-gboolean
-purple_xfer_get_visible(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), FALSE);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->visible;
-}
-
-gboolean
-purple_xfer_is_cancelled(PurpleXfer *xfer)
-{
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), TRUE);
-
- if ((purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) ||
- (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_REMOTE))
- return TRUE;
- else
- return FALSE;
-}
-
-gboolean
-purple_xfer_is_completed(PurpleXfer *xfer)
-{
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), TRUE);
-
- return (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_DONE);
-}
-
-const char *
-purple_xfer_get_filename(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->filename;
-}
-
-const char *
-purple_xfer_get_local_filename(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->local_filename;
-}
-
-goffset
-purple_xfer_get_bytes_sent(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->bytes_sent;
-}
-
-goffset
-purple_xfer_get_bytes_remaining(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->size - priv->bytes_sent;
-}
-
-goffset
-purple_xfer_get_size(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->size;
-}
-
-double
-purple_xfer_get_progress(PurpleXfer *xfer)
-{
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0.0);
-
- if (purple_xfer_get_size(xfer) == 0)
- return 0.0;
-
- return ((double)purple_xfer_get_bytes_sent(xfer) /
- (double)purple_xfer_get_size(xfer));
-}
-
-guint16
-purple_xfer_get_local_port(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), -1);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->local_port;
-}
-
-const char *
-purple_xfer_get_remote_ip(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->remote_ip;
-}
-
-guint16
-purple_xfer_get_remote_port(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), -1);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->remote_port;
-}
-
-gint64
-purple_xfer_get_start_time(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->start_time;
-}
-
-gint64
-purple_xfer_get_end_time(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->end_time;
-}
-
-void purple_xfer_set_fd(PurpleXfer *xfer, int fd)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- priv->fd = fd;
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_FD]);
-}
-
-void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- priv->watcher = watcher;
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_WATCHER]);
-}
-
-void
-purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (completed == TRUE) {
- char *msg = NULL;
- PurpleConversation *im;
- PurpleConversationManager *manager;
-
- 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_xfer_type(xfer) == PURPLE_XFER_TYPE_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"));
- }
-
- manager = purple_conversation_manager_get_default();
- im = purple_conversation_manager_find_im(manager, priv->account,
- priv->who);
- if(PURPLE_IS_IM_CONVERSATION(im)) {
- purple_conversation_write_system_message(im, msg, 0);
- }
- g_free(msg);
- }
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_PROGRESS]);
-}
-
-void
-purple_xfer_set_message(PurpleXfer *xfer, const char *message)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (message != priv->message) {
- g_free(priv->message);
- priv->message = g_strdup(message);
- }
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_MESSAGE]);
-}
-
-const char *
-purple_xfer_get_message(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->message;
-}
-
-void
-purple_xfer_set_filename(PurpleXfer *xfer, const char *filename)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (filename != priv->filename) {
- g_free(priv->filename);
- priv->filename = g_strdup(filename);
- }
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_FILENAME]);
-}
-
-void
-purple_xfer_set_local_filename(PurpleXfer *xfer, const char *filename)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (filename != priv->local_filename) {
- g_free(priv->local_filename);
- priv->local_filename = g_strdup(filename);
- }
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_LOCAL_FILENAME]);
-}
-
-void
-purple_xfer_set_size(PurpleXfer *xfer, goffset size)
-{
- PurpleXferPrivate *priv = NULL;
- GObject *obj;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- priv->size = size;
-
- obj = G_OBJECT(xfer);
- g_object_freeze_notify(obj);
- g_object_notify_by_pspec(obj, properties[PROP_FILE_SIZE]);
- g_object_notify_by_pspec(obj, properties[PROP_PROGRESS]);
- g_object_thaw_notify(obj);
-}
-
-void
-purple_xfer_set_local_port(PurpleXfer *xfer, guint16 local_port)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- priv->local_port = local_port;
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_LOCAL_PORT]);
-}
-
-void
-purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent)
-{
- PurpleXferPrivate *priv = NULL;
- GObject *obj;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
- priv->bytes_sent = bytes_sent;
-
- obj = G_OBJECT(xfer);
- g_object_freeze_notify(obj);
- g_object_notify_by_pspec(obj, properties[PROP_BYTES_SENT]);
- g_object_notify_by_pspec(obj, properties[PROP_PROGRESS]);
- g_object_thaw_notify(obj);
-}
-
-PurpleXferUiOps *
-purple_xfer_get_ui_ops(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
- return priv->ui_ops;
-}
-
-static void
-purple_xfer_increase_buffer_size(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- priv->current_buffer_size = MIN(priv->current_buffer_size * 1.5,
- FT_MAX_BUFFER_SIZE);
-}
-
-static gssize
-do_read(PurpleXfer *xfer, guchar **buffer, gsize size)
-{
- PurpleXferPrivate *priv = NULL;
- gssize r;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
- g_return_val_if_fail(buffer != NULL, 0);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- *buffer = g_malloc0(size);
-
- r = read(priv->fd, *buffer, size);
- if (r < 0 && errno == EAGAIN) {
- r = 0;
- } else if (r < 0) {
- r = -1;
- } else if (r == 0) {
- r = -1;
- }
-
- return r;
-}
-
-gssize
-purple_xfer_read(PurpleXfer *xfer, guchar **buffer)
-{
- PurpleXferPrivate *priv = NULL;
- PurpleXferClass *klass = NULL;
- gsize s;
- gssize r;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
- g_return_val_if_fail(buffer != NULL, 0);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (purple_xfer_get_size(xfer) == 0) {
- s = priv->current_buffer_size;
- } else {
- s = MIN(
- (gssize)purple_xfer_get_bytes_remaining(xfer),
- (gssize)priv->current_buffer_size
- );
- }
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
- if(klass && klass->read) {
- r = klass->read(xfer, buffer, s);
- } else {
- r = do_read(xfer, buffer, s);
- }
-
- if (r >= 0 && (gsize)r == priv->current_buffer_size) {
- /*
- * We managed to read 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);
- }
-
- return r;
-}
-
-static gssize
-do_write(PurpleXfer *xfer, const guchar *buffer, gsize size)
-{
- PurpleXferPrivate *priv = NULL;
- gssize r;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
- g_return_val_if_fail(buffer != NULL, 0);
- g_return_val_if_fail(size != 0, 0);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- r = write(priv->fd, buffer, size);
- if (r < 0 && errno == EAGAIN)
- r = 0;
-
- return r;
-}
-
-gssize
-purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size)
-{
- PurpleXferClass *klass = NULL;
- gssize s;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
-
- s = MIN(
- (gssize)purple_xfer_get_bytes_remaining(xfer),
- (gssize)size
- );
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
- if(klass && klass->write) {
- return klass->write(xfer, buffer, s);
- }
-
- return do_write(xfer, buffer, s);
-}
-
-static gssize
-do_write_local(PurpleXfer *xfer, const guchar *buffer, gssize size)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- if (priv->dest_fp == NULL) {
- purple_debug_error("xfer", "File is not opened for writing");
- return -1;
- }
-
- return fwrite(buffer, 1, size, priv->dest_fp);
-}
-
-gboolean
-purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size)
-{
- PurpleXferPrivate *priv = NULL;
- gsize wc;
- goffset remaining;
- gboolean fs_known;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), FALSE);
- g_return_val_if_fail(buffer != NULL, FALSE);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- fs_known = (priv->size > 0);
-
- remaining = purple_xfer_get_bytes_remaining(xfer);
- if (fs_known && (goffset)size > remaining) {
- purple_debug_warning("xfer",
- "Got too much data (truncating at %" G_GOFFSET_FORMAT
- ").\n", purple_xfer_get_size(xfer));
- size = remaining;
- }
-
- g_signal_emit(xfer, signals[SIG_WRITE_LOCAL], 0, buffer, size, &wc);
-
- if (wc != size) {
- purple_debug_error("xfer",
- "Unable to write whole buffer.\n");
- purple_xfer_cancel_local(xfer);
- return FALSE;
- }
-
- purple_xfer_set_bytes_sent(
- xfer,
- purple_xfer_get_bytes_sent(xfer) + size
- );
-
- return TRUE;
-}
-
-static gssize
-do_read_local(PurpleXfer *xfer, guchar *buffer, gssize size)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
- gssize got_len;
-
- if (priv->dest_fp == NULL) {
- purple_debug_error("xfer", "File is not opened for reading");
- return -1;
- }
-
- got_len = fread(buffer, 1, size, priv->dest_fp);
- if ((got_len < 0 || got_len != size) && ferror(priv->dest_fp)) {
- purple_debug_error("xfer", "Unable to read file.");
- return -1;
- }
-
- return got_len;
-}
-
-gssize
-purple_xfer_read_file(PurpleXfer *xfer, guchar *buffer, gsize size)
-{
- gssize got_len;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), 0);
- g_return_val_if_fail(buffer != NULL, 0);
-
- g_signal_emit(xfer, signals[SIG_READ_LOCAL], 0, buffer, size, &got_len);
- if (got_len < 0 || (gsize)got_len > size) {
- purple_debug_error("xfer", "Unable to read file.");
- purple_xfer_cancel_local(xfer);
- return -1;
- }
-
- if (got_len > 0) {
- purple_xfer_set_bytes_sent(xfer,
- purple_xfer_get_bytes_sent(xfer) + got_len);
- }
-
- return got_len;
-}
-
-static gboolean
-do_data_not_sent(PurpleXfer *xfer, const guchar *buffer, gsize size)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- if (priv->buffer == NULL) {
- priv->buffer = g_byte_array_sized_new(FT_INITIAL_BUFFER_SIZE);
- g_byte_array_append(priv->buffer, buffer, size);
- }
-
- return TRUE;
-}
-
-static void
-do_transfer(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
- guchar *buffer = NULL;
- gssize r = 0;
-
- if (priv->type == PURPLE_XFER_TYPE_RECEIVE) {
- r = purple_xfer_read(xfer, &buffer);
- if (r > 0) {
- if (!purple_xfer_write_file(xfer, buffer, r)) {
- g_free(buffer);
- return;
- }
-
- } else if(r < 0) {
- purple_xfer_cancel_remote(xfer);
- g_free(buffer);
- return;
- }
- } else if (priv->type == PURPLE_XFER_TYPE_SEND) {
- gssize result = 0;
- gsize s = MIN(
- (gsize)purple_xfer_get_bytes_remaining(xfer),
- (gsize)priv->current_buffer_size
- );
- gboolean read_more = TRUE;
- gboolean existing_buffer = FALSE;
-
- /* this is so the protocol can keep the connection open
- if it needs to for some odd reason. */
- if (s == 0) {
- if (priv->watcher) {
- g_source_remove(priv->watcher);
- purple_xfer_set_watcher(xfer, 0);
- }
- return;
- }
-
- if (priv->buffer) {
- existing_buffer = TRUE;
- if (priv->buffer->len < s) {
- s -= priv->buffer->len;
- read_more = TRUE;
- } else {
- read_more = FALSE;
- }
- }
-
- if (read_more) {
- buffer = g_new(guchar, s);
- result = purple_xfer_read_file(xfer, buffer, s);
- if (result == 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 (priv->watcher != 0) {
- g_source_remove(priv->watcher);
- purple_xfer_set_watcher(xfer, 0);
- }
-
- /* Need to indicate the protocol is still ready... */
- priv->ready |= PURPLE_XFER_READY_PROTOCOL;
-
- g_free(buffer);
- g_return_if_reached();
- }
- if (result < 0) {
- 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 = do_write(xfer, buffer, result);
-
- if (r == -1) {
- purple_debug_error("xfer", "do_write failed! %s\n", g_strerror(errno));
- 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 {
- gboolean handler_result = FALSE;
- g_signal_emit(xfer, signals[SIG_DATA_NOT_SENT], 0, buffer + r,
- result - r, &handler_result);
- if (!handler_result) {
- purple_xfer_cancel_local(xfer);
- }
- }
-
- if (existing_buffer && 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) {
- PurpleXferClass *klass = PURPLE_XFER_GET_CLASS(xfer);
-
- if (klass && klass->ack)
- klass->ack(xfer, buffer, r);
- }
-
- g_free(buffer);
-
- if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer) &&
- !purple_xfer_is_completed(xfer)) {
- purple_xfer_set_completed(xfer, TRUE);
- }
-
- /* TODO: Check if above is the only place xfers are marked completed.
- * If so, merge these conditions.
- */
- if (purple_xfer_is_completed(xfer)) {
- purple_xfer_end(xfer);
- }
-}
-
-static void
-transfer_cb(gpointer data, G_GNUC_UNUSED gint source,
- G_GNUC_UNUSED PurpleInputCondition condition)
-{
- PurpleXfer *xfer = data;
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- if (priv->dest_fp == NULL) {
- /* The UI is moderating its side manually */
- if (0 == (priv->ready & PURPLE_XFER_READY_UI)) {
- priv->ready |= PURPLE_XFER_READY_PROTOCOL;
-
- g_source_remove(priv->watcher);
- purple_xfer_set_watcher(xfer, 0);
-
- purple_debug_misc("xfer", "Protocol is ready on ft %p, waiting for UI\n", xfer);
- return;
- }
-
- priv->ready = PURPLE_XFER_READY_NONE;
- }
-
- do_transfer(xfer);
-}
-
-static gboolean
-do_open_local(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- priv->dest_fp =
- g_fopen(purple_xfer_get_local_filename(xfer),
- priv->type == PURPLE_XFER_TYPE_RECEIVE ? "wb" : "rb");
-
- if (priv->dest_fp == NULL) {
- purple_xfer_show_file_error(xfer, purple_xfer_get_local_filename(xfer));
- return FALSE;
- }
-
- if (fseek(priv->dest_fp, priv->bytes_sent, SEEK_SET) != 0) {
- purple_debug_error("xfer", "couldn't seek");
- purple_xfer_show_file_error(xfer, purple_xfer_get_local_filename(xfer));
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-begin_transfer(PurpleXfer *xfer, PurpleInputCondition cond)
-{
- PurpleXferClass *klass = PURPLE_XFER_GET_CLASS(xfer);
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
- gboolean open_status = FALSE;
-
- if (priv->start_time != 0) {
- purple_debug_error("xfer", "Transfer is being started multiple times\n");
- g_return_if_reached();
- }
-
- g_signal_emit(xfer, signals[SIG_OPEN_LOCAL], 0, &open_status);
- if (!open_status) {
- purple_xfer_cancel_local(xfer);
- }
-
- if (priv->fd != -1) {
- purple_xfer_set_watcher(
- xfer,
- purple_input_add(priv->fd, cond, transfer_cb, xfer)
- );
- }
-
- priv->start_time = g_get_monotonic_time();
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_START_TIME]);
-
- if (klass && klass->start) {
- klass->start(xfer);
- }
-}
-
-static void
-connect_cb(GObject *source, GAsyncResult *result, gpointer user_data)
-{
- PurpleXfer *xfer = PURPLE_XFER(user_data);
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
- GSocket *socket;
- GError *error = NULL;
-
- priv->conn = g_socket_client_connect_to_host_finish(G_SOCKET_CLIENT(source),
- result, &error);
- if (priv->conn == NULL) {
- purple_debug_error("xfer", "Unable to connect to destination host: %s",
- error ? error->message : "unknown error");
- purple_xfer_cancel_local(xfer);
- g_clear_error(&error);
- return;
- }
-
- socket = g_socket_connection_get_socket(priv->conn);
- purple_xfer_set_fd(xfer, g_socket_get_fd(socket));
- begin_transfer(xfer, PURPLE_INPUT_READ);
-}
-
-void
-purple_xfer_ui_ready(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
- PurpleInputCondition cond = 0;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- priv->ready |= PURPLE_XFER_READY_UI;
-
- if (0 == (priv->ready & PURPLE_XFER_READY_PROTOCOL)) {
- purple_debug_misc("xfer", "UI is ready on ft %p, waiting for protocol\n", xfer);
- return;
- }
-
- purple_debug_misc("xfer", "UI (and protocol) ready on ft %p, so proceeding\n", xfer);
-
- if (priv->type == PURPLE_XFER_TYPE_SEND) {
- cond = PURPLE_INPUT_WRITE;
- } else if (priv->type == PURPLE_XFER_TYPE_RECEIVE) {
- cond = PURPLE_INPUT_READ;
- }
-
- if (priv->watcher == 0 && priv->fd != -1) {
- purple_xfer_set_watcher(
- xfer,
- purple_input_add(priv->fd, cond, transfer_cb, xfer)
- );
- }
-
- priv->ready = PURPLE_XFER_READY_NONE;
-
- do_transfer(xfer);
-}
-
-void
-purple_xfer_protocol_ready(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- priv->ready |= PURPLE_XFER_READY_PROTOCOL;
-
- /* I don't think fwrite/fread are ever *not* ready */
- if (priv->dest_fp == NULL && 0 == (priv->ready & PURPLE_XFER_READY_UI)) {
- purple_debug_misc("xfer", "Protocol is ready on ft %p, waiting for UI\n", xfer);
- return;
- }
-
- purple_debug_misc("xfer", "Protocol (and UI) ready on ft %p, so proceeding\n", xfer);
-
- priv->ready = PURPLE_XFER_READY_NONE;
-
- do_transfer(xfer);
-}
-
-void
-purple_xfer_start(PurpleXfer *xfer, int fd, const char *ip, guint16 port)
-{
- PurpleXferPrivate *priv = NULL;
- PurpleInputCondition cond;
- GObject *obj;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_STARTED);
-
- if (priv->type == PURPLE_XFER_TYPE_RECEIVE) {
- cond = PURPLE_INPUT_READ;
-
- if (ip != NULL) {
- GSocketClient *client;
- GError *error = NULL;
-
- priv->remote_ip = g_strdup(ip);
- priv->remote_port = port;
-
- obj = G_OBJECT(xfer);
- g_object_freeze_notify(obj);
- g_object_notify_by_pspec(obj, properties[PROP_REMOTE_IP]);
- g_object_notify_by_pspec(obj, properties[PROP_REMOTE_PORT]);
- g_object_thaw_notify(obj);
-
- client = purple_gio_socket_client_new(priv->account, &error);
- if (client == NULL) {
- /* Assume it's a proxy error */
- purple_notify_error(
- NULL, NULL, _("Invalid proxy settings"), error->message,
- purple_request_cpar_from_account(priv->account));
- g_clear_error(&error);
- return;
- }
-
- purple_debug_info("xfer", "Attempting connection to %s:%u\n", ip,
- port);
-
- g_socket_client_connect_to_host_async(client, ip, port, NULL,
- connect_cb, xfer);
- g_object_unref(client);
-
- return;
- } else {
- purple_xfer_set_fd(xfer, fd);
- }
- } else {
- cond = PURPLE_INPUT_WRITE;
-
- purple_xfer_set_fd(xfer, fd);
- }
-
- begin_transfer(xfer, cond);
-}
-
-void
-purple_xfer_end(PurpleXfer *xfer)
-{
- PurpleXferClass *klass = NULL;
- PurpleXferPrivate *priv = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
- priv = purple_xfer_get_instance_private(xfer);
-
- /* See if we are actually trying to cancel this. */
- if (!purple_xfer_is_completed(xfer)) {
- purple_xfer_cancel_local(xfer);
- return;
- }
-
- priv->end_time = g_get_monotonic_time();
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_END_TIME]);
-
- if (klass && klass->end != NULL) {
- klass->end(xfer);
- }
-
- if (priv->watcher != 0) {
- g_source_remove(priv->watcher);
- purple_xfer_set_watcher(xfer, 0);
- }
-
- if (priv->fd != -1) {
- if (close(priv->fd)) {
- purple_debug_error("xfer", "closing file descr in purple_xfer_end() failed: %s",
- g_strerror(errno));
- }
- }
-
- if (priv->dest_fp != NULL) {
- if (fclose(priv->dest_fp)) {
- purple_debug_error("xfer", "closing dest file in purple_xfer_end() failed: %s",
- g_strerror(errno));
- }
- priv->dest_fp = NULL;
- }
-
- g_object_unref(xfer);
-}
-
-void
-purple_xfer_cancel_local(PurpleXfer *xfer)
-{
- PurpleXferClass *klass = NULL;
- PurpleXferPrivate *priv = NULL;
- char *msg = NULL;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
- priv = purple_xfer_get_instance_private(xfer);
-
- /* TODO: We definitely want to close any open request dialogs associated
- with this transfer. However, in some cases the request dialog might
- own a reference on the xfer. This happens at least with the "%s wants
- to send you %s" dialog from purple_xfer_ask_recv(). In these cases
- the ref count will not be decremented when the request dialog is
- closed, so the ref count will never reach 0 and the xfer will never
- be freed. This is a memleak and should be fixed. It's not clear what
- the correct fix is. Probably requests should have a destroy function
- that is called when the request is destroyed. But also, ref counting
- xfer objects makes this code REALLY complicated. An alternate fix is
- to not ref count and instead just make sure the object still exists
- when we try to use it. */
- purple_request_close_with_handle(xfer);
-
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_LOCAL);
- priv->end_time = g_get_monotonic_time();
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_END_TIME]);
-
- 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 (priv->type == PURPLE_XFER_TYPE_SEND)
- {
- if (klass && klass->cancel_send) {
- klass->cancel_send(xfer);
- }
- } else {
- if (klass && klass->cancel_recv) {
- klass->cancel_recv(xfer);
- }
- }
-
- if (priv->watcher != 0) {
- g_source_remove(priv->watcher);
- purple_xfer_set_watcher(xfer, 0);
- }
-
- if (priv->fd != -1) {
- close(priv->fd);
- }
-
- if (priv->dest_fp != NULL) {
- fclose(priv->dest_fp);
- priv->dest_fp = NULL;
- }
-
- g_object_unref(xfer);
-}
-
-void
-purple_xfer_cancel_remote(PurpleXfer *xfer)
-{
- PurpleXferClass *klass = NULL;
- PurpleXferPrivate *priv = NULL;
- gchar *msg;
- PurpleAccount *account;
- PurpleBuddy *buddy;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- klass = PURPLE_XFER_GET_CLASS(xfer);
- priv = purple_xfer_get_instance_private(xfer);
-
- purple_request_close_with_handle(xfer);
- purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_CANCEL_REMOTE);
- priv->end_time = g_get_monotonic_time();
-
- g_object_notify_by_pspec(G_OBJECT(xfer), properties[PROP_END_TIME]);
-
- account = purple_xfer_get_account(xfer);
- buddy = purple_blist_find_buddy(account, priv->who);
-
- if (purple_xfer_get_filename(xfer) != NULL)
- {
- msg = g_strdup_printf(_("%s cancelled the transfer of %s"),
- buddy ? purple_buddy_get_alias(buddy) : priv->who, purple_xfer_get_filename(xfer));
- }
- else
- {
- msg = g_strdup_printf(_("%s cancelled the file transfer"),
- buddy ? purple_buddy_get_alias(buddy) : priv->who);
- }
- purple_xfer_conversation_write(xfer, msg, TRUE);
- purple_xfer_error(purple_xfer_get_xfer_type(xfer), account, priv->who, msg);
- g_free(msg);
-
- if (priv->type == PURPLE_XFER_TYPE_SEND) {
- if (klass && klass->cancel_send) {
- klass->cancel_send(xfer);
- }
- } else if(priv->type == PURPLE_XFER_TYPE_RECEIVE) {
- if (klass && klass->cancel_recv) {
- klass->cancel_recv(xfer);
- }
- }
-
- if (priv->watcher != 0) {
- g_source_remove(priv->watcher);
- purple_xfer_set_watcher(xfer, 0);
- }
-
- if (priv->fd != -1)
- close(priv->fd);
-
- if (priv->dest_fp != NULL) {
- fclose(priv->dest_fp);
- priv->dest_fp = NULL;
- }
-
- g_object_unref(xfer);
-}
-
-void
-purple_xfer_error(PurpleXferType type, PurpleAccount *account, const gchar *who, const gchar *msg)
-{
- gchar *title = NULL;
-
- g_return_if_fail(msg != NULL);
-
- if (account) {
- PurpleBuddy *buddy;
- buddy = purple_blist_find_buddy(account, who);
- if (buddy)
- who = purple_buddy_get_alias(buddy);
- }
-
- if (type == PURPLE_XFER_TYPE_SEND) {
- title = g_strdup_printf(_("File transfer to %s failed."), who);
- } else if (type == PURPLE_XFER_TYPE_RECEIVE) {
- title = g_strdup_printf(_("File transfer from %s failed."), who);
- }
-
- purple_notify_error(NULL, NULL, title, msg,
- purple_request_cpar_from_account(account));
-
- g_free(title);
-}
-
-gconstpointer
-purple_xfer_get_thumbnail(PurpleXfer *xfer, gsize *len)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- if (len) {
- *len = priv->thumbnail_size;
- }
-
- return priv->thumbnail_data;
-}
-
-const gchar *
-purple_xfer_get_thumbnail_mimetype(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = NULL;
-
- g_return_val_if_fail(PURPLE_IS_XFER(xfer), NULL);
-
- priv = purple_xfer_get_instance_private(xfer);
-
- return priv->thumbnail_mimetype;
-}
-
-void
-purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
- gsize size, const gchar *mimetype)
-{
- PurpleXferPrivate *priv = NULL;
- gpointer old_thumbnail_data;
- gchar *old_mimetype;
-
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- priv = purple_xfer_get_instance_private(xfer);
-
- /* Hold onto these in case they are equal to passed-in pointers */
- old_thumbnail_data = priv->thumbnail_data;
- old_mimetype = priv->thumbnail_mimetype;
-
- if (thumbnail && size > 0) {
- priv->thumbnail_data = g_memdup2(thumbnail, size);
- priv->thumbnail_size = size;
- priv->thumbnail_mimetype = g_strdup(mimetype);
- } else {
- priv->thumbnail_data = NULL;
- priv->thumbnail_size = 0;
- priv->thumbnail_mimetype = NULL;
- }
-
- /* Now it's safe to free the pointers */
- g_free(old_thumbnail_data);
- g_free(old_mimetype);
-}
-
-void
-purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats)
-{
- g_return_if_fail(PURPLE_IS_XFER(xfer));
-
- g_signal_emit(xfer, signals[SIG_ADD_THUMBNAIL], 0, formats, NULL);
-}
-
-/**************************************************************************
- * GObject code
- **************************************************************************/
-static void
-purple_xfer_set_property(GObject *obj, guint param_id, const GValue *value,
- GParamSpec *pspec)
-{
- PurpleXfer *xfer = PURPLE_XFER(obj);
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- switch (param_id) {
- case PROP_TYPE:
- priv->type = g_value_get_enum(value);
- break;
- case PROP_ACCOUNT:
- priv->account = g_value_get_object(value);
- break;
- case PROP_REMOTE_USER:
- purple_xfer_set_remote_user(xfer, g_value_get_string(value));
- break;
- case PROP_MESSAGE:
- purple_xfer_set_message(xfer, g_value_get_string(value));
- break;
- case PROP_FILENAME:
- purple_xfer_set_filename(xfer, g_value_get_string(value));
- break;
- case PROP_LOCAL_FILENAME:
- purple_xfer_set_local_filename(xfer, g_value_get_string(value));
- break;
- case PROP_FILE_SIZE:
- purple_xfer_set_size(xfer, g_value_get_int64(value));
- break;
- case PROP_LOCAL_PORT:
- purple_xfer_set_local_port(xfer, g_value_get_int(value));
- break;
- case PROP_FD:
- purple_xfer_set_fd(xfer, g_value_get_int(value));
- break;
- case PROP_WATCHER:
- purple_xfer_set_watcher(xfer, g_value_get_int(value));
- break;
- case PROP_BYTES_SENT:
- purple_xfer_set_bytes_sent(xfer, g_value_get_int64(value));
- break;
- case PROP_STATUS:
- purple_xfer_set_status(xfer, g_value_get_enum(value));
- break;
- case PROP_VISIBLE:
- purple_xfer_set_visible(xfer, g_value_get_boolean(value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-static void
-purple_xfer_get_property(GObject *obj, guint param_id, GValue *value,
- GParamSpec *pspec)
-{
- PurpleXfer *xfer = PURPLE_XFER(obj);
-
- switch (param_id) {
- case PROP_TYPE:
- g_value_set_enum(value, purple_xfer_get_xfer_type(xfer));
- break;
- case PROP_ACCOUNT:
- g_value_set_object(value, purple_xfer_get_account(xfer));
- break;
- case PROP_REMOTE_USER:
- g_value_set_string(value, purple_xfer_get_remote_user(xfer));
- break;
- case PROP_MESSAGE:
- g_value_set_string(value, purple_xfer_get_message(xfer));
- break;
- case PROP_FILENAME:
- g_value_set_string(value, purple_xfer_get_filename(xfer));
- break;
- case PROP_LOCAL_FILENAME:
- g_value_set_string(value, purple_xfer_get_local_filename(xfer));
- break;
- case PROP_FILE_SIZE:
- g_value_set_int64(value, purple_xfer_get_size(xfer));
- break;
- case PROP_REMOTE_IP:
- g_value_set_string(value, purple_xfer_get_remote_ip(xfer));
- break;
- case PROP_LOCAL_PORT:
- g_value_set_int(value, purple_xfer_get_local_port(xfer));
- break;
- case PROP_REMOTE_PORT:
- g_value_set_int(value, purple_xfer_get_remote_port(xfer));
- break;
- case PROP_FD:
- g_value_set_int(value, purple_xfer_get_fd(xfer));
- break;
- case PROP_WATCHER:
- g_value_set_int(value, purple_xfer_get_watcher(xfer));
- break;
- case PROP_BYTES_SENT:
- g_value_set_int64(value, purple_xfer_get_bytes_sent(xfer));
- break;
- case PROP_START_TIME:
- g_value_set_int64(value, purple_xfer_get_start_time(xfer));
- break;
- case PROP_END_TIME:
- g_value_set_int64(value, purple_xfer_get_end_time(xfer));
- break;
- case PROP_STATUS:
- g_value_set_enum(value, purple_xfer_get_status(xfer));
- break;
- case PROP_PROGRESS:
- g_value_set_double(value, purple_xfer_get_progress(xfer));
- break;
- case PROP_VISIBLE:
- g_value_set_boolean(value, purple_xfer_get_visible(xfer));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
- break;
- }
-}
-
-static void
-purple_xfer_init(PurpleXfer *xfer)
-{
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- priv->ui_ops = purple_xfers_get_ui_ops();
- priv->current_buffer_size = FT_INITIAL_BUFFER_SIZE;
- priv->fd = -1;
- priv->ready = PURPLE_XFER_READY_NONE;
-}
-
-static void
-purple_xfer_constructed(GObject *object)
-{
- PurpleXfer *xfer = PURPLE_XFER(object);
- PurpleXferUiOps *ui_ops;
-
- G_OBJECT_CLASS(purple_xfer_parent_class)->constructed(object);
-
- ui_ops = purple_xfers_get_ui_ops();
-
- if (ui_ops != NULL && ui_ops->new_xfer != NULL) {
- ui_ops->new_xfer(xfer);
- }
-
- xfers = g_list_prepend(xfers, xfer);
-}
-
-static void
-purple_xfer_finalize(GObject *object)
-{
- PurpleXfer *xfer = PURPLE_XFER(object);
- PurpleXferPrivate *priv = purple_xfer_get_instance_private(xfer);
-
- /* 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);
- }
-
- xfers = g_list_remove(xfers, xfer);
-
- g_free(priv->who);
- g_free(priv->filename);
- g_free(priv->remote_ip);
- g_free(priv->local_filename);
- g_clear_object(&priv->conn);
-
- if (priv->buffer) {
- g_byte_array_free(priv->buffer, TRUE);
- }
-
- g_free(priv->thumbnail_data);
- g_free(priv->thumbnail_mimetype);
-
- G_OBJECT_CLASS(purple_xfer_parent_class)->finalize(object);
-}
-
-/* Class initializer function */
-static void
-purple_xfer_class_init(PurpleXferClass *klass)
-{
- GObjectClass *obj_class = G_OBJECT_CLASS(klass);
-
- obj_class->finalize = purple_xfer_finalize;
- obj_class->constructed = purple_xfer_constructed;
- obj_class->get_property = purple_xfer_get_property;
- obj_class->set_property = purple_xfer_set_property;
-
- klass->write = do_write;
- klass->read = do_read;
-
- klass->open_local = do_open_local;
- klass->query_local = do_query_local;
- klass->read_local = do_read_local;
- klass->write_local = do_write_local;
- klass->data_not_sent = do_data_not_sent;
-
- /**
- * PurpleXfer:type:
- *
- * The type of the transfer.
- */
- properties[PROP_TYPE] = g_param_spec_enum("type", "Transfer type",
- "The type of file transfer.", PURPLE_TYPE_XFER_TYPE,
- PURPLE_XFER_TYPE_UNKNOWN,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:account:
- *
- * The account that this transfer is for.
- */
- properties[PROP_ACCOUNT] = g_param_spec_object("account", "Account",
- "The account sending or receiving the file.",
- PURPLE_TYPE_ACCOUNT,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:remote-user:
- *
- * The user on the other side of this transfer.
- */
- properties[PROP_REMOTE_USER] = g_param_spec_string("remote-user",
- "Remote user",
- "The name of the remote user.", NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:message:
- *
- * A message that was sent with the transfer.
- */
- properties[PROP_MESSAGE] = g_param_spec_string("message", "Message",
- "The message for the file transfer.", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:filename:
- *
- * The name of the file being transferred.
- */
- properties[PROP_FILENAME] = g_param_spec_string("filename", "Filename",
- "The filename for the file transfer.", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:local-filename:
- *
- * The local filename for this transfer.
- */
- properties[PROP_LOCAL_FILENAME] = g_param_spec_string("local-filename",
- "Local filename",
- "The local filename for the file transfer.", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:file-size:
- *
- * The size of the file in bytes.
- */
- properties[PROP_FILE_SIZE] = g_param_spec_int64("file-size", "File size",
- "Size of the file in a file transfer.",
- G_MININT64, G_MAXINT64, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:remote-ip:
- *
- * The IP address of the remote user.
- */
- properties[PROP_REMOTE_IP] = g_param_spec_string("remote-ip", "Remote IP",
- "The remote IP address in the file transfer.", NULL,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:local-port:
- *
- * The port number on the local side.
- */
- properties[PROP_LOCAL_PORT] = g_param_spec_int("local-port", "Local port",
- "The local port number in the file transfer.",
- G_MININT, G_MAXINT, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:remote-port:
- *
- * The port number on the remote side.
- */
- properties[PROP_REMOTE_PORT] = g_param_spec_int("remote-port",
- "Remote port",
- "The remote port number in the file transfer.",
- G_MININT, G_MAXINT, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:fd:
- *
- * The socket file descriptor for the transfer.
- */
- properties[PROP_FD] = g_param_spec_int("fd", "Socket FD",
- "The socket file descriptor.",
- G_MININT, G_MAXINT, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:watcher:
- *
- * The input watcher for this transfer.
- */
- properties[PROP_WATCHER] = g_param_spec_int("watcher", "Watcher",
- "The watcher for the file transfer.",
- G_MININT, G_MAXINT, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:bytes-sent:
- *
- * The number of bytes that have been sent.
- */
- properties[PROP_BYTES_SENT] = g_param_spec_int64("bytes-sent", "Bytes sent",
- "The number of bytes sent (or received) so far.",
- G_MININT64, G_MAXINT64, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:start-time:
- *
- * The time when the transfer started.
- */
- properties[PROP_START_TIME] = g_param_spec_int64(
- "start-time", "Start time",
- "The monotonic time the transfer of a file started.",
- G_MININT64, G_MAXINT64, 0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:end-time:
- *
- * The time when the transfer ended.
- */
- properties[PROP_END_TIME] = g_param_spec_int64(
- "end-time", "End time",
- "The monotonic time the transfer of a file ended.", G_MININT64,
- G_MAXINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:status:
- *
- * The status of the transfer.
- */
- properties[PROP_STATUS] = g_param_spec_enum("status", "Status",
- "The current status for the file transfer.",
- PURPLE_TYPE_XFER_STATUS, PURPLE_XFER_STATUS_UNKNOWN,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:progress:
- *
- * The current progress of the transfer.
- */
- properties[PROP_PROGRESS] = g_param_spec_double(
- "progress", "Progress",
- "The current progress of the file transfer.", -1.0, 1.0, -1.0,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
-
- /**
- * PurpleXfer:visible:
- *
- * Whether or not user interfaces should display the transfer.
- */
- properties[PROP_VISIBLE] = g_param_spec_boolean(
- "visible", "Visible",
- "Hint for UIs whether this transfer should be visible.", FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
-
- /* Signals */
-
- /**
- * PurpleXfer::open-local:
- * @xfer: The file transfer.
- *
- * Open a file locally for a file transfer.
- *
- * The default class handler will open a file using standard library
- * functions. If you connect to this signal, you should connect to
- * [signal@PurpleXfer::query-local], [signal@PurpleXfer::read-local],
- * [signal@PurpleXfer::write-local] and [signal@PurpleXfer::data-not-sent]
- * as well.
- *
- * Returns: %TRUE if the file was opened successfully, or %FALSE otherwise,
- * and the transfer should be cancelled (libpurple will cancel).
- *
- * Since: 3.0
- */
- signals[SIG_OPEN_LOCAL] = g_signal_new(
- "open-local", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(PurpleXferClass, open_local),
- g_signal_accumulator_first_wins, NULL, NULL, G_TYPE_BOOLEAN, 0);
-
- /**
- * PurpleXfer::query-local:
- * @xfer: The file transfer.
- * @filename: The filename of the transfer.
- *
- * Query a file's properties locally.
- *
- * The default class handler will query a file using standard library
- * functions, and set the transfer's size. If you connect to this signal,
- * you should try to do the same, but it is not necessarily an error if you
- * cannot. If you connect to this signal, you must connect to
- * [signal@PurpleXfer::open-local], [signal@PurpleXfer::read-local],
- * [signal@PurpleXfer::write-local] and [signal@PurpleXfer::data-not-sent]
- * as well.
- *
- * Returns: %TRUE if the properties were queried successfully, or %FALSE
- * otherwise, and the transfer should be cancelled (libpurple will
- * cancel).
- *
- * Since: 3.0
- */
- signals[SIG_QUERY_LOCAL] = g_signal_new(
- "query-local", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(PurpleXferClass, query_local),
- g_signal_accumulator_first_wins, NULL, NULL, G_TYPE_BOOLEAN, 1,
- G_TYPE_STRING);
-
- /**
- * PurpleXfer::read-local:
- * @xfer: The file transfer.
- * @buffer: (out): A pointer to a buffer to fill.
- * @size: The maximum amount of data to put in the buffer.
- *
- * Read data locally to send to the protocol for a file transfer.
- *
- * The default class handler will read from a file using standard library
- * functions. If you connect to this signal, you must connect to
- * [signal@PurpleXfer::open-local], [signal@PurpleXfer::query-local],
- * [signal@PurpleXfer::write-local] and [signal@PurpleXfer::data-not-sent]
- * as well.
- *
- * Returns: The amount of data in the buffer, 0 if nothing is available,
- * and a negative value if an error occurred and the transfer
- * should be cancelled (libpurple will cancel).
- *
- * Since: 3.0
- */
- signals[SIG_READ_LOCAL] = g_signal_new(
- "read-local", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(PurpleXferClass, read_local),
- g_signal_accumulator_first_wins, NULL, NULL, G_TYPE_LONG, 2,
- G_TYPE_POINTER, G_TYPE_LONG);
-
- /**
- * PurpleXfer::write-local:
- * @xfer: The file transfer.
- * @buffer: The buffer to write.
- * @size: The size of the buffer.
- *
- * Write data received from the protocol locally. The signal handler must
- * deal with the entire buffer and return size, or it is treated as an
- * error.
- *
- * The default class handler will write to a file using standard library
- * functions. If you connect to this signal, you must connect to
- * [signal@PurpleXfer::open-local], [signal@PurpleXfer::query-local],
- * [signal@PurpleXfer::read-local] and [signal@PurpleXfer::data-not-sent]
- * as well.
- *
- * Returns: @size if the write was successful, or a value between 0 and
- * @size on error.
- *
- * Since: 3.0
- */
- signals[SIG_WRITE_LOCAL] = g_signal_new(
- "write-local", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(PurpleXferClass, write_local),
- g_signal_accumulator_first_wins, NULL, NULL, G_TYPE_LONG, 2,
- G_TYPE_POINTER, G_TYPE_LONG);
-
- /**
- * PurpleXfer::data-not-sent:
- * @xfer: The file transfer.
- * @buffer: A pointer to the beginning of the unwritten data.
- * @size: The amount of unwritten data.
- *
- * Notify the UI that not all the data read in was written. The UI should
- * re-enqueue this data and return it the next time read is called.
- *
- * If you connect to this signal, you must connect to
- * [signal@PurpleXfer::open-local], [signal@PurpleXfer::query-local],
- * [signal@PurpleXfer::read-local] and [signal@PurpleXfer::write-local] as
- * well.
- *
- * Returns: %TRUE if the data was re-enqueued successfully, or %FALSE
- * otherwise, and the transfer should be cancelled (libpurple
- * will cancel).
- *
- * Since: 3.0
- */
- signals[SIG_DATA_NOT_SENT] = g_signal_new(
- "data-not-sent", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(PurpleXferClass, data_not_sent),
- g_signal_accumulator_first_wins, NULL, NULL, G_TYPE_BOOLEAN, 2,
- G_TYPE_POINTER, G_TYPE_ULONG);
-
- /**
- * PurpleXfer::add-thumbnail:
- * @xfer: The file transfer.
- * @formats: A comma-separated string of allowed image formats.
- *
- * Request that a thumbnail be added to a file transfer.
- *
- * Since: 3.0
- */
- signals[SIG_ADD_THUMBNAIL] = g_signal_new(
- "add-thumbnail", G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, 0, NULL,
- NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
-}
-
-PurpleXfer *
-purple_xfer_new(PurpleAccount *account, PurpleXferType type, const char *who)
-{
- PurpleXfer *xfer;
-
- g_return_val_if_fail(type != PURPLE_XFER_TYPE_UNKNOWN, NULL);
- g_return_val_if_fail(PURPLE_IS_ACCOUNT(account), NULL);
- g_return_val_if_fail(who != NULL, NULL);
-
- xfer = g_object_new(PURPLE_TYPE_XFER,
- "account", account,
- "type", type,
- "remote-user", who,
- NULL
- );
-
- return xfer;
-}
-
-/**************************************************************************
- * File Transfer Subsystem API
- **************************************************************************/
-GList *
-purple_xfers_get_all(void)
-{
- return xfers;
-}
-
-void *
-purple_xfers_get_handle(void) {
- static int handle = 0;
-
- return &handle;
-}
-
-void
-purple_xfers_init(void) {
- void *handle = purple_xfers_get_handle();
-
- /* register signals */
- purple_signal_register(handle, "file-recv-request",
- purple_marshal_VOID__POINTER, G_TYPE_NONE, 1,
- PURPLE_TYPE_XFER);
-}
-
-void
-purple_xfers_uninit(void)
-{
- void *handle = purple_xfers_get_handle();
-
- purple_signals_disconnect_by_handle(handle);
- purple_signals_unregister_by_instance(handle);
-}
-
-void
-purple_xfers_set_ui_ops(PurpleXferUiOps *ops) {
- xfer_ui_ops = ops;
-}
-
-PurpleXferUiOps *
-purple_xfers_get_ui_ops(void) {
- return xfer_ui_ops;
-}
-
-/**************************************************************************
- * GBoxed code
- **************************************************************************/
-static PurpleXferUiOps *
-purple_xfer_ui_ops_copy(PurpleXferUiOps *ops)
-{
- PurpleXferUiOps *ops_new;
-
- g_return_val_if_fail(ops != NULL, NULL);
-
- ops_new = g_new(PurpleXferUiOps, 1);
- *ops_new = *ops;
-
- return ops_new;
-}
-
-GType
-purple_xfer_ui_ops_get_type(void)
-{
- static GType type = 0;
-
- if (type == 0) {
- type = g_boxed_type_register_static("PurpleXferUiOps",
- (GBoxedCopyFunc)purple_xfer_ui_ops_copy,
- (GBoxedFreeFunc)g_free);
- }
-
- return type;
-}
--- a/libpurple/xfer.h Thu Apr 11 04:02:16 2024 -0500
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,985 +0,0 @@
-/*
- * Purple - Internet Messaging Library
- * Copyright (C) Pidgin Developers <devel@pidgin.im>
- *
- * Purple is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * source distribution.
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this library; if not, see <https://www.gnu.org/licenses/>.
- */
-
-#if !defined(PURPLE_GLOBAL_HEADER_INSIDE) && !defined(PURPLE_COMPILATION)
-# error "only <purple.h> may be included directly"
-#endif
-
-#ifndef PURPLE_XFER_H
-#define PURPLE_XFER_H
-
-#define PURPLE_TYPE_XFER_UI_OPS (purple_xfer_ui_ops_get_type())
-
-/**************************************************************************/
-/* Data Structures */
-/**************************************************************************/
-typedef struct _PurpleXferUiOps PurpleXferUiOps;
-
-#include <glib.h>
-#include <stdio.h>
-
-#include "connection.h"
-#include "purpleaccount.h"
-#include "purpleprotocol.h"
-#include "purpleversion.h"
-
-/**
- * PurpleXferType:
- * @PURPLE_XFER_TYPE_UNKNOWN: Unknown file transfer type.
- * @PURPLE_XFER_TYPE_SEND: File sending.
- * @PURPLE_XFER_TYPE_RECEIVE: File receiving.
- *
- * Types of file transfers.
- *
- * Since: 2.0
- */
-typedef enum
-{
- PURPLE_XFER_TYPE_UNKNOWN = 0,
- PURPLE_XFER_TYPE_SEND,
- PURPLE_XFER_TYPE_RECEIVE
-} PurpleXferType;
-
-/**
- * PurpleXferStatus:
- * @PURPLE_XFER_STATUS_UNKNOWN: Unknown, the xfer may be null.
- * @PURPLE_XFER_STATUS_NOT_STARTED: It hasn't started yet.
- * @PURPLE_XFER_STATUS_ACCEPTED: Receive accepted, but destination file
- * not selected yet.
- * @PURPLE_XFER_STATUS_STARTED: purple_xfer_start has been called.
- * @PURPLE_XFER_STATUS_DONE: The xfer completed successfully.
- * @PURPLE_XFER_STATUS_CANCEL_LOCAL: The xfer was cancelled by us.
- * @PURPLE_XFER_STATUS_CANCEL_REMOTE: The xfer was cancelled by the other end,
- * or we couldn't connect.
- *
- * The different states of the xfer.
- *
- * Since: 2.0
- */
-typedef enum
-{
- PURPLE_XFER_STATUS_UNKNOWN = 0,
- PURPLE_XFER_STATUS_NOT_STARTED,
- PURPLE_XFER_STATUS_ACCEPTED,
- PURPLE_XFER_STATUS_STARTED,
- PURPLE_XFER_STATUS_DONE,
- PURPLE_XFER_STATUS_CANCEL_LOCAL,
- PURPLE_XFER_STATUS_CANCEL_REMOTE
-} PurpleXferStatus;
-
-G_BEGIN_DECLS
-
-#define PURPLE_TYPE_XFER (purple_xfer_get_type())
-
-/**
- * PurpleXfer:
- *
- * A representation of a file transfer.
- *
- * Since: 2.0
- */
-
-PURPLE_AVAILABLE_IN_ALL
-G_DECLARE_DERIVABLE_TYPE(PurpleXfer, purple_xfer, PURPLE, XFER, GObject)
-
-/**
- * PurpleXferUiOps:
- * @new_xfer: UI op that's called after a new transfer is created.
- *
- * File transfer UI operations.
- *
- * Any UI representing a file transfer must assign a filled-out
- * PurpleXferUiOps structure to the purple_xfer.
- *
- * Since: 2.0
- */
-struct _PurpleXferUiOps
-{
- void (*new_xfer)(PurpleXfer *xfer);
-};
-
-/**
- * PurpleXferClass:
- * @init: Called when the file transfer is accepted by the user. Must call
- * purple_xfer_start() and must be implemented.
- * @request_denied: Called when the file transfer is denied by the other side.
- * @start: Called to start the file transfer.
- * @end: Called when the file transfer should end.
- * @cancel_send: Handler for cancelling a sending file transfer.
- * @cancel_recv: Handler for cancelling a receiving file transfer.
- * @read: Called when reading data from the file transfer.
- * @write: Called when writing data to the file transfer.
- * @ack: Called when a file transfer is acknowledged.
- * @open_local: The vfunc for PurpleXfer::open-local. Since: 3.0
- * @query_local: The vfunc for PurpleXfer::query-local. Since: 3.0
- * @read_local: The vfunc for PurpleXfer::read-local. Since: 3.0
- * @write_local: The vfunc for PurpleXfer::write-local. Since: 3.0
- * @data_not_sent: The vfunc for PurpleXfer::data-not-sent. Since: 3.0
- *
- * Base class for all #PurpleXfer's
- *
- * Since: 3.0
- */
-struct _PurpleXferClass
-{
- GObjectClass parent_class;
-
- void (*init)(PurpleXfer *xfer);
- void (*request_denied)(PurpleXfer *xfer);
- void (*start)(PurpleXfer *xfer);
- void (*end)(PurpleXfer *xfer);
- void (*cancel_send)(PurpleXfer *xfer);
- void (*cancel_recv)(PurpleXfer *xfer);
- gssize (*read)(PurpleXfer *xfer, guchar **buffer, gsize size);
- gssize (*write)(PurpleXfer *xfer, const guchar *buffer, gsize size);
- void (*ack)(PurpleXfer *xfer, const guchar *buffer, gsize size);
-
- gboolean (*open_local)(PurpleXfer *xfer);
- gboolean (*query_local)(PurpleXfer *xfer, const gchar *filename);
- gssize (*read_local)(PurpleXfer *xfer, guchar *buffer, gssize size);
- gssize (*write_local)(PurpleXfer *xfer, const guchar *buffer, gssize size);
- gboolean (*data_not_sent)(PurpleXfer *xfer, const guchar *buffer,
- gsize size);
-
- /*< private >*/
- gpointer reserved[4];
-};
-
-/**************************************************************************/
-/* File Transfer API */
-/**************************************************************************/
-
-/**
- * purple_xfer_new:
- * @account: The account sending or receiving the file.
- * @type: The type of file transfer.
- * @who: The name of the remote user.
- *
- * Creates a new file transfer handle.
- * This is called by protocols.
- *
- * Returns: A file transfer handle.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleXfer *purple_xfer_new(PurpleAccount *account, PurpleXferType type, const char *who);
-
-/**
- * purple_xfer_request:
- * @xfer: The file transfer to request confirmation on.
- *
- * Requests confirmation for a file transfer from the user. If receiving
- * a file which is known at this point, this requests user to accept and
- * save the file. If the filename is unknown (not set) this only requests user
- * to accept the file transfer. In this case protocol must call this function
- * again once the filename is available.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_request(PurpleXfer *xfer);
-
-/**
- * purple_xfer_request_accepted:
- * @xfer: The file transfer.
- * @filename: The filename.
- *
- * Called if the user accepts the file transfer request.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_request_accepted(PurpleXfer *xfer, const gchar *filename);
-
-/**
- * purple_xfer_request_denied:
- * @xfer: The file transfer.
- *
- * Called if the user rejects the file transfer request.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_request_denied(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_fd:
- * @xfer: The file transfer.
- *
- * Returns the socket file descriptor.
- *
- * Returns: The socket file descriptor.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-int purple_xfer_get_fd(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_watcher:
- * @xfer: The file transfer.
- *
- * Returns the Watcher for the transfer.
- *
- * Returns: The watcher.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-int purple_xfer_get_watcher(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_xfer_type:
- * @xfer: The file transfer.
- *
- * Returns the type of file transfer.
- *
- * Returns: The type of the file transfer.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleXferType purple_xfer_get_xfer_type(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_account:
- * @xfer: The file transfer.
- *
- * Returns the account the file transfer is using.
- *
- * Returns: (transfer none): The account.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleAccount *purple_xfer_get_account(PurpleXfer *xfer);
-
-/**
- * purple_xfer_set_remote_user:
- * @xfer: The file transfer.
- * @who: The name of the remote user.
- *
- * Sets the name of the remote user.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_set_remote_user(PurpleXfer *xfer, const char *who);
-
-/**
- * purple_xfer_get_remote_user:
- * @xfer: The file transfer.
- *
- * Returns the name of the remote user.
- *
- * Returns: The name of the remote user.
- *
- * Since: 2.1
- */
-PURPLE_AVAILABLE_IN_2_1
-const char *purple_xfer_get_remote_user(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_status:
- * @xfer: The file transfer.
- *
- * Returns the status of the xfer.
- *
- * Returns: The status.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleXferStatus purple_xfer_get_status(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_visible:
- * @xfer: The file transfer.
- *
- * Returns whether the UI should show the file transfer in its listing.
- *
- * Note, this is just a hint for UIs and has no effect internally.
- *
- * Returns: The visibility.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-gboolean purple_xfer_get_visible(PurpleXfer *xfer);
-
-/**
- * purple_xfer_is_cancelled:
- * @xfer: The file transfer.
- *
- * Returns true if the file transfer was cancelled.
- *
- * Returns: Whether or not the transfer was cancelled.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-gboolean purple_xfer_is_cancelled(PurpleXfer *xfer);
-
-/**
- * purple_xfer_is_completed:
- * @xfer: The file transfer.
- *
- * Returns the completed state for a file transfer.
- *
- * Returns: The completed state.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gboolean purple_xfer_is_completed(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_filename:
- * @xfer: The file transfer.
- *
- * Returns the name of the file being sent or received.
- *
- * Returns: The filename.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_xfer_get_filename(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_local_filename:
- * @xfer: The file transfer.
- *
- * Returns the file's destination filename,
- *
- * Returns: The destination filename.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_xfer_get_local_filename(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_bytes_sent:
- * @xfer: The file transfer.
- *
- * Returns the number of bytes sent (or received) so far.
- *
- * Returns: The number of bytes sent.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-goffset purple_xfer_get_bytes_sent(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_bytes_remaining:
- * @xfer: The file transfer.
- *
- * Returns the number of bytes remaining to send or receive.
- *
- * Returns: The number of bytes remaining.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-goffset purple_xfer_get_bytes_remaining(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_size:
- * @xfer: The file transfer.
- *
- * Returns the size of the file being sent or received.
- *
- * Returns: The total size of the file.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-goffset purple_xfer_get_size(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_progress:
- * @xfer: The file transfer.
- *
- * Returns the current percentage of progress of the transfer.
- *
- * This is a number between 0 (0%) and 1 (100%).
- *
- * Returns: The percentage complete.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-double purple_xfer_get_progress(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_local_port:
- * @xfer: The file transfer.
- *
- * Returns the local port number in the file transfer.
- *
- * Returns: The port number on this end.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-guint16 purple_xfer_get_local_port(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_remote_ip:
- * @xfer: The file transfer.
- *
- * Returns the remote IP address in the file transfer.
- *
- * Returns: The IP address on the other end.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-const char *purple_xfer_get_remote_ip(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_remote_port:
- * @xfer: The file transfer.
- *
- * Returns the remote port number in the file transfer.
- *
- * Returns: The port number on the other end.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-guint16 purple_xfer_get_remote_port(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_start_time:
- * @xfer: The file transfer.
- *
- * Returns the time the transfer of a file started.
- *
- * Returns: The monotonic time when the transfer started.
- *
- * Since: 2.4
- */
-PURPLE_AVAILABLE_IN_2_4
-gint64 purple_xfer_get_start_time(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_end_time:
- * @xfer: The file transfer.
- *
- * Returns the time the transfer of a file ended.
- *
- * Returns: The monotonic time when the transfer ended.
- *
- * Since: 2.4
- */
-PURPLE_AVAILABLE_IN_2_4
-gint64 purple_xfer_get_end_time(PurpleXfer *xfer);
-
-/**
- * purple_xfer_set_fd:
- * @xfer: The file transfer.
- * @fd: The file descriptor.
- *
- * Sets the socket file descriptor.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_set_fd(PurpleXfer *xfer, int fd);
-
-/**
- * purple_xfer_set_watcher:
- * @xfer: The file transfer.
- * @watcher: The watcher.
- *
- * Sets the watcher for the file transfer.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_set_watcher(PurpleXfer *xfer, int watcher);
-
-/**
- * purple_xfer_set_completed:
- * @xfer: The file transfer.
- * @completed: The completed state.
- *
- * Sets the completed state for the file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_set_completed(PurpleXfer *xfer, gboolean completed);
-
-/**
- * purple_xfer_set_status:
- * @xfer: The file transfer.
- * @status: The current status.
- *
- * Sets the current status for the file transfer.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_set_status(PurpleXfer *xfer, PurpleXferStatus status);
-
-/**
- * purple_xfer_set_visible:
- * @xfer: The file transfer.
- * @visible: The visibility.
- *
- * Sets whether the UI should show the file transfer in its listing.
- *
- * Note, this is just a hint for UIs and has no effect internally.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_set_visible(PurpleXfer *xfer, gboolean visible);
-
-/**
- * purple_xfer_set_message:
- * @xfer: The file transfer.
- * @message: The message.
- *
- * Sets the message for the file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_set_message(PurpleXfer *xfer, const char *message);
-
-/**
- * purple_xfer_get_message:
- * @xfer: The file transfer.
- *
- * Returns the message for the file transfer.
- *
- * Returns: The message.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-const char *purple_xfer_get_message(PurpleXfer *xfer);
-
-/**
- * purple_xfer_set_filename:
- * @xfer: The file transfer.
- * @filename: The filename.
- *
- * Sets the filename for the file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_set_filename(PurpleXfer *xfer, const char *filename);
-
-/**
- * purple_xfer_set_local_filename:
- * @xfer: The file transfer.
- * @filename: The filename
- *
- * Sets the local filename for the file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_set_local_filename(PurpleXfer *xfer, const char *filename);
-
-/**
- * purple_xfer_set_size:
- * @xfer: The file transfer.
- * @size: The size of the file.
- *
- * Sets the size of the file in a file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_set_size(PurpleXfer *xfer, goffset size);
-
-/**
- * purple_xfer_set_local_port:
- * @xfer: The file transfer.
- * @local_port: The local port.
- *
- * Sets the local port of the file transfer.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_set_local_port(PurpleXfer *xfer, guint16 local_port);
-
-/**
- * purple_xfer_set_bytes_sent:
- * @xfer: The file transfer.
- * @bytes_sent: The new current position in the file. If we're
- * sending a file then this is the next byte that we
- * will send. If we're receiving a file, this is the
- * next byte that we expect to receive.
- *
- * Sets the current working position in the active file transfer. This
- * can be used to jump backward in the file if the protocol detects
- * that some bit of data needs to be resent or has been sent twice.
- *
- * It's used for pausing and resuming an oscar file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_set_bytes_sent(PurpleXfer *xfer, goffset bytes_sent);
-
-/**
- * purple_xfer_get_ui_ops:
- * @xfer: The file transfer.
- *
- * Returns the UI operations structure for a file transfer.
- *
- * Returns: The UI operations structure.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleXferUiOps *purple_xfer_get_ui_ops(PurpleXfer *xfer);
-
-/**
- * purple_xfer_read:
- * @xfer: The file transfer.
- * @buffer: The buffer that will be created to contain the data.
- *
- * Reads in data from a file transfer stream.
- *
- * Returns: The number of bytes read, or -1.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gssize purple_xfer_read(PurpleXfer *xfer, guchar **buffer);
-
-/**
- * purple_xfer_write:
- * @xfer: The file transfer.
- * @buffer: The buffer to read the data from.
- * @size: The number of bytes to write.
- *
- * Writes data to a file transfer stream.
- *
- * Returns: The number of bytes written, or -1.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-gssize purple_xfer_write(PurpleXfer *xfer, const guchar *buffer, gsize size);
-
-/**
- * purple_xfer_write_file:
- * @xfer: The file transfer.
- * @buffer: The buffer to read the data from.
- * @size: The number of bytes to write.
- *
- * Writes chunk of received file.
- *
- * Returns: TRUE on success, FALSE otherwise.
- *
- * Since: 2.11
- */
-PURPLE_AVAILABLE_IN_2_11
-gboolean purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size);
-
-/**
- * purple_xfer_read_file:
- * @xfer: The file transfer.
- * @buffer: The buffer to write the data to.
- * @size: The size of buffer.
- *
- * Writes chunk of file being sent.
- *
- * Returns: Number of bytes written (0 means, the device is busy), or -1 on
- * failure.
- *
- * Since: 2.11
- */
-PURPLE_AVAILABLE_IN_2_11
-gssize purple_xfer_read_file(PurpleXfer *xfer, guchar *buffer, gsize size);
-
-/**
- * purple_xfer_start:
- * @xfer: The file transfer.
- * @fd: The file descriptor for the socket.
- * @ip: The IP address to connect to.
- * @port: The port to connect to.
- *
- * Starts a file transfer.
- *
- * Either @fd must be specified <emphasis>or</emphasis> @ip and @port on a
- * file receive transfer. On send, @fd must be specified, and
- * @ip and @port are ignored.
- *
- * Passing @fd as '-1' is a special-case and indicates to the
- * protocol to facilitate the file transfer itself.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_start(PurpleXfer *xfer, int fd, const char *ip, guint16 port);
-
-/**
- * purple_xfer_end:
- * @xfer: The file transfer.
- *
- * Ends a file transfer.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_end(PurpleXfer *xfer);
-
-/**
- * purple_xfer_cancel_local:
- * @xfer: The file transfer.
- *
- * Cancels a file transfer on the local end.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_cancel_local(PurpleXfer *xfer);
-
-/**
- * purple_xfer_cancel_remote:
- * @xfer: The file transfer.
- *
- * Cancels a file transfer from the remote end.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_cancel_remote(PurpleXfer *xfer);
-
-/**
- * purple_xfer_error:
- * @type: The type of file transfer.
- * @account: The account sending or receiving the file.
- * @who: The user on the other end of the transfer.
- * @msg: The message to display.
- *
- * Displays a file transfer-related error message.
- *
- * This is a wrapper around purple_notify_error(), which automatically
- * specifies a title ("File transfer to <literal>user</literal> failed" or
- * "File Transfer from <literal>user</literal> failed").
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_error(PurpleXferType type, PurpleAccount *account, const char *who, const char *msg);
-
-/**
- * purple_xfer_conversation_write:
- * @xfer: The file transfer to which this message relates.
- * @message: The message to display.
- * @is_error: Is this an error message?.
- *
- * Displays a file transfer-related message in the conversation window.
- *
- * This is a wrapper around purple_conversation_write_system_message.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfer_conversation_write(PurpleXfer *xfer, const gchar *message, gboolean is_error);
-
-/**
- * purple_xfer_ui_ready:
- * @xfer: The file transfer which is ready.
- *
- * Allows the UI to signal it's ready to send/receive data (depending on
- * the direction of the file transfer. Used when the UI is providing
- * read/write/data_not_sent UI ops.
- *
- * Since: 2.6
- */
-PURPLE_AVAILABLE_IN_2_6
-void purple_xfer_ui_ready(PurpleXfer *xfer);
-
-/**
- * purple_xfer_protocol_ready:
- * @xfer: The file transfer which is ready.
- *
- * Allows the protocol to signal it's ready to send/receive data (depending on
- * the direction of the file transfer. Used when the protocol provides read/write
- * ops and cannot/does not provide a raw fd to the core.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_xfer_protocol_ready(PurpleXfer *xfer);
-
-/**
- * purple_xfer_get_thumbnail:
- * @xfer: The file transfer to get the thumbnail for
- * @len: If not %NULL, the length of the thumbnail data returned
- * will be set in the location pointed to by this.
- *
- * Gets the thumbnail data for a transfer
- *
- * Returns: The thumbnail data, or NULL if there is no thumbnail
- *
- * Since: 2.7
- */
-PURPLE_AVAILABLE_IN_2_7
-gconstpointer purple_xfer_get_thumbnail(PurpleXfer *xfer, gsize *len);
-
-/**
- * purple_xfer_get_thumbnail_mimetype:
- * @xfer: The file transfer to get the mimetype for
- *
- * Gets the mimetype of the thumbnail preview for a transfer
- *
- * Returns: The mimetype of the thumbnail, or %NULL if not thumbnail is set
- *
- * Since: 2.7
- */
-PURPLE_AVAILABLE_IN_2_7
-const gchar *purple_xfer_get_thumbnail_mimetype(PurpleXfer *xfer);
-
-
-/**
- * purple_xfer_set_thumbnail:
- * @xfer: The file transfer to set the data for
- * @thumbnail: A pointer to the thumbnail data, this will be copied
- * @size: The size in bytes of the passed in thumbnail data
- * @mimetype: The mimetype of the generated thumbnail
- *
- * Sets the thumbnail data for a transfer
- *
- * Since: 2.7
- */
-PURPLE_AVAILABLE_IN_2_7
-void purple_xfer_set_thumbnail(PurpleXfer *xfer, gconstpointer thumbnail,
- gsize size, const gchar *mimetype);
-
-/**
- * purple_xfer_prepare_thumbnail:
- * @xfer: The file transfer to create a thumbnail for
- * @formats: A comma-separated list of mimetypes for image formats
- * the protocols can use for thumbnails.
- *
- * Prepare a thumbnail for a transfer (if the UI supports it)
- * will be no-op in case the UI doesn't implement thumbnail creation
- *
- * Since: 2.7
- */
-PURPLE_AVAILABLE_IN_2_7
-void purple_xfer_prepare_thumbnail(PurpleXfer *xfer, const gchar *formats);
-
-/**************************************************************************/
-/* File Transfer Subsystem API */
-/**************************************************************************/
-
-/**
- * purple_xfer_ui_ops_get_type:
- *
- * The standard _get_type function for #GType's.
- *
- * Returns: The #GType for the #PurpleXferUiOps boxed structure.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-GType purple_xfer_ui_ops_get_type(void);
-
-/**
- * purple_xfers_get_all:
- *
- * Returns all xfers
- *
- * Returns: (element-type Purple.Xfer) (transfer none): all current xfers
- * with refs
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-GList *purple_xfers_get_all(void);
-
-/**
- * purple_xfers_get_handle:
- *
- * Returns the handle to the file transfer subsystem.
- *
- * Returns: The handle.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void *purple_xfers_get_handle(void);
-
-/**
- * purple_xfers_init:
- *
- * Initializes the file transfer subsystem.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfers_init(void);
-
-/**
- * purple_xfers_uninit:
- *
- * Uninitializes the file transfer subsystem.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfers_uninit(void);
-
-/**
- * purple_xfers_set_ui_ops:
- * @ops: The UI operations structure.
- *
- * Sets the UI operations structure to be used in all purple file transfers.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-void purple_xfers_set_ui_ops(PurpleXferUiOps *ops);
-
-/**
- * purple_xfers_get_ui_ops:
- *
- * Returns the UI operations structure to be used in all purple file transfers.
- *
- * Returns: The UI operations structure.
- *
- * Since: 2.0
- */
-PURPLE_AVAILABLE_IN_ALL
-PurpleXferUiOps *purple_xfers_get_ui_ops(void);
-
-G_END_DECLS
-
-#endif /* PURPLE_XFER_H */
--- a/po/POTFILES.in Thu Apr 11 04:02:16 2024 -0500
+++ b/po/POTFILES.in Thu Apr 11 20:34:07 2024 -0500
@@ -206,7 +206,6 @@
pidgin/resources/Protocols/detailed-view.ui
pidgin/resources/Roomlist/roomlist.ui
pidgin/resources/Whiteboard/whiteboard.ui
-pidgin/resources/Xfer/xfer.ui
pidgin/resources/gtk/menus.ui
pidgin/resources/account-row.ui
pidgin/resources/contactlist.ui