summaryrefslogtreecommitdiff
path: root/libmailutils/attribute.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/attribute.c')
-rw-r--r--libmailutils/attribute.c470
1 files changed, 470 insertions, 0 deletions
diff --git a/libmailutils/attribute.c b/libmailutils/attribute.c
new file mode 100644
index 000000000..3e76855fd
--- /dev/null
+++ b/libmailutils/attribute.c
@@ -0,0 +1,470 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2009, 2010 Free
+ Software Foundation, Inc.
+
+ This library 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 3 of the License, or (at your option) any later version.
+
+ This library 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 this library; if not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/errno.h>
+#include <mailutils/mutil.h>
+#include <mailutils/cstr.h>
+#include <mailutils/sys/attribute.h>
+
+int
+mu_attribute_create (mu_attribute_t *pattr, void *owner)
+{
+ mu_attribute_t attr;
+ if (pattr == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ attr = calloc (1, sizeof(*attr));
+ if (attr == NULL)
+ return ENOMEM;
+ attr->owner = owner;
+ *pattr = attr;
+ return 0;
+}
+
+void
+mu_attribute_destroy (mu_attribute_t *pattr, void *owner)
+{
+ if (pattr && *pattr)
+ {
+ mu_attribute_t attr = *pattr;
+ if (attr->owner == owner)
+ free (*pattr);
+ /* Loose the link */
+ *pattr = NULL;
+ }
+}
+
+void *
+mu_attribute_get_owner (mu_attribute_t attr)
+{
+ return (attr) ? attr->owner : NULL;
+}
+
+int
+mu_attribute_is_modified (mu_attribute_t attr)
+{
+ return (attr) ? attr->flags & MU_ATTRIBUTE_MODIFIED : 0;
+}
+
+int
+mu_attribute_clear_modified (mu_attribute_t attr)
+{
+ if (attr)
+ attr->flags &= ~MU_ATTRIBUTE_MODIFIED;
+ return 0;
+}
+
+int
+mu_attribute_set_modified (mu_attribute_t attr)
+{
+ if (attr)
+ attr->flags |= MU_ATTRIBUTE_MODIFIED;
+ return 0;
+}
+
+int
+mu_attribute_get_flags (mu_attribute_t attr, int *pflags)
+{
+ if (attr == NULL)
+ return EINVAL;
+ if (pflags == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ if (attr->_get_flags)
+ return attr->_get_flags (attr, pflags);
+ *pflags = attr->flags;
+ return 0;
+}
+
+int
+mu_attribute_set_flags (mu_attribute_t attr, int flags)
+{
+ int status = 0;
+ int oflags = 0;
+
+ if (attr == NULL)
+ return EINVAL;
+
+ /* If the required bits are already set, do not modify anything */
+ mu_attribute_get_flags (attr, &oflags);
+ if ((oflags & flags) == flags)
+ return 0;
+
+ if (attr->_set_flags)
+ status = attr->_set_flags (attr, flags);
+ else
+ attr->flags |= flags;
+ if (status == 0)
+ mu_attribute_set_modified (attr);
+ return 0;
+}
+
+int
+mu_attribute_unset_flags (mu_attribute_t attr, int flags)
+{
+ int status = 0;
+ int oflags = 0;
+
+ if (attr == NULL)
+ return EINVAL;
+
+ /* If the required bits are already cleared, do not modify anything */
+ mu_attribute_get_flags (attr, &oflags);
+ if ((oflags & flags) == 0)
+ return 0;
+
+ if (attr->_unset_flags)
+ status = attr->_unset_flags (attr, flags);
+ else
+ attr->flags &= ~flags;
+ if (status == 0)
+ mu_attribute_set_modified (attr);
+ return 0;
+}
+
+int
+mu_attribute_set_get_flags (mu_attribute_t attr, int (*_get_flags)
+ (mu_attribute_t, int *), void *owner)
+{
+ if (attr == NULL)
+ return EINVAL;
+ if (attr->owner != owner)
+ return EACCES;
+ attr->_get_flags = _get_flags;
+ return 0;
+}
+
+int
+mu_attribute_set_set_flags (mu_attribute_t attr, int (*_set_flags)
+ (mu_attribute_t, int), void *owner)
+{
+ if (attr == NULL)
+ return EINVAL;
+ if (attr->owner != owner)
+ return EACCES;
+ attr->_set_flags = _set_flags;
+ return 0;
+}
+
+int
+mu_attribute_set_unset_flags (mu_attribute_t attr, int (*_unset_flags)
+ (mu_attribute_t, int), void *owner)
+{
+ if (attr == NULL)
+ return EINVAL;
+ if (attr->owner != owner)
+ return EACCES;
+ attr->_unset_flags = _unset_flags;
+ return 0;
+}
+
+/* We add support for "USER" flag, it is a way for external objects
+ Not being the owner to add custom flags. */
+int
+mu_attribute_set_userflag (mu_attribute_t attr, int flag)
+{
+ if (attr == NULL)
+ return EINVAL;
+ attr->user_flags |= flag;
+ return 0;
+}
+
+int
+mu_attribute_set_seen (mu_attribute_t attr)
+{
+ return mu_attribute_set_flags (attr, MU_ATTRIBUTE_SEEN);
+}
+
+int
+mu_attribute_set_answered (mu_attribute_t attr)
+{
+ return mu_attribute_set_flags (attr, MU_ATTRIBUTE_ANSWERED);
+}
+
+int
+mu_attribute_set_flagged (mu_attribute_t attr)
+{
+ return mu_attribute_set_flags (attr, MU_ATTRIBUTE_FLAGGED);
+}
+
+int
+mu_attribute_set_read (mu_attribute_t attr)
+{
+ return mu_attribute_set_flags (attr, MU_ATTRIBUTE_READ);
+}
+
+int
+mu_attribute_set_deleted (mu_attribute_t attr)
+{
+ return mu_attribute_set_flags (attr, MU_ATTRIBUTE_DELETED);
+}
+
+int
+mu_attribute_set_draft (mu_attribute_t attr)
+{
+ return mu_attribute_set_flags (attr, MU_ATTRIBUTE_DRAFT);
+}
+
+int
+mu_attribute_set_recent (mu_attribute_t attr)
+{
+ int status = mu_attribute_unset_flags (attr, MU_ATTRIBUTE_READ);
+ if (status == 0)
+ status = mu_attribute_unset_flags (attr, MU_ATTRIBUTE_SEEN);
+ return status;
+}
+
+int
+mu_attribute_is_userflag (mu_attribute_t attr, int flag)
+{
+ if (attr == NULL)
+ return 0;
+ return attr->user_flags & flag;
+}
+
+int
+mu_attribute_is_seen (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return flags & MU_ATTRIBUTE_SEEN;
+ return 0;
+}
+
+int
+mu_attribute_is_answered (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return flags & MU_ATTRIBUTE_ANSWERED;
+ return 0;
+}
+
+int
+mu_attribute_is_flagged (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return flags & MU_ATTRIBUTE_FLAGGED;
+ return 0;
+}
+
+int
+mu_attribute_is_read (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return flags & MU_ATTRIBUTE_READ;
+ return 0;
+}
+
+int
+mu_attribute_is_deleted (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return flags & MU_ATTRIBUTE_DELETED;
+ return 0;
+}
+
+int
+mu_attribute_is_draft (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return flags & MU_ATTRIBUTE_DRAFT;
+ return 0;
+}
+
+int
+mu_attribute_is_recent (mu_attribute_t attr)
+{
+ int flags = 0;
+ if (mu_attribute_get_flags (attr, &flags) == 0)
+ return MU_ATTRIBUTE_IS_UNSEEN(flags);
+ return 0;
+}
+
+int
+mu_attribute_unset_userflag (mu_attribute_t attr, int flag)
+{
+ if (attr == NULL)
+ return 0;
+ attr->user_flags &= ~flag;
+ return 0;
+}
+
+int
+mu_attribute_unset_seen (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_SEEN);
+}
+
+int
+mu_attribute_unset_answered (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_ANSWERED);
+}
+
+int
+mu_attribute_unset_flagged (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_FLAGGED);
+}
+
+int
+mu_attribute_unset_read (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_READ);
+}
+
+int
+mu_attribute_unset_deleted (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_DELETED);
+}
+
+int
+mu_attribute_unset_draft (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_DRAFT);
+}
+
+int
+mu_attribute_unset_recent (mu_attribute_t attr)
+{
+ return mu_attribute_unset_flags (attr, MU_ATTRIBUTE_SEEN);
+}
+
+int
+mu_attribute_is_equal (mu_attribute_t attr, mu_attribute_t attr2)
+{
+ int flags2 = 0, flags = 0;
+ mu_attribute_get_flags (attr, &flags);
+ mu_attribute_get_flags (attr2, &flags2);
+ return flags == flags;
+}
+
+/* Miscellaneous. */
+int
+mu_attribute_copy (mu_attribute_t dest, mu_attribute_t src)
+{
+ if (dest == NULL || src == NULL)
+ return EINVAL;
+ /* Can not be a deep copy. */
+ /* memcpy (dest, src, sizeof (*dest)); */
+ dest->flags = src->flags;
+ return 0;
+}
+
+struct flagtrans
+{
+ int flag;
+ char letter;
+};
+
+/* The two macros below are taken from gnulib module verify.h */
+#define mu_verify_true(R) \
+ (!!sizeof \
+ (struct { unsigned int verify_error_if_negative_size__: (R) ? 1 : -1; }))
+#define mu_verify(R) extern int (* verify_function__ (void)) [mu_verify_true (R)]
+
+static struct flagtrans flagtrans[] = {
+ { MU_ATTRIBUTE_SEEN, 'O' },
+ { MU_ATTRIBUTE_ANSWERED, 'A' },
+ { MU_ATTRIBUTE_FLAGGED, 'F' },
+ { MU_ATTRIBUTE_READ, 'R' },
+ { MU_ATTRIBUTE_DELETED, 'd' },
+ { 0 }
+};
+
+/* If cc reports an error in this statement, fix the MU_STATUS_BUF_SIZE
+ declaration in include/mailutils/attribute.h */
+mu_verify (MU_ARRAY_SIZE (flagtrans) == MU_STATUS_BUF_SIZE);
+
+int
+mu_string_to_flags (const char *buffer, int *pflags)
+{
+ const char *sep;
+
+ if (pflags == NULL)
+ return EINVAL;
+
+ /* Set the attribute */
+ if (mu_c_strncasecmp (buffer, "Status:", 7) == 0)
+ {
+ sep = strchr(buffer, ':'); /* pass the ':' */
+ sep++;
+ }
+ else
+ sep = buffer;
+
+ for (; *sep; sep++)
+ {
+ struct flagtrans *ft;
+
+ for (ft = flagtrans; ft->flag; ft++)
+ if (ft->letter == *sep)
+ {
+ *pflags |= ft->flag;
+ break;
+ }
+ }
+ return 0;
+}
+
+/* NOTE: When adding/removing flags, make sure to update the
+ MU_STATUS_BUF_SIZE define in include/mailutils/attribute.h */
+int
+mu_attribute_to_string (mu_attribute_t attr, char *buffer, size_t len,
+ size_t *pn)
+{
+ int flags = 0;
+ char buf[MU_STATUS_BUF_SIZE];
+ int i;
+ int rc;
+ struct flagtrans *ft;
+
+ rc = mu_attribute_get_flags (attr, &flags);
+ if (rc)
+ return rc;
+
+ i = 0;
+ for (ft = flagtrans; ft->flag; ft++)
+ if (ft->flag & flags)
+ buf[i++] = ft->letter;
+ buf[i++] = 0;
+
+ i = mu_cpystr (buffer, buf, i);
+ if (pn)
+ *pn = i;
+ return 0;
+}
+

Return to:

Send suggestions and report system problems to the System administrator.