Commit 528ab7cc 528ab7cc8f07c9f725e6da5fadaa5ba801edc077 by Sergey Poznyakoff

imap4d: rewrite subscription support from scratch.

This still needs some more work because imap4d does not check whether
the objects being subscribed to are valid folders or mailboxes.

* imap4d/imap4d.h (open_subscription): New prototype.
* imap4d/lsub.c (imap4d_lsub): Rewrite using MU properties.
* imap4d/subscribe.c (open_subscription): New function.
(imap4d_subscribe): Rewrite using MU properties.
* imap4d/unsubscribe.c (imap4d_unsubscribe): Rewrite using MU properties.

* examples/mblconv.c: New file.
* examples/Makefile.am: Add mblconv.c
1 parent 34361061
......@@ -34,6 +34,7 @@ noinst_PROGRAMS = \
http\
iconv\
lsf\
mblconv\
msg-send\
mta\
mucat\
......
/* Conversion from "dot mailboxlist" format to Mailutils-3 subscription format.
Copyright (C) 2010 Free Software Foundation, Inc.
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
modifications, as long as this notice is preserved.
GNU Mailutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Use this program to convert IMAP4 subscriptions from Mailutils 2.2 and
earlier to Mailutils-3 format.
Usage:
sort .mailboxlist | uniq | mblconv > .mu-subscr
rm .mailboxlist
*/
#include <stdio.h>
int
main ()
{
int c;
while ((c = getchar ()) != EOF)
{
if (c == '\n')
{
putchar (0);
putchar (0);
}
else
putchar (c);
}
}
......@@ -285,7 +285,6 @@ extern int imap4d_expunge (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_fetch (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_fetch0 (imap4d_tokbuf_t tok, int isuid, char **err_text);
extern int imap4d_list (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_lsub (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_login (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_logout (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_noop (struct imap4d_command *, imap4d_tokbuf_t);
......@@ -303,9 +302,13 @@ extern void starttls_init (void);
extern int imap4d_status (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_store (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_store0 (imap4d_tokbuf_t, int, char **);
mu_property_t open_subscription (void);
extern int imap4d_subscribe (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_uid (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_unsubscribe (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_lsub (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_uid (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_namespace (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_version (struct imap4d_command *, imap4d_tokbuf_t);
extern int imap4d_idle (struct imap4d_command *, imap4d_tokbuf_t);
......
......@@ -16,6 +16,7 @@
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#include "imap4d.h"
#include <mailutils/property.h>
/*
6.3.9. LSUB Command
......@@ -32,12 +33,13 @@
int
imap4d_lsub (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
int rc;
char *ref;
char *wcard;
char *file;
char *pattern;
const char *delim = "/";
FILE *fp;
mu_property_t prop;
mu_iterator_t itr;
if (imap4d_tokbuf_argc (tok) != 4)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
......@@ -48,35 +50,25 @@ imap4d_lsub (struct imap4d_command *command, imap4d_tokbuf_t tok)
pattern = mu_make_file_name (ref, wcard);
if (!pattern)
return io_completion_response (command, RESP_NO, "Not enough memory");
file = mu_make_file_name (real_homedir, ".mailboxlist");
if (!file)
{
free (pattern);
return io_completion_response (command, RESP_NO, "Not enough memory");
}
fp = fopen (file, "r");
free (file);
if (fp)
prop = open_subscription ();
if (!prop)
return io_completion_response (command, RESP_NO, "Cannot unsubscribe");
if ((rc = mu_property_get_iterator (prop, &itr)) == 0)
{
char *buf = NULL;
size_t n = 0;
while (getline (&buf, &n, fp) > 0)
for (mu_iterator_first (itr); !mu_iterator_is_done (itr);
mu_iterator_next (itr))
{
int len = strlen (buf);
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
if (util_wcard_match (buf, pattern, delim) == 0)
io_untagged_response (RESP_NONE, "LIST () \"%s\" %s",
delim, buf);
const char *name, *val;
mu_iterator_current_kv (itr, (const void **)&name, (void**)&val);
if (util_wcard_match (name, pattern, delim) == 0)
io_untagged_response (RESP_NONE, "LIST () \"%s\" %s", delim, name);
}
fclose (fp);
free (buf);
return io_completion_response (command, RESP_OK, "Completed");
}
else if (errno == ENOENT)
return io_completion_response (command, RESP_OK, "Completed");
return io_completion_response (command, RESP_NO, "Cannot list subscriber");
else
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_get_iterator", NULL, rc);
return io_completion_response (command, RESP_OK, "Completed");
}
......
......@@ -16,41 +16,71 @@
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#include "imap4d.h"
#include <mailutils/property.h>
/*
6.3.6. SUBSCRIBE Command
mu_property_t
open_subscription ()
{
int rc;
mu_property_t prop;
mu_stream_t str;
char *filename = mu_make_file_name (real_homedir, ".mu-subscr");
rc = mu_file_stream_create (&str, filename, MU_STREAM_RDWR|MU_STREAM_CREAT);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_file_stream_create", filename, rc);
return NULL;
}
rc = mu_property_create_init (&prop, mu_assoc_property_init, str);
free (filename);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_create_init", NULL, rc);
return NULL;
}
return prop;
}
Arguments: mailbox
/*
6.3.6. SUBSCRIBE Command
Arguments: mailbox
Responses: no specific responses for this command
Responses: no specific responses for this command
Result: OK - subscribe completed
NO - subscribe failure: can't subscribe to that name
BAD - command unknown or arguments invalid
Result: OK - subscribe completed
NO - subscribe failure: can't subscribe to that name
BAD - command unknown or arguments invalid
*/
int
imap4d_subscribe (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
int rc;
char *name;
char *file;
FILE *fp;
mu_property_t prop;
if (imap4d_tokbuf_argc (tok) != 3)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
file = mu_make_file_name (real_homedir, ".mailboxlist");
if (!file)
prop = open_subscription ();
if (!prop)
return io_completion_response (command, RESP_NO, "Cannot subscribe");
fp = fopen (file, "a");
free (file);
if (fp)
rc = mu_property_set_value (prop, name, "", 1);
if (rc)
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_set_value", name, rc);
else
{
fputs (name, fp);
fputs ("\n", fp);
fclose (fp);
return io_completion_response (command, RESP_OK, "Completed");
}
return io_completion_response (command, RESP_NO, "Cannot subscribe");
rc = mu_property_save (prop);
if (rc)
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_save", NULL, rc);
}
mu_property_destroy (&prop);
if (rc)
return io_completion_response (command, RESP_NO, "Cannot subscribe");
return io_completion_response (command, RESP_OK, "Completed");
}
......
......@@ -16,59 +16,7 @@
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#include "imap4d.h"
struct scan_data
{
int result;
char *name;
FILE *tmp;
};
static int
scan_mailbox_list (char *filename,
int (*handler) (struct scan_data *data, char *name),
struct scan_data *data)
{
FILE *fp;
char buffer[124];
fp = fopen (filename, "r");
if (!fp)
return -1;
while (fgets (buffer, sizeof (buffer), fp))
{
size_t n = strlen (buffer);
if (n && buffer[n - 1] == '\n')
buffer[n - 1] = '\0';
if (handler (data, buffer))
break;
}
fclose (fp);
return 0;
}
static int
scan_only (struct scan_data *data, char *name)
{
if (strcmp (data->name, name) == 0)
{
data->result = 1;
return 1;
}
return 0;
}
static int
unsubscribe (struct scan_data *data, char *name)
{
if (strcmp (data->name, name))
{
fputs (name, data->tmp);
fputs ("\n", data->tmp);
}
return 0;
}
#include <mailutils/property.h>
/*
6.3.7. UNSUBSCRIBE Command
......@@ -89,50 +37,33 @@ unsubscribe (struct scan_data *data, char *name)
int
imap4d_unsubscribe (struct imap4d_command *command, imap4d_tokbuf_t tok)
{
char *name;
char *file;
struct scan_data sd;
int rc;
char *name;
mu_property_t prop;
if (imap4d_tokbuf_argc (tok) != 3)
return io_completion_response (command, RESP_BAD, "Invalid arguments");
name = imap4d_tokbuf_getarg (tok, IMAP4_ARG_1);
file = mu_make_file_name (real_homedir, ".mailboxlist");
if (!file)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_make_file_name", NULL, ENOMEM);
return io_completion_response (command, RESP_NO, "Cannot unsubscribe");
}
sd.result = 0;
sd.name = name;
rc = scan_mailbox_list (file, scan_only, &sd);
if (rc == 0)
prop = open_subscription ();
if (!prop)
return io_completion_response (command, RESP_NO, "Cannot unsubscribe");
rc = mu_property_unset (prop, name);
if (rc == MU_ERR_NOENT)
rc = 0;
else if (rc)
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_unset", name, rc);
else
{
if (sd.result)
{
char *tmpname = NULL;
mu_asprintf (&tmpname, "%s.%d", file, getpid ());
sd.tmp = fopen (tmpname, "a");
if (!sd.tmp)
rc = -1;
else
{
rc = scan_mailbox_list (file, unsubscribe, &sd);
fclose (sd.tmp);
if (rc == 0)
rename (tmpname, file);
}
free (tmpname);
}
}
free (file);
rc = mu_property_save (prop);
if (rc)
mu_diag_funcall (MU_DIAG_ERROR, "mu_property_save", NULL, rc);
}
mu_property_destroy (&prop);
if (rc)
return io_completion_response (command, RESP_NO, "Cannot unsubscribe");
return io_completion_response (command, RESP_OK, "Completed");
}
......