The following issue has been UPDATED. 
====================================================================== 
http://www.dbmail.org/mantis/view.php?id=358 
====================================================================== 
Reported By:                blake
Assigned To:                aaron
====================================================================== 
Project:                    DBMail
Issue ID:                   358
Category:                   general delivery
Reproducibility:            always
Severity:                   minor
Priority:                   normal
Status:                     resolved
target:                     2.1.7 
Resolution:                 fixed
Fixed in Version:           2.1.7
====================================================================== 
Date Submitted:             06-Jun-06 08:12 CEST
Last Modified:              20-Jul-06 16:13 CEST
====================================================================== 
Summary:                    Sieve filters only match the first occurrence of a
header.
Description: 
if I have a rule like this:

if allof (
    header :contains "Received" "mail.example.com"
    , header :contains "Delivered-To" "[EMAIL PROTECTED]"
) {
    fileinto "Example/Test";
    stop;
}

It appears, based on looking at the log output, and the way the filters
function, that only the first occurances of "Received" and "Delivered-To"
are checked.
====================================================================== 

---------------------------------------------------------------------- 
 blake - 06-Jun-06 08:14  
---------------------------------------------------------------------- 
Aaron Stone wrote:

I asked Jeffrey Stedfast the GMime maintainer if he could add a simple
function for fetching all instances of a header, and he liked the idea,
but has not included it in GMime yet  :-\ 

The workaround is to loop through all headers belonging to a message and
pull out instances of the header we're looking for. I did not write a
function to do this because I was expecting to see it in GMime 2.2...

I will write the workaround function since we're not likely to see the
real deal in the upstream library anytime soon. 

---------------------------------------------------------------------- 
 blake - 06-Jun-06 08:16  
---------------------------------------------------------------------- 
Let me know if this patch works for you!

Aaron




diff -X exclude -rauN dbmail/dbmail-message.c dbmail-2.1/dbmail-message.c
--- dbmail/dbmail-message.c     2006-06-02 07:41:43.010083552 -0700
+++ dbmail-2.1/dbmail-message.c 2006-06-05 16:08:39.248458120 -0700
@@ -432,11 +432,60 @@
 {
        g_mime_message_set_header(GMIME_MESSAGE(self->content), header, value);
 }
+
 const gchar * dbmail_message_get_header(const struct DbmailMessage *self,
const char *header)
 {
        return g_mime_object_get_header(GMIME_OBJECT(self->content), header);
 }
 
+static void _get_header_repeated(const char *name, const char *value,
gpointer user_data)
+{
+       struct {
+               char *header;
+               char **headers;
+               int pos;
+               int len;
+       } *_my_headers = user_data;
+
+       if (strcmp(name, _my_headers->header)) {
+               if (_my_headers->pos + 1 == _my_headers->len) {
+                       _my_headers->len += 8;
+                       _my_headers->headers = g_renew(char *, 
_my_headers->headers,
_my_headers->len);
+
+                       /* There used to be a renew0, but not anymore. */
+                       int i;
+                       for (i = _my_headers->pos; i < _my_headers->len; i++) {
+                               _my_headers->headers[i] = NULL;
+                       }
+               }
+               _my_headers->headers[_my_headers->pos] = (char *)value;
+               _my_headers->pos++;
+       }
+}
+
+/* Memory for the individual header values is NOT allocated;
+ * Memory for the header array IS allocated and must be freed.
+ * Do NOT use g_strfreev with this return value! */
+gchar ** dbmail_message_get_header_repeated(const struct DbmailMessage
*self, const char *header)
+{
+       struct {
+               char *header;
+               char **headers;
+               int pos;
+               int len;
+       } _my_headers;
+
+       /* Start with 8 slots. */
+       _my_headers.pos = 0;
+       _my_headers.len = 8;
+       _my_headers.header = (char *)header;
+       _my_headers.headers = g_new0(char *, _my_headers.len);
+
+       g_mime_header_foreach(GMIME_OBJECT(self->content)->headers,
_get_header_repeated, &_my_headers);
+
+       return _my_headers.headers;
+}
+
 GList * dbmail_message_get_header_addresses(struct DbmailMessage
*message, const char *field_name)
 {
        InternetAddressList *ialisthead, *ialist;
diff -X exclude -rauN dbmail/dbmail-message.h dbmail-2.1/dbmail-message.h
--- dbmail/dbmail-message.h     2006-04-13 08:47:35.312204272 -0700
+++ dbmail-2.1/dbmail-message.h 2006-06-05 16:03:34.142841224 -0700
@@ -127,6 +127,14 @@
 void dbmail_message_set_header(struct DbmailMessage *self, const char
*header, const char *value);
 const gchar * dbmail_message_get_header(const struct DbmailMessage *self,
const char *header);
 
+/* Get all instances of a header.
+ *
+ * Memory for the individual header values is NOT allocated;
+ * Memory for the header array IS allocated and must be freed.
+ * Do NOT use g_strfreev with this return value!
+ */
+gchar ** dbmail_message_get_header_repeated(const struct DbmailMessage
*self, const char *header);
+
 void dbmail_message_cache_tofield(const struct DbmailMessage *self);
 void dbmail_message_cache_ccfield(const struct DbmailMessage *self);
 void dbmail_message_cache_fromfield(const struct DbmailMessage *self);
diff -X exclude -rauN dbmail/modules/sortsieve.c
dbmail-2.1/modules/sortsieve.c
--- dbmail/modules/sortsieve.c  2006-05-06 23:52:27.291685424 -0700
+++ dbmail-2.1/modules/sortsieve.c      2006-06-05 16:04:14.547698752 -0700
@@ -286,12 +286,9 @@
 
        header = (char *)sieve2_getvalue_string(s, "header");
 
-       bodylist = (char **)dm_malloc(sizeof(char *) * 2);
-       bodylist[0] = (char *)dbmail_message_get_header(m->message, header);
-       bodylist[1] = NULL;
+       bodylist = (char **)dbmail_message_get_header_repeated(m->message,
header);
 
-       /* We have to free the header ourselves. */
-       dm_list_nodeadd(&m->freelist, &bodylist[0], sizeof(char *));
+       /* We have to free the header array, but not its contents. */
        dm_list_nodeadd(&m->freelist, &bodylist, sizeof(char **));
 
        trace(TRACE_INFO, "%s, %s: Getting header [%s] returning value [%s]",
diff -X exclude -rauN dbmail/pool.c dbmail-2.1/pool.c
--- dbmail/pool.c       2006-05-06 15:19:29.020693824 -0700
+++ dbmail-2.1/pool.c   2006-06-05 16:10:17.723487640 -0700
@@ -27,6 +27,7 @@
 
 static State_t state_new(void); 
 static int set_lock(int type);
+static pid_t reap_child(void);
 /*
  *
  * 

---------------------------------------------------------------------- 
 blake - 06-Jun-06 08:18  
---------------------------------------------------------------------- 
The behavior appears to be the same with the patch. (I've sent Aaron some
logs privately to continue to debug the problem.) 

---------------------------------------------------------------------- 
 aaron - 06-Jun-06 08:34  
---------------------------------------------------------------------- 
The patch I originally wrote had "if (strcmp(...,...))" which should have
been "if (strcasecmp(...,...) == 0)". Now in SVN. 

---------------------------------------------------------------------- 
 paul - 06-Jun-06 11:55  
---------------------------------------------------------------------- 
Aaron,

why are you retrieving headers case-insensitive? This breaks gmime
standard behaviour, and is not required afaict.

I've redone this code by using standard glib facilities. Hope you don't
mind :-/ 

---------------------------------------------------------------------- 
 aaron - 08-Jun-06 14:52  
---------------------------------------------------------------------- 
Ok, this is working well now. Turned out that case-insensitive was
required. 

Issue History 
Date Modified   Username       Field                    Change               
====================================================================== 
06-Jun-06 08:12 blake          New Issue                                    
06-Jun-06 08:14 blake          Note Added: 0001224                          
06-Jun-06 08:16 blake          Note Added: 0001225                          
06-Jun-06 08:18 blake          Note Added: 0001226                          
06-Jun-06 08:34 aaron          target                    => 2.1.7           
06-Jun-06 08:34 aaron          Status                   new => resolved     
06-Jun-06 08:34 aaron          Fixed in Version          => SVN Trunk       
06-Jun-06 08:34 aaron          Resolution               open => fixed       
06-Jun-06 08:34 aaron          Assigned To               => aaron           
06-Jun-06 08:34 aaron          Note Added: 0001227                          
06-Jun-06 11:55 paul           Note Added: 0001228                          
06-Jun-06 11:55 paul           Resolution               fixed => reopened   
06-Jun-06 11:57 paul           Status                   resolved => assigned
08-Jun-06 14:52 aaron          Status                   assigned => resolved
08-Jun-06 14:52 aaron          Resolution               reopened => fixed   
08-Jun-06 14:52 aaron          Note Added: 0001229                          
20-Jul-06 16:13 paul           Fixed in Version         SVN Trunk => 2.1.7  
======================================================================

Reply via email to