Commit 48832b4a 48832b4ab9ea10b93c70ad756d9814c261b55f7e by Alain Magloire

UIDL is not looking for "X-UIDL" if not do an md5 of the message.

When expunging check if the message as been modified, for example
"X-UIDL" maybe add in the header it will now be save in the message.
expunge reuse the same code of mbox_append_message().
add a new header_set_fill() to get the header of the messages form the mailbox.
1 parent 4737689b
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
25 25
26 #include <attribute0.h> 26 #include <attribute0.h>
27 27
28 static int flags_to_string __P ((int, char *, size_t, size_t *));
29
28 int 30 int
29 attribute_create (attribute_t *pattr, void *owner) 31 attribute_create (attribute_t *pattr, void *owner)
30 { 32 {
...@@ -59,6 +61,12 @@ attribute_get_owner (attribute_t attr) ...@@ -59,6 +61,12 @@ attribute_get_owner (attribute_t attr)
59 } 61 }
60 62
61 int 63 int
64 attribute_is_modified (attribute_t attr)
65 {
66 return (attr) ? attr->flags != 0 : 0;
67 }
68
69 int
62 attribute_get_flags (attribute_t attr, int *pflags) 70 attribute_get_flags (attribute_t attr, int *pflags)
63 { 71 {
64 if (attr == NULL) 72 if (attr == NULL)
...@@ -76,7 +84,7 @@ attribute_set_flags (attribute_t attr, int flags) ...@@ -76,7 +84,7 @@ attribute_set_flags (attribute_t attr, int flags)
76 if (attr == NULL) 84 if (attr == NULL)
77 return EINVAL; 85 return EINVAL;
78 if (attr->_set_flags) 86 if (attr->_set_flags)
79 return attr->_set_flags (attr, flags); 87 attr->_set_flags (attr, flags);
80 attr->flags |= flags; 88 attr->flags |= flags;
81 return 0; 89 return 0;
82 } 90 }
...@@ -446,7 +454,15 @@ string_to_flags (const char *buffer, int *pflags) ...@@ -446,7 +454,15 @@ string_to_flags (const char *buffer, int *pflags)
446 return 0; 454 return 0;
447 } 455 }
448 456
449 int 457 int
458 attribute_to_string (attribute_t attr, char *buffer, size_t len, size_t *pn)
459 {
460 int flags = 0;;
461 attribute_get_flags (attr, &flags);
462 return flags_to_string (flags, buffer, len, pn);
463 }
464
465 static int
450 flags_to_string (int flags, char *buffer, size_t len, size_t *pn) 466 flags_to_string (int flags, char *buffer, size_t len, size_t *pn)
451 { 467 {
452 char status[32]; 468 char status[32];
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -307,22 +307,10 @@ body_get_fd (stream_t stream, int *pfd) ...@@ -307,22 +307,10 @@ body_get_fd (stream_t stream, int *pfd)
307 static FILE * 307 static FILE *
308 lazy_create () 308 lazy_create ()
309 { 309 {
310 FILE *file; 310 FILE *file = tmpfile ();
311 #ifdef HAVE_MKSTEMP
312 char tmpbuf[L_tmpnam + 1];
313 int fd;
314
315 if (tmpnam (tmpbuf) == NULL ||
316 (fd = mkstemp (tmpbuf)) == -1 ||
317 (file = fdopen(fd, "w+")) == NULL)
318 return NULL;
319 (void)remove(tmpbuf);
320 #else
321 file = tmpfile ();
322 //file = fopen ("/tmp/mystuff", "w+"); 311 //file = fopen ("/tmp/mystuff", "w+");
323 /* make sure the mode is right */ 312 /* make sure the mode is right */
324 if (file) 313 if (file)
325 fchmod (fileno (file), 0600); 314 fchmod (fileno (file), 0600);
326 #endif
327 return file; 315 return file;
328 } 316 }
......
...@@ -334,11 +334,36 @@ folder_list (folder_t folder, const char *dirname, const char *basename, ...@@ -334,11 +334,36 @@ folder_list (folder_t folder, const char *dirname, const char *basename,
334 struct folder_list *pflist) 334 struct folder_list *pflist)
335 { 335 {
336 if (folder == NULL || folder->_list == NULL) 336 if (folder == NULL || folder->_list == NULL)
337 return ENOSYS; 337 return EINVAL;
338 return folder->_list (folder, dirname, basename, pflist); 338 return folder->_list (folder, dirname, basename, pflist);
339 } 339 }
340 340
341 int 341 int
342 folder_lsub (folder_t folder, const char *dirname, const char *basename,
343 struct folder_list *pflist)
344 {
345 if (folder == NULL || folder->_lsub == NULL)
346 return ENOSYS;
347 return folder->_lsub (folder, dirname, basename, pflist);
348 }
349
350 int
351 folder_subscribe (folder_t folder, const char *name)
352 {
353 if (folder == NULL || folder->_subscribe == NULL)
354 return EINVAL;
355 return folder->_subscribe (folder, name);
356 }
357
358 int
359 folder_unsubscribe (folder_t folder, const char *name)
360 {
361 if (folder == NULL || folder->_unsubscribe == NULL)
362 return EINVAL;
363 return folder->_unsubscribe (folder, name);
364 }
365
366 int
342 folder_list_destroy (struct folder_list *pflist) 367 folder_list_destroy (struct folder_list *pflist)
343 { 368 {
344 size_t i; 369 size_t i;
...@@ -353,7 +378,10 @@ folder_list_destroy (struct folder_list *pflist) ...@@ -353,7 +378,10 @@ folder_list_destroy (struct folder_list *pflist)
353 free (pflist->element[i]); 378 free (pflist->element[i]);
354 } 379 }
355 } 380 }
381 if (i > 0)
356 free (pflist->element); 382 free (pflist->element);
383 pflist->element = NULL;
384 pflist->num = 0;
357 return 0; 385 return 0;
358 } 386 }
359 387
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
24 #include <errno.h> 24 #include <errno.h>
25 #include <string.h> 25 #include <string.h>
26 #include <assert.h> 26 #include <assert.h>
27 #include <fnmatch.h>
27 28
28 #include <imap0.h> 29 #include <imap0.h>
29 30
...@@ -384,17 +385,93 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, ...@@ -384,17 +385,93 @@ folder_imap_list (folder_t folder, const char *ref, const char *name,
384 { 385 {
385 f_imap_t f_imap = folder->data; 386 f_imap_t f_imap = folder->data;
386 int status = 0; 387 int status = 0;
388 char *path = NULL;
389
390 /* NOOP. */
391 if (pflist == NULL)
392 return EINVAL;
387 393
388 if (ref == NULL) 394 if (ref == NULL)
389 ref = ""; 395 ref = "";
390 if (name == NULL) 396 if (name == NULL)
391 name = ""; 397 name = "";
392 398
399 path = strdup ("");
400 if (path == NULL)
401 return ENOMEM;
402
403 /* We break the string to pieces and change the occurences of "*?[" for
404 the imap magic "%" for expansion. Then reassemble the string:
405 "/home/?/Mail/a*lain*" --> "/usr/%/Mail/%". */
406 {
407 int done = 0;
408 size_t i;
409 char **node = NULL;
410 size_t nodelen = 0;
411 const char *p = name;
412 /* Disassemble. */
413 while (!done && *p)
414 {
415 char **n;
416 n = realloc (node, (nodelen + 1) * sizeof (*node));
417 if (n == NULL)
418 break;
419 node = n;
420 if (*p == '/')
421 {
422 node[nodelen] = strdup ("/");
423 p++;
424 }
425 else
426 {
427 const char *s = strchr (p, '/');
428 if (s)
429 {
430 node[nodelen] = calloc (s - p + 1, sizeof (char));
431 if (node[nodelen])
432 memcpy (node[nodelen], p, s - p);
433 p = s;
434 }
435 else
436 {
437 node[nodelen] = strdup (p);
438 done = 1;
439 }
440 if (node[nodelen] && strpbrk (node[nodelen], "*?["))
441 {
442 free (node[nodelen]);
443 node[nodelen] = strdup ("%");
444 }
445 }
446 nodelen++;
447 if (done)
448 break;
449 }
450 /* Reassemble. */
451 for (i = 0; i < nodelen; i++)
452 {
453 if (node[i])
454 {
455 char *pth;
456 pth = realloc (path, strlen (path) + strlen (node[i]) + 1);
457 if (pth)
458 {
459 path = pth;
460 strcat (path, node[i]);
461 }
462 free (node[i]);
463 }
464 }
465 if (node)
466 free (node);
467 }
468
393 switch (f_imap->state) 469 switch (f_imap->state)
394 { 470 {
395 case IMAP_NO_STATE: 471 case IMAP_NO_STATE:
396 status = imap_writeline (f_imap, "g%d LIST \"%s\" \"%s\"\r\n", 472 status = imap_writeline (f_imap, "g%d LIST \"%s\" \"%s\"\r\n",
397 f_imap->seq++, ref, name); 473 f_imap->seq++, ref, path);
474 free (path);
398 CHECK_ERROR (f_imap, status); 475 CHECK_ERROR (f_imap, status);
399 FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer); 476 FOLDER_DEBUG0 (folder, MU_DEBUG_PROT, f_imap->buffer);
400 f_imap->state = IMAP_LIST; 477 f_imap->state = IMAP_LIST;
...@@ -412,6 +489,39 @@ folder_imap_list (folder_t folder, const char *ref, const char *name, ...@@ -412,6 +489,39 @@ folder_imap_list (folder_t folder, const char *ref, const char *name,
412 default: 489 default:
413 break; 490 break;
414 } 491 }
492
493 /* Build the folder list. */
494 if (f_imap->callback.flist.num > 0)
495 {
496 struct list_response **plist = NULL;
497 size_t num = f_imap->callback.flist.num;
498 size_t j = 0;
499 plist = calloc (num, sizeof (*plist));
500 if (plist)
501 {
502 size_t i;
503 for (i = 0; i < num; i++)
504 {
505 struct list_response *lr = f_imap->callback.flist.element[i];
506 //printf ("%s --> %s\n", lr->name, name);
507 if (fnmatch (name, lr->name, 0) == 0)
508 {
509 plist[i] = calloc (1, sizeof (**plist));
510 if (plist[i] == NULL
511 || (plist[i]->name = strdup (lr->name)) == NULL)
512 {
513 break;
514 }
515 plist[i]->type = lr->type;
516 plist[i]->separator = lr->separator;
517 j++;
518 }
519 }
520 }
521 pflist->element = plist;
522 pflist->num = j;
523 }
524 folder_list_destroy (&(f_imap->callback.flist));
415 f_imap->state = IMAP_NO_STATE; 525 f_imap->state = IMAP_NO_STATE;
416 return status; 526 return status;
417 } 527 }
...@@ -423,10 +533,13 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, ...@@ -423,10 +533,13 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name,
423 f_imap_t f_imap = folder->data; 533 f_imap_t f_imap = folder->data;
424 int status = 0; 534 int status = 0;
425 535
426 if (ref == NULL) 536 /* NOOP. */
427 ref = ""; 537 if (pflist == NULL)
428 if (name == NULL) 538 return EINVAL;
429 name = ""; 539
540 if (ref == NULL) ref = "";
541 if (name == NULL) name = "";
542
430 switch (f_imap->state) 543 switch (f_imap->state)
431 { 544 {
432 case IMAP_NO_STATE: 545 case IMAP_NO_STATE:
...@@ -449,6 +562,37 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name, ...@@ -449,6 +562,37 @@ folder_imap_lsub (folder_t folder, const char *ref, const char *name,
449 default: 562 default:
450 break; 563 break;
451 } 564 }
565
566 /* Build the folder list. */
567 if (f_imap->callback.flist.num > 0)
568 {
569 struct list_response **plist = NULL;
570 size_t num = f_imap->callback.flist.num;
571 size_t j = 0;
572 plist = calloc (num, sizeof (*plist));
573 if (plist)
574 {
575 size_t i;
576 for (i = 0; i < num; i++)
577 {
578 struct list_response *lr = f_imap->callback.flist.element[i];
579 //printf ("%s --> %s\n", lr->name, name);
580 plist[i] = calloc (1, sizeof (**plist));
581 if (plist[i] == NULL
582 || (plist[i]->name = strdup (lr->name)) == NULL)
583 {
584 break;
585 }
586 plist[i]->type = lr->type;
587 plist[i]->separator = lr->separator;
588 j++;
589 }
590 }
591 pflist->element = plist;
592 pflist->num = j;
593 folder_list_destroy (&(f_imap->callback.flist));
594 }
595 f_imap->state = IMAP_NO_STATE;
452 f_imap->state = IMAP_NO_STATE; 596 f_imap->state = IMAP_NO_STATE;
453 return 0; 597 return 0;
454 } 598 }
...@@ -755,6 +899,86 @@ imap_string (f_imap_t f_imap) ...@@ -755,6 +899,86 @@ imap_string (f_imap_t f_imap)
755 return status; 899 return status;
756 } 900 }
757 901
902 /* FIXME: does not worl for nobloking. */
903 static int
904 imap_list (f_imap_t f_imap)
905 {
906 char *tok;
907 char *sp = NULL;
908 size_t len = f_imap->nl - f_imap->buffer - 1;
909 char *buffer;
910 struct list_response **plr;
911 struct list_response *lr;
912
913 buffer = alloca (len);
914 memcpy (buffer, f_imap->buffer, len);
915 buffer[len] = '\0';
916 plr = realloc (f_imap->callback.flist.element,
917 (f_imap->callback.flist.num + 1) * sizeof (*plr));
918 if (plr == NULL)
919 return ENOMEM;
920 f_imap->callback.flist.element = plr;
921 lr = plr[f_imap->callback.flist.num] = calloc (1, sizeof (*lr));
922 if (lr == NULL)
923 return ENOMEM;
924 (f_imap->callback.flist.num)++;
925
926 /* Glob untag. */
927 tok = strtok_r (buffer, " ", &sp);
928 /* Glob LIST. */
929 tok = strtok_r (NULL, " ", &sp);
930 /* Get the attibutes. */
931 tok = strtok_r (NULL, ")", &sp);
932 if (tok)
933 {
934 char *s = NULL;
935 char *p = tok;
936 while ((tok = strtok_r (p, " ()", &s)) != NULL)
937 {
938 if (strcasecmp (tok, "\\Noselect") == 0)
939 {
940 }
941 else if (strcasecmp (tok, "\\Marked") == 0)
942 {
943 }
944 else if (strcasecmp (tok, "\\Unmarked") == 0)
945 {
946 }
947 else if (strcasecmp (tok, "\\Noinferiors") == 0)
948 {
949 lr->type |= MU_FOLDER_ATTRIBUTE_FILE;
950 }
951 else
952 {
953 lr->type |= MU_FOLDER_ATTRIBUTE_DIRECTORY;
954 }
955 p = NULL;
956 }
957 }
958 /* Hiearchy delimeter. */
959 tok = strtok_r (NULL, " ", &sp);
960 if (tok && strlen (tok) > 2)
961 lr->separator = tok[1];
962 /* The path. */
963 tok = strtok_r (NULL, " ", &sp);
964 if (tok)
965 {
966 char *s = strchr (tok, '{');
967 if (s)
968 {
969 size_t n = strtoul (s + 1, NULL, 10);
970 lr->name = calloc (n + 1, sizeof (char));
971 f_imap->ptr = f_imap->buffer;
972 imap_readline (f_imap);
973 memcpy (lr->name, f_imap->buffer, n);
974 lr->name[n] = '\0';
975 }
976 else
977 lr->name = strdup (tok);
978 }
979 return 0;
980 }
981
758 /* Helping function to figure out the section name of the message: for example 982 /* Helping function to figure out the section name of the message: for example
759 a 2 part message with the first part being sub in two will be: 983 a 2 part message with the first part being sub in two will be:
760 {1}, {1,1} {1,2} The first subpart of the message and its sub parts 984 {1}, {1,1} {1,2} The first subpart of the message and its sub parts
...@@ -803,6 +1027,7 @@ section_name (msg_imap_t msg_imap) ...@@ -803,6 +1027,7 @@ section_name (msg_imap_t msg_imap)
803 return section; 1027 return section;
804 } 1028 }
805 1029
1030 /* FIXME: This does not work for nonblocking. */
806 /* Recursive call, to parse the dismay of parentesis "()" in a BODYSTRUCTURE 1031 /* Recursive call, to parse the dismay of parentesis "()" in a BODYSTRUCTURE
807 call, not we use the short form of BODYSTRUCTURE, BODY with no argument. */ 1032 call, not we use the short form of BODYSTRUCTURE, BODY with no argument. */
808 static int 1033 static int
...@@ -1231,12 +1456,12 @@ imap_parse (f_imap_t f_imap) ...@@ -1231,12 +1456,12 @@ imap_parse (f_imap_t f_imap)
1231 char *tag, *response, *remainder; 1456 char *tag, *response, *remainder;
1232 char *buffer; 1457 char *buffer;
1233 status = imap_readline (f_imap); 1458 status = imap_readline (f_imap);
1234 /* Comment out to see all reading traffic. */
1235 //fprintf (stderr, "\t\t%s", f_imap->buffer);
1236 if (status != 0) 1459 if (status != 0)
1237 { 1460 {
1238 break; 1461 break;
1239 } 1462 }
1463 /* Comment out to see all reading traffic. */
1464 fprintf (stderr, "\t\t%s", f_imap->buffer);
1240 1465
1241 /* We do not want to step over f_imap->buffer since it can be use 1466 /* We do not want to step over f_imap->buffer since it can be use
1242 further down the chain. */ 1467 further down the chain. */
...@@ -1429,9 +1654,11 @@ imap_parse (f_imap_t f_imap) ...@@ -1429,9 +1654,11 @@ imap_parse (f_imap_t f_imap)
1429 } 1654 }
1430 else if (strcmp (response, "LIST") == 0) 1655 else if (strcmp (response, "LIST") == 0)
1431 { 1656 {
1657 status = imap_list (f_imap);
1432 } 1658 }
1433 else if (strcmp (response, "LSUB") == 0) 1659 else if (strcmp (response, "LSUB") == 0)
1434 { 1660 {
1661 status = imap_list (f_imap);
1435 } 1662 }
1436 else if (strcmp (remainder, "RECENT") == 0) 1663 else if (strcmp (remainder, "RECENT") == 0)
1437 { 1664 {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
25 #include <unistd.h> 25 #include <unistd.h>
26 #include <string.h> 26 #include <string.h>
27 #include <glob.h> 27 #include <glob.h>
28 #include <fnmatch.h>
28 #include <stdio.h> 29 #include <stdio.h>
29 #include <stdlib.h> 30 #include <stdlib.h>
30 31
...@@ -87,15 +88,23 @@ static void folder_mbox_destroy __P ((folder_t)); ...@@ -87,15 +88,23 @@ static void folder_mbox_destroy __P ((folder_t));
87 static int folder_mbox_open __P ((folder_t, int)); 88 static int folder_mbox_open __P ((folder_t, int));
88 static int folder_mbox_close __P ((folder_t)); 89 static int folder_mbox_close __P ((folder_t));
89 static int folder_mbox_delete __P ((folder_t, const char *)); 90 static int folder_mbox_delete __P ((folder_t, const char *));
90 static int folder_mbox_rename __P ((folder_t , const char *, const char *)); 91 static int folder_mbox_rename __P ((folder_t , const char *,
92 const char *));
91 static int folder_mbox_list __P ((folder_t, const char *, const char *, 93 static int folder_mbox_list __P ((folder_t, const char *, const char *,
92 struct folder_list *)); 94 struct folder_list *));
95 static int folder_mbox_subscribe __P ((folder_t, const char *));
96 static int folder_mbox_unsubscribe __P ((folder_t, const char *));
97 static int folder_mbox_lsub __P ((folder_t, const char *, const char *,
98 struct folder_list *));
99
93 100
94 static char *get_pathname __P ((const char *, const char *)); 101 static char *get_pathname __P ((const char *, const char *));
95 102
96 struct _fmbox 103 struct _fmbox
97 { 104 {
98 char *dirname; 105 char *dirname;
106 char **subscribe;
107 size_t sublen;
99 }; 108 };
100 typedef struct _fmbox *fmbox_t; 109 typedef struct _fmbox *fmbox_t;
101 110
...@@ -126,9 +135,11 @@ _folder_mbox_init (folder_t folder) ...@@ -126,9 +135,11 @@ _folder_mbox_init (folder_t folder)
126 folder->_close = folder_mbox_close; 135 folder->_close = folder_mbox_close;
127 136
128 folder->_list = folder_mbox_list; 137 folder->_list = folder_mbox_list;
138 folder->_lsub = folder_mbox_lsub;
139 folder->_subscribe = folder_mbox_subscribe;
140 folder->_unsubscribe = folder_mbox_unsubscribe;
129 folder->_delete = folder_mbox_delete; 141 folder->_delete = folder_mbox_delete;
130 folder->_rename = folder_mbox_rename; 142 folder->_rename = folder_mbox_rename;
131
132 return 0; 143 return 0;
133 } 144 }
134 145
...@@ -140,6 +151,8 @@ folder_mbox_destroy (folder_t folder) ...@@ -140,6 +151,8 @@ folder_mbox_destroy (folder_t folder)
140 fmbox_t fmbox = folder->data; 151 fmbox_t fmbox = folder->data;
141 if (fmbox->dirname) 152 if (fmbox->dirname)
142 free (fmbox->dirname); 153 free (fmbox->dirname);
154 if (fmbox->subscribe)
155 free (fmbox->subscribe);
143 free (folder->data); 156 free (folder->data);
144 folder->data = NULL; 157 folder->data = NULL;
145 } 158 }
...@@ -150,7 +163,6 @@ static int ...@@ -150,7 +163,6 @@ static int
150 folder_mbox_open (folder_t folder, int flags) 163 folder_mbox_open (folder_t folder, int flags)
151 { 164 {
152 (void)(folder); 165 (void)(folder);
153
154 (void)(flags); 166 (void)(flags);
155 return 0; 167 return 0;
156 } 168 }
...@@ -281,6 +293,84 @@ folder_mbox_list (folder_t folder, const char *dirname, const char *pattern, ...@@ -281,6 +293,84 @@ folder_mbox_list (folder_t folder, const char *dirname, const char *pattern,
281 return status; 293 return status;
282 } 294 }
283 295
296 static int
297 folder_mbox_lsub (folder_t folder, const char *ref, const char *name,
298 struct folder_list *pflist)
299 {
300 fmbox_t fmbox = folder->data;
301 size_t j = 0;
302
303 if (pflist == NULL)
304 return EINVAL;
305
306 (void)ref;
307 if (name == NULL || *name == '\0')
308 name = "*";
309
310 if (fmbox->sublen > 0)
311 {
312 struct list_response **plist;
313 size_t i;
314 plist = calloc (fmbox->sublen, sizeof (*plist));
315 for (i = 0; i < fmbox->sublen; i++)
316 {
317 if (fmbox->subscribe[i]
318 && fnmatch (name, fmbox->subscribe[i], 0) == 0)
319 {
320 plist[i] = calloc (1, sizeof (**plist));
321 if (plist[i] == NULL
322 || (plist[i]->name = strdup (fmbox->subscribe[i])) == NULL)
323 break;
324 plist[i]->type = MU_FOLDER_ATTRIBUTE_FILE;
325 plist[i]->separator = '/';
326 j++;
327 }
328 }
329 pflist->element = plist;
330 }
331 pflist->num = j;
332 return 0;
333 }
334
335 static int
336 folder_mbox_subscribe (folder_t folder, const char *name)
337 {
338 fmbox_t fmbox = folder->data;
339 char **tmp;
340 size_t i;
341 for (i = 0; i < fmbox->sublen; i++)
342 {
343 if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
344 return 0;
345 }
346 tmp = realloc (fmbox->subscribe, (fmbox->sublen + 1) * sizeof (*tmp));
347 if (tmp == NULL)
348 return ENOMEM;
349 fmbox->subscribe = tmp;
350 fmbox->subscribe[fmbox->sublen] = strdup (name);
351 if (fmbox->subscribe[fmbox->sublen] == NULL)
352 return ENOMEM;
353 fmbox->sublen++;
354 return 0;
355 }
356
357 static int
358 folder_mbox_unsubscribe (folder_t folder, const char *name)
359 {
360 fmbox_t fmbox = folder->data;
361 size_t i;
362 for (i = 0; i < fmbox->sublen; i++)
363 {
364 if (fmbox->subscribe[i] && strcmp (fmbox->subscribe[i], name) == 0)
365 {
366 free (fmbox->subscribe[i]);
367 fmbox->subscribe[i] = NULL;
368 return 0;
369 }
370 }
371 return ENOENT;
372 }
373
284 static char * 374 static char *
285 get_pathname (const char *dirname, const char *basename) 375 get_pathname (const char *dirname, const char *basename)
286 { 376 {
......
...@@ -28,12 +28,14 @@ ...@@ -28,12 +28,14 @@
28 #include <mailutils/stream.h> 28 #include <mailutils/stream.h>
29 #include <header0.h> 29 #include <header0.h>
30 30
31 static int header_parse (header_t h, const char *blurb, int len); 31 #define HEADER_MODIFIED 1
32 static int header_read (stream_t is, char *buf, size_t buflen, 32
33 off_t off, size_t *pnread); 33 static int header_parse __P ((header_t, const char *, int));
34 static int header_write (stream_t os, const char *buf, size_t buflen, 34 static int header_read __P ((stream_t, char *, size_t, off_t, size_t *));
35 off_t off, size_t *pnwrite); 35 static int header_readline __P ((stream_t, char *, size_t, off_t, size_t *));
36 static int fill_blurb (header_t header); 36 static int header_write __P ((stream_t, const char *, size_t, off_t,
37 size_t *));
38 static int fill_blurb __P ((header_t));
37 39
38 int 40 int
39 header_create (header_t *ph, const char *blurb, size_t len, void *owner) 41 header_create (header_t *ph, const char *blurb, size_t len, void *owner)
...@@ -79,6 +81,12 @@ header_get_owner (header_t header) ...@@ -79,6 +81,12 @@ header_get_owner (header_t header)
79 return (header) ? header->owner : NULL; 81 return (header) ? header->owner : NULL;
80 } 82 }
81 83
84 int
85 header_is_modified (header_t header)
86 {
87 return (header) ? (header->flags & HEADER_MODIFIED) : 0;
88 }
89
82 /* Parsing is done in a rather simple fashion. 90 /* Parsing is done in a rather simple fashion.
83 meaning we just consider an entry to be 91 meaning we just consider an entry to be
84 a field-name an a field-value. So they 92 a field-name an a field-value. So they
...@@ -298,6 +306,7 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace) ...@@ -298,6 +306,7 @@ header_set_value (header_t header, const char *fn, const char *fv, int replace)
298 } 306 }
299 header_parse (header, blurb, len + header->blurb_len); 307 header_parse (header, blurb, len + header->blurb_len);
300 free (blurb); 308 free (blurb);
309 header->flags |= HEADER_MODIFIED;
301 return 0; 310 return 0;
302 } 311 }
303 312
...@@ -498,23 +507,43 @@ header_set_stream (header_t header, stream_t stream, void *owner) ...@@ -498,23 +507,43 @@ header_set_stream (header_t header, stream_t stream, void *owner)
498 return 0; 507 return 0;
499 } 508 }
500 509
510 int
511 header_set_fill (header_t header, int
512 (*_fill) __P ((header_t, char *, size_t, off_t, size_t *)),
513 void *owner)
514 {
515 if (header == NULL)
516 return EINVAL;
517 if (header->owner != owner)
518 return EACCES;
519 header->_fill = _fill;
520 return 0;
521 }
522
501 static int 523 static int
502 fill_blurb (header_t header) 524 fill_blurb (header_t header)
503 { 525 {
504 stream_t is; 526 stream_t is = NULL;
505 int status; 527 int status;
506 char buf[1024]; 528 char buf[1024];
507 char *tbuf; 529 char *tbuf;
508 size_t nread = 0; 530 size_t nread = 0;
509 531
532 if (header->_fill == NULL)
533 {
510 status = header_get_stream (header, &is); 534 status = header_get_stream (header, &is);
511 if (status != 0) 535 if (status != 0)
512 return status; 536 return status;
537 }
513 538
514 do 539 do
515 { 540 {
516 status = stream_read (is, buf, sizeof (buf), header->temp_blurb_len, 541 if (header->_fill)
517 &nread); 542 status = header->_fill (header, buf, sizeof (buf),
543 header->temp_blurb_len, &nread) ;
544 else
545 status = stream_read (is, buf, sizeof (buf),
546 header->temp_blurb_len, &nread);
518 if (status != 0) 547 if (status != 0)
519 { 548 {
520 if (status != EAGAIN && status != EINTR) 549 if (status != EAGAIN && status != EINTR)
...@@ -572,8 +601,7 @@ header_write (stream_t os, const char *buf, size_t buflen, ...@@ -572,8 +601,7 @@ header_write (stream_t os, const char *buf, size_t buflen,
572 } 601 }
573 602
574 static int 603 static int
575 header_read (stream_t is, char *buf, size_t buflen, 604 header_read (stream_t is, char *buf, size_t buflen, off_t off, size_t *pnread)
576 off_t off, size_t *pnread)
577 { 605 {
578 header_t header = stream_get_owner (is); 606 header_t header = stream_get_owner (is);
579 int len; 607 int len;
...@@ -581,6 +609,14 @@ header_read (stream_t is, char *buf, size_t buflen, ...@@ -581,6 +609,14 @@ header_read (stream_t is, char *buf, size_t buflen,
581 if (is == NULL || header == NULL) 609 if (is == NULL || header == NULL)
582 return EINVAL; 610 return EINVAL;
583 611
612 /* Try to fill out the buffer, if we know how. */
613 if (header->blurb == NULL)
614 {
615 int err = fill_blurb (header);
616 if (err != 0)
617 return err;
618 }
619
584 len = header->blurb_len - off; 620 len = header->blurb_len - off;
585 if (len > 0) 621 if (len > 0)
586 { 622 {
...@@ -598,6 +634,52 @@ header_read (stream_t is, char *buf, size_t buflen, ...@@ -598,6 +634,52 @@ header_read (stream_t is, char *buf, size_t buflen,
598 return 0; 634 return 0;
599 } 635 }
600 636
637 static int
638 header_readline (stream_t is, char *buf, size_t buflen, off_t off, size_t *pn)
639 {
640 header_t header = stream_get_owner (is);
641 int len;
642
643 if (is == NULL || header == NULL)
644 return EINVAL;
645
646 if (buf == NULL || buflen == 0)
647 {
648 if (pn)
649 *pn = 0;
650 return 0;
651 }
652
653 /* Try to fill out the buffer, if we know how. */
654 if (header->blurb == NULL)
655 {
656 int err = fill_blurb (header);
657 if (err != 0)
658 return err;
659 }
660
661 buflen--; /* Space for the null. */
662
663 len = header->blurb_len - off;
664 if (len > 0)
665 {
666 char *nl = memchr (header->blurb + off, '\n', len);
667 if (nl)
668 len = nl - (header->blurb + off) + 1;
669
670 len = (buflen < (size_t)len) ? buflen : len;
671 memcpy (buf, header->blurb + off, len);
672 buf[len] = '\0';
673 }
674 else
675 len = 0;
676
677 if (pn)
678 *pn = len;
679 return 0;
680 }
681
682
601 int 683 int
602 header_get_stream (header_t header, stream_t *pstream) 684 header_get_stream (header_t header, stream_t *pstream)
603 { 685 {
...@@ -609,6 +691,7 @@ header_get_stream (header_t header, stream_t *pstream) ...@@ -609,6 +691,7 @@ header_get_stream (header_t header, stream_t *pstream)
609 if (status != 0) 691 if (status != 0)
610 return status; 692 return status;
611 stream_set_read (header->stream, header_read, header); 693 stream_set_read (header->stream, header_read, header);
694 stream_set_readline (header->stream, header_readline, header);
612 stream_set_write (header->stream, header_write, header); 695 stream_set_write (header->stream, header_write, header);
613 } 696 }
614 *pstream = header->stream; 697 *pstream = header->stream;
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -61,6 +61,7 @@ struct _header ...@@ -61,6 +61,7 @@ struct _header
61 size_t blurb_len; 61 size_t blurb_len;
62 size_t hdr_count; 62 size_t hdr_count;
63 struct _hdr *hdr; 63 struct _hdr *hdr;
64 int flags;
64 65
65 /* Streams. */ 66 /* Streams. */
66 stream_t stream; 67 stream_t stream;
...@@ -68,6 +69,7 @@ struct _header ...@@ -68,6 +69,7 @@ struct _header
68 int (*_set_value) __P ((header_t, const char *, const char *, int)); 69 int (*_set_value) __P ((header_t, const char *, const char *, int));
69 int (*_lines) __P ((header_t, size_t *)); 70 int (*_lines) __P ((header_t, size_t *));
70 int (*_size) __P ((header_t, size_t *)); 71 int (*_size) __P ((header_t, size_t *));
72 int (*_fill) __P ((header_t, char *, size_t, off_t, size_t *));
71 }; 73 };
72 74
73 #ifdef _cplusplus 75 #ifdef _cplusplus
......
...@@ -121,6 +121,7 @@ struct literal_string ...@@ -121,6 +121,7 @@ struct literal_string
121 size_t total; 121 size_t total;
122 msg_imap_t msg_imap; 122 msg_imap_t msg_imap;
123 enum imap_state type; 123 enum imap_state type;
124 struct folder_list flist;
124 size_t nleft; /* nleft to read in the literal. */ 125 size_t nleft; /* nleft to read in the literal. */
125 }; 126 };
126 127
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
32 /* 32 /*
33 */ 33 */
34 int 34 int
35 mailer_create (mailer_t *pmailer, const char *name, int id) 35 mailer_create (mailer_t *pmailer, const char *name)
36 { 36 {
37 int status = EINVAL; 37 int status = EINVAL;
38 record_t record = NULL; 38 record_t record = NULL;
...@@ -42,7 +42,6 @@ mailer_create (mailer_t *pmailer, const char *name, int id) ...@@ -42,7 +42,6 @@ mailer_create (mailer_t *pmailer, const char *name, int id)
42 iterator_t iterator; 42 iterator_t iterator;
43 int found = 0; 43 int found = 0;
44 44
45 (void)id;
46 if (pmailer == NULL) 45 if (pmailer == NULL)
47 return EINVAL; 46 return EINVAL;
48 47
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -183,15 +183,37 @@ _mapfile_size (stream_t stream, off_t *psize) ...@@ -183,15 +183,37 @@ _mapfile_size (stream_t stream, off_t *psize)
183 { 183 {
184 struct _mapfile_stream *mfs = stream_get_owner (stream); 184 struct _mapfile_stream *mfs = stream_get_owner (stream);
185 struct stat stbuf; 185 struct stat stbuf;
186 int err = 0;
186 187
187 if (mfs == NULL || mfs->ptr == NULL) 188 if (mfs == NULL || mfs->ptr == NULL)
188 return EINVAL; 189 return EINVAL;
189 msync (mfs->ptr, mfs->size, MS_SYNC); 190 msync (mfs->ptr, mfs->size, MS_SYNC);
190 if (fstat(mfs->fd, &stbuf) != 0) 191 if (fstat(mfs->fd, &stbuf) != 0)
191 return errno; 192 return errno;
193 if (mfs->size != (size_t)stbuf.st_size)
194 {
195 if (munmap (mfs->ptr, mfs->size) == 0)
196 {
197 mfs->size = stbuf.st_size;
198 mfs->ptr = mmap (0, mfs->size, mfs->flags , MAP_SHARED, mfs->fd, 0);
199 if (mfs->ptr == MAP_FAILED)
200 err = errno;
201 }
202 else
203 err = errno;
204 }
205 if (err != 0)
206 {
207 mfs->ptr = NULL;
208 close (mfs->fd);
209 mfs->fd = -1;
210 }
211 else
212 {
192 if (psize) 213 if (psize)
193 *psize = stbuf.st_size; 214 *psize = stbuf.st_size;
194 return 0; 215 }
216 return err;
195 } 217 }
196 218
197 static int 219 static int
...@@ -277,6 +299,7 @@ _mapfile_open (stream_t stream, const char *filename, int port, int flags) ...@@ -277,6 +299,7 @@ _mapfile_open (stream_t stream, const char *filename, int port, int flags)
277 { 299 {
278 int err = errno; 300 int err = errno;
279 close (mfs->fd); 301 close (mfs->fd);
302 mfs->ptr = NULL;
280 return err; 303 return err;
281 } 304 }
282 mfs->flags = mflag; 305 mfs->flags = mflag;
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
28 #include <string.h> 28 #include <string.h>
29 #include <ctype.h> 29 #include <ctype.h>
30 30
31 #include "md5.h"
32
31 #include <misc.h> 33 #include <misc.h>
32 #include <message0.h> 34 #include <message0.h>
33 35
...@@ -155,6 +157,15 @@ message_get_owner (message_t msg) ...@@ -155,6 +157,15 @@ message_get_owner (message_t msg)
155 } 157 }
156 158
157 int 159 int
160 message_is_modified (message_t msg)
161 {
162 int mod = 0;
163 mod |= header_is_modified (msg->header);
164 mod |= attribute_is_modified (msg->attribute);
165 return mod;
166 }
167
168 int
158 message_set_mailbox (message_t msg, mailbox_t mailbox) 169 message_set_mailbox (message_t msg, mailbox_t mailbox)
159 { 170 {
160 if (msg == NULL) 171 if (msg == NULL)
...@@ -400,6 +411,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner) ...@@ -400,6 +411,7 @@ message_set_attribute (message_t msg, attribute_t attribute, void *owner)
400 return 0; 411 return 0;
401 } 412 }
402 413
414 /* FIXME: not nonblocking safe. */
403 int 415 int
404 message_get_uid (message_t msg, char *buffer, size_t buflen, size_t *pwriten) 416 message_get_uid (message_t msg, char *buffer, size_t buflen, size_t *pwriten)
405 { 417 {
...@@ -411,16 +423,19 @@ message_get_uid (message_t msg, char *buffer, size_t buflen, size_t *pwriten) ...@@ -411,16 +423,19 @@ message_get_uid (message_t msg, char *buffer, size_t buflen, size_t *pwriten)
411 return EINVAL; 423 return EINVAL;
412 424
413 buffer[0] = '\0'; 425 buffer[0] = '\0';
426 /* Try the function overload if error fallback. */
414 if (msg->_get_uid) 427 if (msg->_get_uid)
415 return msg->_get_uid (msg, buffer, buflen, pwriten); 428 {
429 status = msg->_get_uid (msg, buffer, buflen, pwriten);
430 if (status == 0)
431 return status;
432 }
416 433
417 /* Be compatible with Qpopper ? qppoper saves the UIDL in "X-UIDL". 434 /* Be compatible with Qpopper ? qppoper saves the UIDL in "X-UIDL".
418 We use "Message-ID" as a fallback. Is this bad ? should we generate 435 We generate a chksum and save it in the header. */
419 a chksum or do the same as Qpopper save it in the header. */
420 message_get_header (msg, &header); 436 message_get_header (msg, &header);
421 if ((status = header_get_value (header, "X-UIDL", buffer, buflen, &n)) == 0 437 status = header_get_value (header, "X-UIDL", buffer, buflen, &n);
422 || (status = header_get_value (header, "Message-ID", buffer, 438 if (status == 0 && n > 0)
423 buflen, &n)) == 0)
424 { 439 {
425 /* FIXME: Is header_get_value suppose to do this ? */ 440 /* FIXME: Is header_get_value suppose to do this ? */
426 /* We need to collapse the header if it was mutiline. e points to the 441 /* We need to collapse the header if it was mutiline. e points to the
...@@ -437,6 +452,32 @@ message_get_uid (message_t msg, char *buffer, size_t buflen, size_t *pwriten) ...@@ -437,6 +452,32 @@ message_get_uid (message_t msg, char *buffer, size_t buflen, size_t *pwriten)
437 } 452 }
438 } 453 }
439 } 454 }
455 else
456 {
457 struct md5_ctx md5context;
458 stream_t stream = NULL;
459 char buf[1024];
460 off_t offset = 0;
461 unsigned char md5digest[16];
462 char *tmp;
463 n = 0;
464 message_get_stream (msg, &stream);
465 md5_init_ctx (&md5context);
466 while (stream_read (stream, buf, sizeof (buf), offset, &n) == 0
467 && n > 0)
468 {
469 md5_process_bytes (buf, n, &md5context);
470 offset += n;
471 }
472 md5_finish_ctx (&md5context, md5digest);
473 tmp = buf;
474 for (n = 0; n < 16; n++, tmp += 2)
475 sprintf (tmp, "%02x", md5digest[n]);
476 *tmp = '\0';
477 header_set_value (header, "X-UIDL", buf, 1);
478 buflen--; /* leave space for the NULL. */
479 strncpy (buffer, buf, buflen)[buflen] = '\0';
480 }
440 return status; 481 return status;
441 } 482 }
442 483
......
1 /* GNU mailutils - a suite of utilities for electronic mail 1 /* GNU mailutils - a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000 Free Software Foundation, Inc. 2 Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
3 3
4 This program is free software; you can redistribute it and/or modify 4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Library Public License as published by 5 it under the terms of the GNU General Library Public License as published by
...@@ -649,7 +649,7 @@ mime_destroy(mime_t *pmime) ...@@ -649,7 +649,7 @@ mime_destroy(mime_t *pmime)
649 } 649 }
650 650
651 int 651 int
652 mime_get_part(mime_t mime, int part, message_t *msg) 652 mime_get_part(mime_t mime, size_t part, message_t *msg)
653 { 653 {
654 size_t nmtp_parts; 654 size_t nmtp_parts;
655 int ret = 0; 655 int ret = 0;
......