aboutsummaryrefslogblamecommitdiffstats
path: root/em-format/e-mail-part-list.c
blob: bcf7490634cc8d69df79f0b7b4429780ff9edfd4 (plain) (tree)





















                                                                             



















                                                             

                                                              


                                       
           

                                                    
 






                                                                


           

                                                      
 
                                                            
 











                                                                   
 



























                                                              

         












































                                                                       

         






                                                
                                                                 


















                                                                         



                                                                          
                                                       


                                   

                                                                        
                                              







































                                                                 




                                                
                                                                   
 
                                                    


               


































                                                                             
 









                                                                     
                                                 




                                                    
                                     

                                                      

                                                    


           

                                                    
 

                                


                                                                     
                                                     
 
                                                                 
 
                                                    
 


                                                                    

                                                                
 
                           
                                                                       
                    
                                                                      
 
                                                             
                                                         

                              

         


                                                      


   



                                                                    
  


                                                                            
  
                                                                             
                         






                                                       
 




                                                                      
 
                                                    
 
                                                                
 

                                                                 


                                                                        
                                                                      
 
                                                                   








                                                         

                                 
                                                                      
                               

         


                                                      
 


















                                                                        
/*
 * e-mail-part-list.c
 *
 * 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; either
 * version 2 of the License, or (at your option) version 3.
 *
 * 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the program; if not, see <http://www.gnu.org/licenses/>
 *
 */

#include <camel/camel.h>

#include "e-mail-part-list.h"

#define E_MAIL_PART_LIST_GET_PRIVATE(obj) \
    (G_TYPE_INSTANCE_GET_PRIVATE \
    ((obj), E_TYPE_MAIL_PART_LIST, EMailPartListPrivate))

struct _EMailPartListPrivate {
    CamelFolder *folder;
    CamelMimeMessage *message;
    gchar *message_uid;

    GQueue queue;
    GMutex queue_lock;
};

enum {
    PROP_0,
    PROP_FOLDER,
    PROP_MESSAGE,
    PROP_MESSAGE_UID
};

G_DEFINE_TYPE (EMailPartList, e_mail_part_list, G_TYPE_OBJECT)

static CamelObjectBag *registry = NULL;
G_LOCK_DEFINE_STATIC (registry);

static void
mail_part_list_set_folder (EMailPartList *part_list,
                           CamelFolder *folder)
{
    g_return_if_fail (part_list->priv->folder == NULL);

    /* The folder property is optional. */
    if (folder != NULL) {
        g_return_if_fail (CAMEL_IS_FOLDER (folder));
        part_list->priv->folder = g_object_ref (folder);
    }
}

static void
mail_part_list_set_message (EMailPartList *part_list,
                            CamelMimeMessage *message)
{
    g_return_if_fail (part_list->priv->message == NULL);

    /* The message property is optional. */
    if (message != NULL) {
        g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
        part_list->priv->message = g_object_ref (message);
    }
}

static void
mail_part_list_set_message_uid (EMailPartList *part_list,
                                const gchar *message_uid)
{
    g_return_if_fail (part_list->priv->message_uid == NULL);

    /* The message_uid property is optional. */
    part_list->priv->message_uid = g_strdup (message_uid);
}

static void
mail_part_list_set_property (GObject *object,
                             guint property_id,
                             const GValue *value,
                             GParamSpec *pspec)
{
    switch (property_id) {
        case PROP_FOLDER:
            mail_part_list_set_folder (
                E_MAIL_PART_LIST (object),
                g_value_get_object (value));
            return;

        case PROP_MESSAGE:
            mail_part_list_set_message (
                E_MAIL_PART_LIST (object),
                g_value_get_object (value));
            return;

        case PROP_MESSAGE_UID:
            mail_part_list_set_message_uid (
                E_MAIL_PART_LIST (object),
                g_value_get_string (value));
            return;
    }

    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
mail_part_list_get_property (GObject *object,
                             guint property_id,
                             GValue *value,
                             GParamSpec *pspec)
{
    switch (property_id) {
        case PROP_FOLDER:
            g_value_set_object (
                value,
                e_mail_part_list_get_folder (
                E_MAIL_PART_LIST (object)));
            return;

        case PROP_MESSAGE:
            g_value_set_object (
                value,
                e_mail_part_list_get_message (
                E_MAIL_PART_LIST (object)));
            return;

        case PROP_MESSAGE_UID:
            g_value_set_string (
                value,
                e_mail_part_list_get_message_uid (
                E_MAIL_PART_LIST (object)));
            return;
    }

    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}

static void
mail_part_list_dispose (GObject *object)
{
    EMailPartListPrivate *priv;

    priv = E_MAIL_PART_LIST_GET_PRIVATE (object);

    if (priv->folder != NULL) {
        g_object_unref (priv->folder);
        priv->folder = NULL;
    }

    if (priv->message != NULL) {
        g_object_unref (priv->message);
        priv->message = NULL;
    }

    g_mutex_lock (&priv->queue_lock);
    while (!g_queue_is_empty (&priv->queue))
        g_object_unref (g_queue_pop_head (&priv->queue));
    g_mutex_unlock (&priv->queue_lock);

    /* Chain up to parent's dispose() method. */
    G_OBJECT_CLASS (e_mail_part_list_parent_class)->dispose (object);
}

static void
mail_part_list_finalize (GObject *object)
{
    EMailPartListPrivate *priv;

    priv = E_MAIL_PART_LIST_GET_PRIVATE (object);

    g_free (priv->message_uid);

    g_warn_if_fail (g_queue_is_empty (&priv->queue));
    g_mutex_clear (&priv->queue_lock);

    /* Chain up to parent's finalize() method. */
    G_OBJECT_CLASS (e_mail_part_list_parent_class)->finalize (object);
}

static void
e_mail_part_list_class_init (EMailPartListClass *class)
{
    GObjectClass *object_class;

    g_type_class_add_private (class, sizeof (EMailPartListPrivate));

    object_class = G_OBJECT_CLASS (class);
    object_class->set_property = mail_part_list_set_property;
    object_class->get_property = mail_part_list_get_property;
    object_class->dispose = mail_part_list_dispose;
    object_class->finalize = mail_part_list_finalize;

    g_object_class_install_property (
        object_class,
        PROP_FOLDER,
        g_param_spec_object (
            "folder",
            "Folder",
            NULL,
            CAMEL_TYPE_FOLDER,
            G_PARAM_READWRITE |
            G_PARAM_CONSTRUCT_ONLY |
            G_PARAM_STATIC_STRINGS));

    g_object_class_install_property (
        object_class,
        PROP_MESSAGE,
        g_param_spec_object (
            "message",
            "Message",
            NULL,
            CAMEL_TYPE_MIME_MESSAGE,
            G_PARAM_READWRITE |
            G_PARAM_CONSTRUCT_ONLY |
            G_PARAM_STATIC_STRINGS));

    g_object_class_install_property (
        object_class,
        PROP_MESSAGE_UID,
        g_param_spec_string (
            "message-uid",
            "Message UID",
            NULL,
            NULL,
            G_PARAM_READWRITE |
            G_PARAM_CONSTRUCT_ONLY |
            G_PARAM_STATIC_STRINGS));
}

static void
e_mail_part_list_init (EMailPartList *part_list)
{
    part_list->priv = E_MAIL_PART_LIST_GET_PRIVATE (part_list);

    g_mutex_init (&part_list->priv->queue_lock);
}

EMailPartList *
e_mail_part_list_new (CamelMimeMessage *message,
                      const gchar *message_uid,
                      CamelFolder *folder)
{
    if (message != NULL)
        g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);

    if (folder != NULL)
        g_return_val_if_fail (CAMEL_IS_FOLDER (folder), NULL);

    return g_object_new (
        E_TYPE_MAIL_PART_LIST,
        "message", message,
        "message-uid", message_uid,
        "folder", folder, NULL);
}

CamelFolder *
e_mail_part_list_get_folder (EMailPartList *part_list)
{
    g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);

    return part_list->priv->folder;
}

CamelMimeMessage *
e_mail_part_list_get_message (EMailPartList *part_list)
{
    g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);

    return part_list->priv->message;
}

const gchar *
e_mail_part_list_get_message_uid (EMailPartList *part_list)
{
    g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);

    return part_list->priv->message_uid;
}

void
e_mail_part_list_add_part (EMailPartList *part_list,
                           EMailPart *part)
{
    g_return_if_fail (E_IS_MAIL_PART_LIST (part_list));
    g_return_if_fail (E_IS_MAIL_PART (part));

    g_mutex_lock (&part_list->priv->queue_lock);

    g_queue_push_tail (
        &part_list->priv->queue,
        g_object_ref (part));

    g_mutex_unlock (&part_list->priv->queue_lock);

    e_mail_part_set_part_list (part, part_list);
}

EMailPart *
e_mail_part_list_ref_part (EMailPartList *part_list,
                           const gchar *part_id)
{
    EMailPart *match = NULL;
    GList *head, *link;
    gboolean by_cid;

    g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), NULL);
    g_return_val_if_fail (part_id != NULL, NULL);

    by_cid = (g_ascii_strncasecmp (part_id, "cid:", 4) == 0);

    g_mutex_lock (&part_list->priv->queue_lock);

    head = g_queue_peek_head_link (&part_list->priv->queue);

    for (link = head; link != NULL; link = g_list_next (link)) {
        EMailPart *candidate = E_MAIL_PART (link->data);
        const gchar *candidate_id;

        if (by_cid)
            candidate_id = e_mail_part_get_cid (candidate);
        else
            candidate_id = e_mail_part_get_id (candidate);

        if (g_strcmp0 (candidate_id, part_id) == 0) {
            match = g_object_ref (candidate);
            break;
        }
    }

    g_mutex_unlock (&part_list->priv->queue_lock);

    return match;
}

/**
 * e_mail_part_list_queue_parts:
 * @part_list: an #EMailPartList
 * @part_id: the #EMailPart ID to begin queueing from, or %NULL
 * @result_queue: a #GQueue in which to deposit #EMailPart instances
 *
 * Populates @result_queue with a sequence of #EMailPart instances beginning
 * with the part having @part_id.  If @part_id is %NULL, the entire sequence
 * of #EMailPart instances is queued.
 *
 * Each #EMailPart is referenced for thread-safety and should be unreferenced
 * with g_object_unref().
 *
 * Returns: the number of parts added to @result_queue
 **/
guint
e_mail_part_list_queue_parts (EMailPartList *part_list,
                              const gchar *part_id,
                              GQueue *result_queue)
{
    GList *link;
    guint parts_queued = 0;

    g_return_val_if_fail (E_IS_MAIL_PART_LIST (part_list), FALSE);
    g_return_val_if_fail (result_queue != NULL, FALSE);

    g_mutex_lock (&part_list->priv->queue_lock);

    link = g_queue_peek_head_link (&part_list->priv->queue);

    if (part_id != NULL) {
        for (; link != NULL; link = g_list_next (link)) {
            EMailPart *candidate = E_MAIL_PART (link->data);
            const gchar *candidate_id;

            candidate_id = e_mail_part_get_id (candidate);

            if (g_strcmp0 (candidate_id, part_id) == 0)
                break;
        }
    }

    /* We skip the loop entirely if link is NULL. */
    for (; link != NULL; link = g_list_next (link)) {
        EMailPart *part = link->data;

        if (part == NULL)
            continue;

        g_queue_push_tail (result_queue, g_object_ref (part));
        parts_queued++;
    }

    g_mutex_unlock (&part_list->priv->queue_lock);

    return parts_queued;
}

/**
 * e_mail_part_list_get_registry:
 *
 * Returns a #CamelObjectBag where parsed #EMailPartLists can be stored.
 */
CamelObjectBag *
e_mail_part_list_get_registry (void)
{
    G_LOCK (registry);
    if (registry == NULL) {
        registry = camel_object_bag_new (
                g_str_hash, g_str_equal,
                (CamelCopyFunc) g_strdup, g_free);
    }
    G_UNLOCK (registry);

    return registry;
}