/* GNU mailutils - a suite of utilities for electronic mail Copyright (C) 1999, 2000 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <errno.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #ifdef HAVE_STRINGS_H # include <strings.h> #endif #include <registrar0.h> #include <url0.h> static void url_mbox_destroy (url_t purl); static void url_mbox_destroy (url_t url) { (void) url; } /* Default mailbox path generator */ static char * _url_path_default (const char *spooldir, const char *user, int unused) { char *mbox = malloc (sizeof(spooldir) + strlen(user) + 2); if (!mbox) errno = ENOMEM; else sprintf (mbox, "%s/%s", spooldir, user); return mbox; } /* Hashed indexing */ static char * _url_path_hashed (const char *spooldir, const char *user, int param) { int i; int ulen = strlen (user); char *mbox; unsigned hash; if (param > ulen) param = ulen; for (i = 0, hash = 0; i < param; i++) hash += user[i]; mbox = malloc (ulen + strlen (spooldir) + 5); sprintf (mbox, "%s/%02X/%s", spooldir, hash % 256, user); return mbox; } static int transtab[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'b', 'c', 'd', 'e', 'f', 'g' }; /* Forward Indexing */ static char * _url_path_index (const char *spooldir, const char *iuser, int index_depth) { const unsigned char* user = (const unsigned char*) iuser; int i, ulen = strlen (user); char *mbox, *p; if (ulen == 0) return NULL; mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 2); strcpy (mbox, spooldir); p = mbox + strlen (mbox); for (i = 0; i < index_depth && i < ulen; i++) { *p++ = '/'; *p++ = transtab[ user[i] ]; } for (; i < index_depth; i++) { *p++ = '/'; *p++ = transtab[ user[ulen-1] ]; } *p++ = '/'; strcpy (p, user); return mbox; } /* Reverse Indexing */ static char * _url_path_rev_index (const char *spooldir, const char *iuser, int index_depth) { const unsigned char* user = (const unsigned char*) iuser; int i, ulen = strlen (user); char *mbox, *p; if (ulen == 0) return NULL; mbox = malloc (ulen + strlen (spooldir) + 2*index_depth + 1); strcpy (mbox, spooldir); p = mbox + strlen (mbox); for (i = 0; i < index_depth && i < ulen; i++) { *p++ = '/'; *p++ = transtab[ user[ulen - i - 1] ]; } for (; i < index_depth; i++) { *p++ = '/'; *p++ = transtab[ user[0] ]; } *p++ = '/'; strcpy (p, user); return mbox; } /* UNIX Mbox mbox:path[;type=TYPE][;param=PARAM][;user=USERNAME] */ int _url_mbox_init (url_t url) { const char *name = url_to_string (url); size_t len = strlen (name); char *p; /* reject the obvious */ if (name == NULL || strncmp (MU_MBOX_SCHEME, name, MU_MBOX_SCHEME_LEN) != 0 || len < (MU_MBOX_SCHEME_LEN + 1) /* (scheme)+1(path)*/) return EINVAL; /* do I need to decode url encoding '% hex hex' ? */ /* TYPE */ url->_destroy = url_mbox_destroy; /* SCHEME */ url->scheme = strdup (MU_MBOX_SCHEME); if (url->scheme == NULL) { url_mbox_destroy (url); return ENOMEM; } /* PATH */ name += MU_MBOX_SCHEME_LEN; /* pass the scheme */ url->path = strdup (name); if (url->path == NULL) { url_mbox_destroy (url); return ENOMEM; } p = strchr (url->path, ';'); if (p) { char *(*fun)() = _url_path_default; char *user = NULL; int param = 0; *p++ = 0; while (p) { char *q = strchr (p, ';'); if (q) *q++ = 0; if (strncasecmp (p, "type=", 5) == 0) { char *type = p + 5; if (strcmp (type, "hash") == 0) fun = _url_path_hashed; else if (strcmp (type, "index") == 0) fun = _url_path_index; else if (strcmp (type, "rev-index") == 0) fun = _url_path_rev_index; else { url_mbox_destroy (url); return ENOENT; } } else if (strncasecmp (p, "user=", 5) == 0) { user = p + 5; } else if (strncasecmp (p, "param=", 6) == 0) { param = strtoul (p+6, NULL, 0); } p = q; } if (user) { p = fun (url->path, user, param); free (url->path); url->path = p; } else { url_mbox_destroy (url); return ENOENT; } } return 0; }