aboutsummaryrefslogblamecommitdiffstats
path: root/plugins/mailing-list-actions/mailing-list-actions.c
blob: 069a0bd06cde13eba7bb4c4c6441d12ad261040e (plain) (tree)
1
2
3
4
5
6
7
8
9
  


                                                                           
  



                                                                             
  

                                                                           




                                                        

                                                          

   



                    

                   
                    


                           
 





                                         



                                   

                              
 
                        





                                                                            










                                








                                                   










                                                               



                                                                          


                                                    

                                 


                 
 



                                          
                            
                          












                                                   
 
           


                                           
 
                                               

                                
                               

                                  
                                   
                      
                        
                              
                                  
                                     
                          

                          
                             
 

                                                              

                                                                   




                                                          





                                                                           

                       

















                                                                       

                                                            
                                                              
 

                                                       
 


                                              
 



                                                                            

                                                                  






                                                                       



                                                             
                                                                              




                           
                                                  

                                                                

                                                                           


                                  
 




                                                                                     
                                                     
                                                                 
                                                                             

                                  
 
                                     
                                                             
 
                                                              
                                                               
                                                                        
                            
                                                                                     
                                                                         
                                                   

                                                                        

                                                            
                                                           
                                                                                    



                                                                                              
                                                               

                                                                              
                                                                                              


                                  
                                         
                                                 
                                  
                 
                             

                                  
 





                                                        
 
                                                     
                                                                              
 
     


                                        
                                 
                     

                                     





                                      


                                  

                            
                                 
 


                                                          
 






                                                            
 

                                                   



                                                        
 

                                 
                                 




















                                                       

 


                                                 
 
                                                    

 


                                                      
 
                                                         

 


                                                        
 
                                                           

 























































                                                                                    
                                 


                                                
 

                                                                          





                                                                 
 


















                                                                         

 


                                            
 


                                                            

 


                                               
 






                                                                    
 
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation.
 *
 * 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 Lesser General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
 *
 * Authors:
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 * Copyright (C) 2004 Meilof Veeningen <meilof@wanadoo.nl>
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib/gi18n-lib.h>

#include <e-util/e-util.h>

#include <shell/e-shell-view.h>
#include <shell/e-shell-window.h>
#include <shell/e-shell-window-actions.h>

#include <composer/e-msg-composer.h>

#include <mail/e-mail-browser.h>
#include <mail/e-mail-reader.h>
#include <mail/em-composer-utils.h>
#include <mail/em-config.h>
#include <mail/em-utils.h>
#include <mail/message-list.h>

/* EAlert Message IDs */
#define MESSAGE_PREFIX          "org.gnome.mailing-list-actions:"
#define MESSAGE_NO_ACTION       MESSAGE_PREFIX "no-action"
#define MESSAGE_NO_HEADER       MESSAGE_PREFIX "no-header"
#define MESSAGE_ASK_SEND_MESSAGE    MESSAGE_PREFIX "ask-send-message"
#define MESSAGE_MALFORMED_HEADER    MESSAGE_PREFIX "malformed-header"
#define MESSAGE_POSTING_NOT_ALLOWED MESSAGE_PREFIX "posting-not-allowed"

typedef enum {
    EMLA_ACTION_HELP,
    EMLA_ACTION_UNSUBSCRIBE,
    EMLA_ACTION_SUBSCRIBE,
    EMLA_ACTION_POST,
    EMLA_ACTION_OWNER,
    EMLA_ACTION_ARCHIVE
} EmlaAction;

typedef struct {
    /* action enumeration */
    EmlaAction action;

    /* whether the user needs to edit a mailto:
     * message (e.g. for post action) */
    gboolean interactive;

    /* header representing the action */
    const gchar *header;
} EmlaActionHeader;

const EmlaActionHeader emla_action_headers[] = {
    { EMLA_ACTION_HELP,        FALSE, "List-Help" },
    { EMLA_ACTION_UNSUBSCRIBE, TRUE,  "List-Unsubscribe" },
    { EMLA_ACTION_SUBSCRIBE,   FALSE, "List-Subscribe" },
    { EMLA_ACTION_POST,        TRUE,  "List-Post" },
    { EMLA_ACTION_OWNER,       TRUE,  "List-Owner" },
    { EMLA_ACTION_ARCHIVE,     FALSE, "List-Archive" },
};

gboolean    mail_browser_init       (GtkUIManager *ui_manager,
                         EMailBrowser *browser);
gboolean    mail_shell_view_init        (GtkUIManager *ui_manager,
                         EShellView *shell_view);
gint e_plugin_lib_enable (EPlugin *ep, gint enable);

gint
e_plugin_lib_enable (EPlugin *ep,
                     gint enable)
{
    return 0;
}

typedef struct _AsyncContext AsyncContext;

struct _AsyncContext {
    EActivity *activity;
    EMailReader *reader;
    EmlaAction action;
};

static void
async_context_free (AsyncContext *context)
{
    if (context->activity != NULL)
        g_object_unref (context->activity);

    if (context->reader != NULL)
        g_object_unref (context->reader);

    g_slice_free (AsyncContext, context);
}

static void
emla_list_action_cb (CamelFolder *folder,
                     GAsyncResult *result,
                     AsyncContext *context)
{
    const gchar *header = NULL, *headerpos;
    gchar *end, *url = NULL;
    gint t;
    EMsgComposer *composer;
    EAlertSink *alert_sink;
    CamelMimeMessage *message;
    gint send_message_response;
    EShell *shell;
    ESource *source;
    EMailBackend *backend;
    ESourceRegistry *registry;
    EShellBackend *shell_backend;
    GtkWindow *window;
    CamelStore *store;
    const gchar *uid;
    GError *error = NULL;

    window = e_mail_reader_get_window (context->reader);
    backend = e_mail_reader_get_backend (context->reader);
    alert_sink = e_activity_get_alert_sink (context->activity);

    shell_backend = E_SHELL_BACKEND (backend);
    shell = e_shell_backend_get_shell (shell_backend);

    registry = e_shell_get_registry (shell);

    message = camel_folder_get_message_finish (folder, result, &error);

    if (e_activity_handle_cancellation (context->activity, error)) {
        g_warn_if_fail (message == NULL);
        async_context_free (context);
        g_error_free (error);
        return;

    } else if (error != NULL) {
        g_warn_if_fail (message == NULL);
        e_alert_submit (
            alert_sink, "mail:no-retrieve-message",
            error->message, NULL);
        async_context_free (context);
        g_error_free (error);
        return;
    }

    g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));

    /* Finalize the activity here so we don't leave a
     * message in the task bar while display a dialog. */
    e_activity_set_state (context->activity, E_ACTIVITY_COMPLETED);
    g_object_unref (context->activity);
    context->activity = NULL;

    store = camel_folder_get_parent_store (folder);
    uid = camel_service_get_uid (CAMEL_SERVICE (store));
    source = e_source_registry_ref_source (registry, uid);

    /* Reuse this to hold the mail identity UID. */
    uid = NULL;

    if (source != NULL) {
        ESourceMailAccount *extension;
        const gchar *extension_name;

        extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT;
        extension = e_source_get_extension (source, extension_name);
        uid = e_source_mail_account_get_identity_uid (extension);
    }

    for (t = 0; t < G_N_ELEMENTS (emla_action_headers); t++) {
        if (emla_action_headers[t].action == context->action) {
            header = camel_medium_get_header (
                CAMEL_MEDIUM (message),
                emla_action_headers[t].header);
            if (header != NULL)
                break;
        }
    }

    if (!header) {
        /* there was no header matching the action */
        e_alert_run_dialog_for_args (window, MESSAGE_NO_HEADER, NULL);
        goto exit;
    }

    headerpos = header;

    if (context->action == EMLA_ACTION_POST) {
        while (*headerpos == ' ') headerpos++;
        if (g_ascii_strcasecmp (headerpos, "NO") == 0) {
            e_alert_run_dialog_for_args (
                window, MESSAGE_POSTING_NOT_ALLOWED, NULL);
            goto exit;
        }
    }

    /* parse the action value */
    while (*headerpos) {
        /* skip whitespace */
        while (*headerpos == ' ') headerpos++;
        if (*headerpos != '<' || (end = strchr (headerpos++, '>')) == NULL) {
            e_alert_run_dialog_for_args (
                window, MESSAGE_MALFORMED_HEADER,
                emla_action_headers[t].header, header, NULL);
            goto exit;
        }

        /* get URL portion */
        url = g_strndup (headerpos, end - headerpos);

        if (url && strncmp (url, "mailto:", 6) == 0) {
            if (emla_action_headers[t].interactive)
                send_message_response = GTK_RESPONSE_NO;
            else
                send_message_response = e_alert_run_dialog_for_args (
                    window, MESSAGE_ASK_SEND_MESSAGE,
                    url, NULL);

            if (send_message_response == GTK_RESPONSE_YES) {
                EComposerHeaderTable *table;

                /* directly send message */
                composer = e_msg_composer_new_from_url (shell, url);
                table = e_msg_composer_get_header_table (composer);

                if (uid != NULL)
                    e_composer_header_table_set_identity_uid (table, uid);
                e_msg_composer_send (composer);
            } else if (send_message_response == GTK_RESPONSE_NO) {
                /* show composer */
                em_utils_compose_new_message_with_mailto (shell, url, folder);
            }

            goto exit;
        } else if (url && *url) {
            e_show_uri (window, url);
            goto exit;
        }
        g_free (url);
        url = NULL;
        headerpos = end++;

        /* ignore everything 'till next comma */
        headerpos = strchr (headerpos, ',');
        if (!headerpos)
            break;
        headerpos++;
    }

    /* if we got here, there's no valid action */
    e_alert_run_dialog_for_args (window, MESSAGE_NO_ACTION, header, NULL);

exit:
    if (source != NULL)
        g_object_unref (source);

    g_object_unref (message);
    g_free (url);

    async_context_free (context);
}

static void
emla_list_action (EMailReader *reader,
                  EmlaAction action)
{
    EActivity *activity;
    AsyncContext *context;
    GCancellable *cancellable;
    CamelFolder *folder;
    GPtrArray *uids;
    const gchar *message_uid;

    uids = e_mail_reader_get_selected_uids (reader);
    g_return_if_fail (uids != NULL && uids->len == 1);
    message_uid = g_ptr_array_index (uids, 0);

    activity = e_mail_reader_new_activity (reader);
    cancellable = e_activity_get_cancellable (activity);

    context = g_slice_new0 (AsyncContext);
    context->activity = activity;
    context->reader = g_object_ref (reader);
    context->action = action;

    folder = e_mail_reader_ref_folder (reader);

    camel_folder_get_message (
        folder, message_uid, G_PRIORITY_DEFAULT,
        cancellable, (GAsyncReadyCallback)
        emla_list_action_cb, context);

    g_clear_object (&folder);

    g_ptr_array_unref (uids);
}

static void
action_mailing_list_archive_cb (GtkAction *action,
                                EMailReader *reader)
{
    emla_list_action (reader, EMLA_ACTION_ARCHIVE);
}

static void
action_mailing_list_help_cb (GtkAction *action,
                             EMailReader *reader)
{
    emla_list_action (reader, EMLA_ACTION_HELP);
}

static void
action_mailing_list_owner_cb (GtkAction *action,
                              EMailReader *reader)
{
    emla_list_action (reader, EMLA_ACTION_OWNER);
}

static void
action_mailing_list_post_cb (GtkAction *action,
                             EMailReader *reader)
{
    emla_list_action (reader, EMLA_ACTION_POST);
}

static void
action_mailing_list_subscribe_cb (GtkAction *action,
                                  EMailReader *reader)
{
    emla_list_action (reader, EMLA_ACTION_SUBSCRIBE);
}

static void
action_mailing_list_unsubscribe_cb (GtkAction *action,
                                    EMailReader *reader)
{
    emla_list_action (reader, EMLA_ACTION_UNSUBSCRIBE);
}

static GtkActionEntry mailing_list_entries[] = {

    { "mailing-list-archive",
      NULL,
      N_("Get List _Archive"),
      NULL,
      N_("Get an archive of the list this message belongs to"),
      G_CALLBACK (action_mailing_list_archive_cb) },

    { "mailing-list-help",
      NULL,
      N_("Get List _Usage Information"),
      NULL,
      N_("Get information about the usage of the list this message belongs to"),
      G_CALLBACK (action_mailing_list_help_cb) },

    { "mailing-list-owner",
      NULL,
      N_("Contact List _Owner"),
      NULL,
      N_("Contact the owner of the mailing list this message belongs to"),
      G_CALLBACK (action_mailing_list_owner_cb) },

    { "mailing-list-post",
      NULL,
      N_("_Post Message to List"),
      NULL,
      N_("Post a message to the mailing list this message belongs to"),
      G_CALLBACK (action_mailing_list_post_cb) },

    { "mailing-list-subscribe",
      NULL,
      N_("_Subscribe to List"),
      NULL,
      N_("Subscribe to the mailing list this message belongs to"),
      G_CALLBACK (action_mailing_list_subscribe_cb) },

    { "mailing-list-unsubscribe",
      NULL,
      N_("_Unsubscribe from List"),
      NULL,
      N_("Unsubscribe from the mailing list this message belongs to"),
      G_CALLBACK (action_mailing_list_unsubscribe_cb) },

    /*** Menus ***/

    { "mailing-list-menu",
      NULL,
      N_("Mailing _List"),
      NULL,
      NULL,
      NULL }
};

static void
update_actions_cb (EMailReader *reader,
                   guint32 state,
                   GtkActionGroup *action_group)
{
    gboolean sensitive;

    sensitive = (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST) != 0
         && (state & E_MAIL_READER_SELECTION_SINGLE) != 0;
    gtk_action_group_set_sensitive (action_group, sensitive);
}

static void
setup_actions (EMailReader *reader,
               GtkUIManager *ui_manager)
{
    GtkActionGroup *action_group;
    const gchar *domain = GETTEXT_PACKAGE;

    action_group = gtk_action_group_new ("mailing-list");
    gtk_action_group_set_translation_domain (action_group, domain);
    gtk_action_group_add_actions (
        action_group, mailing_list_entries,
        G_N_ELEMENTS (mailing_list_entries), reader);
    gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
    g_object_unref (action_group);

    /* GtkUIManager now owns the action group reference.
     * The signal we're connecting to will only be emitted
     * during the GtkUIManager's lifetime, so the action
     * group will not disappear on us. */

    g_signal_connect (
        reader, "update-actions",
        G_CALLBACK (update_actions_cb), action_group);
}

gboolean
mail_browser_init (GtkUIManager *ui_manager,
                   EMailBrowser *browser)
{
    setup_actions (E_MAIL_READER (browser), ui_manager);

    return TRUE;
}

gboolean
mail_shell_view_init (GtkUIManager *ui_manager,
                      EShellView *shell_view)
{
    EShellContent *shell_content;

    shell_content = e_shell_view_get_shell_content (shell_view);

    setup_actions (E_MAIL_READER (shell_content), ui_manager);

    return TRUE;
}