Tree of tag thunar-4.20.7 (commit df0e054) from https://gitlab.xfce.org/xfce/thunar. Upstream history is not included here to keep the repository small.
705 lines
21 KiB
C
705 lines
21 KiB
C
/* vi:set et ai sw=2 sts=2 ts=2: */
|
|
/*-
|
|
* Copyright (c) 2006 Benedikt Meurer <benny@xfce.org>
|
|
* Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>
|
|
*
|
|
* This program 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 program 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 program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
* Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_TYPES_H
|
|
#include <sys/types.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_WAIT_H
|
|
#include <sys/wait.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_ERRNO_H
|
|
#include <errno.h>
|
|
#endif
|
|
#ifdef HAVE_MEMORY_H
|
|
#include <memory.h>
|
|
#endif
|
|
#ifdef HAVE_SIGNAL_H
|
|
#include <signal.h>
|
|
#endif
|
|
#ifdef HAVE_STDARG_H
|
|
#include <stdarg.h>
|
|
#endif
|
|
#ifdef HAVE_STDLIB_H
|
|
#include <stdlib.h>
|
|
#endif
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
#ifdef HAVE_TIME_H
|
|
#include <time.h>
|
|
#endif
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
#include <exo/exo.h>
|
|
#include <gio/gio.h>
|
|
#include <glib.h>
|
|
#include <glib/gstdio.h>
|
|
#include <gtk/gtk.h>
|
|
#include <libxfce4util/libxfce4util.h>
|
|
|
|
|
|
|
|
typedef struct _TseData TseData;
|
|
|
|
struct _TseData
|
|
{
|
|
GFileInfo *info;
|
|
GFile *file;
|
|
};
|
|
|
|
|
|
|
|
/* well known archive types */
|
|
static const char *TSE_MIME_TYPES[] = {
|
|
"application/x-7z-compressed",
|
|
"application/x-7z-compressed-tar",
|
|
"application/x-ar",
|
|
"application/x-arj",
|
|
"application/x-brotli",
|
|
"application/x-brotli-compressed-tar",
|
|
"application/x-bzip",
|
|
"application/x-bzip-compressed-tar",
|
|
"application/x-compress",
|
|
"application/x-compressed-tar",
|
|
"application/x-deb",
|
|
"application/x-gtar",
|
|
"application/x-gzip",
|
|
"application/x-lha",
|
|
"application/x-lhz",
|
|
"application/x-lzma",
|
|
"application/x-lzma-compressed-tar",
|
|
"application/x-rar",
|
|
"application/x-rar-compressed",
|
|
"application/x-tar",
|
|
"application/x-xz",
|
|
"application/x-xz-compressed-tar",
|
|
"application/x-zip",
|
|
"application/x-zip-compressed",
|
|
"application/zip",
|
|
"multipart/x-zip",
|
|
"application/x-rpm",
|
|
"application/x-jar",
|
|
"application/x-java-archive",
|
|
"application/x-lzop",
|
|
"application/x-zoo",
|
|
"application/x-cd-image",
|
|
"application/zstd",
|
|
"application/x-zstd-compressed-tar",
|
|
};
|
|
|
|
|
|
|
|
/* compress response ids */
|
|
enum
|
|
{
|
|
TSE_RESPONSE_COMPRESS,
|
|
TSE_RESPONSE_PLAIN,
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
tse_error (GError *error,
|
|
const gchar *format,
|
|
...)
|
|
{
|
|
GtkWidget *dialog;
|
|
va_list args;
|
|
gchar *primary_text;
|
|
|
|
/* determine the primary error text */
|
|
va_start (args, format);
|
|
primary_text = g_strdup_vprintf (format, args);
|
|
va_end (args);
|
|
|
|
/* allocate the error dialog */
|
|
dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "%s.", primary_text);
|
|
gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
|
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s.", error->message);
|
|
|
|
/* display the dialog */
|
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
|
|
|
/* cleanup */
|
|
gtk_widget_destroy (dialog);
|
|
g_free (primary_text);
|
|
}
|
|
|
|
/**
|
|
* Check if the single file is already an archive
|
|
**/
|
|
static gboolean
|
|
tse_file_is_archive (GFileInfo *file_info)
|
|
{
|
|
const gchar *content_type;
|
|
guint n;
|
|
/* determine the content type */
|
|
content_type = g_file_info_get_attribute_string (file_info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
|
|
if (content_type == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
for (n = 0; n < G_N_ELEMENTS (TSE_MIME_TYPES); ++n)
|
|
{
|
|
/* check if this mime type matches */
|
|
if (g_content_type_is_a (content_type, TSE_MIME_TYPES[n]))
|
|
{
|
|
/* yep, that's a match then */
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static gint
|
|
tse_ask_compress (GList *infos)
|
|
{
|
|
TseData *tse_data;
|
|
GtkWidget *message;
|
|
guint64 total_size = 0;
|
|
GList *lp;
|
|
gint response = TSE_RESPONSE_PLAIN;
|
|
gint n_archives = 0;
|
|
gint n_infos = 0;
|
|
|
|
/* check the file infos */
|
|
for (lp = infos; lp != NULL; lp = lp->next, ++n_infos)
|
|
{
|
|
/* need to compress if we have any directories */
|
|
tse_data = (TseData *) lp->data;
|
|
|
|
if (g_file_info_get_file_type (tse_data->info) == G_FILE_TYPE_DIRECTORY)
|
|
return TSE_RESPONSE_COMPRESS;
|
|
|
|
if (tse_file_is_archive (tse_data->info))
|
|
++n_archives;
|
|
|
|
/* add file size to total */
|
|
total_size += g_file_info_get_size (tse_data->info);
|
|
}
|
|
|
|
/* check if the total size is larger than 200KiB, or we have more than
|
|
* one file, and at least one of the files is not already an archive.
|
|
*/
|
|
if ((n_infos > 1 || total_size > 200 * 1024) && n_infos != n_archives)
|
|
{
|
|
/* check if we have more than one file */
|
|
if (G_LIKELY (n_infos == 1))
|
|
{
|
|
/* ask the user whether to compress the file */
|
|
tse_data = (TseData *) infos->data;
|
|
message = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
|
|
_("Send \"%s\" as compressed archive?"),
|
|
g_file_info_get_display_name (tse_data->info));
|
|
gtk_window_set_title (GTK_WINDOW (message), _("Send email"));
|
|
gtk_dialog_add_button (GTK_DIALOG (message), _("_Cancel"), GTK_RESPONSE_CANCEL);
|
|
gtk_dialog_add_button (GTK_DIALOG (message), _("Send _directly"), TSE_RESPONSE_PLAIN);
|
|
gtk_dialog_add_button (GTK_DIALOG (message), _("Send com_pressed"), TSE_RESPONSE_COMPRESS);
|
|
gtk_dialog_set_default_response (GTK_DIALOG (message), TSE_RESPONSE_COMPRESS);
|
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), _("When sending a file via email, you can either choose to "
|
|
"send the file directly, as is, or compress the file before "
|
|
"attaching it to an email. It is highly recommended to "
|
|
"compress large files before sending them."));
|
|
response = gtk_dialog_run (GTK_DIALOG (message));
|
|
gtk_widget_destroy (message);
|
|
}
|
|
else
|
|
{
|
|
/* ask the user whether to send files as archive */
|
|
message = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
|
|
ngettext ("Send %d file as compressed archive?",
|
|
"Send %d files as compressed archive?",
|
|
n_infos),
|
|
n_infos);
|
|
gtk_window_set_title (GTK_WINDOW (message), _("Send email"));
|
|
gtk_dialog_add_button (GTK_DIALOG (message), _("_Cancel"), GTK_RESPONSE_CANCEL);
|
|
gtk_dialog_add_button (GTK_DIALOG (message), _("Send _directly"), TSE_RESPONSE_PLAIN);
|
|
gtk_dialog_add_button (GTK_DIALOG (message), _("Send as _archive"), TSE_RESPONSE_COMPRESS);
|
|
gtk_dialog_set_default_response (GTK_DIALOG (message), TSE_RESPONSE_COMPRESS);
|
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (message), _("When sending multiple files via email, you can either choose "
|
|
"to send the files directly, attaching multiple files to an "
|
|
"email, or send all files compressed into a single archive "
|
|
"file and attach the archive. It is highly recommended to "
|
|
"send multiple large files as archive."));
|
|
response = gtk_dialog_run (GTK_DIALOG (message));
|
|
gtk_widget_destroy (message);
|
|
}
|
|
}
|
|
|
|
return response;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
tse_child_watch (GPid pid,
|
|
gint status,
|
|
gpointer user_data)
|
|
{
|
|
g_object_set_data (G_OBJECT (user_data), I_ ("tse-child-status"), GINT_TO_POINTER (status));
|
|
gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_YES);
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
tse_progress_cb (gpointer user_data)
|
|
{
|
|
GtkWidget *pulse = user_data;
|
|
|
|
gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pulse));
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
tse_progress (const gchar *working_directory,
|
|
gchar **argv,
|
|
GError **error)
|
|
{
|
|
GtkWidget *progress;
|
|
GtkWidget *dialog;
|
|
GtkWidget *image;
|
|
GtkWidget *label;
|
|
GtkWidget *hbox;
|
|
GtkWidget *vbox;
|
|
gboolean succeed = FALSE;
|
|
GPid pid;
|
|
guint pulse_timer_id;
|
|
gint watch_id;
|
|
gint response;
|
|
gint status;
|
|
|
|
/* try to run the command */
|
|
if (!g_spawn_async (working_directory, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, NULL, NULL, &pid, error))
|
|
return FALSE;
|
|
|
|
/* allocate the progress dialog */
|
|
dialog = gtk_dialog_new_with_buttons (_("Compressing files..."),
|
|
NULL, 0,
|
|
_("_Cancel"), GTK_RESPONSE_CANCEL,
|
|
NULL);
|
|
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CANCEL);
|
|
gtk_window_set_default_size (GTK_WINDOW (dialog), 300, -1);
|
|
|
|
/* setup the hbox */
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
|
|
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), hbox, TRUE, TRUE, 0);
|
|
gtk_widget_show (hbox);
|
|
|
|
/* setup the image */
|
|
image = gtk_image_new_from_icon_name ("gnome-package", GTK_ICON_SIZE_DIALOG);
|
|
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
|
|
gtk_widget_set_valign (image, GTK_ALIGN_START);
|
|
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
|
|
gtk_widget_show (image);
|
|
|
|
/* setup the vbox */
|
|
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
|
|
gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
|
|
gtk_widget_show (vbox);
|
|
|
|
/* setup the label */
|
|
label = gtk_label_new (_("Compressing files..."));
|
|
gtk_label_set_xalign (GTK_LABEL (label), 0.0f);
|
|
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
|
gtk_widget_show (label);
|
|
|
|
/* setup the progress bar */
|
|
progress = gtk_progress_bar_new ();
|
|
gtk_box_pack_start (GTK_BOX (vbox), progress, FALSE, FALSE, 0);
|
|
gtk_widget_show (progress);
|
|
|
|
/* start the child watch */
|
|
watch_id = g_child_watch_add (pid, tse_child_watch, dialog);
|
|
|
|
/* start the pulse timer */
|
|
pulse_timer_id = g_timeout_add (125, tse_progress_cb, progress);
|
|
|
|
/* run the dialog */
|
|
response = gtk_dialog_run (GTK_DIALOG (dialog));
|
|
if (response == GTK_RESPONSE_YES)
|
|
{
|
|
/* check if the command failed */
|
|
status = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (dialog), I_ ("tse-child-status")));
|
|
if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
|
|
{
|
|
/* tell the user that the command failed */
|
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("ZIP command terminated with error %d"), status);
|
|
}
|
|
else
|
|
{
|
|
/* the command succeed */
|
|
succeed = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* terminate the ZIP command */
|
|
kill (pid, SIGQUIT);
|
|
}
|
|
|
|
/* cleanup */
|
|
g_source_remove (pulse_timer_id);
|
|
gtk_widget_destroy (dialog);
|
|
g_source_remove (watch_id);
|
|
|
|
return succeed;
|
|
}
|
|
|
|
|
|
|
|
#ifndef HAVE_MKDTEMP
|
|
static gchar *
|
|
mkdtemp (gchar *tmpl)
|
|
{
|
|
static const gchar LETTERS[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
static guint64 value;
|
|
guint64 v;
|
|
gint len;
|
|
gint i, j;
|
|
|
|
len = strlen (tmpl);
|
|
if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX") != 0)
|
|
{
|
|
errno = EINVAL;
|
|
return NULL;
|
|
}
|
|
|
|
value += ((guint64) time (NULL)) ^ getpid ();
|
|
|
|
for (i = 0; i < TMP_MAX; ++i, value += 7777)
|
|
{
|
|
/* fill in the random bits */
|
|
for (j = 0, v = value; j < 6; ++j)
|
|
tmpl[(len - 6) + j] = LETTERS[v % 62];
|
|
v /= 62;
|
|
|
|
/* try to create the directory */
|
|
if (g_mkdir (tmpl, 0700) == 0)
|
|
return tmpl;
|
|
else if (errno != EEXIST)
|
|
return NULL;
|
|
}
|
|
|
|
errno = EEXIST;
|
|
return NULL;
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
static gboolean
|
|
tse_compress (GList *infos,
|
|
gchar **zipfile_return)
|
|
{
|
|
TseData *tse_data;
|
|
gboolean succeed = TRUE;
|
|
GError *error = NULL;
|
|
GFile *parent;
|
|
GFile *parent_parent;
|
|
gchar **argv;
|
|
gchar *base_name;
|
|
gchar *zipfile;
|
|
gchar *tmppath;
|
|
gchar *tmpdir;
|
|
gchar *path;
|
|
gchar *dot;
|
|
GList *lp;
|
|
gint n;
|
|
|
|
/* create a temporary directory */
|
|
tmpdir = g_strdup ("/tmp/thunar-sendto-email.XXXXXX");
|
|
if (G_UNLIKELY (mkdtemp (tmpdir) == NULL))
|
|
{
|
|
/* tell the user that we failed to create a temporary directory */
|
|
error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (errno), g_strerror (errno));
|
|
tse_error (error, _("Failed to create temporary directory"));
|
|
g_error_free (error);
|
|
return FALSE;
|
|
}
|
|
|
|
/* check if we have only a single file/folder to compress */
|
|
if (G_LIKELY (infos != NULL && infos->next == NULL))
|
|
{
|
|
/* determine the name for the ZIP file */
|
|
tse_data = (TseData *) infos->data;
|
|
path = g_strdup (g_file_info_get_display_name (tse_data->info));
|
|
dot = strrchr (path, '.');
|
|
if (G_LIKELY (dot != NULL))
|
|
*dot = '\0';
|
|
zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, path, ".zip", NULL);
|
|
g_free (path);
|
|
}
|
|
else
|
|
{
|
|
/* determine the name for the ZIP file */
|
|
tse_data = (TseData *) infos->data;
|
|
parent = g_file_get_parent (tse_data->file);
|
|
|
|
/* we assume the parent exists because we only allow non-root
|
|
* files as TseData in main () */
|
|
g_assert (parent != NULL);
|
|
|
|
parent_parent = g_file_get_parent (parent);
|
|
|
|
if (parent_parent != NULL)
|
|
{
|
|
/* use the parent directory's name */
|
|
base_name = g_file_get_basename (parent);
|
|
zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, base_name, ".zip", NULL);
|
|
g_free (base_name);
|
|
|
|
g_object_unref (parent_parent);
|
|
}
|
|
else
|
|
{
|
|
/* use the first file's name */
|
|
zipfile = g_strconcat (tmpdir, G_DIR_SEPARATOR_S, g_file_info_get_display_name (tse_data->info), ".zip", NULL);
|
|
}
|
|
|
|
g_object_unref (parent);
|
|
}
|
|
|
|
/* generate the argument list for the ZIP command */
|
|
argv = g_new0 (gchar *, g_list_length (infos) + 5);
|
|
argv[0] = g_strdup ("zip");
|
|
argv[1] = g_strdup ("-q");
|
|
argv[2] = g_strdup ("-r");
|
|
argv[3] = g_strdup (zipfile);
|
|
for (lp = infos, n = 4; lp != NULL && succeed; lp = lp->next, ++n)
|
|
{
|
|
/* create a symlink for the file to the tmp dir */
|
|
tse_data = (TseData *) lp->data;
|
|
path = g_file_get_path (tse_data->file);
|
|
|
|
if (path == NULL)
|
|
{
|
|
error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (ENOTSUP), g_strerror (errno));
|
|
tse_error (error, _("Failed to create symbolic link for \"%s\""), g_file_info_get_display_name (tse_data->info));
|
|
g_error_free (error);
|
|
}
|
|
else
|
|
{
|
|
tmppath = g_build_filename (tmpdir, g_file_get_basename (tse_data->file), NULL);
|
|
succeed = (symlink (path, tmppath) == 0);
|
|
if (G_UNLIKELY (!succeed))
|
|
{
|
|
/* tell the user that we failed to create a symlink for this file */
|
|
error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (errno), g_strerror (errno));
|
|
tse_error (error, _("Failed to create symbolic link for \"%s\""), g_file_info_get_display_name (tse_data->info));
|
|
g_error_free (error);
|
|
}
|
|
else
|
|
{
|
|
/* add the file to the ZIP command line */
|
|
argv[n] = g_path_get_basename (tmppath);
|
|
}
|
|
g_free (tmppath);
|
|
g_free (path);
|
|
}
|
|
}
|
|
|
|
/* check if we succeed up to this point */
|
|
if (G_LIKELY (succeed))
|
|
{
|
|
/* try to run the ZIP command */
|
|
succeed = tse_progress (tmpdir, argv, &error);
|
|
if (G_UNLIKELY (!succeed))
|
|
{
|
|
/* check if we failed or the user cancelled */
|
|
if (G_LIKELY (error != NULL))
|
|
{
|
|
/* tell the user that we failed to compress the file(s) */
|
|
tse_error (error, ngettext ("Failed to compress %d file", "Failed to compress %d files", g_list_length (infos)),
|
|
g_list_length (infos));
|
|
g_error_free (error);
|
|
}
|
|
|
|
/* delete the temporary directory */
|
|
dot = g_strdup_printf ("rm -rf '%s'", tmpdir);
|
|
g_spawn_command_line_sync (dot, NULL, NULL, NULL, NULL);
|
|
g_free (dot);
|
|
}
|
|
else
|
|
{
|
|
/* return the path to the compressed file */
|
|
*zipfile_return = zipfile;
|
|
zipfile = NULL;
|
|
}
|
|
}
|
|
|
|
/* cleanup */
|
|
g_strfreev (argv);
|
|
g_free (zipfile);
|
|
g_free (tmpdir);
|
|
|
|
return succeed;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
main (int argc, char **argv)
|
|
{
|
|
GFileInfo *info;
|
|
TseData *tse_data;
|
|
GFile *file;
|
|
GFile *parent;
|
|
GString *mailto;
|
|
GError *error = NULL;
|
|
GList *infos = NULL;
|
|
gchar **attachments = NULL;
|
|
gchar *zipfile = NULL;
|
|
GList *lp;
|
|
gint response;
|
|
gint n;
|
|
|
|
/* setup translation domain */
|
|
xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
|
|
|
|
#ifdef G_ENABLE_DEBUG
|
|
/* Do NOT remove this line for now, If something doesn't work,
|
|
* fix your code instead!
|
|
*/
|
|
g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
|
|
#endif
|
|
|
|
/* initialize Gtk+ */
|
|
gtk_init (&argc, &argv);
|
|
|
|
/* set default icon for dialogs */
|
|
gtk_window_set_default_icon_name ("internet-mail");
|
|
|
|
/* verify that atleast one file was supplied */
|
|
if (G_UNLIKELY (argc == 1))
|
|
{
|
|
g_fprintf (stderr, "Usage: thunar-sendto-email [FILES...]\n");
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
/* determine the GFiles and GFileInfos (bundled as TseData) for the files */
|
|
for (n = 1; n < argc; ++n)
|
|
{
|
|
/* try to transform to a GFile */
|
|
file = g_file_new_for_commandline_arg (argv[n]);
|
|
|
|
/* verify that we're not trying to send root */
|
|
parent = g_file_get_parent (file);
|
|
if (parent == NULL)
|
|
{
|
|
error = g_error_new_literal (G_FILE_ERROR, g_file_error_from_errno (EFBIG), g_strerror (EFBIG));
|
|
g_fprintf (stderr, "thunar-sendto-email: Invalid argument \"%s\": %s\n", argv[n], error->message);
|
|
g_error_free (error);
|
|
g_object_unref (file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
g_object_unref (parent);
|
|
}
|
|
|
|
/* try to determine the info */
|
|
info = g_file_query_info (file,
|
|
G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
|
|
G_FILE_QUERY_INFO_NONE, NULL, &error);
|
|
|
|
/* check if we failed */
|
|
if (G_UNLIKELY (info == NULL))
|
|
{
|
|
g_fprintf (stderr, "thunar-sendto-email: Invalid argument \"%s\": %s\n", argv[n], error->message);
|
|
g_error_free (error);
|
|
g_object_unref (file);
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
tse_data = g_slice_new0 (TseData);
|
|
tse_data->info = info;
|
|
tse_data->file = file;
|
|
|
|
/* add to our list of infos */
|
|
infos = g_list_append (infos, tse_data);
|
|
}
|
|
|
|
/* check whether to compress the files */
|
|
response = tse_ask_compress (infos);
|
|
if (response == TSE_RESPONSE_COMPRESS)
|
|
{
|
|
/* try to compress the files */
|
|
if (tse_compress (infos, &zipfile))
|
|
{
|
|
/* we have only a single attachment now */
|
|
attachments = g_new0 (gchar *, 2);
|
|
attachments[0] = g_filename_to_uri (zipfile, NULL, NULL);
|
|
g_free (zipfile);
|
|
}
|
|
}
|
|
else if (response == TSE_RESPONSE_PLAIN)
|
|
{
|
|
/* attach the files one by one */
|
|
attachments = g_new0 (gchar *, g_list_length (infos) + 1);
|
|
for (lp = infos, n = 0; lp != NULL; lp = lp->next, ++n)
|
|
{
|
|
tse_data = (TseData *) lp->data;
|
|
attachments[n] = g_file_get_uri (tse_data->file);
|
|
}
|
|
}
|
|
|
|
/* check if we have anything to attach */
|
|
if (G_LIKELY (attachments != NULL))
|
|
{
|
|
/* no specific email address */
|
|
mailto = g_string_new ("?");
|
|
for (n = 0; attachments[n] != NULL; ++n)
|
|
g_string_append_printf (mailto, "attach=%s&", attachments[n]);
|
|
g_strfreev (attachments);
|
|
|
|
/* open the mail composer */
|
|
if (!exo_execute_preferred_application ("MailReader", mailto->str, NULL, NULL, &error))
|
|
{
|
|
/* tell the user that we failed */
|
|
tse_error (error, _("Failed to compose new email"));
|
|
g_error_free (error);
|
|
}
|
|
|
|
/* cleanup */
|
|
g_string_free (mailto, TRUE);
|
|
}
|
|
|
|
/* cleanup */
|
|
for (lp = infos; lp != NULL; lp = lp->next)
|
|
{
|
|
tse_data = (TseData *) lp->data;
|
|
g_object_unref (tse_data->file);
|
|
g_object_unref (tse_data->info);
|
|
g_slice_free (TseData, tse_data);
|
|
}
|
|
g_list_free (infos);
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|