Blame view

mailbox/attribute.c 9.22 KB
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2
   Copyright (C) 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
3

4 5 6 7
   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 2 of the License, or (at your option) any later version.
8

9
   This library is distributed in the hope that it will be useful,
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11 12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
13

14 15 16
   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., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA  */
17

18 19 20
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
21 22 23

#include <sys/types.h>
#include <stdlib.h>
24
#include <string.h>
25 26
#include <errno.h>

27 28 29 30
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif

31
#include <mailutils/errno.h>
32 33
#include <attribute0.h>

34 35
static int flags_to_string __P ((int, char *, size_t, size_t *));

36
int
37
attribute_create (attribute_t *pattr, void *owner)
38 39
{
  attribute_t attr;
40
  if (pattr == NULL)
41
    return MU_ERR_OUT_PTR_NULL;
42 43 44
  attr = calloc (1, sizeof(*attr));
  if (attr == NULL)
    return ENOMEM;
45
  attr->owner = owner;
46 47 48 49 50
  *pattr = attr;
  return 0;
}

void
51
attribute_destroy (attribute_t *pattr, void *owner)
52 53 54
{
  if (pattr && *pattr)
    {
55
      attribute_t attr = *pattr;
56
      if (attr->owner == owner)
57
	free (*pattr);
58
      /* Loose the link */
59
      *pattr = NULL;
60 61 62
    }
}

63 64 65 66 67 68
void *
attribute_get_owner (attribute_t attr)
{
  return (attr) ? attr->owner : NULL;
}

69
int
70 71
attribute_is_modified (attribute_t attr)
{
72
  return (attr) ? attr->flags & MU_ATTRIBUTE_MODIFIED : 0;
73 74 75
}

int
76 77
attribute_clear_modified (attribute_t attr)
{
78
  if (attr)
79
    attr->flags &= ~MU_ATTRIBUTE_MODIFIED;
80 81 82 83
  return 0;
}

int
84 85
attribute_set_modified (attribute_t attr)
{
86
  if (attr)
87 88
    attr->flags |= MU_ATTRIBUTE_MODIFIED;
  return 0;
89 90 91
}

int
92 93
attribute_get_flags (attribute_t attr, int *pflags)
{
94
  if (attr == NULL)
95
    return EINVAL;
96 97
  if (pflags == NULL)
    return MU_ERR_OUT_PTR_NULL;
98 99
  if (attr->_get_flags)
    return attr->_get_flags (attr, pflags);
100
  *pflags = attr->flags;
101 102 103 104 105 106
  return 0;
}

int
attribute_set_flags (attribute_t attr, int flags)
{
107
  int status = 0;
108 109
  int oflags = 0;
  
110 111
  if (attr == NULL)
    return EINVAL;
112 113 114 115 116 117

  /* If the required bits are already set, do not modify anything */
  attribute_get_flags (attr, &oflags);
  if ((oflags & flags) == flags)
    return 0;
  
118
  if (attr->_set_flags)
119 120 121 122 123
    status = attr->_set_flags (attr, flags);
  else
    attr->flags |= flags;
  if (status == 0)
    attribute_set_modified (attr);
124 125 126 127
  return 0;
}

int
128 129
attribute_unset_flags (attribute_t attr, int flags)
{
130
  int status = 0;
131 132
  int oflags = 0;

133 134
  if (attr == NULL)
    return EINVAL;
135 136 137 138 139 140

  /* If the required bits are already cleared, do not modify anything */
  attribute_get_flags (attr, &oflags);
  if ((oflags & flags) == 0)
    return 0;

141
  if (attr->_unset_flags)
142 143 144 145 146
    status = attr->_unset_flags (attr, flags);
  else
    attr->flags &= ~flags;
  if (status == 0)
    attribute_set_modified (attr);
147 148 149 150
  return 0;
}

int
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
attribute_set_get_flags (attribute_t attr, int (*_get_flags)
			 (attribute_t, int *), void *owner)
{
  if (attr == NULL)
    return EINVAL;
  if (attr->owner != owner)
    return EACCES;
  attr->_get_flags = _get_flags;
  return 0;
}

int
attribute_set_set_flags (attribute_t attr, int (*_set_flags)
			 (attribute_t, int), void *owner)
{
  if (attr == NULL)
    return EINVAL;
  if (attr->owner != owner)
    return EACCES;
  attr->_set_flags = _set_flags;
  return 0;
}

int
attribute_set_unset_flags (attribute_t attr, int (*_unset_flags)
			 (attribute_t, int), void *owner)
{
  if (attr == NULL)
    return EINVAL;
  if (attr->owner != owner)
    return EACCES;
  attr->_unset_flags = _unset_flags;
  return 0;
}

186 187 188 189 190 191 192 193 194 195 196
/* We add support for "USER" flag, it is a way for external objects
   Not being the owner to add custom flags.  */
int
attribute_set_userflag (attribute_t attr, int flag)
{
  if (attr == NULL)
    return EINVAL;
  attr->user_flags |= flag;
  return 0;
}

197
int
198
attribute_set_seen (attribute_t attr)
199
{
200
  return attribute_set_flags (attr, MU_ATTRIBUTE_SEEN);
201 202 203
}

int
204
attribute_set_answered (attribute_t attr)
205
{
206
  return attribute_set_flags (attr, MU_ATTRIBUTE_ANSWERED);
207 208 209
}

int
210
attribute_set_flagged (attribute_t attr)
211
{
212
  return attribute_set_flags (attr, MU_ATTRIBUTE_FLAGGED);
213 214 215
}

int
216
attribute_set_read (attribute_t attr)
217
{
218
  return attribute_set_flags (attr, MU_ATTRIBUTE_READ);
219 220 221
}

int
222
attribute_set_deleted (attribute_t attr)
223
{
224
  return attribute_set_flags (attr, MU_ATTRIBUTE_DELETED);
225 226 227
}

int
228
attribute_set_draft (attribute_t attr)
229
{
230
  return attribute_set_flags (attr, MU_ATTRIBUTE_DRAFT);
231 232 233
}

int
234
attribute_set_recent (attribute_t attr)
235
{
236 237 238
  int status = attribute_unset_flags (attr, MU_ATTRIBUTE_READ);
  if (status == 0)
    status = attribute_unset_flags (attr, MU_ATTRIBUTE_SEEN);
239
  return status;
240 241 242
}

int
243 244 245 246 247 248 249 250
attribute_is_userflag (attribute_t attr, int flag)
{
  if (attr == NULL)
    return 0;
  return attr->user_flags & flag;
}

int
251 252
attribute_is_seen (attribute_t attr)
{
253 254 255 256
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
    return flags & MU_ATTRIBUTE_SEEN;
  return 0;
257 258 259 260 261
}

int
attribute_is_answered (attribute_t attr)
{
262 263 264 265
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
    return flags & MU_ATTRIBUTE_ANSWERED;
  return 0;
266 267 268 269 270
}

int
attribute_is_flagged (attribute_t attr)
{
271 272 273 274
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
    return flags & MU_ATTRIBUTE_FLAGGED;
  return 0;
275 276 277 278 279
}

int
attribute_is_read (attribute_t attr)
{
280 281 282 283
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
    return flags & MU_ATTRIBUTE_READ;
  return 0;
284 285 286 287 288
}

int
attribute_is_deleted (attribute_t attr)
{
289 290 291 292
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
    return flags & MU_ATTRIBUTE_DELETED;
  return 0;
293 294 295 296 297
}

int
attribute_is_draft (attribute_t attr)
{
298 299 300 301
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
    return flags & MU_ATTRIBUTE_DRAFT;
  return 0;
302 303 304 305 306
}

int
attribute_is_recent (attribute_t attr)
{
307 308
  int flags = 0;
  if (attribute_get_flags (attr, &flags) == 0)
309
    return MU_ATTRIBUTE_IS_UNSEEN(flags);
310
  return 0;
311 312 313
}

int
314 315 316 317 318 319 320 321 322
attribute_unset_userflag (attribute_t attr, int flag)
{
  if (attr == NULL)
    return 0;
  attr->user_flags &= ~flag;
  return 0;
}

int
323
attribute_unset_seen (attribute_t attr)
324
{
325
  return attribute_unset_flags (attr, MU_ATTRIBUTE_SEEN);
326 327 328
}

int
329
attribute_unset_answered (attribute_t attr)
330
{
331
  return attribute_unset_flags (attr, MU_ATTRIBUTE_ANSWERED);
332 333 334
}

int
335
attribute_unset_flagged (attribute_t attr)
336
{
337
  return attribute_unset_flags (attr, MU_ATTRIBUTE_FLAGGED);
338 339 340
}

int
341
attribute_unset_read (attribute_t attr)
342
{
343
  return attribute_unset_flags (attr, MU_ATTRIBUTE_READ);
344 345 346
}

int
347
attribute_unset_deleted (attribute_t attr)
348
{
349
  return attribute_unset_flags (attr, MU_ATTRIBUTE_DELETED);
350 351 352
}

int
353
attribute_unset_draft (attribute_t attr)
354
{
355
  return attribute_unset_flags (attr, MU_ATTRIBUTE_DRAFT);
356 357 358
}

int
359
attribute_unset_recent (attribute_t attr)
360
{
361
  return attribute_unset_flags (attr, MU_ATTRIBUTE_SEEN);
362 363
}

364 365 366
int
attribute_is_equal (attribute_t attr, attribute_t attr2)
{
367 368 369 370
  int flags2 = 0, flags = 0;
  attribute_get_flags (attr, &flags);
  attribute_get_flags (attr2, &flags2);
  return flags == flags;
371 372
}

373
/*   Miscellaneous.  */
374
int
375
attribute_copy (attribute_t dest, attribute_t src)
376 377 378
{
  if (dest == NULL || src == NULL)
    return EINVAL;
379 380 381
  /* Can not be a deep copy.  */
  /* memcpy (dest, src, sizeof (*dest)); */
  dest->flags = src->flags;
382
  return 0;
383 384 385
}

int
386
string_to_flags (const char *buffer, int *pflags)
387
{
388
  const char *sep;
389

390 391
  if (pflags == NULL)
    return EINVAL;
392 393

  /* Set the attribute */
394
  if (strncasecmp (buffer, "Status:", 7) == 0)
395 396
    {
      sep = strchr(buffer, ':'); /* pass the ':' */
397
      sep++;
398
    }
399
  else
400
    sep = buffer;
401

402 403 404 405 406 407 408 409 410 411 412 413
  while (*sep)
    {
      if (strchr (sep, 'R') != NULL || strchr (sep, 'r') != NULL)
	*pflags |= MU_ATTRIBUTE_READ;
      if (strchr (sep, 'O') != NULL || strchr (sep, 'o') != NULL)
	*pflags |= MU_ATTRIBUTE_SEEN;
      if (strchr (sep, 'A') != NULL || strchr (sep, 'a') != NULL)
	*pflags |= MU_ATTRIBUTE_ANSWERED;
      if (strchr (sep, 'F') != NULL || strchr (sep, 'f') != NULL)
	*pflags |= MU_ATTRIBUTE_FLAGGED;
      sep++;
    }
414 415
  return 0;
}
416

417 418 419 420 421 422 423 424 425
int
attribute_to_string (attribute_t attr, char *buffer, size_t len, size_t *pn)
{
  int flags = 0;;
  attribute_get_flags (attr, &flags);
  return flags_to_string (flags, buffer, len, pn);
}

static int
426
flags_to_string (int flags, char *buffer, size_t len, size_t *pn)
427 428 429 430 431 432 433
{
  char status[32];
  char a[8];
  size_t i;

  *status = *a = '\0';

434
  if (flags & MU_ATTRIBUTE_SEEN)
435
    strcat (a, "O");
436
  if (flags & MU_ATTRIBUTE_ANSWERED)
437
    strcat (a, "A");
438
  if (flags & MU_ATTRIBUTE_FLAGGED)
439
    strcat (a, "F");
440
  if (flags & MU_ATTRIBUTE_READ)
441
    strcat (a, "R");
442 443
  if (flags & MU_ATTRIBUTE_DELETED)
    strcat (a, "d");
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463

  if (*a != '\0')
    {
      strcpy (status, "Status: ");
      strcat (status, a);
      strcat (status, "\n");
    }

  i = strlen (status);

  if (buffer && len != 0)
    {
      strncpy (buffer, status, len - 1);
      buffer[len - 1] = '\0';
      i = strlen (buffer);
    }
  if (pn)
    *pn = i;
  return 0;
}
464