예제 #1
0
int
mu_msgset_add_range (mu_msgset_t mset, size_t beg, size_t end, int mode)
{
  int rc;
  struct mu_msgrange *range;
  
  if (!mset || beg == 0)
    return EINVAL;
  if (end && beg > end)
    {
      size_t t = end;
      end = beg;
      beg = t;
    }
  range = calloc (1, sizeof (*range));
  if (!range)
    return ENOMEM;
  range->msg_beg = beg;
  range->msg_end = end;
  rc = _mu_msgset_translate_range (mset, mode, range);
  if (rc)
    {
      free (range);
      return rc;
    }
  rc = mu_list_append (mset->list, range);
  if (rc)
    free (range);
  mset->flags &= ~_MU_MSGSET_AGGREGATED;
  return rc;
}
예제 #2
0
static void
recursive_alias_expand (const char *name, mu_list_t exlist, mu_list_t origlist)
{ 
  alias_t al;
  mu_iterator_t itr;
  
  if ((al = alias_lookup (name)) == NULL)
    {
      if (mu_list_locate (exlist, (void*)name, NULL) == MU_ERR_NOENT)
	mu_list_append (exlist, (void*)name);
      return;
    }
  
  mu_list_get_iterator (al->list, &itr);
  for (mu_iterator_first (itr);
       !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      char *word;
      
      mu_iterator_current (itr, (void **)&word);
      if (mu_list_locate (origlist, word, NULL) == MU_ERR_NOENT)
	{
	  mu_list_push (origlist, word);
	  recursive_alias_expand (word, exlist, origlist);
	  mu_list_pop (origlist, NULL);
	}
    }
  mu_iterator_destroy (&itr);
}
예제 #3
0
static int
sieve_register (mu_list_t *pool,
		mu_list_t *list,
		const char *name, mu_sieve_handler_t handler,
		mu_sieve_data_type *req_arg_types,
		mu_sieve_data_type *opt_arg_types,
		mu_sieve_tag_group_t *tags, int required)
{
  mu_sieve_register_t *reg = mu_sieve_palloc (pool, sizeof (*reg));

  if (!reg)
    return ENOMEM;
  reg->name = name;
  reg->handler = handler;

  reg->req_args = req_arg_types;
  reg->opt_args = opt_arg_types;
  reg->tags = tags;
  reg->required = required;
  
  if (!*list)
    {
      int rc = mu_list_create (list);
      if (rc)
	{
	  free (reg);
	  return rc;
	}
    }
  
  return mu_list_append (*list, reg);
}
예제 #4
0
static int
_regex_compile (void *item, void *data)
{
  struct regex_data *rd = data;
  int rc;
  regex_t *preg = mu_sieve_malloc (mu_sieve_machine, sizeof (*preg));
  
  rc = regcomp (preg, (char*)item, rd->flags);
  if (rc)
    {
      size_t size = regerror (rc, preg, NULL, 0);
      char *errbuf = malloc (size + 1);
      if (errbuf)
	{
	  regerror (rc, preg, errbuf, size);
	  mu_sv_compile_error (&mu_sieve_locus, _("regex error: %s"), errbuf);
	  free (errbuf);
	}
      else
	mu_sv_compile_error (&mu_sieve_locus, _("regex error"));
      return rc;
    }

  mu_list_append (rd->list, preg);
  
  return 0;
}
예제 #5
0
int
mu_sieve_register_comparator (mu_sieve_machine_t mach,
			   const char *name,
			   int required,
			   mu_sieve_comparator_t is,
			   mu_sieve_comparator_t contains,
			   mu_sieve_comparator_t matches,
			   mu_sieve_comparator_t regex,
			   mu_sieve_comparator_t eq)
{
  sieve_comparator_record_t *rp;

  if (!mach->comp_list)
    {
      int rc = mu_list_create (&mach->comp_list);
      if (rc)
	return rc;
    }

  rp = mu_sieve_malloc (mach, sizeof (*rp));
  rp->required = required;
  rp->name = name;
  rp->comp[MU_SIEVE_MATCH_IS] = is;       
  rp->comp[MU_SIEVE_MATCH_CONTAINS] = contains; 
  rp->comp[MU_SIEVE_MATCH_MATCHES] = matches;  
  rp->comp[MU_SIEVE_MATCH_REGEX] = regex;    
  rp->comp[MU_SIEVE_MATCH_EQ] = eq;    

  return mu_list_append (mach->comp_list, rp);
}
예제 #6
0
static void
list_untagged_handler (mu_imap_t imap, mu_list_t resp, void *data)
{
  struct list_closure *clos = data;
  struct imap_list_element *elt;
  size_t count;
  
  if (clos->error_code)
    return;

  mu_list_count (resp, &count);
  if (count == 4 &&
      _mu_imap_list_nth_element_is_string (resp, 0, clos->command))
    {
      struct mu_list_response *rp;

      rp = calloc (1, sizeof (*rp));
      if (!rp)
	{
	  clos->error_code = ENOMEM;
	  return;
	}
	  
      elt = _mu_imap_list_at (resp, 1);
      if (!(elt && elt->type == imap_eltype_list))
	return;
      rp->type = 0;
      mu_list_foreach (elt->v.list, list_attr_conv, rp);

      elt = _mu_imap_list_at (resp, 3);
      if (!(elt && elt->type == imap_eltype_string))
	return;
      rp->name = strdup (elt->v.string);
      if (!rp->name)
	{
	  free (rp);
	  clos->error_code = ENOMEM;
	  return;
	}

      elt = _mu_imap_list_at (resp, 2);
      if (!elt)
	return;
      if (_mu_imap_list_element_is_nil (elt))
	{
	  rp->separator = 0;
	  rp->level = 0;
	}
      else if (elt->type != imap_eltype_string)
	return;
      else
	{
	  rp->separator = elt->v.string[0];
	  rp->level = count_level (rp->name, rp->separator);
	}
      if ((clos->error_code = mu_list_append (clos->retlist, rp)))
	mu_list_response_free (rp);
    }
}
예제 #7
0
static void
add_sequence (char *name)
{
  if (!seq_list && mu_list_create (&seq_list))
    {
      mu_error (_("cannot create sequence list"));
      exit (1);
    }
  mu_list_append (seq_list, name);
}
예제 #8
0
void
imap4d_capability_add (const char *str)
{
  if (!capa_list)
    {
      mu_list_create (&capa_list);
      mu_list_set_comparator (capa_list, comp);
    }
  mu_list_append (capa_list, (void*)str);
}
예제 #9
0
파일: capa.c 프로젝트: Distrotech/mailutils
static void
pop3d_append_capa_string (struct pop3d_session *sess, const char *name,
			  const char *value)
{
  struct pop3d_capa *cp;

  cp = mu_alloc (sizeof (*cp));
  cp->type = capa_string;
  cp->name = name;
  cp->value.string = value ? mu_strdup (value) : NULL;
  if (mu_list_append (sess->capa, cp))
    mu_alloc_die ();
}
예제 #10
0
/* Computes an intersection of two lists and returns it in PDEST.
   The resulting list contains elements from A that are
   also encountered in B (as per comparison function of
   the latter).

   If DUP_ITEM is not NULL, it is used to create copies of
   items to be stored in PDEST.  In this case, the destroy_item
   function of B is also attached to PDEST.  Otherwise, if
   DUP_ITEM is NULL, pointers to elements are stored and
   no destroy_item function is assigned. */
int
mu_list_intersect_dup (mu_list_t *pdest, mu_list_t a, mu_list_t b,
		       int (*dup_item) (void **, void *, void *),
		       void *dup_closure)
{
  mu_list_t dest;
  int rc;
  mu_iterator_t itr;
  
  rc = mu_list_create (&dest);
  if (rc)
    return rc;

  mu_list_set_comparator (dest, b->comp);
  if (dup_item)
    mu_list_set_destroy_item (dest, b->destroy_item);
  
  rc = mu_list_get_iterator (a, &itr);
  if (rc)
    {
      mu_list_destroy (&dest);
      return rc;
    }

  rc = 0;
  for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      void *data;
      mu_iterator_current (itr, &data);
      if (mu_list_locate (b, data, NULL) == 0)
	{
	  void *new_data;
	  if (dup_item && data)
	    {
	      rc = dup_item (&new_data, data, dup_closure);
	      if (rc)
		break;
	    }
	  else
	    new_data = data;
	
	  mu_list_append (dest, new_data); /* FIXME: Check return, and? */
	}
    }
  mu_iterator_destroy (&itr);
  *pdest = dest;
  return rc;
}
예제 #11
0
파일: capa.c 프로젝트: Distrotech/mailutils
static void
pop3d_append_capa_func (struct pop3d_session *sess, const char *name,
			void (*func) (const char *, struct pop3d_session *))
{
  struct pop3d_capa *cp;

  if (!func)
    return;
  cp = mu_alloc (sizeof (*cp));
  cp->type = capa_func;
  cp->name = name;
  cp->value.func = func;
  if (mu_list_append (sess->capa, cp))
    mu_alloc_die ();
}  
예제 #12
0
void
auth_add (char *name, imap4d_auth_handler_fp handler)
{
  struct imap_auth *p = mu_alloc (sizeof (*p));

  p->name = name;
  p->handler = handler;
  if (!imap_auth_list)
    {
      mu_list_create (&imap_auth_list);
      mu_list_set_comparator (imap_auth_list, comp);
      mu_list_set_destroy_item (imap_auth_list, mu_list_free_item);
    }
  mu_list_append (imap_auth_list, (void*)p);
}
예제 #13
0
int
mu_registrar_record (mu_record_t record)
{
  int status;
  mu_list_t list;
  mu_list_comparator_t comp;
  
  if (!record)
    return 0;
  _registrar_get_list (&list);
  comp = mu_list_set_comparator (list, _compare_prio);
  status = mu_list_insert (list, record, record, 1);
  if (status == MU_ERR_NOENT)
    status = mu_list_append (list, record);
  mu_list_set_comparator (list, comp);
  return status;
}
예제 #14
0
int
mu_onexit (mu_onexit_t func, void *data)
{
  struct onexit_closure *clos = malloc (sizeof (*clos));
  if (!clos)
    return ENOMEM;
  clos->function = func;
  clos->data = data;
  if (!onexit_list)
    {
      int rc = mu_list_create (&onexit_list);
      mu_list_set_destroy_item (onexit_list, mu_list_free_item);
      if (rc)
	return rc;
      atexit (_mu_onexit_run);
    }
  return mu_list_append (onexit_list, clos);
}
예제 #15
0
파일: sortm.c 프로젝트: ssvlab/esbmc-gpu
static void
addop (char *field, compfun comp)
{
  struct comp_op *op = xmalloc (sizeof (*op));
  
  if (!oplist)
    {
      if (mu_list_create (&oplist))
	{
	  mu_error (_("can't create operation list"));
	  exit (1);
	}
      mu_list_set_destroy_item (oplist, mu_list_free_item);
    }
  op->field = field;
  op->comp = comp;
  mu_list_append (oplist, op);
}
예제 #16
0
int
mu_pop3_stream_to_list (mu_pop3_t pop3, mu_stream_t stream, mu_list_t list)
{
  int status;
  size_t n;
  
  while ((status = mu_stream_getline (stream, &pop3->rdbuf, &pop3->rdsize, &n))
	 == 0
	 && n > 0)
    {
      char *np = strdup (pop3->rdbuf);
      if (!np)
	{
	  status = ENOMEM;
	  break;
	}
      mu_rtrim_class (np, MU_CTYPE_SPACE);
      status = mu_list_append (list, np);
      if (status)
	break;
    }
  return status;
}
예제 #17
0
static void
update_list (mu_list_t *plist, const char *arg)
{
  size_t j;
  struct mu_wordsplit ws;
  mu_list_t list = *plist;
  
  if (!list)
    {
      MU_ASSERT (mu_list_create (&list));
      *plist = list;
    }

  ws.ws_delim = ",";
  if (mu_wordsplit (arg, &ws, MU_WRDSF_DEFFLAGS | MU_WRDSF_DELIM))
    {
      mu_error ("mu_wordsplit: %s", mu_wordsplit_strerror (&ws));
      exit (1);
    }
  for (j = 0; j < ws.ws_wordc; j++)
    MU_ASSERT (mu_list_append (list, ws.ws_wordv[j]));
  ws.ws_wordc = 0;
  mu_wordsplit_free (&ws);
}
예제 #18
0
int
main (int argc, char **argv)
{
  int i;
  char *host = NULL;
  char *infile = NULL;
  char *port = NULL;
  int tls = 0;
  int raw = 1;
  int flags = 0;
  mu_stream_t stream;
  mu_smtp_t smtp;
  mu_stream_t instr;
  char *from = NULL;
  mu_list_t rcpt_list = NULL;
  mu_list_t meth_list = NULL;
  mu_list_t skiphdr_list = NULL;
  struct mu_sockaddr *sa;
  struct mu_sockaddr_hints hints;
  
  mu_set_program_name (argv[0]);
  mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
  
  if (argc < 2)
    usage ();

  memset (&hints, 0, sizeof (hints)); 
  hints.flags = MU_AH_DETECT_FAMILY;
  hints.port = 25;
  hints.protocol = IPPROTO_TCP;
  hints.socktype = SOCK_STREAM;

  MU_ASSERT (mu_smtp_create (&smtp));

  for (i = 1; i < argc; i++)
    {
      if (strncmp (argv[i], "port=", 5) == 0)
	port = argv[i] + 5;
      else if (strncmp (argv[i], "family=", 7) == 0)
	{
	  hints.flags &= ~MU_AH_DETECT_FAMILY;
	  switch (argv[i][7])
	    {
	    case '4':
	      hints.family = AF_INET;
	      break;
	    case '6':
	      hints.family = AF_INET6;
	      break;
	    default:
	      mu_error ("invalid family name: %s", argv[i]+7);
	      exit (1);
	    }
	}
      else if (strncmp (argv[i], "trace=", 6) == 0)
	{
	  char *arg = argv[i] + 6;

	  if (mu_isdigit (arg[0]))
	    mu_smtp_trace (smtp, atoi (argv[i] + 6) ?
			   MU_SMTP_TRACE_SET : MU_SMTP_TRACE_CLR);
	  else
	    {
	      mu_smtp_trace (smtp, MU_SMTP_TRACE_SET);
	      if (strcmp (arg, "secure") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_SECURE);
	      else if (strcmp (arg, "payload") == 0)
		mu_smtp_trace_mask (smtp, MU_SMTP_TRACE_SET,
				    MU_XSCRIPT_PAYLOAD);
	    }
	}
      else if (strncmp (argv[i], "tls=", 4) == 0)
	tls = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "domain=", 7) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_DOMAIN,
				      argv[i] + 7));
      else if (strncmp (argv[i], "user="******"pass="******"service=", 8) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_SERVICE,
				      argv[i] + 8));
      else if (strncmp (argv[i], "realm=", 6) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_REALM,
				      argv[i] + 6));
      else if (strncmp (argv[i], "host=", 5) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_HOST,
				      argv[i] + 5));
      else if (strncmp (argv[i], "url=", 4) == 0)
	MU_ASSERT (mu_smtp_set_param (smtp, MU_SMTP_PARAM_URL,
				      argv[i] + 4));
      else if (strncmp (argv[i], "input=", 6) == 0)
	infile = argv[i] + 6;
      else if (strncmp (argv[i], "raw=", 4) == 0)
	raw = atoi (argv[i] + 4);
      else if (strncmp (argv[i], "rcpt=", 5) == 0)
	{
	  if (!rcpt_list)
	    MU_ASSERT (mu_list_create (&rcpt_list));
	  MU_ASSERT (mu_list_append (rcpt_list, argv[i] + 5));
	}
      else if (strncmp (argv[i], "from=", 5) == 0)
	from = argv[i] + 5;
      else if (strncmp (argv[i], "auth=", 5) == 0)
	update_list (&meth_list, argv[i] + 5);
      else if (strncmp (argv[i], "skiphdr=", 8) == 0)
	{
	  update_list (&skiphdr_list, argv[i] + 8);
	  raw = 0;
	}
      else if (host)
	{
	  mu_error ("server name already given: %s, new name %s?",
		    host, argv[i]);
	  exit (1);
	}
      else
	host = argv[i];
    }

  if (!host)
    usage ();

  if (!raw)
    flags = MU_STREAM_SEEK;
  if (infile)
    MU_ASSERT (mu_file_stream_create (&instr, infile, MU_STREAM_READ|flags));
  else
    MU_ASSERT (mu_stdio_stream_create (&instr, MU_STDIN_FD, flags));
  
  host = argv[1];

  MU_ASSERT (mu_sockaddr_from_node (&sa, host, port, &hints));

  MU_ASSERT (mu_tcp_stream_create_from_sa (&stream, sa, NULL, MU_STREAM_RDWR));
  
  mu_smtp_set_carrier (smtp, stream);
  mu_stream_unref (stream);
  
  if (!from)
    {
      from = getenv ("USER");
      if (!from)
	{
	  mu_error ("cannot determine sender name");
	  exit (1);
	}
    }

  if (raw && !rcpt_list)
    {
      mu_error ("no recipients");
      exit (1);
    }
  
  MU_ASSERT (mu_smtp_open (smtp));
  MU_ASSERT (mu_smtp_ehlo (smtp));

  if (tls && mu_smtp_capa_test (smtp, "STARTTLS", NULL) == 0)
    {
      MU_ASSERT (mu_smtp_starttls (smtp));
      MU_ASSERT (mu_smtp_ehlo (smtp));
    }

  if (meth_list)
    {
      int status;
      
      MU_ASSERT (mu_smtp_add_auth_mech_list (smtp, meth_list));
      status = mu_smtp_auth (smtp);
      switch (status)
	{
	case 0:
	  MU_ASSERT (mu_smtp_ehlo (smtp));
	  break;
	  
	case ENOSYS:
	case MU_ERR_NOENT:
	  /* Ok, skip it */
	  break;

	default:
	  mu_error ("authentication failed: %s", mu_strerror (status));
	  exit (1);
	}
    }
  
  MU_ASSERT (mu_smtp_mail_basic (smtp, from, NULL));
  mu_list_foreach (rcpt_list, send_rcpt_command, smtp);
  
  if (raw)
    {
      /* Raw sending mode: send from the stream directly */
      MU_ASSERT (mu_smtp_send_stream (smtp, instr));
    }
  else
    {
      /* Message (standard) sending mode: send a MU message. */

      mu_message_t msg;
      mu_stream_t ostr, bstr;
      mu_header_t hdr;
      mu_iterator_t itr;
      mu_body_t body;

      if (skiphdr_list)
	mu_list_set_comparator (skiphdr_list, headercmp);
      
      MU_ASSERT (mu_stream_to_message (instr, &msg));
      mu_stream_unref (instr);
      MU_ASSERT (mu_smtp_data (smtp, &ostr));
      MU_ASSERT (mu_message_get_header (msg, &hdr));
      MU_ASSERT (mu_header_get_iterator (hdr, &itr));
      for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
	   mu_iterator_next (itr))
	{
	  const char *name;
	  void *value;

	  mu_iterator_current_kv (itr, (void*) &name, &value);
	  if (mu_list_locate (skiphdr_list, (void*) name, NULL) == 0)
	    continue;

	  mu_stream_printf (ostr, "%s: %s\n", name, (char*)value);
	}
      mu_iterator_destroy (&itr);
      MU_ASSERT (mu_stream_write (ostr, "\n", 1, NULL));
      
      MU_ASSERT (mu_message_get_body (msg, &body));
      MU_ASSERT (mu_body_get_streamref (body, &bstr));
      MU_ASSERT (mu_stream_copy (ostr, bstr, 0, NULL));
      mu_stream_destroy (&bstr);
      mu_stream_close (ostr);
      mu_stream_destroy (&ostr);
    }
  MU_ASSERT (mu_smtp_dot (smtp));
  MU_ASSERT (mu_smtp_quit (smtp));
  
  mu_smtp_destroy (&smtp);
  mu_stream_close (instr);
  mu_stream_destroy (&instr);
  return 0;
}
예제 #19
0
int
mu_sieve_match_part_checker (const char *name, mu_list_t tags, mu_list_t args)
{
  mu_iterator_t itr;
  mu_sieve_runtime_tag_t *match = NULL;
  mu_sieve_runtime_tag_t *comp = NULL;
  mu_sieve_runtime_tag_t *tmp;
  mu_sieve_comparator_t compfun = NULL;
  char *compname = "false";
  
  int matchtype;
  int err = 0;
  
  if (!tags || mu_list_get_iterator (tags, &itr))
    return 0;

  for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
       mu_iterator_next (itr))
    {
      mu_sieve_runtime_tag_t *t;
      mu_iterator_current (itr, (void **)&t);
      
      if (strcmp (t->tag, "is") == 0
	  || strcmp (t->tag, "contains") == 0
	  || strcmp (t->tag, "matches") == 0
	  || strcmp (t->tag, "regex") == 0
	  || strcmp (t->tag, "count") == 0
	  || strcmp (t->tag, "value") == 0)
	{
	  if (match)
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
			     _("match type specified twice in call to `%s'"),
				   name);
	      err = 1;
	    }
	  else
	    match = t;
	}
      else if (strcmp (t->tag, "comparator") == 0) 
	comp = t;
    }

  mu_iterator_destroy (&itr);

  if (err)
    return 1;

  if (!match || strcmp (match->tag, "is") == 0)
    matchtype = MU_SIEVE_MATCH_IS;
  else if (strcmp (match->tag, "contains") == 0)
    matchtype = MU_SIEVE_MATCH_CONTAINS;
  else if (strcmp (match->tag, "matches") == 0)
    matchtype = MU_SIEVE_MATCH_MATCHES;
  else if (strcmp (match->tag, "regex") == 0)
    matchtype = MU_SIEVE_MATCH_REGEX;
  else
    {
      char *str = match->arg->v.string;
      if (strcmp (match->tag, "count") == 0)
	{
	  mu_sieve_value_t *val;
	  char *str;
	  size_t count;
	  
	  if (comp && strcmp (comp->arg->v.string, "i;ascii-numeric"))
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
				   /* TRANSLATORS: Do not translate ':count'.
				      It is the name of a Sieve tag */
				   _("comparator %s is incompatible with "
				     ":count in call to `%s'"),
				   comp->arg->v.string,
				   name);
	      return 1;
	    }

          matchtype = MU_SIEVE_MATCH_LAST; /* to not leave it undefined */
	  compfun = comp_false;
	  val = mu_sieve_value_get (args, 1);
	  if (!val)
	    return 1; /* shouldn't happen */
	  /* NOTE: Type of v is always SVT_STRING_LIST */
	  mu_list_count (val->v.list, &count);
	  if (count > 1)
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
			_("second argument must be a list of one element"));
	      return 1;
	    }
	  mu_list_get (val->v.list, 0, (void **) &str);
	  count = strtoul (str, &str, 10);
	  if (*str)
	    {
	      mu_sv_compile_error (&mu_sieve_locus, 
			   _("second argument cannot be converted to number"));
	      return 1;
	    }
	}
      else
	matchtype = MU_SIEVE_MATCH_EQ;

      if (mu_sieve_str_to_relcmp (str, NULL, NULL))
	{
	  mu_sv_compile_error (&mu_sieve_locus, 
			       _("invalid relational match `%s' in call to `%s'"),
			       str, name);
	  return 1;
	}
    }

  if (!compfun)
    {
      compname = comp ? comp->arg->v.string : "i;ascii-casemap";
      compfun = mu_sieve_comparator_lookup (mu_sieve_machine, compname, 
                                            matchtype);
      if (!compfun)
	{
	  mu_sv_compile_error (&mu_sieve_locus, 
			   _("comparator `%s' is incompatible with match type `%s' in call to `%s'"),
			       compname, match ? match->tag : "is", name);
	  return 1;
	}
    }

  tmp = mu_sieve_malloc (mu_sieve_machine, sizeof (*tmp));
  tmp->tag = TAG_COMPFUN;
  tmp->arg = mu_sieve_value_create (SVT_POINTER, compfun);
  mu_list_append (tags, tmp);
  
  if (matchtype == MU_SIEVE_MATCH_REGEX)
    {
      /* To speed up things, compile all patterns at once.
	 Notice that it is supposed that patterns are in arg 2 */
      mu_sieve_value_t *val, *newval;
      struct regex_data rd;
      int rc;
      
      if (mu_list_get (args, 1, (void**)&val))
	return 0;

      rd.flags = REG_EXTENDED;
      if (strcmp (compname, "i;ascii-casemap") == 0)
	rd.flags |= REG_ICASE;

      mu_list_create (&rd.list);
      
      rc = mu_sieve_vlist_do (val, _regex_compile, &rd);

      mu_sieve_machine_add_destructor (mu_sieve_machine, _free_reglist, 
                                       rd.list);

      if (rc)
	return rc;
      newval = mu_sieve_value_create (SVT_STRING_LIST, rd.list);
      mu_list_replace (args, val, newval);
    }
#ifndef FNM_CASEFOLD
  else if (matchtype == MU_SIEVE_MATCH_MATCHES
	   && strcmp (compname, "i;ascii-casemap") == 0)
    {
      int rc;
      mu_sieve_value_t *val;

      if (mu_list_get (args, 1, (void**)&val))
	return 0;
      rc = mu_sieve_vlist_do (val, _pattern_upcase, NULL);
      if (rc)
	return rc;
    }
#endif
  return 0;
}
예제 #20
0
/* A folder could be remote (IMAP), or local(a spool directory) like $HOME/Mail
   etc ..  We maintain a list of known folders to avoid creating multiple
   folders for the same URL.  So, when mu_folder_create is called we check if
   we already have a folder for that URL and return it, otherwise we create a
   new one.  Downsides: the scheme to detect the same URL is very weak, and
   there could be cases where you'll want a different folder for the same URL,
   there is not easy way to do this.  */
int
mu_folder_create_from_record (mu_folder_t *pfolder, mu_url_t url,
			      mu_record_t record)
{
  if (!pfolder)
    return MU_ERR_OUT_PTR_NULL;

  if (record || 
      /* Look in the registrar list(iterator), for a possible concrete mailbox
	 implementation that could match the URL.  */
      mu_registrar_lookup_url (url, MU_FOLDER_ATTRIBUTE_DIRECTORY, &record,
			       NULL) == 0)
    {
      int (*f_init) (mu_folder_t) = NULL;
      
      mu_record_get_folder (record, &f_init);
      if (f_init)
        {
	  int status, mask;
	  mu_folder_t folder;
	  int (*u_init) (mu_url_t) = NULL;

	  status = mu_record_check_url (record, url, &mask);
	  if (status)
	    /* FIXME: mask would provide more info */
	    return status;
	  
	  mu_record_get_url (record, &u_init);
	  if (u_init)
	    {
	      status = u_init (url);
	      if (status)
		return status;
	    }
	  
	  mu_monitor_wrlock (&folder_lock);

	  /* Check if we already have the same URL folder.  */
	  if (is_known_folder (url, &folder))
	    {
	      folder->ref++;
	      *pfolder = folder;
	      mu_url_destroy (&url); /* FIXME: Hmm */
	      mu_monitor_unlock (&folder_lock);
	      return  0;
	    }
	  else
	    mu_monitor_unlock (&folder_lock);
	  
	  /* Create a new folder.  */

	  /* Allocate memory for the folder.  */
	  folder = calloc (1, sizeof (*folder));
	  if (folder != NULL)
	    {
	      folder->url = url;
	      /* Initialize the internal foilder lock, now so the
		 concrete folder could use it.  */
	      status = mu_monitor_create (&folder->monitor, 0, folder);
	      if (status == 0)
		{
		  /* Create the concrete folder type.  */
		  status = f_init (folder);
		  if (status == 0)
		    {
		      if (!folder->_match)
			folder->_match = mu_folder_imap_match;
		      *pfolder = folder;
		      folder->ref++;
		      /* Put on the internal list of known folders.  */
		      if (known_folder_list == NULL)
			mu_list_create (&known_folder_list);
		      mu_list_append (known_folder_list, folder);
		    }
		}
	      /* Something went wrong, destroy the object. */
	      if (status)
		{
		  if (folder->monitor)
		    mu_monitor_destroy (&folder->monitor, folder);
		  free (folder);
		}
	    }
	  return status;
	}
    }

  return MU_ERR_NOENT;
}