2 * Autoaccept - Auto-accept file transfers from selected users
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 #define PLUGIN_ID "core-plugin_pack-autoaccept"
23 #define PLUGIN_NAME N_("Autoaccept")
24 #define PLUGIN_CATEGORY N_("Utility")
25 #define PLUGIN_STATIC_NAME Autoaccept
26 #define PLUGIN_SUMMARY N_("Auto-accept file transfer requests from selected users.")
27 #define PLUGIN_DESCRIPTION N_("Auto-accept file transfer requests from selected users.")
28 #define PLUGIN_AUTHORS {"Sadrul H Chowdhury <sadrul@users.sourceforge.net>", NULL}
32 #include <glib/gstdio.h>
38 #include <buddylist.h>
39 #include <conversation.h>
45 #define PREF_PREFIX "/plugins/core/" PLUGIN_ID
46 #define PREF_PATH PREF_PREFIX "/path"
47 #define PREF_STRANGER PREF_PREFIX "/stranger"
48 #define PREF_NOTIFY PREF_PREFIX "/notify"
49 #define PREF_NEWDIR PREF_PREFIX "/newdir"
50 #define PREF_ESCAPE PREF_PREFIX "/escape"
52 #define PREF_STRANGER_OLD PREF_PREFIX "/reject_stranger"
62 ensure_path_exists(const char *dir
)
64 if (!g_file_test(dir
, G_FILE_TEST_IS_DIR
))
66 if (purple_build_dir(dir
, S_IRUSR
| S_IWUSR
| S_IXUSR
))
74 auto_accept_complete_cb(PurpleXfer
*xfer
, PurpleXfer
*my
)
76 if (xfer
== my
&& purple_prefs_get_bool(PREF_NOTIFY
) &&
77 !purple_conversations_find_im_with_account(purple_xfer_get_remote_user(xfer
), purple_xfer_get_account(xfer
)))
79 char *message
= g_strdup_printf(_("Autoaccepted file transfer of \"%s\" from \"%s\" completed."),
80 purple_xfer_get_filename(xfer
), purple_xfer_get_remote_user(xfer
));
81 purple_notify_info(NULL
, _("Autoaccept complete"), message
,
82 NULL
, purple_request_cpar_from_account(
83 purple_xfer_get_account(xfer
)));
89 file_recv_request_cb(PurpleXfer
*xfer
, gpointer handle
)
91 PurpleAccount
*account
;
92 PurpleBlistNode
*node
;
99 account
= purple_xfer_get_account(xfer
);
100 node
= PURPLE_BLIST_NODE(purple_blist_find_buddy(account
, purple_xfer_get_remote_user(xfer
)));
102 /* If person is on buddy list, use the buddy setting; otherwise, use the
105 node
= purple_blist_node_get_parent(node
);
106 g_return_if_fail(PURPLE_IS_CONTACT(node
));
107 accept_setting
= purple_blist_node_get_int(node
, "autoaccept");
109 accept_setting
= purple_prefs_get_int(PREF_STRANGER
);
112 switch (accept_setting
)
117 pref
= purple_prefs_get_string(PREF_PATH
);
118 if (ensure_path_exists(pref
))
122 gchar
**name_and_ext
;
126 if (purple_prefs_get_bool(PREF_NEWDIR
))
127 dirname
= g_build_filename(pref
, purple_normalize(account
, purple_xfer_get_remote_user(xfer
)), NULL
);
129 dirname
= g_build_filename(pref
, NULL
);
131 if (!ensure_path_exists(dirname
))
137 /* Escape filename (if escaping is turned on) */
138 if (purple_prefs_get_bool(PREF_ESCAPE
)) {
139 escape
= purple_escape_filename(purple_xfer_get_filename(xfer
));
141 escape
= purple_xfer_get_filename(xfer
);
143 filename
= g_build_filename(dirname
, escape
, NULL
);
145 /* Split at the first dot, to avoid uniquifying "foo.tar.gz" to "foo.tar-2.gz" */
146 name_and_ext
= g_strsplit(escape
, ".", 2);
147 name
= name_and_ext
[0];
148 g_return_if_fail(name
!= NULL
);
149 if (name_and_ext
[1] != NULL
) {
150 /* g_strsplit does not include the separator in each chunk. */
151 ext
= g_strdup_printf(".%s", name_and_ext
[1]);
156 /* Make sure the file doesn't exist. Do we want some better checking than this? */
157 /* FIXME: There is a race here: if the newly uniquified file name gets created between
158 * this g_file_test and the transfer starting, the file created in the meantime
159 * will be clobbered. But it's not at all straightforward to fix.
161 while (g_file_test(filename
, G_FILE_TEST_EXISTS
)) {
162 char *file
= g_strdup_printf("%s-%d%s", name
, count
++, ext
);
164 filename
= g_build_filename(dirname
, file
, NULL
);
168 purple_xfer_request_accepted(xfer
, filename
);
170 g_strfreev(name_and_ext
);
176 purple_signal_connect(purple_xfers_get_handle(), "file-recv-complete", handle
,
177 PURPLE_CALLBACK(auto_accept_complete_cb
), xfer
);
180 purple_xfer_set_status(xfer
, PURPLE_XFER_STATUS_CANCEL_LOCAL
);
186 save_cb(PurpleBlistNode
*node
, int choice
)
188 if (PURPLE_IS_BUDDY(node
))
189 node
= purple_blist_node_get_parent(node
);
190 g_return_if_fail(PURPLE_IS_CONTACT(node
));
191 purple_blist_node_set_int(node
, "autoaccept", choice
);
195 set_auto_accept_settings(PurpleBlistNode
*node
, gpointer plugin
)
199 if (PURPLE_IS_BUDDY(node
))
200 node
= purple_blist_node_get_parent(node
);
201 g_return_if_fail(PURPLE_IS_CONTACT(node
));
203 message
= g_strdup_printf(_("When a file-transfer request arrives from %s"),
204 purple_contact_get_alias(PURPLE_CONTACT(node
)));
205 purple_request_choice(plugin
, _("Set Autoaccept Setting"), message
,
206 NULL
, GINT_TO_POINTER(purple_blist_node_get_int(node
, "autoaccept")),
207 _("_Save"), G_CALLBACK(save_cb
),
210 _("Ask"), GINT_TO_POINTER(FT_ASK
),
211 _("Auto Accept"), GINT_TO_POINTER(FT_ACCEPT
),
212 _("Auto Reject"), GINT_TO_POINTER(FT_REJECT
),
218 context_menu(PurpleBlistNode
*node
, GList
**menu
, gpointer plugin
)
220 PurpleMenuAction
*action
;
222 if (!PURPLE_IS_BUDDY(node
) && !PURPLE_IS_CONTACT(node
) &&
223 !purple_blist_node_is_transient(node
))
226 action
= purple_menu_action_new(_("Autoaccept File Transfers..."),
227 PURPLE_CALLBACK(set_auto_accept_settings
), plugin
, NULL
);
228 (*menu
) = g_list_prepend(*menu
, action
);
231 static PurplePluginPrefFrame
*
232 get_plugin_pref_frame(PurplePlugin
*plugin
)
234 PurplePluginPrefFrame
*frame
;
235 PurplePluginPref
*pref
;
237 frame
= purple_plugin_pref_frame_new();
239 /* XXX: Is there a better way than this? There really should be. */
240 pref
= purple_plugin_pref_new_with_name_and_label(PREF_PATH
, _("Path to save the files in\n"
241 "(Please provide the full path)"));
242 purple_plugin_pref_frame_add(frame
, pref
);
244 pref
= purple_plugin_pref_new_with_name_and_label(PREF_STRANGER
,
245 _("When a file-transfer request arrives from a user who is\n"
246 "*not* on your buddy list:"));
247 purple_plugin_pref_set_pref_type(pref
, PURPLE_PLUGIN_PREF_CHOICE
);
248 purple_plugin_pref_add_choice(pref
, _("Ask"), GINT_TO_POINTER(FT_ASK
));
249 purple_plugin_pref_add_choice(pref
, _("Auto Accept"), GINT_TO_POINTER(FT_ACCEPT
));
250 purple_plugin_pref_add_choice(pref
, _("Auto Reject"), GINT_TO_POINTER(FT_REJECT
));
251 purple_plugin_pref_frame_add(frame
, pref
);
253 pref
= purple_plugin_pref_new_with_name_and_label(PREF_NOTIFY
,
254 _("Notify with a popup when an autoaccepted file transfer is complete\n"
255 "(only when there's no conversation with the sender)"));
256 purple_plugin_pref_frame_add(frame
, pref
);
258 pref
= purple_plugin_pref_new_with_name_and_label(PREF_NEWDIR
,
259 _("Create a new directory for each user"));
260 purple_plugin_pref_frame_add(frame
, pref
);
262 pref
= purple_plugin_pref_new_with_name_and_label(PREF_ESCAPE
,
263 _("Escape the filenames"));
264 purple_plugin_pref_frame_add(frame
, pref
);
269 static PurplePluginInfo
*
270 plugin_query(GError
**error
)
272 const gchar
* const authors
[] = PLUGIN_AUTHORS
;
274 return purple_plugin_info_new(
277 "version", DISPLAY_VERSION
,
278 "category", PLUGIN_CATEGORY
,
279 "summary", PLUGIN_SUMMARY
,
280 "description", PLUGIN_DESCRIPTION
,
282 "website", PURPLE_WEBSITE
,
283 "abi-version", PURPLE_ABI_VERSION
,
284 "pref-frame-cb", get_plugin_pref_frame
,
290 plugin_load(PurplePlugin
*plugin
, GError
**error
)
294 dirname
= g_build_filename(purple_user_dir(), "autoaccept", NULL
);
295 purple_prefs_add_none(PREF_PREFIX
);
296 purple_prefs_add_string(PREF_PATH
, dirname
);
297 purple_prefs_add_bool(PREF_NOTIFY
, TRUE
);
298 purple_prefs_add_bool(PREF_NEWDIR
, TRUE
);
299 purple_prefs_add_bool(PREF_ESCAPE
, TRUE
);
302 /* migrate the old pref (we should only care if the plugin is actually *used*) */
304 * TODO: We should eventually call purple_prefs_remove(PREFS_STRANGER_OLD)
305 * to clean up after ourselves, but we don't want to do it yet
306 * so that we don't break users who share a .purple directory
307 * between old libpurple clients and new libpurple clients.
308 * --Mark Doliner, 2011-01-03
310 if (!purple_prefs_exists(PREF_STRANGER
)) {
311 if (purple_prefs_exists(PREF_STRANGER_OLD
) && purple_prefs_get_bool(PREF_STRANGER_OLD
))
312 purple_prefs_add_int(PREF_STRANGER
, FT_REJECT
);
314 purple_prefs_set_int(PREF_STRANGER
, FT_ASK
);
317 purple_signal_connect(purple_xfers_get_handle(), "file-recv-request", plugin
,
318 PURPLE_CALLBACK(file_recv_request_cb
), plugin
);
319 purple_signal_connect(purple_blist_get_handle(), "blist-node-extended-menu", plugin
,
320 PURPLE_CALLBACK(context_menu
), plugin
);
325 plugin_unload(PurplePlugin
*plugin
, GError
**error
)
330 PURPLE_PLUGIN_INIT(PLUGIN_STATIC_NAME
, plugin_query
, plugin_load
, plugin_unload
);