summaryrefslogtreecommitdiff
path: root/examples/numaddr.c
blob: 0c9f6def4894f7967d13138fd2cc5de3fe62afad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* GNU Mailutils -- a suite of utilities for electronic mail
   Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.

   GNU Mailutils 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, or (at your option)
   any later version.

   GNU Mailutils 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 GNU Mailutils; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

/*  This is an example on how to write extension tests for GNU sieve.
    It provides test "numaddr".

    Syntax:   numaddr [":over" / ":under"] <header-names: string-list>
              <limit: number>

    The "numaddr" test counts Internet addresses in structured headers
    that contain addresses.  It returns true if the total number of
    addresses satisfies the requested relation:

    If the argument is ":over" and the number of addresses is greater than
    the number provided, the test is true; otherwise, it is false.

    If the argument is ":under" and the number of addresses is less than
    the number provided, the test is true; otherwise, it is false.

    If the argument is empty, ":over" is assumed. */

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

#include <stdlib.h>
#include <mailutils/libsieve.h>

struct val_ctr {  /* Data passed to the counter function */
  header_t hdr;   /* Headers of the current message */
  size_t limit;   /* Limit for the number of addresses */
  size_t count;   /* Number of addresses counted so far */
};

/* Count addresses in a single header value.

   Input:
     ITEM is the name of the header to scan.
     DATA is a pointer to the val_ctr structure 
   Return value:
     non-zero if the limit on the number of addresses has been reached. */
     
static int
_count_items (void *item, void *data)
{
  char *name = item;
  struct val_ctr *vp = data;
  char *val;
  address_t addr;
  size_t count = 0;
  
  if (header_aget_value (vp->hdr, name, &val))
    return 0;
  if (address_create (&addr, val) == 0)
    {
      address_get_count (addr, &count);
      address_destroy (&addr);
      vp->count += count;
    }
  free (val);
  return vp->count >= vp->limit;
}

/* Handler for the numaddr test */
static int
numaddr_test (sieve_machine_t mach, list_t args, list_t tags)
{
  sieve_value_t *h, *v;
  struct val_ctr vc;
  int rc;
  
  if (sieve_get_debug_level (mach) & MU_SIEVE_DEBUG_TRACE)
    sieve_debug (mach, "NUMADDR\n");

  /* Retrieve required arguments: */
  /* First argument: list of header names */
  h = sieve_value_get (args, 0);
  if (!h)
    {
      sieve_error (mach, "numaddr: can't get argument 1");
      sieve_abort (mach);
    }
  /* Second argument: Limit on the number of addresses */
  v = sieve_value_get (args, 1);
  if (!v)
    {
      sieve_error (mach, "numaddr: can't get argument 2");
      sieve_abort (mach);
    }

  /* Fill in the val_ctr structure */
  message_get_header (sieve_get_message (mach), &vc.hdr);
  vc.count = 0;
  vc.limit = v->v.number;

  /* Count the addresses */
  rc = sieve_vlist_do (h, _count_items, &vc);

  /* Here rc >= 1 iff the counted number of addresses is greater or equal
     to vc.limit. If `:under' tag was given we reverse the return value */
  if (sieve_tag_lookup (tags, "under", NULL))
    rc = !rc;
  return rc;
}

/* Syntactic definitions for the numaddr test */

/* Required arguments: */
static sieve_data_type numaddr_req_args[] = {
  SVT_STRING_LIST,
  SVT_NUMBER,
  SVT_VOID
};

/* Tagged arguments: */
static sieve_tag_def_t numaddr_tags[] = {
  { "over", SVT_VOID },
  { "under", SVT_VOID },
  { NULL }
};

static sieve_tag_group_t numaddr_tag_groups[] = {
  { numaddr_tags, NULL },
  { NULL }
};

/* Initialization function. It is the only function exported from this
   module. */
int
SIEVE_EXPORT(numaddr,init) (sieve_machine_t mach)
{
  return sieve_register_test (mach, "numaddr", numaddr_test,
                              numaddr_req_args, numaddr_tag_groups, 1);
}

Return to:

Send suggestions and report system problems to the System administrator.