summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorilja <ilja@7b491191-dbf0-0310-aff6-d879d4d69008>2004-03-19 14:11:53 +0000
committerilja <ilja@7b491191-dbf0-0310-aff6-d879d4d69008>2004-03-19 14:11:53 +0000
commitb3f64296e16029fa5b5c215d58a3cee14c620d94 (patch)
tree1f57650e8f6ea99431b9ff7947930d6bd1ddc9e4
parent3e6f33ac32e6f09c770003503494af56bde1df88 (diff)
indent -i8 -kr has now been used on all dbmail source files (*.c and *.h).
All files are now indented as K&R. git-svn-id: https://svn.ic-s.nl/svn/dbmail/trunk/dbmail@1028 7b491191-dbf0-0310-aff6-d879d4d69008
-rw-r--r--dbmailtypes.h5
-rw-r--r--dsn.c459
-rw-r--r--dsn.h39
-rw-r--r--forward.c18
-rw-r--r--forward.h3
-rw-r--r--header.c246
-rw-r--r--header.h3
-rw-r--r--imap4.c663
-rw-r--r--imap4.h53
-rw-r--r--imapcommands.c7261
-rw-r--r--imapcommands.h64
-rw-r--r--imapd.c408
-rw-r--r--imaputil.c5044
-rw-r--r--imaputil.h48
-rw-r--r--list.c230
-rw-r--r--list.h22
-rw-r--r--lmtp.c1265
-rw-r--r--lmtp.h109
-rw-r--r--lmtpd.c402
-rw-r--r--main.c566
-rw-r--r--maintenance.c952
-rw-r--r--maintenance.h1
-rw-r--r--mbox2dbmail.c140
-rw-r--r--md5.c343
-rw-r--r--md5.h13
-rw-r--r--memblock.c625
-rw-r--r--memblock.h40
-rw-r--r--mime.h16
-rw-r--r--misc.c583
-rw-r--r--misc.h14
-rw-r--r--mysql/dbmysql.c227
-rw-r--r--pgsql/dbpgsql.c423
-rw-r--r--pipe.c934
-rw-r--r--pipe.h9
-rw-r--r--pop3.c1735
-rw-r--r--pop3.h37
-rw-r--r--pop3d.c436
-rw-r--r--proctitleutils.c106
-rw-r--r--proctitleutils.h5
-rw-r--r--quota.c160
-rw-r--r--quota.h20
-rw-r--r--rfcmsg.c1337
-rw-r--r--rfcmsg.h18
-rw-r--r--server.c393
-rw-r--r--server.h32
-rw-r--r--serverchild.c536
-rw-r--r--serverchild.h19
-rw-r--r--settings.c139
-rw-r--r--sievecmd.c558
-rw-r--r--sievecmd.h5
-rw-r--r--smtp-convert.c389
-rw-r--r--sort.h14
-rw-r--r--sort/sort.c560
-rw-r--r--sort/sortsieve.c527
-rw-r--r--sort/sortsieve.h5
-rw-r--r--timsieve.c1434
-rw-r--r--timsieve.h17
-rw-r--r--timsieved.c402
-rw-r--r--user.c1409
-rw-r--r--user.h1
-rw-r--r--vut2dbmail.c240
61 files changed, 16414 insertions, 15348 deletions
diff --git a/dbmailtypes.h b/dbmailtypes.h
index 6d341d6c..df62adfc 100644
--- a/dbmailtypes.h
+++ b/dbmailtypes.h
@@ -123,7 +123,7 @@ typedef struct {
#define IMAP_NFLAGS 6
enum IMAP4_CLIENT_STATES { IMAPCS_INITIAL_CONNECT,
- IMAPCS_NON_AUTHENTICATED,
+ IMAPCS_NON_AUTHENTICATED,
IMAPCS_AUTHENTICATED, IMAPCS_SELECTED, IMAPCS_LOGOUT
};
@@ -135,7 +135,8 @@ enum IMAP4_FLAGS { IMAPFLAG_SEEN = 0x01, IMAPFLAG_ANSWERED = 0x02,
enum IMAP4_PERMISSION { IMAPPERM_READ = 0x01, IMAPPERM_READWRITE = 0x02 };
enum IMAP4_FLAG_ACTIONS { IMAPFA_NONE, IMAPFA_REPLACE, IMAPFA_ADD,
- IMAPFA_REMOVE };
+ IMAPFA_REMOVE
+};
enum BODY_FETCH_ITEM_TYPES { BFIT_TEXT, BFIT_HEADER, BFIT_MIME,
BFIT_HEADER_FIELDS,
diff --git a/dsn.c b/dsn.c
index 019e8dff..d3b29e28 100644
--- a/dsn.c
+++ b/dsn.c
@@ -10,259 +10,288 @@
#include "debug.h"
-int dsnuser_init(deliver_to_user_t *dsnuser)
+int dsnuser_init(deliver_to_user_t * dsnuser)
{
- dsnuser->useridnr = 0;
- dsnuser->dsn.class = 0;
- dsnuser->dsn.subject = 0;
- dsnuser->dsn.detail = 0;
+ dsnuser->useridnr = 0;
+ dsnuser->dsn.class = 0;
+ dsnuser->dsn.subject = 0;
+ dsnuser->dsn.detail = 0;
- dsnuser->address = NULL;
- dsnuser->mailbox = NULL;
+ dsnuser->address = NULL;
+ dsnuser->mailbox = NULL;
- dsnuser->userids = (struct list *)my_malloc(sizeof(struct list));
+ dsnuser->userids = (struct list *) my_malloc(sizeof(struct list));
if (dsnuser->userids == NULL)
return -1;
- dsnuser->forwards = (struct list *)my_malloc(sizeof(struct list));
+ dsnuser->forwards = (struct list *) my_malloc(sizeof(struct list));
if (dsnuser->forwards == NULL)
return -1;
- list_init(dsnuser->userids);
- list_init(dsnuser->forwards);
+ list_init(dsnuser->userids);
+ list_init(dsnuser->forwards);
trace(TRACE_DEBUG, "%s, %s: dsnuser initialized",
- __FILE__, __FUNCTION__);
+ __FILE__, __FUNCTION__);
return 0;
}
-void dsnuser_free(deliver_to_user_t *dsnuser)
+void dsnuser_free(deliver_to_user_t * dsnuser)
{
- dsnuser->useridnr = 0;
- dsnuser->dsn.class = 0;
- dsnuser->dsn.subject = 0;
- dsnuser->dsn.detail = 0;
+ dsnuser->useridnr = 0;
+ dsnuser->dsn.class = 0;
+ dsnuser->dsn.subject = 0;
+ dsnuser->dsn.detail = 0;
/* These are nominally const, but
* we really do want to free them. */
- my_free((char *)dsnuser->address);
- my_free((char *)dsnuser->mailbox);
+ my_free((char *) dsnuser->address);
+ my_free((char *) dsnuser->mailbox);
- list_freelist(&dsnuser->userids->start);
- list_freelist(&dsnuser->forwards->start);
+ list_freelist(&dsnuser->userids->start);
+ list_freelist(&dsnuser->forwards->start);
- my_free(dsnuser->userids);
- my_free(dsnuser->forwards);
+ my_free(dsnuser->userids);
+ my_free(dsnuser->forwards);
trace(TRACE_DEBUG, "%s, %s: dsnuser freed",
- __FILE__, __FUNCTION__);
+ __FILE__, __FUNCTION__);
}
int dsnuser_resolve_list(struct list *deliveries)
{
- u64_t userid;
- int alias_count = 0, domain_count = 0;
- char *domain = NULL;
- char *username = NULL;
- struct element *element;
-
- /* Loop through the users list */
- for (element = list_getstart(deliveries); element != NULL; element = element->nextnode)
- {
- deliver_to_user_t *delivery = (deliver_to_user_t *)element->data;
-
- /* If the userid is already set, then we're doing direct-to-userid. */
- if (delivery->useridnr != 0)
- {
- /* This seems to be the only way to see if a useridnr is valid. */
- username = auth_get_userid(delivery->useridnr);
- if (username != NULL)
- {
- /* Free the username, we don't actually need it. */
- my_free(username);
-
- /* Copy the delivery useridnr into the userids list. */
- if (list_nodeadd(delivery->userids, &delivery->useridnr, sizeof(delivery->useridnr)) == 0)
- {
- trace(TRACE_ERROR, "%s, %s: out of memory",
- __FILE__, __FUNCTION__);
- return -1;
- }
-
- /* The userid was valid... */
- delivery->dsn.class = DSN_CLASS_OK; /* Success. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 5; /* Valid. */
- }
- else /* from: 'if (username != NULL)' */
- {
- /* The userid was invalid... */
- delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 1; /* Does not exist. */
- }
- }
- /* We don't have a useridnr, so we have either a username or an alias. */
- else /* from: 'if (delivery->useridnr != 0)' */
- {
- /* See if the address is a username. */
- switch (auth_user_exists(delivery->address, &userid))
- {
- case -1:
- {
- /* An error occurred */
- trace(TRACE_ERROR,"%s, %s: error checking user [%s]",
- __FILE__, __FUNCTION__, delivery->address);
- return -1;
- break;
- }
- case 1:
- {
- if (list_nodeadd(delivery->userids, &userid, sizeof(u64_t)) == 0)
- {
- trace(TRACE_ERROR, "%s, %s: out of memory",
- __FILE__, __FUNCTION__);
- return -1;
- }
- else
- {
-
- trace(TRACE_DEBUG, "%s, %s: added user [%s] id [%llu] to delivery list",
- __FILE__, __FUNCTION__, delivery->address, userid);
- /* The userid was valid... */
- delivery->dsn.class = DSN_CLASS_OK; /* Success. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 5; /* Valid. */
- }
- break;
- }
- /* The address needs to be looked up */
- default:
- {
- alias_count = auth_check_user_ext(delivery->address, delivery->userids, delivery->forwards, -1);
- trace(TRACE_DEBUG, "%s, %s: user [%s] found total of [%d] aliases",
- __FILE__, __FUNCTION__, delivery->address, alias_count);
-
- /* No aliases found for this user */
- if (alias_count == 0)
- {
- trace(TRACE_INFO,"%s, %s: user [%s] checking for domain forwards.",
- __FILE__, __FUNCTION__, delivery->address);
-
- domain = strchr(delivery->address, '@');
-
- if (domain == NULL)
- {
- /* That's it, we're done here. */
- /* Permanent failure... */
- delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 1; /* Does not exist. */
- }
- else
- {
- trace(TRACE_DEBUG, "%s, %s: domain [%s] checking for domain forwards",
- __FILE__, __FUNCTION__, domain);
-
- /* Checking for domain aliases */
- domain_count = auth_check_user_ext(domain, delivery->userids, delivery->forwards, -1);
- trace(TRACE_DEBUG,"%s, %s: domain [%s] found total of [%d] aliases",
- __FILE__, __FUNCTION__, domain, domain_count);
-
- if (domain_count == 0)
- {
- /* Permanent failure... */
- delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 1; /* Does not exist. */
- }
- else /* from: 'if (domain_count == 0)' */
- {
- /* The userid was valid... */
- delivery->dsn.class = DSN_CLASS_OK; /* Success. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 5; /* Valid. */
- } /* from: 'if (domain_count == 0)' */
- } /* from: 'if (domain == NULL)' */
- }
- else /* from: 'if (alias_count == 0)' */
- {
- /* The userid was valid... */
- delivery->dsn.class = DSN_CLASS_OK; /* Success. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 5; /* Valid. */
- } /* from: 'if (alias_count == 0)' */
- } /* from: 'default:' */
- } /* from: 'switch (auth_user_exists(delivery->address, &userid))' */
- } /* from: 'if (delivery->useridnr != 0)' */
- } /* from: the main for loop */
-
- return 0;
+ u64_t userid;
+ int alias_count = 0, domain_count = 0;
+ char *domain = NULL;
+ char *username = NULL;
+ struct element *element;
+
+ /* Loop through the users list */
+ for (element = list_getstart(deliveries); element != NULL;
+ element = element->nextnode) {
+ deliver_to_user_t *delivery =
+ (deliver_to_user_t *) element->data;
+
+ /* If the userid is already set, then we're doing direct-to-userid. */
+ if (delivery->useridnr != 0) {
+ /* This seems to be the only way to see if a useridnr is valid. */
+ username = auth_get_userid(delivery->useridnr);
+ if (username != NULL) {
+ /* Free the username, we don't actually need it. */
+ my_free(username);
+
+ /* Copy the delivery useridnr into the userids list. */
+ if (list_nodeadd
+ (delivery->userids,
+ &delivery->useridnr,
+ sizeof(delivery->useridnr)) == 0) {
+ trace(TRACE_ERROR,
+ "%s, %s: out of memory",
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+
+ /* The userid was valid... */
+ delivery->dsn.class = DSN_CLASS_OK; /* Success. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 5; /* Valid. */
+ } else { /* from: 'if (username != NULL)' */
+
+ /* The userid was invalid... */
+ delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 1; /* Does not exist. */
+ }
+ }
+ /* We don't have a useridnr, so we have either a username or an alias. */
+ else { /* from: 'if (delivery->useridnr != 0)' */
+
+ /* See if the address is a username. */
+ switch (auth_user_exists
+ (delivery->address, &userid)) {
+ case -1:
+ {
+ /* An error occurred */
+ trace(TRACE_ERROR,
+ "%s, %s: error checking user [%s]",
+ __FILE__, __FUNCTION__,
+ delivery->address);
+ return -1;
+ break;
+ }
+ case 1:
+ {
+ if (list_nodeadd
+ (delivery->userids, &userid,
+ sizeof(u64_t)) == 0) {
+ trace(TRACE_ERROR,
+ "%s, %s: out of memory",
+ __FILE__,
+ __FUNCTION__);
+ return -1;
+ } else {
+
+ trace(TRACE_DEBUG,
+ "%s, %s: added user [%s] id [%llu] to delivery list",
+ __FILE__,
+ __FUNCTION__,
+ delivery->address,
+ userid);
+ /* The userid was valid... */
+ delivery->dsn.class = DSN_CLASS_OK; /* Success. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 5; /* Valid. */
+ }
+ break;
+ }
+ /* The address needs to be looked up */
+ default:
+ {
+ alias_count =
+ auth_check_user_ext(delivery->
+ address,
+ delivery->
+ userids,
+ delivery->
+ forwards,
+ -1);
+ trace(TRACE_DEBUG,
+ "%s, %s: user [%s] found total of [%d] aliases",
+ __FILE__, __FUNCTION__,
+ delivery->address,
+ alias_count);
+
+ /* No aliases found for this user */
+ if (alias_count == 0) {
+ trace(TRACE_INFO,
+ "%s, %s: user [%s] checking for domain forwards.",
+ __FILE__,
+ __FUNCTION__,
+ delivery->address);
+
+ domain =
+ strchr(delivery->
+ address, '@');
+
+ if (domain == NULL) {
+ /* That's it, we're done here. */
+ /* Permanent failure... */
+ delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 1; /* Does not exist. */
+ } else {
+ trace(TRACE_DEBUG,
+ "%s, %s: domain [%s] checking for domain forwards",
+ __FILE__,
+ __FUNCTION__,
+ domain);
+
+ /* Checking for domain aliases */
+ domain_count =
+ auth_check_user_ext
+ (domain,
+ delivery->
+ userids,
+ delivery->
+ forwards, -1);
+ trace(TRACE_DEBUG,
+ "%s, %s: domain [%s] found total of [%d] aliases",
+ __FILE__,
+ __FUNCTION__,
+ domain,
+ domain_count);
+
+ if (domain_count ==
+ 0) {
+ /* Permanent failure... */
+ delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 1; /* Does not exist. */
+ } else { /* from: 'if (domain_count == 0)' */
+
+ /* The userid was valid... */
+ delivery->dsn.class = DSN_CLASS_OK; /* Success. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 5; /* Valid. */
+ } /* from: 'if (domain_count == 0)' */
+ } /* from: 'if (domain == NULL)' */
+ } else { /* from: 'if (alias_count == 0)' */
+
+ /* The userid was valid... */
+ delivery->dsn.class = DSN_CLASS_OK; /* Success. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 5; /* Valid. */
+ } /* from: 'if (alias_count == 0)' */
+ } /* from: 'default:' */
+ } /* from: 'switch (auth_user_exists(delivery->address, &userid))' */
+ } /* from: 'if (delivery->useridnr != 0)' */
+ } /* from: the main for loop */
+
+ return 0;
}
void dsnuser_free_list(struct list *deliveries)
{
- struct element *tmp;
+ struct element *tmp;
- for(tmp = list_getstart(deliveries); tmp != NULL; tmp = tmp->nextnode)
- dsnuser_free((deliver_to_user_t *)tmp->data);
+ for (tmp = list_getstart(deliveries); tmp != NULL;
+ tmp = tmp->nextnode)
+ dsnuser_free((deliver_to_user_t *) tmp->data);
- list_freelist(&deliveries->start);
+ list_freelist(&deliveries->start);
}
dsn_class_t dsnuser_worstcase_int(int has_2, int has_4, int has_5)
{
- dsn_class_t exitcode;
-
- /* If only one code, use it. */
- if (has_2 && !has_4 && !has_5) /* Only 2 */
- exitcode = DSN_CLASS_OK;
- else if (!has_2 && has_4 && !has_5) /* Only 4 */
- exitcode = DSN_CLASS_TEMP;
- else if (!has_2 && !has_4 && has_5) /* Only 5 */
- exitcode = DSN_CLASS_FAIL;
- /* If two codes, prefer temporary, otherwise fail. */
- else if (has_2 && has_4 && !has_5) /* 2 and 4 */
- exitcode = DSN_CLASS_TEMP;
- else if (has_2 && !has_4 && has_5) /* 2 and 5 */
- exitcode = DSN_CLASS_FAIL;
- else if (!has_2 && has_4 && has_5) /* 4 and 5 */
- exitcode = DSN_CLASS_TEMP;
- /* All three or none, again prefer temporary. */
- else /* 2, 4, 5 */
- exitcode = DSN_CLASS_TEMP;
-
- return exitcode;
+ dsn_class_t exitcode;
+
+ /* If only one code, use it. */
+ if (has_2 && !has_4 && !has_5) /* Only 2 */
+ exitcode = DSN_CLASS_OK;
+ else if (!has_2 && has_4 && !has_5) /* Only 4 */
+ exitcode = DSN_CLASS_TEMP;
+ else if (!has_2 && !has_4 && has_5) /* Only 5 */
+ exitcode = DSN_CLASS_FAIL;
+ /* If two codes, prefer temporary, otherwise fail. */
+ else if (has_2 && has_4 && !has_5) /* 2 and 4 */
+ exitcode = DSN_CLASS_TEMP;
+ else if (has_2 && !has_4 && has_5) /* 2 and 5 */
+ exitcode = DSN_CLASS_FAIL;
+ else if (!has_2 && has_4 && has_5) /* 4 and 5 */
+ exitcode = DSN_CLASS_TEMP;
+ /* All three or none, again prefer temporary. */
+ else /* 2, 4, 5 */
+ exitcode = DSN_CLASS_TEMP;
+
+ return exitcode;
}
-dsn_class_t dsnuser_worstcase_list(struct list *deliveries)
+dsn_class_t dsnuser_worstcase_list(struct list * deliveries)
{
- struct element *tmp;
- int has_2 = 0, has_4 = 0, has_5 = 0;
-
- /* Get one reasonable error code for everyone. */
- for(tmp = list_getstart(deliveries); tmp != NULL; tmp = tmp->nextnode)
- {
- switch (((deliver_to_user_t *)tmp->data)->dsn.class)
- {
- case DSN_CLASS_OK:
- /* Success. */
- has_2 = 1;
- break;
- case DSN_CLASS_TEMP:
- /* Temporary transient failure. */
- has_4 = 1;
- break;
- case DSN_CLASS_FAIL:
- /* Permanent failure. */
- has_5 = 1;
- break;
- }
- }
-
- /* If we never made it into the list, all zeroes will
- * yield a temporary failure, which is pretty reasonable. */
- return dsnuser_worstcase_int(has_2, has_4, has_5);
-}
+ struct element *tmp;
+ int has_2 = 0, has_4 = 0, has_5 = 0;
+ /* Get one reasonable error code for everyone. */
+ for (tmp = list_getstart(deliveries); tmp != NULL;
+ tmp = tmp->nextnode) {
+ switch (((deliver_to_user_t *) tmp->data)->dsn.class) {
+ case DSN_CLASS_OK:
+ /* Success. */
+ has_2 = 1;
+ break;
+ case DSN_CLASS_TEMP:
+ /* Temporary transient failure. */
+ has_4 = 1;
+ break;
+ case DSN_CLASS_FAIL:
+ /* Permanent failure. */
+ has_5 = 1;
+ break;
+ }
+ }
+
+ /* If we never made it into the list, all zeroes will
+ * yield a temporary failure, which is pretty reasonable. */
+ return dsnuser_worstcase_int(has_2, has_4, has_5);
+}
diff --git a/dsn.h b/dsn.h
index 0e31af80..f4a3d939 100644
--- a/dsn.h
+++ b/dsn.h
@@ -12,28 +12,25 @@
* accessed by functions in dsn.c
*/
-typedef enum
-{
- DSN_CLASS_OK = 2,
- DSN_CLASS_TEMP = 4,
- DSN_CLASS_FAIL = 5
+typedef enum {
+ DSN_CLASS_OK = 2,
+ DSN_CLASS_TEMP = 4,
+ DSN_CLASS_FAIL = 5
} dsn_class_t;
-typedef struct
-{
- dsn_class_t class;
- int subject;
- int detail;
+typedef struct {
+ dsn_class_t class;
+ int subject;
+ int detail;
} delivery_status_t;
-typedef struct
-{
- u64_t useridnr; /* Specific user id recipient (from outside). */
- const char *address; /* Envelope recipient (from outside). */
- const char *mailbox; /* Default mailbox to use for userid deliveries (from outside). */
- struct list *userids; /* List of u64_t* -- internal useridnr's to deliver to (internal). */
- struct list *forwards; /* List of char* -- external addresses to forward to (internal). */
- delivery_status_t dsn; /* Return status of this "delivery basket" (to outside). */
+typedef struct {
+ u64_t useridnr; /* Specific user id recipient (from outside). */
+ const char *address; /* Envelope recipient (from outside). */
+ const char *mailbox; /* Default mailbox to use for userid deliveries (from outside). */
+ struct list *userids; /* List of u64_t* -- internal useridnr's to deliver to (internal). */
+ struct list *forwards; /* List of char* -- external addresses to forward to (internal). */
+ delivery_status_t dsn; /* Return status of this "delivery basket" (to outside). */
} deliver_to_user_t;
/**
@@ -43,9 +40,9 @@ typedef struct
* - 0 on success
* - -1 on failure
*/
-int dsnuser_init(deliver_to_user_t *dsnuser);
+int dsnuser_init(deliver_to_user_t * dsnuser);
-void dsnuser_free(deliver_to_user_t *dsnuser);
+void dsnuser_free(deliver_to_user_t * dsnuser);
void dsnuser_free_list(struct list *deliveries);
/**
@@ -86,4 +83,4 @@ dsn_class_t dsnuser_worstcase_list(struct list *deliveries);
*/
dsn_class_t dsnuser_worstcase_int(int has_2, int has_4, int has_5);
-#endif /* DSN_H */
+#endif /* DSN_H */
diff --git a/forward.c b/forward.c
index 9b782e0f..0f144601 100644
--- a/forward.c
+++ b/forward.c
@@ -82,15 +82,14 @@ int forward(u64_t msgidnr, struct list *targets, const char *from,
}
target = list_getstart(targets);
-
+
while (target != NULL) {
if ((((char *) target->data)[0] == '|')
|| (((char *) target->data)[0] == '!')) {
/* external pipe command */
- command =
- (char *)
- my_malloc(strlen((char *) (target->data)));
+ command = (char *)
+ my_malloc(strlen((char *) (target->data)));
if (!command) {
trace(TRACE_ERROR,
"%s,%s: out of memory",
@@ -101,10 +100,10 @@ int forward(u64_t msgidnr, struct list *targets, const char *from,
strcpy(command, (char *) (target->data) + 1);
} else {
/* pipe to sendmail */
- command = (char *)
- my_malloc(strlen((char *)
- (target->data)) +
- strlen(sendmail) + 2);
+ command = (char *)
+ my_malloc(strlen((char *)
+ (target->data)) +
+ strlen(sendmail) + 2);
/* +2 for extra space and \0 */
if (!command) {
trace(TRACE_ERROR,
@@ -170,7 +169,8 @@ int forward(u64_t msgidnr, struct list *targets, const char *from,
* is no message to send. */
trace(TRACE_DEBUG,
"%s,%s: writing header to "
- "pipe", __FILE__, __FUNCTION__);
+ "pipe", __FILE__,
+ __FUNCTION__);
fprintf(pipe, "%s", header);
}
diff --git a/forward.h b/forward.h
index 123d28d2..37121ad4 100644
--- a/forward.h
+++ b/forward.h
@@ -29,6 +29,7 @@
#define FW_SENDMAIL SENDMAIL
-int forward(u64_t msgidnr, struct list *targets, const char *from, const char *header, u64_t headersize);
+int forward(u64_t msgidnr, struct list *targets, const char *from,
+ const char *header, u64_t headersize);
#endif
diff --git a/header.c b/header.c
index b93b1126..b72e2c9f 100644
--- a/header.c
+++ b/header.c
@@ -21,9 +21,9 @@
#include <string.h>
#include <errno.h>
-extern struct list mimelist;
-extern struct list users;
-extern struct list smtpItems;
+extern struct list mimelist;
+extern struct list users;
+extern struct list smtpItems;
#define HEADER_BLOCK_SIZE 1024
@@ -43,120 +43,130 @@ extern struct list smtpItems;
* 1 on success
* 0 on failure
* */
-int read_header(FILE *instream, u64_t *headerrfcsize, u64_t *headersize, char **header)
+int read_header(FILE * instream, u64_t * headerrfcsize, u64_t * headersize,
+ char **header)
{
- char *tmpline;
- char *tmpheader;
- u64_t tmpheadersize=0, tmpheaderrfcsize=0;
- size_t usedmem=0, linemem=0;
- size_t allocated_blocks=1;
- int myeof=0;
-
- memtst((tmpheader = (char *)my_malloc(HEADER_BLOCK_SIZE))==NULL);
- memtst((tmpline = (char *)my_malloc(MAX_LINE_SIZE))==NULL);
-
- /* Resetting */
- memset(tmpline, '\0', MAX_LINE_SIZE);
- memset(tmpheader, '\0', HEADER_BLOCK_SIZE);
-
- /* here we will start a loop to read in the message header */
- /* the header will be everything up until \n\n or an EOF of */
- /* in_stream (instream) */
-
- trace(TRACE_INFO, "read_header(): readheader start\n");
-
- while (!feof(instream) && !myeof)
- {
- /* fgets will read until \n occurs, and \n is *included* in tmpline */
- if (!fgets(tmpline, MAX_LINE_SIZE, instream))
- break;
- linemem = strlen(tmpline);
- tmpheadersize += linemem;
- tmpheaderrfcsize += linemem;
- /* The RFC size assumes all lines end in \r\n,
- * so if we have a newline (\n) but don't have
- * a carriage return (\r), count it in rfcsize. */
- if (linemem > 0 && tmpline[linemem-1] == '\n')
- if (linemem == 1 || (linemem > 1 && tmpline[linemem-2] != '\r'))
- tmpheaderrfcsize++;
-
- if (ferror(instream))
- {
- trace(TRACE_ERROR,"read_header(): error on instream: [%s]", strerror(errno));
- my_free(tmpline);
- /* NOTA BENE: Make sure that the caller knows to free
- * the header block even if there's been an error! */
- return -1;
- }
-
- /* The end of the header could be \n\n, \r\n\r\n,
- * or \r\n.\r\n, in the accidental case that we
- * ate the whole SMTP message, too! */
- if (strcmp(tmpline, ".\r\n") == 0)
- {
- /* This is the end of the message! */
- trace (TRACE_DEBUG,"read_header(): single period found");
- myeof = 1;
- }
- else if (strcmp(tmpline, "\n") == 0 || strcmp(tmpline, "\r\n") == 0)
- {
- /* We've found the end of the header */
- trace (TRACE_DEBUG,"read_header(): single blank line found");
- myeof = 1;
- }
-
- /* Even if we hit the end of the header, don't forget to copy the extra
- * returns. They will always be needed to separate the header from the
- * message during any future retrieval of the fully concatenated message.
- * */
-
- trace (TRACE_DEBUG,"read_header(): copying line into header");
-
- /* If this happends it's a very big header */
- if (usedmem + linemem > (allocated_blocks*HEADER_BLOCK_SIZE))
- {
- /* Update block counter */
- allocated_blocks++;
- trace (TRACE_DEBUG,"read_header(): mem current: [%d] reallocated to [%d]",
- usedmem, allocated_blocks*HEADER_BLOCK_SIZE);
- memtst((tmpheader = (char *)realloc(tmpheader, allocated_blocks*HEADER_BLOCK_SIZE))==NULL);
- }
-
- /* This *should* always happen, but better safe than overflowing! */
- if (usedmem + linemem < (allocated_blocks*HEADER_BLOCK_SIZE))
- {
- /* Copy starting at the current usage offset */
- strncpy( (tmpheader+usedmem), tmpline, linemem);
- usedmem += linemem;
-
- /* Resetting strlen for tmpline */
- tmpline[0] = '\0';
- linemem=0;
- }
- }
-
- trace (TRACE_DEBUG, "read_header(): readheader done");
- trace (TRACE_DEBUG, "read_header(): found header [%s] of len [%d] using mem [%d]",
- tmpheader, strlen(tmpheader), usedmem);
-
- my_free(tmpline);
-
- if (usedmem==0)
- {
- /* FIXME: Why are we hard aborting? That's ridiculous. */
- trace(TRACE_STOP, "read_header(): no valid mail header found\n");
- return 0;
- }
-
- /* Assign to the external variable */
- *header = tmpheader;
- *headersize = tmpheadersize;
- *headerrfcsize = tmpheaderrfcsize;
-
- /* The caller is responsible for freeing header/tmpheader. */
-
- trace (TRACE_INFO, "read_header(): function successfull\n");
- return 1;
+ char *tmpline;
+ char *tmpheader;
+ u64_t tmpheadersize = 0, tmpheaderrfcsize = 0;
+ size_t usedmem = 0, linemem = 0;
+ size_t allocated_blocks = 1;
+ int myeof = 0;
+
+ memtst((tmpheader =
+ (char *) my_malloc(HEADER_BLOCK_SIZE)) == NULL);
+ memtst((tmpline = (char *) my_malloc(MAX_LINE_SIZE)) == NULL);
+
+ /* Resetting */
+ memset(tmpline, '\0', MAX_LINE_SIZE);
+ memset(tmpheader, '\0', HEADER_BLOCK_SIZE);
+
+ /* here we will start a loop to read in the message header */
+ /* the header will be everything up until \n\n or an EOF of */
+ /* in_stream (instream) */
+
+ trace(TRACE_INFO, "read_header(): readheader start\n");
+
+ while (!feof(instream) && !myeof) {
+ /* fgets will read until \n occurs, and \n is *included* in tmpline */
+ if (!fgets(tmpline, MAX_LINE_SIZE, instream))
+ break;
+ linemem = strlen(tmpline);
+ tmpheadersize += linemem;
+ tmpheaderrfcsize += linemem;
+ /* The RFC size assumes all lines end in \r\n,
+ * so if we have a newline (\n) but don't have
+ * a carriage return (\r), count it in rfcsize. */
+ if (linemem > 0 && tmpline[linemem - 1] == '\n')
+ if (linemem == 1
+ || (linemem > 1
+ && tmpline[linemem - 2] != '\r'))
+ tmpheaderrfcsize++;
+
+ if (ferror(instream)) {
+ trace(TRACE_ERROR,
+ "read_header(): error on instream: [%s]",
+ strerror(errno));
+ my_free(tmpline);
+ /* NOTA BENE: Make sure that the caller knows to free
+ * the header block even if there's been an error! */
+ return -1;
+ }
+
+ /* The end of the header could be \n\n, \r\n\r\n,
+ * or \r\n.\r\n, in the accidental case that we
+ * ate the whole SMTP message, too! */
+ if (strcmp(tmpline, ".\r\n") == 0) {
+ /* This is the end of the message! */
+ trace(TRACE_DEBUG,
+ "read_header(): single period found");
+ myeof = 1;
+ } else if (strcmp(tmpline, "\n") == 0
+ || strcmp(tmpline, "\r\n") == 0) {
+ /* We've found the end of the header */
+ trace(TRACE_DEBUG,
+ "read_header(): single blank line found");
+ myeof = 1;
+ }
+
+ /* Even if we hit the end of the header, don't forget to copy the extra
+ * returns. They will always be needed to separate the header from the
+ * message during any future retrieval of the fully concatenated message.
+ * */
+
+ trace(TRACE_DEBUG,
+ "read_header(): copying line into header");
+
+ /* If this happends it's a very big header */
+ if (usedmem + linemem >
+ (allocated_blocks * HEADER_BLOCK_SIZE)) {
+ /* Update block counter */
+ allocated_blocks++;
+ trace(TRACE_DEBUG,
+ "read_header(): mem current: [%d] reallocated to [%d]",
+ usedmem,
+ allocated_blocks * HEADER_BLOCK_SIZE);
+ memtst((tmpheader =
+ (char *) realloc(tmpheader,
+ allocated_blocks *
+ HEADER_BLOCK_SIZE)) ==
+ NULL);
+ }
+
+ /* This *should* always happen, but better safe than overflowing! */
+ if (usedmem + linemem <
+ (allocated_blocks * HEADER_BLOCK_SIZE)) {
+ /* Copy starting at the current usage offset */
+ strncpy((tmpheader + usedmem), tmpline, linemem);
+ usedmem += linemem;
+
+ /* Resetting strlen for tmpline */
+ tmpline[0] = '\0';
+ linemem = 0;
+ }
+ }
+
+ trace(TRACE_DEBUG, "read_header(): readheader done");
+ trace(TRACE_DEBUG,
+ "read_header(): found header [%s] of len [%d] using mem [%d]",
+ tmpheader, strlen(tmpheader), usedmem);
+
+ my_free(tmpline);
+
+ if (usedmem == 0) {
+ /* FIXME: Why are we hard aborting? That's ridiculous. */
+ trace(TRACE_STOP,
+ "read_header(): no valid mail header found\n");
+ return 0;
+ }
+
+ /* Assign to the external variable */
+ *header = tmpheader;
+ *headersize = tmpheadersize;
+ *headerrfcsize = tmpheaderrfcsize;
+
+ /* The caller is responsible for freeing header/tmpheader. */
+
+ trace(TRACE_INFO, "read_header(): function successfull\n");
+ return 1;
}
-
-
diff --git a/header.h b/header.h
index 6c8f78dc..6a0ba251 100644
--- a/header.h
+++ b/header.h
@@ -23,6 +23,7 @@
* - 1 on success
* - 0 on failure
*/
-int read_header(FILE *instream, u64_t *newlines, u64_t *headersize, char **header);
+int read_header(FILE * instream, u64_t * newlines, u64_t * headersize,
+ char **header);
#endif
diff --git a/imap4.c b/imap4.c
index 24819221..238fbdc5 100644
--- a/imap4.c
+++ b/imap4.c
@@ -51,60 +51,64 @@
cache_t cached_msg;
/* consts */
-const char AcceptedChars[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-"!@#$%^&*()-=_+`~[]{}\\|'\" ;:,.<>/? \n\r";
-
-const char AcceptedTagChars[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-"!@#$%^&-=_`~\\|'\" ;:,.<>/? ";
+const char AcceptedChars[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "!@#$%^&*()-=_+`~[]{}\\|'\" ;:,.<>/? \n\r";
+
+const char AcceptedTagChars[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "!@#$%^&-=_`~\\|'\" ;:,.<>/? ";
+
+const char AcceptedMailboxnameChars[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=/ _.&,+";
+
+const char *IMAP_COMMANDS[] = {
+ "", "capability", "noop", "logout",
+ "authenticate", "login",
+ "select", "examine", "create", "delete", "rename", "subscribe",
+ "unsubscribe",
+ "list", "lsub", "status", "append",
+ "check", "close", "expunge", "search", "fetch", "store", "copy",
+ "uid",
+ "getquotaroot", "getquota",
+ "setacl", "deleteacl", "getacl", "listrights", "myrights",
+ "namespace",
+ "***NOMORE***"
+};
-const char AcceptedMailboxnameChars[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=/ _.&,+";
-const char *IMAP_COMMANDS[] =
-{
- "", "capability", "noop", "logout",
- "authenticate", "login",
- "select", "examine", "create", "delete", "rename", "subscribe", "unsubscribe",
- "list", "lsub", "status", "append",
- "check", "close", "expunge", "search", "fetch", "store", "copy", "uid",
- "getquotaroot", "getquota",
- "setacl", "deleteacl", "getacl", "listrights", "myrights",
- "namespace",
- "***NOMORE***"
+enum IMAP_COMMAND_TYPES { IMAP_COMM_NONE,
+ IMAP_COMM_CAPABILITY, IMAP_COMM_NOOP, IMAP_COMM_LOGOUT,
+ IMAP_COMM_AUTH, IMAP_COMM_LOGIN,
+ IMAP_COMM_SELECT, IMAP_COMM_EXAMINE, IMAP_COMM_CREATE,
+ IMAP_COMM_DELETE, IMAP_COMM_RENAME, IMAP_COMM_SUBSCRIBE,
+ IMAP_COMM_UNSUBSCRIBE, IMAP_COMM_LIST, IMAP_COMM_LSUB,
+ IMAP_COMM_STATUS, IMAP_COMM_APPEND,
+ IMAP_COMM_CHECK, IMAP_COMM_CLOSE, IMAP_COMM_EXPUNGE,
+ IMAP_COMM_SEARCH, IMAP_COMM_FETCH, IMAP_COMM_STORE,
+ IMAP_COMM_COPY, IMAP_COMM_UID,
+ IMAP_COMM_GETQUOTAROOT, IMAP_COMM_GETQUOTA,
+ IMAP_COMM_SETACL, IMAP_COMM_DELETEACL, IMAP_COMM_GETACL,
+ IMAP_COMM_LISTRIGHTS, IMAP_COMM_MYRIGHTS,
+ IMAP_COMM_NAMESPACE,
+ IMAP_COMM_LAST
};
-enum IMAP_COMMAND_TYPES { IMAP_COMM_NONE,
- IMAP_COMM_CAPABILITY, IMAP_COMM_NOOP, IMAP_COMM_LOGOUT,
- IMAP_COMM_AUTH, IMAP_COMM_LOGIN,
- IMAP_COMM_SELECT, IMAP_COMM_EXAMINE, IMAP_COMM_CREATE,
- IMAP_COMM_DELETE, IMAP_COMM_RENAME, IMAP_COMM_SUBSCRIBE,
- IMAP_COMM_UNSUBSCRIBE, IMAP_COMM_LIST, IMAP_COMM_LSUB,
- IMAP_COMM_STATUS, IMAP_COMM_APPEND,
- IMAP_COMM_CHECK, IMAP_COMM_CLOSE, IMAP_COMM_EXPUNGE,
- IMAP_COMM_SEARCH, IMAP_COMM_FETCH, IMAP_COMM_STORE,
- IMAP_COMM_COPY, IMAP_COMM_UID,
- IMAP_COMM_GETQUOTAROOT, IMAP_COMM_GETQUOTA,
- IMAP_COMM_SETACL, IMAP_COMM_DELETEACL, IMAP_COMM_GETACL,
- IMAP_COMM_LISTRIGHTS, IMAP_COMM_MYRIGHTS,
- IMAP_COMM_NAMESPACE,
- IMAP_COMM_LAST };
-
-
-const IMAP_COMMAND_HANDLER imap_handler_functions[] =
-{
- NULL,
- _ic_capability, _ic_noop, _ic_logout,
- _ic_authenticate, _ic_login,
- _ic_select, _ic_examine, _ic_create, _ic_delete, _ic_rename,
- _ic_subscribe, _ic_unsubscribe, _ic_list, _ic_lsub, _ic_status, _ic_append,
- _ic_check, _ic_close, _ic_expunge, _ic_search, _ic_fetch, _ic_store, _ic_copy, _ic_uid,
- _ic_getquotaroot, _ic_getquota,
- _ic_setacl, _ic_deleteacl, _ic_getacl, _ic_listrights, _ic_myrights,
- _ic_namespace,
- NULL
+const IMAP_COMMAND_HANDLER imap_handler_functions[] = {
+ NULL,
+ _ic_capability, _ic_noop, _ic_logout,
+ _ic_authenticate, _ic_login,
+ _ic_select, _ic_examine, _ic_create, _ic_delete, _ic_rename,
+ _ic_subscribe, _ic_unsubscribe, _ic_list, _ic_lsub, _ic_status,
+ _ic_append,
+ _ic_check, _ic_close, _ic_expunge, _ic_search, _ic_fetch,
+ _ic_store, _ic_copy, _ic_uid,
+ _ic_getquotaroot, _ic_getquota,
+ _ic_setacl, _ic_deleteacl, _ic_getacl, _ic_listrights,
+ _ic_myrights,
+ _ic_namespace,
+ NULL
};
@@ -115,321 +119,332 @@ const IMAP_COMMAND_HANDLER imap_handler_functions[] =
*
* returns EOF on logout/fatal error or 1 otherwise
*/
-int IMAPClientHandler(ClientInfo *ci)
+int IMAPClientHandler(ClientInfo * ci)
{
- char line[MAX_LINESIZE];
- char *tag = NULL,*cpy,**args,*command;
- int i,done,result;
- int nfaultyresponses;
- imap_userdata_t *ud = NULL;
- mailbox_t newmailbox;
- int this_was_noop = 0;
-
- /* init: add userdata */
- ci->userData = my_malloc(sizeof(imap_userdata_t));
- if (!ci->userData)
- {
- /* out of mem */
- trace(TRACE_ERROR,"IMAPClientHandler(): not enough memory.");
- return -1;
- }
-
- memset(ci->userData, 0, sizeof(imap_userdata_t));
- ((imap_userdata_t*)ci->userData)->state = IMAPCS_NON_AUTHENTICATED;
- ud = ci->userData;
-
- /* greet user */
- fprintf(ci->tx,"* OK dbmail imap (protocol version 4r1) server %s ready to run\r\n",
- IMAP_SERVER_VERSION);
- fflush(ci->tx);
-
- /* init: cache */
- if (init_cache() != 0)
- {
- trace(TRACE_ERROR, "IMAPClientHandler(): cannot open temporary file\n");
- fprintf(ci->tx, "* BYE internal system failure\r\n");
-
- null_free(ci->userData);
- return EOF;
- }
-
- done = 0;
- args = NULL;
- nfaultyresponses = 0;
-
- do
- {
- if (nfaultyresponses >= MAX_FAULTY_RESPONSES)
- {
- /* we have had just about it with this user */
- sleep(2); /* avoid DOS attacks */
- fprintf(ci->tx,"* BYE [TRY RFC]\r\n");
- done = 1;
- break;
+ char line[MAX_LINESIZE];
+ char *tag = NULL, *cpy, **args, *command;
+ int i, done, result;
+ int nfaultyresponses;
+ imap_userdata_t *ud = NULL;
+ mailbox_t newmailbox;
+ int this_was_noop = 0;
+
+ /* init: add userdata */
+ ci->userData = my_malloc(sizeof(imap_userdata_t));
+ if (!ci->userData) {
+ /* out of mem */
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): not enough memory.");
+ return -1;
}
- if (ferror(ci->rx))
- {
- trace(TRACE_ERROR, "IMAPClientHandler(): error [%s] on read-stream\n",strerror(errno));
- if (errno == EPIPE)
- {
- close_cache();
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
- null_free(ci->userData);
-
- return -1; /* broken pipe */
- }
- else
- clearerr(ci->rx);
+ memset(ci->userData, 0, sizeof(imap_userdata_t));
+ ((imap_userdata_t *) ci->userData)->state =
+ IMAPCS_NON_AUTHENTICATED;
+ ud = ci->userData;
+
+ /* greet user */
+ fprintf(ci->tx,
+ "* OK dbmail imap (protocol version 4r1) server %s ready to run\r\n",
+ IMAP_SERVER_VERSION);
+ fflush(ci->tx);
+
+ /* init: cache */
+ if (init_cache() != 0) {
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): cannot open temporary file\n");
+ fprintf(ci->tx, "* BYE internal system failure\r\n");
+
+ null_free(ci->userData);
+ return EOF;
}
- if (ferror(ci->tx))
- {
- trace(TRACE_ERROR, "IMAPClientHandler(): error [%s] on write-stream\n",strerror(errno));
- if (errno == EPIPE)
- {
- close_cache();
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
- null_free(ci->userData);
-
- return -1; /* broken pipe */
- }
- else
- clearerr(ci->tx);
- }
+ done = 0;
+ args = NULL;
+ nfaultyresponses = 0;
+
+ do {
+ if (nfaultyresponses >= MAX_FAULTY_RESPONSES) {
+ /* we have had just about it with this user */
+ sleep(2); /* avoid DOS attacks */
+ fprintf(ci->tx, "* BYE [TRY RFC]\r\n");
+ done = 1;
+ break;
+ }
- alarm(ci->timeout); /* install timeout handler */
- fgets(line, MAX_LINESIZE, ci->rx); /* read command line */
- alarm(0); /* remove timeout handler */
-
- if (!ci->rx || !ci->tx)
- {
- /* if a timeout occured the streams will be closed & set to NULL */
- trace(TRACE_ERROR, "IMAPClientHandler(): timeout occurred.");
- close_cache();
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
- null_free(ci->userData);
-
- return 1;
- }
+ if (ferror(ci->rx)) {
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): error [%s] on read-stream\n",
+ strerror(errno));
+ if (errno == EPIPE) {
+ close_cache();
+ null_free(((imap_userdata_t *) ci->
+ userData)->mailbox.seq_list);
+ null_free(ci->userData);
- trace(TRACE_DEBUG,"IMAPClientHandler(): line read for PID %d\n",getpid());
+ return -1; /* broken pipe */
+ } else
+ clearerr(ci->rx);
+ }
- if (!checkchars(line))
- {
- /* foute tekens ingetikt */
- fprintf(ci->tx, "* BYE Input contains invalid characters\r\n");
- close_cache();
+ if (ferror(ci->tx)) {
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): error [%s] on write-stream\n",
+ strerror(errno));
+ if (errno == EPIPE) {
+ close_cache();
+ null_free(((imap_userdata_t *) ci->
+ userData)->mailbox.seq_list);
+ null_free(ci->userData);
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
- null_free(ci->userData);
+ return -1; /* broken pipe */
+ } else
+ clearerr(ci->tx);
+ }
- return 1;
- }
+ alarm(ci->timeout); /* install timeout handler */
+ fgets(line, MAX_LINESIZE, ci->rx); /* read command line */
+ alarm(0); /* remove timeout handler */
- /* clarify data a little */
- cpy = &line[strlen(line)];
- cpy--;
- while (cpy >= line && (*cpy == '\r' || *cpy == '\n'))
- {
- *cpy = '\0';
- cpy--;
- }
+ if (!ci->rx || !ci->tx) {
+ /* if a timeout occured the streams will be closed & set to NULL */
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): timeout occurred.");
+ close_cache();
+ null_free(((imap_userdata_t *) ci->userData)->
+ mailbox.seq_list);
+ null_free(ci->userData);
-// clarify_data(line);
+ return 1;
+ }
- trace(COMMAND_SHOW_LEVEL,"COMMAND: [%s]\n",line);
-
- if (!(*line))
- {
- fprintf(ci->tx, "* BAD No tag specified\r\n");
- nfaultyresponses++;
- continue;
- }
-
- /* read tag & command */
- cpy = line;
-
- i = stridx(cpy,' '); /* find next space */
- if (i == (int) strlen(cpy))
- {
- if (strcmp(cpy, "yeah!") == 0)
- fprintf(ci->tx,"* YEAH dbmail ROCKS sunnyboy!\r\n");
- else
- {
- if (checktag(cpy))
- fprintf(ci->tx, "%s BAD No command specified\r\n",cpy);
- else
- fprintf(ci->tx, "* BAD Invalid tag specified\r\n");
-
- nfaultyresponses++;
- }
-
- continue;
- }
+ trace(TRACE_DEBUG,
+ "IMAPClientHandler(): line read for PID %d\n",
+ getpid());
+ if (!checkchars(line)) {
+ /* foute tekens ingetikt */
+ fprintf(ci->tx,
+ "* BYE Input contains invalid characters\r\n");
+ close_cache();
- tag = cpy; /* set tag */
- cpy[i] = '\0';
- cpy = cpy+i+1; /* cpy points to command now */
+ null_free(((imap_userdata_t *) ci->userData)->
+ mailbox.seq_list);
+ null_free(ci->userData);
- /* check tag */
- if (!checktag(tag))
- {
- fprintf(ci->tx, "* BAD Invalid tag specified\r\n");
- nfaultyresponses++;
- continue;
- }
+ return 1;
+ }
- command = cpy; /* set command */
- i = stridx(cpy,' '); /* find next space */
- if (i == (int) strlen(cpy))
- {
- /* no arguments present */
- args = build_args_array("");
- }
- else
- {
- cpy[i] = '\0'; /* terminated command */
- cpy = cpy+i+1; /* cpy points to args now */
- args = build_args_array_ext(cpy, ci); /* build argument array */
-
- if (!ci->rx || !ci->tx || ferror(ci->rx) || ferror(ci->tx))
- {
- /* some error occurred during the read of extra command info */
- trace(TRACE_ERROR, "IMAPClientHandler(): error reading extra command info");
- close_cache();
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
- null_free(ci->userData);
-
- return -1;
- }
- }
+ /* clarify data a little */
+ cpy = &line[strlen(line)];
+ cpy--;
+ while (cpy >= line && (*cpy == '\r' || *cpy == '\n')) {
+ *cpy = '\0';
+ cpy--;
+ }
- if (!args)
- {
- fprintf(ci->tx,"%s BAD invalid argument specified\r\n",tag);
- nfaultyresponses++;
- continue;
- }
+// clarify_data(line);
- for (i=IMAP_COMM_NONE; i<IMAP_COMM_LAST && strcasecmp(command, IMAP_COMMANDS[i]); i++);
-
- if (i <= IMAP_COMM_NONE || i >= IMAP_COMM_LAST)
- {
- /* unknown command */
- fprintf(ci->tx,"%s BAD command not recognized\r\n",tag);
- nfaultyresponses++;
-
- /* free used memory */
- for (i=0; args[i]; i++)
- {
- my_free(args[i]);
- args[i] = NULL;
- }
-
- continue;
- }
+ trace(COMMAND_SHOW_LEVEL, "COMMAND: [%s]\n", line);
- trace(TRACE_INFO, "IMAPClientHandler(): Executing command %s...\n",IMAP_COMMANDS[i]);
+ if (!(*line)) {
+ fprintf(ci->tx, "* BAD No tag specified\r\n");
+ nfaultyresponses++;
+ continue;
+ }
-// dirty hack to bypass a NOOP problem:
-// unilateral server responses are not recognised by some clients
-// if they are after the OK response
- this_was_noop = 0;
-
- if (i != IMAP_COMM_NOOP)
- result = (*imap_handler_functions[i])(tag, args, ci);
- else
- {
- this_was_noop = 1;
- result = 0;
- }
-
- //result = (*imap_handler_functions[i])(tag, args, ci);
- if (result == -1)
- done = 1; /* fatal error occurred, kick this user */
-
- if (result == 1)
- nfaultyresponses++; /* server returned BAD or NO response */
-
- if (result == 0 && i == IMAP_COMM_LOGOUT)
- done = 1;
-
-
- fflush(ci->tx); /* write! */
-
- trace(TRACE_INFO, "IMAPClientHandler(): Finished command %s\n",IMAP_COMMANDS[i]);
-
- /* check if mailbox status has changed (notify client) */
- if (ud->state == IMAPCS_SELECTED)
- {
- if (i == IMAP_COMM_NOOP ||
- i == IMAP_COMM_CHECK ||
- i == IMAP_COMM_SELECT ||
- i == IMAP_COMM_EXPUNGE) {
- /* update mailbox info */
- memset(&newmailbox, 0, sizeof(newmailbox));
- newmailbox.uid = ud->mailbox.uid;
-
- result = db_getmailbox(&newmailbox);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- trace(TRACE_ERROR, "IMAPClientHandler(): could not get mailbox info\n");
-
+ /* read tag & command */
+ cpy = line;
+
+ i = stridx(cpy, ' '); /* find next space */
+ if (i == (int) strlen(cpy)) {
+ if (strcmp(cpy, "yeah!") == 0)
+ fprintf(ci->tx,
+ "* YEAH dbmail ROCKS sunnyboy!\r\n");
+ else {
+ if (checktag(cpy))
+ fprintf(ci->tx,
+ "%s BAD No command specified\r\n",
+ cpy);
+ else
+ fprintf(ci->tx,
+ "* BAD Invalid tag specified\r\n");
+
+ nfaultyresponses++;
+ }
+
+ continue;
+ }
+
+
+ tag = cpy; /* set tag */
+ cpy[i] = '\0';
+ cpy = cpy + i + 1; /* cpy points to command now */
+
+ /* check tag */
+ if (!checktag(tag)) {
+ fprintf(ci->tx, "* BAD Invalid tag specified\r\n");
+ nfaultyresponses++;
+ continue;
+ }
+
+ command = cpy; /* set command */
+ i = stridx(cpy, ' '); /* find next space */
+ if (i == (int) strlen(cpy)) {
+ /* no arguments present */
+ args = build_args_array("");
+ } else {
+ cpy[i] = '\0'; /* terminated command */
+ cpy = cpy + i + 1; /* cpy points to args now */
+ args = build_args_array_ext(cpy, ci); /* build argument array */
+
+ if (!ci->rx || !ci->tx || ferror(ci->rx)
+ || ferror(ci->tx)) {
+ /* some error occurred during the read of extra command info */
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): error reading extra command info");
close_cache();
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
+ null_free(((imap_userdata_t *) ci->
+ userData)->mailbox.seq_list);
null_free(ci->userData);
- for (i=0; args[i]; i++)
- {
- my_free(args[i]);
- args[i] = NULL;
- }
-
return -1;
}
+ }
+
+ if (!args) {
+ fprintf(ci->tx,
+ "%s BAD invalid argument specified\r\n",
+ tag);
+ nfaultyresponses++;
+ continue;
+ }
+
+ for (i = IMAP_COMM_NONE;
+ i < IMAP_COMM_LAST
+ && strcasecmp(command, IMAP_COMMANDS[i]); i++);
- if (newmailbox.exists != ud->mailbox.exists)
- {
- fprintf(ci->tx, "* %u EXISTS\r\n", newmailbox.exists);
- trace(TRACE_INFO, "IMAPClientHandler(): ok update sent\r\n");
+ if (i <= IMAP_COMM_NONE || i >= IMAP_COMM_LAST) {
+ /* unknown command */
+ fprintf(ci->tx,
+ "%s BAD command not recognized\r\n", tag);
+ nfaultyresponses++;
+
+ /* free used memory */
+ for (i = 0; args[i]; i++) {
+ my_free(args[i]);
+ args[i] = NULL;
}
- if (newmailbox.recent != ud->mailbox.recent)
- fprintf(ci->tx, "* %u RECENT\r\n", newmailbox.recent);
+ continue;
+ }
+
+ trace(TRACE_INFO,
+ "IMAPClientHandler(): Executing command %s...\n",
+ IMAP_COMMANDS[i]);
- my_free(ud->mailbox.seq_list);
- memcpy(&ud->mailbox, &newmailbox, sizeof(newmailbox));
+// dirty hack to bypass a NOOP problem:
+// unilateral server responses are not recognised by some clients
+// if they are after the OK response
+ this_was_noop = 0;
+
+ if (i != IMAP_COMM_NOOP)
+ result =
+ (*imap_handler_functions[i]) (tag, args, ci);
+ else {
+ this_was_noop = 1;
+ result = 0;
}
- }
- if (this_was_noop)
- fprintf(ci->tx, "%s OK NOOP completed\r\n", tag);
- for (i=0; args[i]; i++)
- {
- my_free(args[i]);
- args[i] = NULL;
- }
+ //result = (*imap_handler_functions[i])(tag, args, ci);
+ if (result == -1)
+ done = 1; /* fatal error occurred, kick this user */
- } while (!done);
+ if (result == 1)
+ nfaultyresponses++; /* server returned BAD or NO response */
- /* cleanup */
- close_cache();
+ if (result == 0 && i == IMAP_COMM_LOGOUT)
+ done = 1;
- null_free(((imap_userdata_t*)ci->userData)->mailbox.seq_list);
- null_free(ci->userData);
- fprintf(ci->tx,"%s OK completed\r\n",tag);
- trace(TRACE_MESSAGE,"IMAPClientHandler(): Closing connection for client from IP [%s]\n",ci->ip);
+ fflush(ci->tx); /* write! */
- __debug_dumpallocs();
+ trace(TRACE_INFO,
+ "IMAPClientHandler(): Finished command %s\n",
+ IMAP_COMMANDS[i]);
- return EOF;
+ /* check if mailbox status has changed (notify client) */
+ if (ud->state == IMAPCS_SELECTED) {
+ if (i == IMAP_COMM_NOOP ||
+ i == IMAP_COMM_CHECK ||
+ i == IMAP_COMM_SELECT ||
+ i == IMAP_COMM_EXPUNGE) {
+ /* update mailbox info */
+ memset(&newmailbox, 0, sizeof(newmailbox));
+ newmailbox.uid = ud->mailbox.uid;
-}
+ result = db_getmailbox(&newmailbox);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "* BYE internal dbase error\r\n");
+ trace(TRACE_ERROR,
+ "IMAPClientHandler(): could not get mailbox info\n");
+
+ close_cache();
+ null_free(((imap_userdata_t *) ci->
+ userData)->mailbox.
+ seq_list);
+ null_free(ci->userData);
+ for (i = 0; args[i]; i++) {
+ my_free(args[i]);
+ args[i] = NULL;
+ }
+ return -1;
+ }
+
+ if (newmailbox.exists !=
+ ud->mailbox.exists) {
+ fprintf(ci->tx, "* %u EXISTS\r\n",
+ newmailbox.exists);
+ trace(TRACE_INFO,
+ "IMAPClientHandler(): ok update sent\r\n");
+ }
+ if (newmailbox.recent !=
+ ud->mailbox.recent)
+ fprintf(ci->tx, "* %u RECENT\r\n",
+ newmailbox.recent);
+ my_free(ud->mailbox.seq_list);
+ memcpy(&ud->mailbox, &newmailbox,
+ sizeof(newmailbox));
+ }
+ }
+ if (this_was_noop)
+ fprintf(ci->tx, "%s OK NOOP completed\r\n", tag);
+
+ for (i = 0; args[i]; i++) {
+ my_free(args[i]);
+ args[i] = NULL;
+ }
+
+ } while (!done);
+
+ /* cleanup */
+ close_cache();
+
+ null_free(((imap_userdata_t *) ci->userData)->mailbox.seq_list);
+ null_free(ci->userData);
+
+ fprintf(ci->tx, "%s OK completed\r\n", tag);
+ trace(TRACE_MESSAGE,
+ "IMAPClientHandler(): Closing connection for client from IP [%s]\n",
+ ci->ip);
+
+ __debug_dumpallocs();
+
+ return EOF;
+
+}
diff --git a/imap4.h b/imap4.h
index c6c64e1e..5483e9bb 100644
--- a/imap4.h
+++ b/imap4.h
@@ -44,51 +44,47 @@
/* max number of retries when synchronizing mailbox with dbase */
#define MAX_RETRIES 20
-int IMAPClientHandler(ClientInfo *ci);
+int IMAPClientHandler(ClientInfo * ci);
-typedef int (*IMAP_COMMAND_HANDLER)(char*, char**, ClientInfo*);
+typedef int (*IMAP_COMMAND_HANDLER) (char *, char **, ClientInfo *);
-typedef struct
-{
- int noseen; /* set the seen flag ? */
- int itemtype; /* the item to be fetched */
- int argstart; /* start index in the arg array */
- int argcnt; /* number of args belonging to this bodyfetch */
- long long octetstart,octetcnt; /* number of octets to be retrieved */
+typedef struct {
+ int noseen; /* set the seen flag ? */
+ int itemtype; /* the item to be fetched */
+ int argstart; /* start index in the arg array */
+ int argcnt; /* number of args belonging to this bodyfetch */
+ long long octetstart, octetcnt; /* number of octets to be retrieved */
- char partspec[IMAP_MAX_PARTSPEC_LEN]; /* part specifier (i.e. '2.1.3' */
+ char partspec[IMAP_MAX_PARTSPEC_LEN]; /* part specifier (i.e. '2.1.3' */
} body_fetch_t;
-typedef struct
-{
+typedef struct {
/* int nbodyfetches;
body_fetch_t *bodyfetches;
*/
- body_fetch_t bodyfetch;
+ body_fetch_t bodyfetch;
- int msgparse_needed;
+ int msgparse_needed;
- int getBodyTotal,getBodyTotalPeek;
- int getInternalDate,getFlags,getUID;
- int getMIME_IMB,getEnvelope,getSize;
- int getMIME_IMB_noextension;
- int getRFC822Header,getRFC822Text;
- int getRFC822,getRFC822Peek;
+ int getBodyTotal, getBodyTotalPeek;
+ int getInternalDate, getFlags, getUID;
+ int getMIME_IMB, getEnvelope, getSize;
+ int getMIME_IMB_noextension;
+ int getRFC822Header, getRFC822Text;
+ int getRFC822, getRFC822Peek;
} fetch_items_t;
-typedef struct
-{
- int state; /* IMAP state of client */
- u64_t userid; /* userID of client in dbase */
- mailbox_t mailbox; /* currently selected mailbox */
+typedef struct {
+ int state; /* IMAP state of client */
+ u64_t userid; /* userID of client in dbase */
+ mailbox_t mailbox; /* currently selected mailbox */
} imap_userdata_t;
-typedef enum
-{
+typedef enum {
IMAP_STORE_FLAG_SEEN,
IMAP_STORE_FLAG_ANSWERED,
IMAP_STORE_FLAG_DELETED,
@@ -98,6 +94,3 @@ typedef enum
} imap_store_flag_t;
#endif
-
-
-
diff --git a/imapcommands.c b/imapcommands.c
index af518470..730c7003 100644
--- a/imapcommands.c
+++ b/imapcommands.c
@@ -68,14 +68,13 @@
#define MAX_RETRIES 12
#endif
-const char *imap_flag_desc[IMAP_NFLAGS] =
-{
- "Seen", "Answered", "Deleted", "Flagged", "Draft", "Recent"
+const char *imap_flag_desc[IMAP_NFLAGS] = {
+ "Seen", "Answered", "Deleted", "Flagged", "Draft", "Recent"
};
-const char *imap_flag_desc_escaped[IMAP_NFLAGS] =
-{
- "\\Seen", "\\Answered", "\\Deleted", "\\Flagged", "\\Draft", "\\Recent"
+const char *imap_flag_desc_escaped[IMAP_NFLAGS] = {
+ "\\Seen", "\\Answered", "\\Deleted", "\\Flagged", "\\Draft",
+ "\\Recent"
};
int imapcommands_use_uid = 0;
@@ -105,15 +104,15 @@ extern int imap_before_smtp;
*
* returns a string to the client containing the server capabilities
*/
-int _ic_capability(char *tag, char **args, ClientInfo *ci)
+int _ic_capability(char *tag, char **args, ClientInfo * ci)
{
- if (!check_state_and_args("CAPABILITY", tag, args, 0, -1, ci))
- return 1; /* error, return */
-
- fprintf(ci->tx,"* CAPABILITY %s\r\n",IMAP_CAPABILITY_STRING);
- fprintf(ci->tx,"%s OK CAPABILITY completed\r\n",tag);
+ if (!check_state_and_args("CAPABILITY", tag, args, 0, -1, ci))
+ return 1; /* error, return */
- return 0;
+ fprintf(ci->tx, "* CAPABILITY %s\r\n", IMAP_CAPABILITY_STRING);
+ fprintf(ci->tx, "%s OK CAPABILITY completed\r\n", tag);
+
+ return 0;
}
@@ -122,13 +121,13 @@ int _ic_capability(char *tag, char **args, ClientInfo *ci)
*
* performs No operation
*/
-int _ic_noop(char *tag, char **args, ClientInfo *ci)
+int _ic_noop(char *tag, char **args, ClientInfo * ci)
{
- if (!check_state_and_args("NOOP", tag, args, 0, -1, ci))
- return 1; /* error, return */
-
- fprintf(ci->tx,"%s OK NOOP completed\r\n",tag);
- return 0;
+ if (!check_state_and_args("NOOP", tag, args, 0, -1, ci))
+ return 1; /* error, return */
+
+ fprintf(ci->tx, "%s OK NOOP completed\r\n", tag);
+ return 0;
}
@@ -137,24 +136,25 @@ int _ic_noop(char *tag, char **args, ClientInfo *ci)
*
* prepares logout from IMAP-server
*/
-int _ic_logout(char *tag, char **args, ClientInfo *ci)
+int _ic_logout(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- timestring_t timestring;
-
- create_current_timestring(&timestring);
- if (!check_state_and_args("LOGOUT", tag, args, 0, -1, ci))
- return 1; /* error, return */
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ timestring_t timestring;
- /* change status */
- ud->state = IMAPCS_LOGOUT;
+ create_current_timestring(&timestring);
+ if (!check_state_and_args("LOGOUT", tag, args, 0, -1, ci))
+ return 1; /* error, return */
- trace(TRACE_MESSAGE, "_ic_logout(): user (id:%llu) logging out @ [%s]\r\n",
- ud->userid, timestring);
+ /* change status */
+ ud->state = IMAPCS_LOGOUT;
- fprintf(ci->tx,"* BYE dbmail imap server kisses you goodbye\r\n");
+ trace(TRACE_MESSAGE,
+ "_ic_logout(): user (id:%llu) logging out @ [%s]\r\n",
+ ud->userid, timestring);
- return 0;
+ fprintf(ci->tx, "* BYE dbmail imap server kisses you goodbye\r\n");
+
+ return 0;
}
/*
@@ -166,60 +166,64 @@ int _ic_logout(char *tag, char **args, ClientInfo *ci)
*
* Performs login-request handling.
*/
-int _ic_login(char *tag, char **args, ClientInfo *ci)
+int _ic_login(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t userid;
- timestring_t timestring;
- int validate_result;
-
- create_current_timestring(&timestring);
-
- if (!check_state_and_args("LOGIN", tag, args, 2, IMAPCS_NON_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- trace(TRACE_DEBUG, "_ic_login(): trying to validate user");
- validate_result = auth_validate(args[0], args[1], &userid);
- trace(TRACE_MESSAGE, "_ic_login(): user (id:%llu, name %s) tries login\r\n",
- userid,args[0]);
-
- if (validate_result == -1)
- {
- /* a db-error occurred */
- fprintf(ci->tx,"* BYE internal db error validating user\r\n");
- trace(TRACE_ERROR,"_ic_login(): db-validate error while validating user %s (pass %s).",
- args[0],args[1]);
- return -1;
- }
-
- if (validate_result == 0)
- {
- sleep(2); /* security */
-
- /* validation failed: invalid user/pass combination */
- trace(TRACE_MESSAGE, "IMAPD [PID %d]: user (name %s) login rejected @ %s\r\n",
- (int)getpid(),args[0],timestring);
- fprintf(ci->tx, "%s NO login rejected\r\n",tag);
-
- return 1;
- }
-
- /* login ok */
- trace(TRACE_MESSAGE, "_ic_login(): user (id %llu, name %s) login accepted @ %s\r\n",
- userid,args[0],timestring);
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t userid;
+ timestring_t timestring;
+ int validate_result;
+
+ create_current_timestring(&timestring);
+
+ if (!check_state_and_args
+ ("LOGIN", tag, args, 2, IMAPCS_NON_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ trace(TRACE_DEBUG, "_ic_login(): trying to validate user");
+ validate_result = auth_validate(args[0], args[1], &userid);
+ trace(TRACE_MESSAGE,
+ "_ic_login(): user (id:%llu, name %s) tries login\r\n",
+ userid, args[0]);
+
+ if (validate_result == -1) {
+ /* a db-error occurred */
+ fprintf(ci->tx,
+ "* BYE internal db error validating user\r\n");
+ trace(TRACE_ERROR,
+ "_ic_login(): db-validate error while validating user %s (pass %s).",
+ args[0], args[1]);
+ return -1;
+ }
+
+ if (validate_result == 0) {
+ sleep(2); /* security */
+
+ /* validation failed: invalid user/pass combination */
+ trace(TRACE_MESSAGE,
+ "IMAPD [PID %d]: user (name %s) login rejected @ %s\r\n",
+ (int) getpid(), args[0], timestring);
+ fprintf(ci->tx, "%s NO login rejected\r\n", tag);
+
+ return 1;
+ }
+
+ /* login ok */
+ trace(TRACE_MESSAGE,
+ "_ic_login(): user (id %llu, name %s) login accepted @ %s\r\n",
+ userid, args[0], timestring);
#ifdef PROC_TITLES
- set_proc_title("USER %s [%s]", args[0], ci->ip);
+ set_proc_title("USER %s [%s]", args[0], ci->ip);
#endif
- /* update client info */
- ud->userid = userid;
- ud->state = IMAPCS_AUTHENTICATED;
+ /* update client info */
+ ud->userid = userid;
+ ud->state = IMAPCS_AUTHENTICATED;
- if (imap_before_smtp)
- db_log_ip(ci->ip);
+ if (imap_before_smtp)
+ db_log_ip(ci->ip);
- fprintf(ci->tx,"%s OK LOGIN completed\r\n",tag);
- return 0;
+ fprintf(ci->tx, "%s OK LOGIN completed\r\n", tag);
+ return 0;
}
@@ -230,93 +234,96 @@ int _ic_login(char *tag, char **args, ClientInfo *ci)
*
*
*/
-int _ic_authenticate(char *tag, char **args, ClientInfo *ci)
+int _ic_authenticate(char *tag, char **args, ClientInfo * ci)
{
- u64_t userid;
- char username[MAX_LINESIZE],buf[MAX_LINESIZE],pass[MAX_LINESIZE];
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- int validate_result;
- timestring_t timestring;
-
- create_current_timestring(&timestring);
- if (!check_state_and_args("AUTHENTICATE", tag, args, 1, IMAPCS_NON_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- /* check authentication method */
- if (strcasecmp(args[0], "login") != 0)
- {
- fprintf(ci->tx,"%s NO Invalid authentication mechanism specified\r\n",tag);
- return 1;
- }
-
- /* ask for username (base64 encoded) */
- memset(buf,0,MAX_LINESIZE);
- base64encode("username\r\n",buf);
- fprintf(ci->tx,"+ %s\r\n",buf);
- fflush(ci->tx);
-
- alarm(ci->timeout);
- fgets(buf, MAX_LINESIZE, ci->rx);
- alarm(0);
-
- base64decode(buf, username);
-
- /* ask for password */
- memset(buf,0,MAX_LINESIZE);
- base64encode("password\r\n",buf);
- fprintf(ci->tx,"+ %s\r\n",buf);
- fflush(ci->tx);
-
- alarm(ci->timeout);
- fgets(buf, MAX_LINESIZE, ci->rx);
- alarm(0);
-
- base64decode(buf,pass);
-
-
- /* try to validate user */
- validate_result = auth_validate(username, pass, &userid);
-
- if (validate_result == -1)
- {
- /* a db-error occurred */
- fprintf(ci->tx,"* BYE internal db error validating user\r\n");
- trace(TRACE_ERROR,"IMAPD: authenticate(): db-validate error while validating user %s "
- "(pass %s).",
- username,pass);
- return -1;
- }
-
- if (validate_result == 0)
- {
- sleep(2); /* security */
-
- /* validation failed: invalid user/pass combination */
- fprintf(ci->tx, "%s NO login rejected\r\n",tag);
-
- /* validation failed: invalid user/pass combination */
- trace(TRACE_MESSAGE, "IMAPD [PID %d]: user (name %s) login rejected @ %s\r\n",
- (int)getpid(),username,timestring);
-
- return 1;
- }
-
- /* login ok */
- /* update client info */
- ud->userid = userid;
- ud->state = IMAPCS_AUTHENTICATED;
-
- if (imap_before_smtp)
- db_log_ip(ci->ip);
-
- trace(TRACE_MESSAGE, "IMAPD [PID %d]: user (id %llu, name %s) login accepted @ %s\r\n",(int)getpid(),
- userid,username,timestring);
+ u64_t userid;
+ char username[MAX_LINESIZE], buf[MAX_LINESIZE], pass[MAX_LINESIZE];
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ int validate_result;
+ timestring_t timestring;
+
+ create_current_timestring(&timestring);
+ if (!check_state_and_args
+ ("AUTHENTICATE", tag, args, 1, IMAPCS_NON_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ /* check authentication method */
+ if (strcasecmp(args[0], "login") != 0) {
+ fprintf(ci->tx,
+ "%s NO Invalid authentication mechanism specified\r\n",
+ tag);
+ return 1;
+ }
+
+ /* ask for username (base64 encoded) */
+ memset(buf, 0, MAX_LINESIZE);
+ base64encode("username\r\n", buf);
+ fprintf(ci->tx, "+ %s\r\n", buf);
+ fflush(ci->tx);
+
+ alarm(ci->timeout);
+ fgets(buf, MAX_LINESIZE, ci->rx);
+ alarm(0);
+
+ base64decode(buf, username);
+
+ /* ask for password */
+ memset(buf, 0, MAX_LINESIZE);
+ base64encode("password\r\n", buf);
+ fprintf(ci->tx, "+ %s\r\n", buf);
+ fflush(ci->tx);
+
+ alarm(ci->timeout);
+ fgets(buf, MAX_LINESIZE, ci->rx);
+ alarm(0);
+
+ base64decode(buf, pass);
+
+
+ /* try to validate user */
+ validate_result = auth_validate(username, pass, &userid);
+
+ if (validate_result == -1) {
+ /* a db-error occurred */
+ fprintf(ci->tx,
+ "* BYE internal db error validating user\r\n");
+ trace(TRACE_ERROR,
+ "IMAPD: authenticate(): db-validate error while validating user %s "
+ "(pass %s).", username, pass);
+ return -1;
+ }
+
+ if (validate_result == 0) {
+ sleep(2); /* security */
+
+ /* validation failed: invalid user/pass combination */
+ fprintf(ci->tx, "%s NO login rejected\r\n", tag);
+
+ /* validation failed: invalid user/pass combination */
+ trace(TRACE_MESSAGE,
+ "IMAPD [PID %d]: user (name %s) login rejected @ %s\r\n",
+ (int) getpid(), username, timestring);
+
+ return 1;
+ }
+
+ /* login ok */
+ /* update client info */
+ ud->userid = userid;
+ ud->state = IMAPCS_AUTHENTICATED;
+
+ if (imap_before_smtp)
+ db_log_ip(ci->ip);
+
+ trace(TRACE_MESSAGE,
+ "IMAPD [PID %d]: user (id %llu, name %s) login accepted @ %s\r\n",
+ (int) getpid(), userid, username, timestring);
#ifdef PROC_TITLES
- set_proc_title("USER %s [%s]", args[0], ci->ip);
+ set_proc_title("USER %s [%s]", args[0], ci->ip);
#endif
-
- fprintf(ci->tx,"%s OK AUTHENTICATE completed\r\n",tag);
- return 0;
+
+ fprintf(ci->tx, "%s OK AUTHENTICATE completed\r\n", tag);
+ return 0;
}
@@ -331,134 +338,156 @@ int _ic_authenticate(char *tag, char **args, ClientInfo *ci)
*
* select a specified mailbox
*/
-int _ic_select(char *tag, char **args, ClientInfo *ci)
+int _ic_select(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t mboxid,key;
- int result;
- unsigned idx;
- char permstring[80];
-
- if (!check_state_and_args("SELECT", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- fprintf(ci->tx, "* BYE internal dbase error\r\n");
- return -1;
- }
- if (mboxid == 0) {
- fprintf(ci->tx, "%s NO Could not find specified mailbox\r\n", tag);
-
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
-
- return 1;
- }
-
- /* check if user has right to select mailbox */
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_READ);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to select mailbox\r\n", tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
- /* check if mailbox is selectable */
- result = db_isselectable(mboxid);
- if (result == 0)
- {
- /* error: cannot select mailbox */
- fprintf(ci->tx, "%s NO specified mailbox is not selectable\r\n",tag);
-
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
-
- return 1;
- }
- if (result == -1)
- {
- fprintf(ci->tx, "* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
-
- ud->mailbox.uid = mboxid;
-
- /* read info from mailbox */ result = db_getmailbox(&ud->mailbox);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
-
- /* show mailbox info */
- /* msg counts */
- fprintf(ci->tx, "* %u EXISTS\r\n",ud->mailbox.exists);
- fprintf(ci->tx, "* %u RECENT\r\n",ud->mailbox.recent);
-
- /* flags */
- fprintf(ci->tx, "* FLAGS (");
-
- if (ud->mailbox.flags & IMAPFLAG_SEEN) fprintf(ci->tx, "\\Seen ");
- if (ud->mailbox.flags & IMAPFLAG_ANSWERED) fprintf(ci->tx, "\\Answered ");
- if (ud->mailbox.flags & IMAPFLAG_DELETED) fprintf(ci->tx, "\\Deleted ");
- if (ud->mailbox.flags & IMAPFLAG_FLAGGED) fprintf(ci->tx, "\\Flagged ");
- if (ud->mailbox.flags & IMAPFLAG_DRAFT) fprintf(ci->tx, "\\Draft ");
- if (ud->mailbox.flags & IMAPFLAG_RECENT) fprintf(ci->tx, "\\Recent ");
-
- fprintf(ci->tx,")\r\n");
-
- /* permanent flags */
- fprintf(ci->tx, "* OK [PERMANENTFLAGS (");
- if (ud->mailbox.flags & IMAPFLAG_SEEN) fprintf(ci->tx, "\\Seen ");
- if (ud->mailbox.flags & IMAPFLAG_ANSWERED) fprintf(ci->tx, "\\Answered ");
- if (ud->mailbox.flags & IMAPFLAG_DELETED) fprintf(ci->tx, "\\Deleted ");
- if (ud->mailbox.flags & IMAPFLAG_FLAGGED) fprintf(ci->tx, "\\Flagged ");
- if (ud->mailbox.flags & IMAPFLAG_DRAFT) fprintf(ci->tx, "\\Draft ");
- if (ud->mailbox.flags & IMAPFLAG_RECENT) fprintf(ci->tx, "\\Recent ");
-
- fprintf(ci->tx,")]\r\n");
-
- /* UID */
- fprintf(ci->tx,"* OK [UIDVALIDITY %llu] UID value\r\n",ud->mailbox.uid);
-
- /* show idx of first unseen msg (if present) */
- key = db_first_unseen(ud->mailbox.uid);
- if (key == (u64_t)(-1))
- {
- fprintf(ci->tx, "* BYE internal dbase error\r\n");
- return -1;
- }
- if (binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
- key, &idx) != -1)
- fprintf(ci->tx,"* OK [UNSEEN %u] first unseen message\r\n",idx+1);
-
- /* permission */
- switch (ud->mailbox.permission)
- {
- case IMAPPERM_READ: sprintf(permstring, "READ-ONLY"); break;
- case IMAPPERM_READWRITE: sprintf(permstring, "READ-WRITE"); break;
- default:
- /* invalid permission --> fatal */
- trace(TRACE_ERROR,"IMAPD: select(): detected invalid permission mode for mailbox %llu ('%s')",
- ud->mailbox.uid, args[0]);
-
- fprintf(ci->tx, "* BYE fatal: detected invalid mailbox settings\r\n");
- return -1;
- }
-
- /* ok, update state */
- ud->state = IMAPCS_SELECTED;
-
- fprintf(ci->tx,"%s OK [%s] SELECT completed\r\n",tag,permstring);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t mboxid, key;
+ int result;
+ unsigned idx;
+ char permstring[80];
+
+ if (!check_state_and_args
+ ("SELECT", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+ if (mboxid == 0) {
+ fprintf(ci->tx,
+ "%s NO Could not find specified mailbox\r\n", tag);
+
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+
+ return 1;
+ }
+
+ /* check if user has right to select mailbox */
+ result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_READ);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to select mailbox\r\n", tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+ /* check if mailbox is selectable */
+ result = db_isselectable(mboxid);
+ if (result == 0) {
+ /* error: cannot select mailbox */
+ fprintf(ci->tx,
+ "%s NO specified mailbox is not selectable\r\n",
+ tag);
+
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+
+ return 1;
+ }
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+
+ ud->mailbox.uid = mboxid;
+
+ /* read info from mailbox */ result = db_getmailbox(&ud->mailbox);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+
+ /* show mailbox info */
+ /* msg counts */
+ fprintf(ci->tx, "* %u EXISTS\r\n", ud->mailbox.exists);
+ fprintf(ci->tx, "* %u RECENT\r\n", ud->mailbox.recent);
+
+ /* flags */
+ fprintf(ci->tx, "* FLAGS (");
+
+ if (ud->mailbox.flags & IMAPFLAG_SEEN)
+ fprintf(ci->tx, "\\Seen ");
+ if (ud->mailbox.flags & IMAPFLAG_ANSWERED)
+ fprintf(ci->tx, "\\Answered ");
+ if (ud->mailbox.flags & IMAPFLAG_DELETED)
+ fprintf(ci->tx, "\\Deleted ");
+ if (ud->mailbox.flags & IMAPFLAG_FLAGGED)
+ fprintf(ci->tx, "\\Flagged ");
+ if (ud->mailbox.flags & IMAPFLAG_DRAFT)
+ fprintf(ci->tx, "\\Draft ");
+ if (ud->mailbox.flags & IMAPFLAG_RECENT)
+ fprintf(ci->tx, "\\Recent ");
+
+ fprintf(ci->tx, ")\r\n");
+
+ /* permanent flags */
+ fprintf(ci->tx, "* OK [PERMANENTFLAGS (");
+ if (ud->mailbox.flags & IMAPFLAG_SEEN)
+ fprintf(ci->tx, "\\Seen ");
+ if (ud->mailbox.flags & IMAPFLAG_ANSWERED)
+ fprintf(ci->tx, "\\Answered ");
+ if (ud->mailbox.flags & IMAPFLAG_DELETED)
+ fprintf(ci->tx, "\\Deleted ");
+ if (ud->mailbox.flags & IMAPFLAG_FLAGGED)
+ fprintf(ci->tx, "\\Flagged ");
+ if (ud->mailbox.flags & IMAPFLAG_DRAFT)
+ fprintf(ci->tx, "\\Draft ");
+ if (ud->mailbox.flags & IMAPFLAG_RECENT)
+ fprintf(ci->tx, "\\Recent ");
+
+ fprintf(ci->tx, ")]\r\n");
+
+ /* UID */
+ fprintf(ci->tx, "* OK [UIDVALIDITY %llu] UID value\r\n",
+ ud->mailbox.uid);
+
+ /* show idx of first unseen msg (if present) */
+ key = db_first_unseen(ud->mailbox.uid);
+ if (key == (u64_t) (-1)) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+ if (binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
+ key, &idx) != -1)
+ fprintf(ci->tx,
+ "* OK [UNSEEN %u] first unseen message\r\n",
+ idx + 1);
+
+ /* permission */
+ switch (ud->mailbox.permission) {
+ case IMAPPERM_READ:
+ sprintf(permstring, "READ-ONLY");
+ break;
+ case IMAPPERM_READWRITE:
+ sprintf(permstring, "READ-WRITE");
+ break;
+ default:
+ /* invalid permission --> fatal */
+ trace(TRACE_ERROR,
+ "IMAPD: select(): detected invalid permission mode for mailbox %llu ('%s')",
+ ud->mailbox.uid, args[0]);
+
+ fprintf(ci->tx,
+ "* BYE fatal: detected invalid mailbox settings\r\n");
+ return -1;
+ }
+
+ /* ok, update state */
+ ud->state = IMAPCS_SELECTED;
+
+ fprintf(ci->tx, "%s OK [%s] SELECT completed\r\n", tag,
+ permstring);
+ return 0;
}
@@ -467,102 +496,117 @@ int _ic_select(char *tag, char **args, ClientInfo *ci)
*
* examines a specified mailbox
*/
-int _ic_examine(char *tag, char **args, ClientInfo *ci)
+int _ic_examine(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t mboxid;
- int result;
-
- if (!check_state_and_args("EXAMINE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- fprintf(ci->tx, "* BYE internal dbase error\r\n");
- return -1;
- }
- if (mboxid == 0) {
- fprintf(ci->tx, "%s NO Could not find specified mailbox\r\n", tag);
- return 1;
- }
-
- /* check if user has right to examine mailbox */
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_READ);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to examine mailbox\r\n", tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
- /* check if mailbox is selectable */
- result = db_isselectable(mboxid);
- if (result == 0)
- {
- /* error: cannot select mailbox */
- fprintf(ci->tx, "%s NO specified mailbox is not selectable\r\n",tag);
- return 1; /* fatal */
- }
- if (result == -1)
- {
- fprintf(ci->tx, "* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
-
- ud->mailbox.uid = mboxid;
-
- /* read info from mailbox */
- result = db_getmailbox(&ud->mailbox);
-
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
-
- /* show mailbox info */
- /* msg counts */
- fprintf(ci->tx, "* %u EXISTS\r\n",ud->mailbox.exists);
- fprintf(ci->tx, "* %u RECENT\r\n",ud->mailbox.recent);
-
- /* flags */
- fprintf(ci->tx, "* FLAGS (");
-
- if (ud->mailbox.flags & IMAPFLAG_SEEN) fprintf(ci->tx, "\\Seen ");
- if (ud->mailbox.flags & IMAPFLAG_ANSWERED) fprintf(ci->tx, "\\Answered ");
- if (ud->mailbox.flags & IMAPFLAG_DELETED) fprintf(ci->tx, "\\Deleted ");
- if (ud->mailbox.flags & IMAPFLAG_FLAGGED) fprintf(ci->tx, "\\Flagged ");
- if (ud->mailbox.flags & IMAPFLAG_DRAFT) fprintf(ci->tx, "\\Draft ");
- if (ud->mailbox.flags & IMAPFLAG_RECENT) fprintf(ci->tx, "\\Recent ");
-
- fprintf(ci->tx,")\r\n");
-
- /* permanent flags */
- fprintf(ci->tx, "* OK [PERMANENTFLAGS (");
- if (ud->mailbox.flags & IMAPFLAG_SEEN) fprintf(ci->tx, "\\Seen ");
- if (ud->mailbox.flags & IMAPFLAG_ANSWERED) fprintf(ci->tx, "\\Answered ");
- if (ud->mailbox.flags & IMAPFLAG_DELETED) fprintf(ci->tx, "\\Deleted ");
- if (ud->mailbox.flags & IMAPFLAG_FLAGGED) fprintf(ci->tx, "\\Flagged ");
- if (ud->mailbox.flags & IMAPFLAG_DRAFT) fprintf(ci->tx, "\\Draft ");
- if (ud->mailbox.flags & IMAPFLAG_RECENT) fprintf(ci->tx, "\\Recent ");
-
- fprintf(ci->tx,")]\r\n");
-
- /* UID */
- fprintf(ci->tx,"* OK [UIDVALIDITY %llu] UID value\r\n",ud->mailbox.uid);
-
- /* update permission: examine forces read-only */
- ud->mailbox.permission = IMAPPERM_READ;
-
- /* ok, update state */
- ud->state = IMAPCS_SELECTED;
-
- fprintf(ci->tx,"%s OK [READ-ONLY] EXAMINE completed\r\n",tag);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t mboxid;
+ int result;
+
+ if (!check_state_and_args
+ ("EXAMINE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+ if (mboxid == 0) {
+ fprintf(ci->tx,
+ "%s NO Could not find specified mailbox\r\n", tag);
+ return 1;
+ }
+
+ /* check if user has right to examine mailbox */
+ result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_READ);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to examine mailbox\r\n", tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+ /* check if mailbox is selectable */
+ result = db_isselectable(mboxid);
+ if (result == 0) {
+ /* error: cannot select mailbox */
+ fprintf(ci->tx,
+ "%s NO specified mailbox is not selectable\r\n",
+ tag);
+ return 1; /* fatal */
+ }
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+
+ ud->mailbox.uid = mboxid;
+
+ /* read info from mailbox */
+ result = db_getmailbox(&ud->mailbox);
+
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+
+ /* show mailbox info */
+ /* msg counts */
+ fprintf(ci->tx, "* %u EXISTS\r\n", ud->mailbox.exists);
+ fprintf(ci->tx, "* %u RECENT\r\n", ud->mailbox.recent);
+
+ /* flags */
+ fprintf(ci->tx, "* FLAGS (");
+
+ if (ud->mailbox.flags & IMAPFLAG_SEEN)
+ fprintf(ci->tx, "\\Seen ");
+ if (ud->mailbox.flags & IMAPFLAG_ANSWERED)
+ fprintf(ci->tx, "\\Answered ");
+ if (ud->mailbox.flags & IMAPFLAG_DELETED)
+ fprintf(ci->tx, "\\Deleted ");
+ if (ud->mailbox.flags & IMAPFLAG_FLAGGED)
+ fprintf(ci->tx, "\\Flagged ");
+ if (ud->mailbox.flags & IMAPFLAG_DRAFT)
+ fprintf(ci->tx, "\\Draft ");
+ if (ud->mailbox.flags & IMAPFLAG_RECENT)
+ fprintf(ci->tx, "\\Recent ");
+
+ fprintf(ci->tx, ")\r\n");
+
+ /* permanent flags */
+ fprintf(ci->tx, "* OK [PERMANENTFLAGS (");
+ if (ud->mailbox.flags & IMAPFLAG_SEEN)
+ fprintf(ci->tx, "\\Seen ");
+ if (ud->mailbox.flags & IMAPFLAG_ANSWERED)
+ fprintf(ci->tx, "\\Answered ");
+ if (ud->mailbox.flags & IMAPFLAG_DELETED)
+ fprintf(ci->tx, "\\Deleted ");
+ if (ud->mailbox.flags & IMAPFLAG_FLAGGED)
+ fprintf(ci->tx, "\\Flagged ");
+ if (ud->mailbox.flags & IMAPFLAG_DRAFT)
+ fprintf(ci->tx, "\\Draft ");
+ if (ud->mailbox.flags & IMAPFLAG_RECENT)
+ fprintf(ci->tx, "\\Recent ");
+
+ fprintf(ci->tx, ")]\r\n");
+
+ /* UID */
+ fprintf(ci->tx, "* OK [UIDVALIDITY %llu] UID value\r\n",
+ ud->mailbox.uid);
+
+ /* update permission: examine forces read-only */
+ ud->mailbox.permission = IMAPPERM_READ;
+
+ /* ok, update state */
+ ud->state = IMAPCS_SELECTED;
+
+ fprintf(ci->tx, "%s OK [READ-ONLY] EXAMINE completed\r\n", tag);
+ return 0;
}
@@ -571,206 +615,211 @@ int _ic_examine(char *tag, char **args, ClientInfo *ci)
*
* create a mailbox
*/
-int _ic_create(char *tag, char **args, ClientInfo *ci)
+int _ic_create(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- int result,i;
- u64_t mboxid, tmp_mboxid;
- u64_t parent_mboxid = 0; /* id of parent mailbox (if applicable) */
- char **chunks,*cpy;
- int other_namespace = 0;
-
- if (!check_state_and_args("CREATE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- /* remove trailing '/' if present */
- while (strlen(args[0]) > 0 && args[0][strlen(args[0]) - 1] == '/')
- args[0][strlen(args[0]) - 1] = '\0';
-
- /* remove leading '/' if present */
- for (i=0; args[0][i] && args[0][i] == '/'; i++) ;
- memmove(&args[0][0],&args[0][i], (strlen(args[0]) - i) * sizeof(char));
-
- /* check if this mailbox already exists */
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
-
- if (mboxid != 0)
- {
- /* mailbox already exists */
- fprintf(ci->tx,"%s NO mailbox already exists\r\n",tag);
- return 1;
- }
-
- /* check if new name is valid */
- if (!checkmailboxname(args[0]))
- {
- fprintf(ci->tx,"%s BAD new mailbox name contains invalid characters\r\n",tag);
- return 1;
- }
-
- /* alloc a ptr which can contain up to the full name */
- cpy = (char*)my_malloc(sizeof(char) * (strlen(args[0]) + 1));
- if (!cpy)
- {
- /* out of mem */
- trace(TRACE_ERROR, "IMAPD: create(): not enough memory");
- fprintf(ci->tx, "* BYE server ran out of memory\r\n");
- return -1;
- }
-
- /* split up the name & create parent folders as necessary */
- chunks = give_chunks(args[0], '/');
-
- if (chunks == NULL)
- {
- /* serious error while making chunks */
- trace(TRACE_ERROR, "IMAPD: create(): could not create chunks");
- fprintf(ci->tx, "* BYE server ran out of memory\r\n");
- my_free(cpy);
- return -1;
- }
-
- if (chunks[0] == NULL)
- {
- /* wrong argument */
- fprintf(ci->tx,"%s NO invalid mailbox name specified\r\n",tag);
- free_chunks(chunks);
- my_free(cpy);
- return 1;
- }
-
- /* now go create */
- strcpy(cpy,"");
-
- for (i=0; chunks[i]; i++)
- {
- if (strlen(chunks[i]) == 0)
- {
- /* no can do */
- fprintf(ci->tx, "%s NO invalid mailbox name specified\r\n",tag);
- free_chunks(chunks);
- my_free(cpy);
- return 1;
- }
-
- if (i == 0)
- {
- if (strcasecmp(chunks[0], "inbox") == 0)
- strcpy(chunks[0], "INBOX"); /* make inbox uppercase */
-
- strcat(cpy, chunks[i]);
- /* check to see if this is a folder in Other Users/ or Public
- namespace */
- if (strcmp(cpy, NAMESPACE_USER) == 0 ||
- strcmp(cpy, NAMESPACE_PUBLIC) == 0) {
- other_namespace = 1;
- continue;
- }
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ int result, i;
+ u64_t mboxid, tmp_mboxid;
+ u64_t parent_mboxid = 0; /* id of parent mailbox (if applicable) */
+ char **chunks, *cpy;
+ int other_namespace = 0;
+
+ if (!check_state_and_args
+ ("CREATE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ /* remove trailing '/' if present */
+ while (strlen(args[0]) > 0 && args[0][strlen(args[0]) - 1] == '/')
+ args[0][strlen(args[0]) - 1] = '\0';
+
+ /* remove leading '/' if present */
+ for (i = 0; args[0][i] && args[0][i] == '/'; i++);
+ memmove(&args[0][0], &args[0][i],
+ (strlen(args[0]) - i) * sizeof(char));
+
+ /* check if this mailbox already exists */
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ /* dbase failure */
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
}
- else
- {
- strcat(cpy, "/");
- strcat(cpy, chunks[i]);
- /* if this is in Other Users namespace, continue to the next chunk */
- if (i == 1 && strncmp(cpy, NAMESPACE_USER, strlen(NAMESPACE_USER)) == 0)
- continue;
-
- }
-
- trace(TRACE_DEBUG,"checking for '%s'...",cpy);
-
- /* check if this mailbox already exists */
- if (db_findmailbox(cpy, ud->userid, &mboxid) == -1) {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- free_chunks(chunks);
- my_free(cpy);
- return -1; /* fatal */
- }
-
- if (mboxid == 0)
- {
- /* mailbox does not exist */
- /* check if we have the right to create mailboxes in this
- hierarchy */
- trace(TRACE_DEBUG, "%s,%s: Checking if we have the right to "
- "create mailboxes under mailbox [%llu]",
- __FILE__, __FUNCTION__, parent_mboxid);
- if (parent_mboxid != 0) {
- result = acl_has_right(ud->userid, parent_mboxid,
- ACL_RIGHT_CREATE);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database "
- "error\r\n");
- free_chunks(chunks);
- my_free(cpy);
- return -1; /* fatal */
+
+ if (mboxid != 0) {
+ /* mailbox already exists */
+ fprintf(ci->tx, "%s NO mailbox already exists\r\n", tag);
+ return 1;
+ }
+
+ /* check if new name is valid */
+ if (!checkmailboxname(args[0])) {
+ fprintf(ci->tx,
+ "%s BAD new mailbox name contains invalid characters\r\n",
+ tag);
+ return 1;
+ }
+
+ /* alloc a ptr which can contain up to the full name */
+ cpy = (char *) my_malloc(sizeof(char) * (strlen(args[0]) + 1));
+ if (!cpy) {
+ /* out of mem */
+ trace(TRACE_ERROR, "IMAPD: create(): not enough memory");
+ fprintf(ci->tx, "* BYE server ran out of memory\r\n");
+ return -1;
+ }
+
+ /* split up the name & create parent folders as necessary */
+ chunks = give_chunks(args[0], '/');
+
+ if (chunks == NULL) {
+ /* serious error while making chunks */
+ trace(TRACE_ERROR,
+ "IMAPD: create(): could not create chunks");
+ fprintf(ci->tx, "* BYE server ran out of memory\r\n");
+ my_free(cpy);
+ return -1;
+ }
+
+ if (chunks[0] == NULL) {
+ /* wrong argument */
+ fprintf(ci->tx, "%s NO invalid mailbox name specified\r\n",
+ tag);
+ free_chunks(chunks);
+ my_free(cpy);
+ return 1;
+ }
+
+ /* now go create */
+ strcpy(cpy, "");
+
+ for (i = 0; chunks[i]; i++) {
+ if (strlen(chunks[i]) == 0) {
+ /* no can do */
+ fprintf(ci->tx,
+ "%s NO invalid mailbox name specified\r\n",
+ tag);
+ free_chunks(chunks);
+ my_free(cpy);
+ return 1;
+ }
+
+ if (i == 0) {
+ if (strcasecmp(chunks[0], "inbox") == 0)
+ strcpy(chunks[0], "INBOX"); /* make inbox uppercase */
+
+ strcat(cpy, chunks[i]);
+ /* check to see if this is a folder in Other Users/ or Public
+ namespace */
+ if (strcmp(cpy, NAMESPACE_USER) == 0 ||
+ strcmp(cpy, NAMESPACE_PUBLIC) == 0) {
+ other_namespace = 1;
+ continue;
+ }
+ } else {
+ strcat(cpy, "/");
+ strcat(cpy, chunks[i]);
+ /* if this is in Other Users namespace, continue to the next chunk */
+ if (i == 1
+ && strncmp(cpy, NAMESPACE_USER,
+ strlen(NAMESPACE_USER)) == 0)
+ continue;
+
+ }
+
+ trace(TRACE_DEBUG, "checking for '%s'...", cpy);
+
+ /* check if this mailbox already exists */
+ if (db_findmailbox(cpy, ud->userid, &mboxid) == -1) {
+ /* dbase failure */
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ free_chunks(chunks);
+ my_free(cpy);
+ return -1; /* fatal */
+ }
+
+ if (mboxid == 0) {
+ /* mailbox does not exist */
+ /* check if we have the right to create mailboxes in this
+ hierarchy */
+ trace(TRACE_DEBUG,
+ "%s,%s: Checking if we have the right to "
+ "create mailboxes under mailbox [%llu]",
+ __FILE__, __FUNCTION__, parent_mboxid);
+ if (parent_mboxid != 0) {
+ result =
+ acl_has_right(ud->userid,
+ parent_mboxid,
+ ACL_RIGHT_CREATE);
+ if (result < 0) {
+ fprintf(ci->tx,
+ "* BYE internal database "
+ "error\r\n");
+ free_chunks(chunks);
+ my_free(cpy);
+ return -1; /* fatal */
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to create "
+ "mailbox here\r\n", tag);
+ free_chunks(chunks);
+ my_free(cpy);
+ return 1;
+ }
+ } else {
+ if (other_namespace) {
+ /* if we want to create a new mailbox in
+ another namespace, but we don't specify
+ the parent's mailbox, we should not be
+ allowed to do so */
+ fprintf(ci->tx,
+ "%s NO no permission to create "
+ "mailbox here\r\n", tag);
+ free_chunks(chunks);
+ my_free(cpy);
+ return 1;
+ }
+ }
+ result =
+ db_createmailbox(cpy, ud->userid, &tmp_mboxid);
+
+
+ if (result == -1) {
+ fprintf(ci->tx,
+ "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
}
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to create "
- "mailbox here\r\n", tag);
+ } else {
+ /* this might be the parent of our new mailbox. store it's id */
+ parent_mboxid = mboxid;
+ /* mailbox does exist, failure if no_inferiors flag set */
+ result = db_noinferiors(mboxid);
+ if (result == 1) {
+ fprintf(ci->tx,
+ "%s NO mailbox cannot have inferior names\r\n",
+ tag);
free_chunks(chunks);
my_free(cpy);
return 1;
}
- } else {
- if (other_namespace) {
- /* if we want to create a new mailbox in
- another namespace, but we don't specify
- the parent's mailbox, we should not be
- allowed to do so */
- fprintf(ci->tx, "%s NO no permission to create "
- "mailbox here\r\n", tag);
+
+
+ if (result == -1) {
+ /* dbase failure */
+ fprintf(ci->tx,
+ "* BYE internal dbase error\r\n");
free_chunks(chunks);
my_free(cpy);
- return 1;
+ return -1; /* fatal */
}
}
- result = db_createmailbox(cpy, ud->userid, &tmp_mboxid);
-
-
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
- }
- else
- {
- /* this might be the parent of our new mailbox. store it's id */
- parent_mboxid = mboxid;
- /* mailbox does exist, failure if no_inferiors flag set */
- result = db_noinferiors(mboxid);
- if (result == 1)
- {
- fprintf(ci->tx, "%s NO mailbox cannot have inferior names\r\n",tag);
- free_chunks(chunks);
- my_free(cpy);
- return 1;
- }
-
-
- if (result == -1)
- {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- free_chunks(chunks);
- my_free(cpy);
- return -1; /* fatal */
- }
}
- }
- /* creation complete */
- free_chunks(chunks);
- my_free(cpy);
+ /* creation complete */
+ free_chunks(chunks);
+ my_free(cpy);
- fprintf(ci->tx,"%s OK CREATE completed\r\n",tag);
- return 0;
+ fprintf(ci->tx, "%s OK CREATE completed\r\n", tag);
+ return 0;
}
@@ -779,120 +828,121 @@ int _ic_create(char *tag, char **args, ClientInfo *ci)
*
* deletes a specified mailbox
*/
-int _ic_delete(char *tag, char **args, ClientInfo *ci)
+int _ic_delete(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- int result,nchildren = 0;
- u64_t *children = NULL,mboxid;
-
- if (!check_state_and_args("DELETE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- /* remove trailing '/' if present */
- while (strlen(args[0]) > 0 && args[0][strlen(args[0]) - 1] == '/')
- args[0][strlen(args[0]) - 1] = '\0';
-
- /* check if this mailbox exists */
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
- if (mboxid == 0) {
- /* mailbox does not exist */
- fprintf(ci->tx,"%s NO mailbox does not exist\r\n",tag);
- return 1;
- }
-
- /* check if the user is the owner of this mailbox. If so, then
- the user has the right to delete it. */
- result = db_user_is_mailbox_owner(ud->userid, mboxid);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to delete mailbox\r\n", tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
-
- /* check if there is an attempt to delete inbox */
- if (strcasecmp(args[0],"inbox") == 0)
- {
- fprintf(ci->tx,"%s NO cannot delete special mailbox INBOX\r\n",tag);
- return 1;
- }
-
- /* check for children of this mailbox */
- result = db_listmailboxchildren(mboxid, ud->userid, &children, &nchildren, "%");
- if (result == -1)
- {
- /* error */
- trace(TRACE_ERROR, "IMAPD: delete(): cannot retrieve list of mailbox children");
- fprintf(ci->tx, "* BYE dbase/memory error\r\n");
- return -1;
- }
-
- if (nchildren != 0)
- {
- /* mailbox has inferior names; error if \noselect specified */
- result = db_isselectable(mboxid);
- if (result == 0)
- {
- fprintf(ci->tx,"%s NO mailbox is non-selectable\r\n",tag);
- my_free(children);
- return 1;
- }
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(children);
- return -1; /* fatal */
- }
-
- /* mailbox has inferior names; remove all msgs and set noselect flag */
- result = db_removemsg(ud->userid, mboxid);
- if (result != -1)
- result = db_setselectable(mboxid, 0); /* set non-selectable flag */
-
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(children);
- return -1; /* fatal */
- }
-
- /* check if this was the currently selected mailbox */
- if (mboxid == ud->mailbox.uid)
- {
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- ud->state = IMAPCS_AUTHENTICATED;
- }
-
- /* ok done */
- fprintf(ci->tx,"%s OK DELETE completed\r\n",tag);
- my_free(children);
- return 0;
- }
-
- /* ok remove mailbox */
- db_delete_mailbox(mboxid, 0, 1);
-
- /* check if this was the currently selected mailbox */
- if (mboxid == ud->mailbox.uid)
- {
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- ud->state = IMAPCS_AUTHENTICATED;
- }
-
- fprintf(ci->tx,"%s OK DELETE completed\r\n",tag);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ int result, nchildren = 0;
+ u64_t *children = NULL, mboxid;
+
+ if (!check_state_and_args
+ ("DELETE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ /* remove trailing '/' if present */
+ while (strlen(args[0]) > 0 && args[0][strlen(args[0]) - 1] == '/')
+ args[0][strlen(args[0]) - 1] = '\0';
+
+ /* check if this mailbox exists */
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ /* dbase failure */
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+ if (mboxid == 0) {
+ /* mailbox does not exist */
+ fprintf(ci->tx, "%s NO mailbox does not exist\r\n", tag);
+ return 1;
+ }
+
+ /* check if the user is the owner of this mailbox. If so, then
+ the user has the right to delete it. */
+ result = db_user_is_mailbox_owner(ud->userid, mboxid);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to delete mailbox\r\n", tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+
+ /* check if there is an attempt to delete inbox */
+ if (strcasecmp(args[0], "inbox") == 0) {
+ fprintf(ci->tx,
+ "%s NO cannot delete special mailbox INBOX\r\n",
+ tag);
+ return 1;
+ }
+
+ /* check for children of this mailbox */
+ result =
+ db_listmailboxchildren(mboxid, ud->userid, &children,
+ &nchildren, "%");
+ if (result == -1) {
+ /* error */
+ trace(TRACE_ERROR,
+ "IMAPD: delete(): cannot retrieve list of mailbox children");
+ fprintf(ci->tx, "* BYE dbase/memory error\r\n");
+ return -1;
+ }
+
+ if (nchildren != 0) {
+ /* mailbox has inferior names; error if \noselect specified */
+ result = db_isselectable(mboxid);
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO mailbox is non-selectable\r\n",
+ tag);
+ my_free(children);
+ return 1;
+ }
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(children);
+ return -1; /* fatal */
+ }
+
+ /* mailbox has inferior names; remove all msgs and set noselect flag */
+ result = db_removemsg(ud->userid, mboxid);
+ if (result != -1)
+ result = db_setselectable(mboxid, 0); /* set non-selectable flag */
+
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(children);
+ return -1; /* fatal */
+ }
+
+ /* check if this was the currently selected mailbox */
+ if (mboxid == ud->mailbox.uid) {
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ ud->state = IMAPCS_AUTHENTICATED;
+ }
+
+ /* ok done */
+ fprintf(ci->tx, "%s OK DELETE completed\r\n", tag);
+ my_free(children);
+ return 0;
+ }
+
+ /* ok remove mailbox */
+ db_delete_mailbox(mboxid, 0, 1);
+
+ /* check if this was the currently selected mailbox */
+ if (mboxid == ud->mailbox.uid) {
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ ud->state = IMAPCS_AUTHENTICATED;
+ }
+
+ fprintf(ci->tx, "%s OK DELETE completed\r\n", tag);
+ return 0;
}
@@ -901,190 +951,195 @@ int _ic_delete(char *tag, char **args, ClientInfo *ci)
*
* renames a specified mailbox
*/
-int _ic_rename(char *tag, char **args, ClientInfo *ci)
+int _ic_rename(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t mboxid,newmboxid,*children,oldnamelen,parentmboxid;
- int nchildren,i,result;
- char newname[IMAP_MAX_MAILBOX_NAMELEN],name[IMAP_MAX_MAILBOX_NAMELEN];
-
- if (!check_state_and_args("RENAME", tag, args, 2, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- /* remove trailing '/' if present */
- while (strlen(args[0]) > 0 && args[0][strlen(args[0]) - 1] == '/') args[0][strlen(args[0]) - 1] = '\0';
- while (strlen(args[1]) > 0 && args[1][strlen(args[1]) - 1] == '/') args[1][strlen(args[1]) - 1] = '\0';
-
- /* remove leading '/' if present */
- for (i=0; args[1][i] && args[1][i] == '/'; i++) ;
- memmove(&args[1][0],&args[1][i], (strlen(args[1]) - i) * sizeof(char));
-
- for (i=0; args[0][i] && args[0][i] == '/'; i++) ;
- memmove(&args[0][0],&args[0][i], (strlen(args[0]) - i) * sizeof(char));
-
-
- /* check if new mailbox exists */
- if (db_findmailbox(args[1], ud->userid, &mboxid) == -1) {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
- if (mboxid != 0)
- {
- /* mailbox exists */
- fprintf(ci->tx,"%s NO new mailbox already exists\r\n",tag);
- return 1;
- }
-
- /* check if original mailbox exists */
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
- if (mboxid == 0)
- {
- /* mailbox does not exist */
- fprintf(ci->tx,"%s NO mailbox does not exist\r\n",tag);
- return 1;
- }
-
- /* check if the user is the owner of this mailbox. If so, then
- the user has the right to delete it. */
- result = db_user_is_mailbox_owner(ud->userid, mboxid);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to rename mailbox\r\n", tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
- /* check if new name is valid */
- if (!checkmailboxname(args[1]))
- {
- fprintf(ci->tx,"%s NO new mailbox name contains invalid characters\r\n",tag);
- return 1;
- }
-
- oldnamelen = strlen(args[0]);
-
- /* check if new name would invade structure as in
- * test (exists)
- * rename test test/testing
- * would create test/testing but delete test
- */
- if (strncasecmp(args[0], args[1], oldnamelen) == 0 &&
- strlen(args[1]) > oldnamelen && args[1][oldnamelen] == '/')
- {
- fprintf(ci->tx,"%s NO new mailbox would invade mailbox structure\r\n",tag);
- return 1;
- }
-
-
- /* check if structure of new name is valid */
- /* i.e. only last part (after last '/' can be nonexistent) */
- for (i=strlen(args[1])-1; i>=0 && args[1][i] != '/'; i--) ;
- if (i >= 0)
- {
- args[1][i] = '\0'; /* note: original char was '/' */
-
- if (db_findmailbox(args[1], ud->userid, &parentmboxid) == -1) {
- /* dbase failure */
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
- if (parentmboxid == 0)
- {
- /* parent mailbox does not exist */
- fprintf(ci->tx,"%s NO new mailbox would invade mailbox structure\r\n",tag);
- return 1;
- }
-
- /* ok, reset arg */
- args[1][i] = '/';
- }
-
- /* check if it is INBOX to be renamed */
- if (strcasecmp(args[0],"inbox") == 0)
- {
- /* ok, renaming inbox */
- /* this means creating a new mailbox and moving all the INBOX msgs to the new mailbox */
- /* inferior names of INBOX are left unchanged */
- result = db_createmailbox(args[1], ud->userid, &newmboxid);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
-
- result = db_movemsg(newmboxid, mboxid);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t mboxid, newmboxid, *children, oldnamelen, parentmboxid;
+ int nchildren, i, result;
+ char newname[IMAP_MAX_MAILBOX_NAMELEN],
+ name[IMAP_MAX_MAILBOX_NAMELEN];
+
+ if (!check_state_and_args
+ ("RENAME", tag, args, 2, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ /* remove trailing '/' if present */
+ while (strlen(args[0]) > 0 && args[0][strlen(args[0]) - 1] == '/')
+ args[0][strlen(args[0]) - 1] = '\0';
+ while (strlen(args[1]) > 0 && args[1][strlen(args[1]) - 1] == '/')
+ args[1][strlen(args[1]) - 1] = '\0';
+
+ /* remove leading '/' if present */
+ for (i = 0; args[1][i] && args[1][i] == '/'; i++);
+ memmove(&args[1][0], &args[1][i],
+ (strlen(args[1]) - i) * sizeof(char));
+
+ for (i = 0; args[0][i] && args[0][i] == '/'; i++);
+ memmove(&args[0][0], &args[0][i],
+ (strlen(args[0]) - i) * sizeof(char));
+
+
+ /* check if new mailbox exists */
+ if (db_findmailbox(args[1], ud->userid, &mboxid) == -1) {
+ /* dbase failure */
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
}
-
- /* ok done */
- fprintf(ci->tx,"%s OK RENAME completed\r\n",tag);
- return 0;
- }
-
- /* check for inferior names */
- result = db_listmailboxchildren(mboxid, ud->userid, &children, &nchildren, "%");
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
-
- /* replace name for each child */
- for (i=0; i<nchildren; i++)
- {
- result = db_getmailboxname(children[i], ud->userid, name);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(children);
- return -1;
+ if (mboxid != 0) {
+ /* mailbox exists */
+ fprintf(ci->tx, "%s NO new mailbox already exists\r\n",
+ tag);
+ return 1;
}
- if (oldnamelen >= strlen(name))
- {
- /* strange error, let's say its fatal */
- trace(TRACE_ERROR,"IMAPD: rename(): mailbox names are fucked up");
- fprintf(ci->tx,"* BYE internal error regarding mailbox names\r\n");
- my_free(children);
- return -1;
+ /* check if original mailbox exists */
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ /* dbase failure */
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+ if (mboxid == 0) {
+ /* mailbox does not exist */
+ fprintf(ci->tx, "%s NO mailbox does not exist\r\n", tag);
+ return 1;
}
-
- snprintf(newname, IMAP_MAX_MAILBOX_NAMELEN, "%s%s",args[1],&name[oldnamelen]);
- result = db_setmailboxname(children[i], newname);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(children);
- return -1;
+ /* check if the user is the owner of this mailbox. If so, then
+ the user has the right to delete it. */
+ result = db_user_is_mailbox_owner(ud->userid, mboxid);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to rename mailbox\r\n", tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+ /* check if new name is valid */
+ if (!checkmailboxname(args[1])) {
+ fprintf(ci->tx,
+ "%s NO new mailbox name contains invalid characters\r\n",
+ tag);
+ return 1;
+ }
+
+ oldnamelen = strlen(args[0]);
+
+ /* check if new name would invade structure as in
+ * test (exists)
+ * rename test test/testing
+ * would create test/testing but delete test
+ */
+ if (strncasecmp(args[0], args[1], oldnamelen) == 0 &&
+ strlen(args[1]) > oldnamelen && args[1][oldnamelen] == '/') {
+ fprintf(ci->tx,
+ "%s NO new mailbox would invade mailbox structure\r\n",
+ tag);
+ return 1;
+ }
+
+
+ /* check if structure of new name is valid */
+ /* i.e. only last part (after last '/' can be nonexistent) */
+ for (i = strlen(args[1]) - 1; i >= 0 && args[1][i] != '/'; i--);
+ if (i >= 0) {
+ args[1][i] = '\0'; /* note: original char was '/' */
+
+ if (db_findmailbox(args[1], ud->userid, &parentmboxid) ==
+ -1) {
+ /* dbase failure */
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+ if (parentmboxid == 0) {
+ /* parent mailbox does not exist */
+ fprintf(ci->tx,
+ "%s NO new mailbox would invade mailbox structure\r\n",
+ tag);
+ return 1;
+ }
+
+ /* ok, reset arg */
+ args[1][i] = '/';
+ }
+
+ /* check if it is INBOX to be renamed */
+ if (strcasecmp(args[0], "inbox") == 0) {
+ /* ok, renaming inbox */
+ /* this means creating a new mailbox and moving all the INBOX msgs to the new mailbox */
+ /* inferior names of INBOX are left unchanged */
+ result = db_createmailbox(args[1], ud->userid, &newmboxid);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ result = db_movemsg(newmboxid, mboxid);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ /* ok done */
+ fprintf(ci->tx, "%s OK RENAME completed\r\n", tag);
+ return 0;
+ }
+
+ /* check for inferior names */
+ result =
+ db_listmailboxchildren(mboxid, ud->userid, &children,
+ &nchildren, "%");
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ /* replace name for each child */
+ for (i = 0; i < nchildren; i++) {
+ result = db_getmailboxname(children[i], ud->userid, name);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(children);
+ return -1;
+ }
+
+ if (oldnamelen >= strlen(name)) {
+ /* strange error, let's say its fatal */
+ trace(TRACE_ERROR,
+ "IMAPD: rename(): mailbox names are fucked up");
+ fprintf(ci->tx,
+ "* BYE internal error regarding mailbox names\r\n");
+ my_free(children);
+ return -1;
+ }
+
+ snprintf(newname, IMAP_MAX_MAILBOX_NAMELEN, "%s%s",
+ args[1], &name[oldnamelen]);
+
+ result = db_setmailboxname(children[i], newname);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(children);
+ return -1;
+ }
}
- }
- if (children)
- my_free(children);
+ if (children)
+ my_free(children);
- /* now replace name */
- result = db_setmailboxname(mboxid, args[1]);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
+ /* now replace name */
+ result = db_setmailboxname(mboxid, args[1]);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
- fprintf(ci->tx,"%s OK RENAME completed\r\n",tag);
- return 0;
+ fprintf(ci->tx, "%s OK RENAME completed\r\n", tag);
+ return 0;
}
@@ -1093,51 +1148,51 @@ int _ic_rename(char *tag, char **args, ClientInfo *ci)
*
* subscribe to a specified mailbox
*/
-int _ic_subscribe(char *tag, char **args, ClientInfo *ci)
+int _ic_subscribe(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t mboxid;
- int result;
-
-
- if (!check_state_and_args("SUBSCRIBE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
- if (mboxid == 0)
- {
- /* mailbox does not exist */
- fprintf(ci->tx,"%s NO mailbox does not exist\r\n", tag);
- return 0;
- }
-
- /* check for the lookup-right. RFC is unclear about which right to
- use, so I guessed it should be lookup */
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_LOOKUP);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to subscribe to mailbox\r\n",
- tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
- if (db_subscribe(mboxid, ud->userid) == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
-
- fprintf(ci->tx,"%s OK SUBSCRIBE completed\r\n",tag);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t mboxid;
+ int result;
+
+
+ if (!check_state_and_args
+ ("SUBSCRIBE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+ if (mboxid == 0) {
+ /* mailbox does not exist */
+ fprintf(ci->tx, "%s NO mailbox does not exist\r\n", tag);
+ return 0;
+ }
+
+ /* check for the lookup-right. RFC is unclear about which right to
+ use, so I guessed it should be lookup */
+ result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_LOOKUP);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to subscribe to mailbox\r\n",
+ tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+ if (db_subscribe(mboxid, ud->userid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ fprintf(ci->tx, "%s OK SUBSCRIBE completed\r\n", tag);
+ return 0;
}
@@ -1146,51 +1201,51 @@ int _ic_subscribe(char *tag, char **args, ClientInfo *ci)
*
* removes a mailbox from the users' subscription list
*/
-int _ic_unsubscribe(char *tag, char **args, ClientInfo *ci)
+int _ic_unsubscribe(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t mboxid;
- int result;
-
-
- if (!check_state_and_args("UNSUBSCRIBE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
- if (mboxid == 0)
- {
- /* mailbox does not exist */
- fprintf(ci->tx,"%s NO mailbox does not exist\r\n", tag);
- return 0;
- }
-
- /* check for the lookup-right. RFC is unclear about which right to
- use, so I guessed it should be lookup */
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_LOOKUP);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to unsubscribe from mailbox\r\n",
- tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
- if (db_unsubscribe(mboxid, ud->userid) == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
-
- fprintf(ci->tx,"%s OK UNSUBSCRIBE completed\r\n",tag);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t mboxid;
+ int result;
+
+
+ if (!check_state_and_args
+ ("UNSUBSCRIBE", tag, args, 1, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+ if (mboxid == 0) {
+ /* mailbox does not exist */
+ fprintf(ci->tx, "%s NO mailbox does not exist\r\n", tag);
+ return 0;
+ }
+
+ /* check for the lookup-right. RFC is unclear about which right to
+ use, so I guessed it should be lookup */
+ result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_LOOKUP);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to unsubscribe from mailbox\r\n",
+ tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+ if (db_unsubscribe(mboxid, ud->userid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ fprintf(ci->tx, "%s OK UNSUBSCRIBE completed\r\n", tag);
+ return 0;
}
@@ -1199,146 +1254,143 @@ int _ic_unsubscribe(char *tag, char **args, ClientInfo *ci)
*
* executes a list command
*/
-int _ic_list(char *tag, char **args, ClientInfo *ci)
+int _ic_list(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t *children=NULL;
- int result;
- unsigned slen,plen;
- unsigned i,j;
- unsigned nchildren;
- char name[IMAP_MAX_MAILBOX_NAMELEN];
- char *pattern;
- char *thisname = list_is_lsub ? "LSUB" : "LIST";
-
- if (!check_state_and_args(thisname, tag, args, 2, IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
-
- /* check if args are both empty strings */
- if (strlen(args[0]) == 0 && strlen(args[1]) == 0)
- {
- /* this has special meaning; show root & delimiter */
- trace(TRACE_ERROR, "_ic_list(): showing delimiter [(\\NoSelect) \"/\" \"\"]");
- fprintf(ci->tx,"* %s (\\NoSelect) \"/\" \"\"\r\n",thisname);
- fprintf(ci->tx,"%s OK %s completed\r\n",tag,thisname);
- return 0;
- }
-
- /* check the reference name, should contain only accepted mailboxname chars */
- for (i=0,slen=strlen(args[0]); args[0][i]; i++)
- {
- if (stridx(AcceptedMailboxnameChars, args[0][i]) == slen)
- {
- /* wrong char found */
- fprintf(ci->tx,"%s BAD reference name contains invalid characters\r\n",tag);
- return 1;
- }
- }
-
- plen = strlen(args[1]) * 6;
- pattern = (char*)my_malloc(sizeof(char) * (plen + slen + 10)); /* +10 for some xtra space */
- if (!pattern)
- {
- fprintf(ci->tx,"* BYE out of memory\r\n");
- return -1;
- }
-
- memset(pattern, '\0', plen + slen + 10);
- pattern[0] = '^';
- strcpy(&pattern[1], args[0]);
-
- i = slen+1;
- for (j=0; args[1][j] && i < (plen + slen + 1); j++)
- {
- if (args[1][j] == '*')
- {
- pattern[i++] = '.';
- pattern[i++] = '*';
- }
- else if (args[1][j] == '%')
- {
- pattern[i++] = '[';
- pattern[i++] = '^';
- pattern[i++] = '\\';
- pattern[i++] = '/';
- pattern[i++] = ']';
- pattern[i++] = '*';
- }
- else
- pattern[i++] = args[1][j];
- }
-
- pattern[i] = '$';
-
- trace(TRACE_INFO,"ic_list(): build the pattern: [%s]\n",pattern);
-
- result = db_findmailbox_by_regex(ud->userid, pattern, &children, &nchildren, list_is_lsub);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(children);
- my_free(pattern);
- return -1;
- }
-
- if (result == 1)
- {
- fprintf(ci->tx,"%s BAD invalid pattern specified\r\n",tag);
- my_free(children);
- my_free(pattern);
- return 1;
- }
-
-
- for (i=0; i<nchildren; i++)
- {
- /* get name */
- result = db_getmailboxname(children[i], ud->userid, name);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(children);
- my_free(pattern);
- return -1;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t *children = NULL;
+ int result;
+ unsigned slen, plen;
+ unsigned i, j;
+ unsigned nchildren;
+ char name[IMAP_MAX_MAILBOX_NAMELEN];
+ char *pattern;
+ char *thisname = list_is_lsub ? "LSUB" : "LIST";
+
+ if (!check_state_and_args
+ (thisname, tag, args, 2, IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+
+ /* check if args are both empty strings */
+ if (strlen(args[0]) == 0 && strlen(args[1]) == 0) {
+ /* this has special meaning; show root & delimiter */
+ trace(TRACE_ERROR,
+ "_ic_list(): showing delimiter [(\\NoSelect) \"/\" \"\"]");
+ fprintf(ci->tx, "* %s (\\NoSelect) \"/\" \"\"\r\n",
+ thisname);
+ fprintf(ci->tx, "%s OK %s completed\r\n", tag, thisname);
+ return 0;
+ }
+
+ /* check the reference name, should contain only accepted mailboxname chars */
+ for (i = 0, slen = strlen(args[0]); args[0][i]; i++) {
+ if (stridx(AcceptedMailboxnameChars, args[0][i]) == slen) {
+ /* wrong char found */
+ fprintf(ci->tx,
+ "%s BAD reference name contains invalid characters\r\n",
+ tag);
+ return 1;
+ }
}
- fprintf(ci->tx,"* %s (",thisname);
+ plen = strlen(args[1]) * 6;
+ pattern = (char *) my_malloc(sizeof(char) * (plen + slen + 10)); /* +10 for some xtra space */
+ if (!pattern) {
+ fprintf(ci->tx, "* BYE out of memory\r\n");
+ return -1;
+ }
- /* show flags */
- result = db_isselectable(children[i]);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- my_free(children);
- my_free(pattern);
- return -1;
+ memset(pattern, '\0', plen + slen + 10);
+ pattern[0] = '^';
+ strcpy(&pattern[1], args[0]);
+
+ i = slen + 1;
+ for (j = 0; args[1][j] && i < (plen + slen + 1); j++) {
+ if (args[1][j] == '*') {
+ pattern[i++] = '.';
+ pattern[i++] = '*';
+ } else if (args[1][j] == '%') {
+ pattern[i++] = '[';
+ pattern[i++] = '^';
+ pattern[i++] = '\\';
+ pattern[i++] = '/';
+ pattern[i++] = ']';
+ pattern[i++] = '*';
+ } else
+ pattern[i++] = args[1][j];
}
- if (!result) fprintf(ci->tx,"\\noselect ");
+ pattern[i] = '$';
- result = db_noinferiors(children[i]);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- my_free(children);
- my_free(pattern);
- return -1;
+ trace(TRACE_INFO, "ic_list(): build the pattern: [%s]\n", pattern);
+
+ result =
+ db_findmailbox_by_regex(ud->userid, pattern, &children,
+ &nchildren, list_is_lsub);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(children);
+ my_free(pattern);
+ return -1;
+ }
+
+ if (result == 1) {
+ fprintf(ci->tx, "%s BAD invalid pattern specified\r\n",
+ tag);
+ my_free(children);
+ my_free(pattern);
+ return 1;
}
- if (result) fprintf(ci->tx,"\\noinferiors ");
- /* show delimiter & name */
- fprintf(ci->tx,") \"/\" \"%s\"\r\n",name);
- }
+ for (i = 0; i < nchildren; i++) {
+ /* get name */
+ result = db_getmailboxname(children[i], ud->userid, name);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(children);
+ my_free(pattern);
+ return -1;
+ }
- if (children)
- my_free(children);
-
- my_free(pattern);
+ fprintf(ci->tx, "* %s (", thisname);
- fprintf(ci->tx,"%s OK %s completed\r\n",tag,thisname);
- return 0;
+ /* show flags */
+ result = db_isselectable(children[i]);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ my_free(children);
+ my_free(pattern);
+ return -1;
+ }
+
+ if (!result)
+ fprintf(ci->tx, "\\noselect ");
+
+ result = db_noinferiors(children[i]);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ my_free(children);
+ my_free(pattern);
+ return -1;
+ }
+
+ if (result)
+ fprintf(ci->tx, "\\noinferiors ");
+
+ /* show delimiter & name */
+ fprintf(ci->tx, ") \"/\" \"%s\"\r\n", name);
+ }
+
+ if (children)
+ my_free(children);
+
+ my_free(pattern);
+
+ fprintf(ci->tx, "%s OK %s completed\r\n", tag, thisname);
+ return 0;
}
@@ -1347,14 +1399,14 @@ int _ic_list(char *tag, char **args, ClientInfo *ci)
*
* list subscribed mailboxes
*/
-int _ic_lsub(char *tag, char **args, ClientInfo *ci)
+int _ic_lsub(char *tag, char **args, ClientInfo * ci)
{
- int result;
+ int result;
- list_is_lsub = 1;
- result = _ic_list(tag,args,ci);
- list_is_lsub = 0;
- return result;
+ list_is_lsub = 1;
+ result = _ic_list(tag, args, ci);
+ list_is_lsub = 0;
+ return result;
}
@@ -1363,125 +1415,125 @@ int _ic_lsub(char *tag, char **args, ClientInfo *ci)
*
* inquire the status of a mailbox
*/
-int _ic_status(char *tag, char **args, ClientInfo *ci)
+int _ic_status(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- mailbox_t mb;
- int i,endfound,result;
-
- if (ud->state != IMAPCS_AUTHENTICATED && ud->state != IMAPCS_SELECTED)
- {
- fprintf(ci->tx,"%s BAD STATUS command received in invalid state\r\n", tag);
- return 1;
- }
-
- if (!args[0] || !args[1] || !args[2])
- {
- fprintf(ci->tx,"%s BAD missing argument(s) to STATUS\r\n", tag);
- return 1;
- }
-
- if (strcmp(args[1],"(") != 0)
- {
- fprintf(ci->tx,"%s BAD argument list should be parenthesed\r\n", tag);
- return 1;
- }
-
- /* check final arg: should be ')' and no new '(' in between */
- for (i=2,endfound=0; args[i]; i++)
- {
- if (strcmp(args[i], ")") == 0)
- {
- endfound = i;
- break;
- }
-
- if (strcmp(args[i], "(") == 0)
- {
- fprintf(ci->tx,"%s BAD too many parentheses specified\r\n", tag);
- return 1;
- }
- }
-
- if (endfound == 2)
- {
- fprintf(ci->tx,"%s BAD argument list empty\r\n", tag);
- return 1;
- }
-
- if (args[endfound+1])
- {
- fprintf(ci->tx,"%s BAD argument list too long\r\n", tag);
- return 1;
- }
-
-
- /* zero init */
- memset(&mb, 0, sizeof(mb));
-
- /* check if mailbox exists */
- if (db_findmailbox(args[0], ud->userid, &(mb.uid)) == -1) {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
-
- if (mb.uid == 0)
- {
- /* mailbox does not exist */
- fprintf(ci->tx,"%s NO specified mailbox does not exist\r\n",tag);
- return 1;
- }
-
- result = acl_has_right(ud->userid, mb.uid, ACL_RIGHT_READ);
- if (result == -1) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no rights to get status for mailbox\r\n",
- tag);
- return 1;
- }
-
- /* retrieve mailbox data */
- result = db_getmailbox(&mb);
-
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
-
- fprintf(ci->tx, "* STATUS \"%s\" (", args[0]);
-
- for (i=2; args[i]; i++)
- {
- if (strcasecmp(args[i], "messages") == 0)
- fprintf(ci->tx, "MESSAGES %u ",mb.exists);
- else if (strcasecmp(args[i], "recent") == 0)
- fprintf(ci->tx, "RECENT %u ",mb.recent);
- else if (strcasecmp(args[i], "unseen") == 0)
- fprintf(ci->tx, "UNSEEN %u ",mb.unseen);
- else if (strcasecmp(args[i], "uidnext") == 0)
- fprintf(ci->tx, "UIDNEXT %llu ",mb.msguidnext);
- else if (strcasecmp(args[i], "uidvalidity") == 0)
- fprintf(ci->tx, "UIDVALIDITY %llu ",mb.uid);
- else if (strcasecmp(args[i], ")") == 0)
- break; /* done */
- else
- {
- fprintf(ci->tx,"\r\n%s BAD unrecognized option '%s' specified\r\n",tag,args[i]);
- my_free(mb.seq_list);
- return 1;
- }
- }
-
- fprintf(ci->tx,")\r\n");
-
- fprintf(ci->tx,"%s OK STATUS completed\r\n",tag);
-
- my_free(mb.seq_list);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ mailbox_t mb;
+ int i, endfound, result;
+
+ if (ud->state != IMAPCS_AUTHENTICATED
+ && ud->state != IMAPCS_SELECTED) {
+ fprintf(ci->tx,
+ "%s BAD STATUS command received in invalid state\r\n",
+ tag);
+ return 1;
+ }
+
+ if (!args[0] || !args[1] || !args[2]) {
+ fprintf(ci->tx, "%s BAD missing argument(s) to STATUS\r\n",
+ tag);
+ return 1;
+ }
+
+ if (strcmp(args[1], "(") != 0) {
+ fprintf(ci->tx,
+ "%s BAD argument list should be parenthesed\r\n",
+ tag);
+ return 1;
+ }
+
+ /* check final arg: should be ')' and no new '(' in between */
+ for (i = 2, endfound = 0; args[i]; i++) {
+ if (strcmp(args[i], ")") == 0) {
+ endfound = i;
+ break;
+ }
+
+ if (strcmp(args[i], "(") == 0) {
+ fprintf(ci->tx,
+ "%s BAD too many parentheses specified\r\n",
+ tag);
+ return 1;
+ }
+ }
+
+ if (endfound == 2) {
+ fprintf(ci->tx, "%s BAD argument list empty\r\n", tag);
+ return 1;
+ }
+
+ if (args[endfound + 1]) {
+ fprintf(ci->tx, "%s BAD argument list too long\r\n", tag);
+ return 1;
+ }
+
+
+ /* zero init */
+ memset(&mb, 0, sizeof(mb));
+
+ /* check if mailbox exists */
+ if (db_findmailbox(args[0], ud->userid, &(mb.uid)) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ if (mb.uid == 0) {
+ /* mailbox does not exist */
+ fprintf(ci->tx,
+ "%s NO specified mailbox does not exist\r\n", tag);
+ return 1;
+ }
+
+ result = acl_has_right(ud->userid, mb.uid, ACL_RIGHT_READ);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no rights to get status for mailbox\r\n",
+ tag);
+ return 1;
+ }
+
+ /* retrieve mailbox data */
+ result = db_getmailbox(&mb);
+
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+
+ fprintf(ci->tx, "* STATUS \"%s\" (", args[0]);
+
+ for (i = 2; args[i]; i++) {
+ if (strcasecmp(args[i], "messages") == 0)
+ fprintf(ci->tx, "MESSAGES %u ", mb.exists);
+ else if (strcasecmp(args[i], "recent") == 0)
+ fprintf(ci->tx, "RECENT %u ", mb.recent);
+ else if (strcasecmp(args[i], "unseen") == 0)
+ fprintf(ci->tx, "UNSEEN %u ", mb.unseen);
+ else if (strcasecmp(args[i], "uidnext") == 0)
+ fprintf(ci->tx, "UIDNEXT %llu ", mb.msguidnext);
+ else if (strcasecmp(args[i], "uidvalidity") == 0)
+ fprintf(ci->tx, "UIDVALIDITY %llu ", mb.uid);
+ else if (strcasecmp(args[i], ")") == 0)
+ break; /* done */
+ else {
+ fprintf(ci->tx,
+ "\r\n%s BAD unrecognized option '%s' specified\r\n",
+ tag, args[i]);
+ my_free(mb.seq_list);
+ return 1;
+ }
+ }
+
+ fprintf(ci->tx, ")\r\n");
+
+ fprintf(ci->tx, "%s OK STATUS completed\r\n", tag);
+
+ my_free(mb.seq_list);
+ return 0;
}
@@ -1490,196 +1542,215 @@ int _ic_status(char *tag, char **args, ClientInfo *ci)
*
* append a message to a mailbox
*/
-int _ic_append(char *tag, char **args, ClientInfo *ci)
+int _ic_append(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t mboxid;
- u64_t msg_idnr;
- int i, j, result;
- timestring_t sqldate;
- int flaglist[IMAP_NFLAGS];
- int flagcount = 0;
-
- for (i = 0; i < IMAP_NFLAGS; i++)
- flaglist[i] = 0;
-
- if (!args[0] || !args[1])
- {
- fprintf(ci->tx,"%s BAD invalid arguments specified to APPEND\r\n", tag);
- return 1;
- }
-
- /* find the mailbox to place the message */
- if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
- fprintf(ci->tx,"* BYE internal dbase error");
- return -1;
- }
-
- if (mboxid == 0)
- {
- fprintf(ci->tx,"%s NO [TRYCREATE] could not find specified mailbox\r\n", tag);
- return 1;
- }
-
- trace(TRACE_DEBUG, "ic_append(): mailbox [%s] found, id: %llu\n",args[0],mboxid);
- /* check if user has right to append to mailbox */
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_INSERT);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to append to mailbox\r\n", tag);
- ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- return 1;
- }
-
-
- i=1;
-
- /* check if a flag list has been specified */
- /* FIXME: We need to take of care of the Flags that are set here. They
- should be set to the new message!
- */
- if (args[i][0] == '(')
- {
- /* ok fetch the flags specified */
- trace(TRACE_DEBUG, "ic_append(): flag list found:\n");
-
- while (args[i] && args[i][0] != ')')
- {
- trace(TRACE_DEBUG, "%s ",args[i]);
- for (j = 0; j < IMAP_NFLAGS; j++) {
- if (strcasecmp(args[i], imap_flag_desc_escaped[j]) == 0) {
- flaglist[j] = 1;
- flagcount++;
- break;
- }
- }
- i++;
- }
-
- i++;
- trace(TRACE_DEBUG, ")\n");
- }
-
- if (!args[i])
- {
- trace(TRACE_INFO,"ic_append(): unexpected end of arguments\n");
- fprintf(ci->tx,"%s BAD invalid arguments specified to APPEND\r\n", tag);
- return 1;
- }
-
-
- for (j = 0; j < IMAP_NFLAGS; j++)
- if (flaglist[j] == 1)
- trace(TRACE_DEBUG, "%s,%s: %s set",
- __FILE__, __FUNCTION__, imap_flag_desc[j]);
-
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t mboxid;
+ u64_t msg_idnr;
+ int i, j, result;
+ timestring_t sqldate;
+ int flaglist[IMAP_NFLAGS];
+ int flagcount = 0;
+
+ for (i = 0; i < IMAP_NFLAGS; i++)
+ flaglist[i] = 0;
+
+ if (!args[0] || !args[1]) {
+ fprintf(ci->tx,
+ "%s BAD invalid arguments specified to APPEND\r\n",
+ tag);
+ return 1;
+ }
+
+ /* find the mailbox to place the message */
+ if (db_findmailbox(args[0], ud->userid, &mboxid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error");
+ return -1;
+ }
+
+ if (mboxid == 0) {
+ fprintf(ci->tx,
+ "%s NO [TRYCREATE] could not find specified mailbox\r\n",
+ tag);
+ return 1;
+ }
+
+ trace(TRACE_DEBUG, "ic_append(): mailbox [%s] found, id: %llu\n",
+ args[0], mboxid);
+ /* check if user has right to append to mailbox */
+ result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_INSERT);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to append to mailbox\r\n",
+ tag);
+ ud->state = IMAPCS_AUTHENTICATED;
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ return 1;
+ }
+
+
+ i = 1;
+
+ /* check if a flag list has been specified */
+ /* FIXME: We need to take of care of the Flags that are set here. They
+ should be set to the new message!
+ */
+ if (args[i][0] == '(') {
+ /* ok fetch the flags specified */
+ trace(TRACE_DEBUG, "ic_append(): flag list found:\n");
+
+ while (args[i] && args[i][0] != ')') {
+ trace(TRACE_DEBUG, "%s ", args[i]);
+ for (j = 0; j < IMAP_NFLAGS; j++) {
+ if (strcasecmp
+ (args[i],
+ imap_flag_desc_escaped[j]) == 0) {
+ flaglist[j] = 1;
+ flagcount++;
+ break;
+ }
+ }
+ i++;
+ }
+
+ i++;
+ trace(TRACE_DEBUG, ")\n");
+ }
+
+ if (!args[i]) {
+ trace(TRACE_INFO,
+ "ic_append(): unexpected end of arguments\n");
+ fprintf(ci->tx,
+ "%s BAD invalid arguments specified to APPEND\r\n",
+ tag);
+ return 1;
+ }
+
+
+ for (j = 0; j < IMAP_NFLAGS; j++)
+ if (flaglist[j] == 1)
+ trace(TRACE_DEBUG, "%s,%s: %s set",
+ __FILE__, __FUNCTION__, imap_flag_desc[j]);
+
/** check ACL's for STORE */
- if (flaglist[IMAP_STORE_FLAG_SEEN] == 1) {
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_SEEN);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1; /* fatal */
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no right to store \\SEEN flag\r\n",
- tag);
- return 1;
- }
- }
- if (flaglist[IMAP_STORE_FLAG_DELETED] == 1) {
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_DELETE);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1; /* fatal */
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no right to store \\DELETED flag\r\n",
- tag);
- return 1;
- }
- }
- if (flaglist[IMAP_STORE_FLAG_ANSWERED] == 1 ||
- flaglist[IMAP_STORE_FLAG_FLAGGED] == 1 ||
- flaglist[IMAP_STORE_FLAG_DRAFT] == 1 ||
- flaglist[IMAP_STORE_FLAG_RECENT] == 1) {
- result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_WRITE);
- if (result < 0) {
- fprintf(ci->tx, "*BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no right to store flags\r\n", tag);
- return 1;
- }
- }
-
-
- /* there could be a literal date here, check if the next argument exists
- * if so, assume this is the literal date.
- * FIXME: this internal date has to be used in the append command to set
- * the internal date of the message (if it should be something else than
- * CURRENT_TIMESTAMP.
- */
- if (args[i+1])
- {
- struct tm tm;
-
- if (strptime(args[i], "%d-%b-%Y %T", &tm) != NULL)
- strftime(sqldate,
- sizeof(sqldate), "%Y-%m-%d %H:%M:%S", &tm);
- else
- sqldate[0] = '\0';
- /* internal date specified */
-
- i++;
- trace(TRACE_DEBUG, "ic_append(): internal date [%s] found, next arg [%s]\n",
- sqldate, args[i]);
- }
- else {
- sqldate[0] = '\0';
- }
-
- /* ok literal msg should be in args[i] */
- /* insert this msg */
-
- result = db_imap_append_msg(args[i], strlen(args[i]), mboxid, ud->userid,
- sqldate, &msg_idnr);
- switch (result)
- {
- case -1:
- trace(TRACE_ERROR,"ic_append(): error appending msg\n");
- fprintf(ci->tx,"* BYE internal dbase error storing message\r\n");
- break;
-
- case 1:
- trace(TRACE_ERROR,"ic_append(): faulty msg\n");
- fprintf(ci->tx,"%s NO invalid message specified\r\n", tag);
- break;
-
- case 2:
- trace(TRACE_INFO,"ic_append(): quotum would exceed\n");
- fprintf(ci->tx,"%s NO not enough quotum left\r\n", tag);
- break;
-
- case 0:
- fprintf(ci->tx,"%s OK APPEND completed\r\n",tag);
- break;
- }
-
- if (result == 0 && flagcount > 0) {
- if(db_set_msgflag(msg_idnr, mboxid, flaglist, IMAPFA_ADD) < 0) {
- trace(TRACE_ERROR, "%s,%s: error setting flags for message "
- "[%llu]", __FILE__, __FUNCTION__, msg_idnr);
- return -1;
- }
- }
-
- return result;
+ if (flaglist[IMAP_STORE_FLAG_SEEN] == 1) {
+ result = acl_has_right(ud->userid, mboxid, ACL_RIGHT_SEEN);
+ if (result < 0) {
+ fprintf(ci->tx,
+ "* BYE internal database error\r\n");
+ return -1; /* fatal */
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no right to store \\SEEN flag\r\n",
+ tag);
+ return 1;
+ }
+ }
+ if (flaglist[IMAP_STORE_FLAG_DELETED] == 1) {
+ result =
+ acl_has_right(ud->userid, mboxid, ACL_RIGHT_DELETE);
+ if (result < 0) {
+ fprintf(ci->tx,
+ "* BYE internal database error\r\n");
+ return -1; /* fatal */
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no right to store \\DELETED flag\r\n",
+ tag);
+ return 1;
+ }
+ }
+ if (flaglist[IMAP_STORE_FLAG_ANSWERED] == 1 ||
+ flaglist[IMAP_STORE_FLAG_FLAGGED] == 1 ||
+ flaglist[IMAP_STORE_FLAG_DRAFT] == 1 ||
+ flaglist[IMAP_STORE_FLAG_RECENT] == 1) {
+ result =
+ acl_has_right(ud->userid, mboxid, ACL_RIGHT_WRITE);
+ if (result < 0) {
+ fprintf(ci->tx,
+ "*BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no right to store flags\r\n", tag);
+ return 1;
+ }
+ }
+
+
+ /* there could be a literal date here, check if the next argument exists
+ * if so, assume this is the literal date.
+ * FIXME: this internal date has to be used in the append command to set
+ * the internal date of the message (if it should be something else than
+ * CURRENT_TIMESTAMP.
+ */
+ if (args[i + 1]) {
+ struct tm tm;
+
+ if (strptime(args[i], "%d-%b-%Y %T", &tm) != NULL)
+ strftime(sqldate,
+ sizeof(sqldate), "%Y-%m-%d %H:%M:%S",
+ &tm);
+ else
+ sqldate[0] = '\0';
+ /* internal date specified */
+
+ i++;
+ trace(TRACE_DEBUG,
+ "ic_append(): internal date [%s] found, next arg [%s]\n",
+ sqldate, args[i]);
+ } else {
+ sqldate[0] = '\0';
+ }
+
+ /* ok literal msg should be in args[i] */
+ /* insert this msg */
+
+ result =
+ db_imap_append_msg(args[i], strlen(args[i]), mboxid,
+ ud->userid, sqldate, &msg_idnr);
+ switch (result) {
+ case -1:
+ trace(TRACE_ERROR, "ic_append(): error appending msg\n");
+ fprintf(ci->tx,
+ "* BYE internal dbase error storing message\r\n");
+ break;
+
+ case 1:
+ trace(TRACE_ERROR, "ic_append(): faulty msg\n");
+ fprintf(ci->tx, "%s NO invalid message specified\r\n",
+ tag);
+ break;
+
+ case 2:
+ trace(TRACE_INFO, "ic_append(): quotum would exceed\n");
+ fprintf(ci->tx, "%s NO not enough quotum left\r\n", tag);
+ break;
+
+ case 0:
+ fprintf(ci->tx, "%s OK APPEND completed\r\n", tag);
+ break;
+ }
+
+ if (result == 0 && flagcount > 0) {
+ if (db_set_msgflag(msg_idnr, mboxid, flaglist, IMAPFA_ADD)
+ < 0) {
+ trace(TRACE_ERROR,
+ "%s,%s: error setting flags for message "
+ "[%llu]", __FILE__, __FUNCTION__, msg_idnr);
+ return -1;
+ }
+ }
+
+ return result;
}
@@ -1695,27 +1766,29 @@ int _ic_append(char *tag, char **args, ClientInfo *ci)
* request a checkpoint for the selected mailbox
* (equivalent to NOOP)
*/
-int _ic_check(char *tag, char **args, ClientInfo *ci)
+int _ic_check(char *tag, char **args, ClientInfo * ci)
{
int result;
- imap_userdata_t *ud = (imap_userdata_t*) ci->userData;
-
- if (!check_state_and_args("CHECK", tag, args, 0, IMAPCS_SELECTED, ci))
-
- return 1; /* error, return */
-
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+
+ if (!check_state_and_args
+ ("CHECK", tag, args, 0, IMAPCS_SELECTED, ci))
+
+ return 1; /* error, return */
+
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
if (result < 0) {
fprintf(ci->tx, "* BYE Internal database error\r\n");
return -1;
}
if (result == 0) {
- fprintf(ci->tx,"%s NO no permission to do check on "
+ fprintf(ci->tx, "%s NO no permission to do check on "
"mailbox\r\n", tag);
return 1;
}
-
- fprintf(ci->tx,"%s OK CHECK completed\r\n",tag);
+
+ fprintf(ci->tx, "%s OK CHECK completed\r\n", tag);
return 0;
}
@@ -1725,36 +1798,39 @@ int _ic_check(char *tag, char **args, ClientInfo *ci)
*
* expunge deleted messages from selected mailbox & return to AUTH state
* do not show expunge-output
- */
-int _ic_close(char *tag, char **args, ClientInfo *ci)
+ */
+int _ic_close(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- int result;
-
- if (!check_state_and_args("CLOSE", tag, args, 0, IMAPCS_SELECTED, ci))
- return 1; /* error, return */
-
- /* check if the user has to right to expunge all messages from the
- mailbox. */
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_DELETE);
- if (result < 0) {
- fprintf(ci->tx, "* BYE Internal database error\r\n");
- return -1;
- }
- /* only perform the expunge if the user has the right to do it */
- if (result == 1)
- if (ud->mailbox.permission == IMAPPERM_READWRITE)
- db_expunge(ud->mailbox.uid, ud->userid, NULL, NULL);
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ int result;
+
+ if (!check_state_and_args
+ ("CLOSE", tag, args, 0, IMAPCS_SELECTED, ci))
+ return 1; /* error, return */
+
+ /* check if the user has to right to expunge all messages from the
+ mailbox. */
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_DELETE);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE Internal database error\r\n");
+ return -1;
+ }
+ /* only perform the expunge if the user has the right to do it */
+ if (result == 1)
+ if (ud->mailbox.permission == IMAPPERM_READWRITE)
+ db_expunge(ud->mailbox.uid, ud->userid, NULL,
+ NULL);
+
-
- /* ok, update state (always go to IMAPCS_AUTHENTICATED)*/
- ud->state = IMAPCS_AUTHENTICATED;
+ /* ok, update state (always go to IMAPCS_AUTHENTICATED) */
+ ud->state = IMAPCS_AUTHENTICATED;
- my_free(ud->mailbox.seq_list);
- memset(&ud->mailbox, 0, sizeof(ud->mailbox));
+ my_free(ud->mailbox.seq_list);
+ memset(&ud->mailbox, 0, sizeof(ud->mailbox));
- fprintf(ci->tx,"%s OK CLOSE completed\r\n",tag);
- return 0;
+ fprintf(ci->tx, "%s OK CLOSE completed\r\n", tag);
+ return 0;
}
@@ -1764,80 +1840,81 @@ int _ic_close(char *tag, char **args, ClientInfo *ci)
* expunge deleted messages from selected mailbox
* show expunge output per message
*/
-int _ic_expunge(char *tag, char **args, ClientInfo *ci)
+int _ic_expunge(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- mailbox_t newmailbox;
- u64_t *msgids;
- u64_t nmsgs, i;
- unsigned idx;
- int result;
-
- if (!check_state_and_args("EXPUNGE", tag, args, 0, IMAPCS_SELECTED, ci))
- return 1; /* error, return */
-
- if (ud->mailbox.permission != IMAPPERM_READWRITE)
- {
- fprintf(ci->tx,"%s NO you do not have write permission on this folder\r\n",tag);
- return 1;
- }
-
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_DELETE);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO you do not have delete rights on this "
- "mailbox\r\n", tag);
- return -1;
- }
-
- /* delete messages */
- result = db_expunge(ud->mailbox.uid, ud->userid, &msgids,&nmsgs);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE dbase/memory error\r\n");
- return -1;
- }
-
- /* show expunge info */
- for (i=0; i<nmsgs; i++)
- {
- /* find the message sequence number */
- binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
- msgids[i], &idx);
-
- fprintf(ci->tx,"* %u EXPUNGE\r\n",idx+1); /* add one: IMAP MSN starts at 1 not zero */
- }
- my_free(msgids);
- msgids = NULL;
-
- /* update mailbox info */
-
- memset(&newmailbox, 0, sizeof(newmailbox));
- newmailbox.uid = ud->mailbox.uid;
-
- result = db_getmailbox(&newmailbox);
-
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- my_free(newmailbox.seq_list);
- return -1; /* fatal */
- }
-
- if (newmailbox.exists != ud->mailbox.exists)
- fprintf(ci->tx,"* %u EXISTS\r\n", newmailbox.exists);
-
- if (newmailbox.recent != ud->mailbox.recent)
- fprintf(ci->tx, "* %u RECENT\r\n", newmailbox.recent);
-
- my_free(ud->mailbox.seq_list);
- memcpy(&ud->mailbox, &newmailbox, sizeof(newmailbox));
-
- fprintf(ci->tx,"%s OK EXPUNGE completed\r\n",tag);
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ mailbox_t newmailbox;
+ u64_t *msgids;
+ u64_t nmsgs, i;
+ unsigned idx;
+ int result;
+
+ if (!check_state_and_args
+ ("EXPUNGE", tag, args, 0, IMAPCS_SELECTED, ci))
+ return 1; /* error, return */
+
+ if (ud->mailbox.permission != IMAPPERM_READWRITE) {
+ fprintf(ci->tx,
+ "%s NO you do not have write permission on this folder\r\n",
+ tag);
+ return 1;
+ }
+
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_DELETE);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO you do not have delete rights on this "
+ "mailbox\r\n", tag);
+ return -1;
+ }
+
+ /* delete messages */
+ result = db_expunge(ud->mailbox.uid, ud->userid, &msgids, &nmsgs);
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE dbase/memory error\r\n");
+ return -1;
+ }
+
+ /* show expunge info */
+ for (i = 0; i < nmsgs; i++) {
+ /* find the message sequence number */
+ binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
+ msgids[i], &idx);
+
+ fprintf(ci->tx, "* %u EXPUNGE\r\n", idx + 1); /* add one: IMAP MSN starts at 1 not zero */
+ }
+ my_free(msgids);
+ msgids = NULL;
+
+ /* update mailbox info */
+
+ memset(&newmailbox, 0, sizeof(newmailbox));
+ newmailbox.uid = ud->mailbox.uid;
+
+ result = db_getmailbox(&newmailbox);
+
+ if (result == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ my_free(newmailbox.seq_list);
+ return -1; /* fatal */
+ }
+
+ if (newmailbox.exists != ud->mailbox.exists)
+ fprintf(ci->tx, "* %u EXISTS\r\n", newmailbox.exists);
+
+ if (newmailbox.recent != ud->mailbox.recent)
+ fprintf(ci->tx, "* %u RECENT\r\n", newmailbox.recent);
+
+ my_free(ud->mailbox.seq_list);
+ memcpy(&ud->mailbox, &newmailbox, sizeof(newmailbox));
+
+ fprintf(ci->tx, "%s OK EXPUNGE completed\r\n", tag);
+ return 0;
}
@@ -1847,87 +1924,90 @@ int _ic_expunge(char *tag, char **args, ClientInfo *ci)
* search the selected mailbox for messages
*
*/
-int _ic_search(char *tag, char **args, ClientInfo *ci)
+int _ic_search(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- unsigned *result_set;
- unsigned i;
- int result=0,only_ascii=0,idx=0;
- search_key_t sk;
-
- if (ud->state != IMAPCS_SELECTED)
- {
- fprintf(ci->tx,"%s BAD SEARCH command received in invalid state\r\n", tag);
- return 1;
- }
-
- memset(&sk, 0, sizeof(sk));
- list_init(&sk.sub_search);
-
- if (!args[0])
- {
- fprintf(ci->tx,"%s BAD invalid arguments to SEARCH\r\n",tag);
- return 1;
- }
-
- if (strcasecmp(args[0], "charset") == 0)
- {
- /* charset specified */
- if (!args[1])
- {
- fprintf(ci->tx,"%s BAD invalid argument list\r\n",tag);
- return 1;
- }
-
- if (strcasecmp(args[1], "us-ascii") != 0)
- {
- fprintf(ci->tx,"%s NO specified charset is not supported\r\n",tag);
- return 0;
- }
-
- only_ascii = 1;
- idx = 2;
- }
-
- /* parse the search keys */
- while ( args[idx] && (result = build_imap_search(args, &sk.sub_search, &idx)) >= 0);
-
- if (result == -2)
- {
- free_searchlist(&sk.sub_search);
- fprintf(ci->tx, "* BYE server ran out of memory\r\n");
- return -1;
- }
-
- if (result == -1)
- {
- free_searchlist(&sk.sub_search);
- fprintf(ci->tx, "%s BAD syntax error in search keys\r\n",tag);
- return 1;
- }
-
- /* check if user has the right to search in this mailbox */
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
- if (result < 0) {
- fprintf(ci->tx,"* BYE internal database error\r\n");
- free_searchlist(&sk.sub_search);
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx,"%s NO no permission to search mailbox\r\n", tag);
- free_searchlist(&sk.sub_search);
- return 1;
- }
-
- /* make it a top-level search key */
- sk.type = IST_SUBSEARCH_AND;
-
- i = 0;
- do
- {
- /* update mailbox info */
- /* commented out: the search should be on the mailbox
- as the client thinks it is (!) */
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ unsigned *result_set;
+ unsigned i;
+ int result = 0, only_ascii = 0, idx = 0;
+ search_key_t sk;
+
+ if (ud->state != IMAPCS_SELECTED) {
+ fprintf(ci->tx,
+ "%s BAD SEARCH command received in invalid state\r\n",
+ tag);
+ return 1;
+ }
+
+ memset(&sk, 0, sizeof(sk));
+ list_init(&sk.sub_search);
+
+ if (!args[0]) {
+ fprintf(ci->tx, "%s BAD invalid arguments to SEARCH\r\n",
+ tag);
+ return 1;
+ }
+
+ if (strcasecmp(args[0], "charset") == 0) {
+ /* charset specified */
+ if (!args[1]) {
+ fprintf(ci->tx, "%s BAD invalid argument list\r\n",
+ tag);
+ return 1;
+ }
+
+ if (strcasecmp(args[1], "us-ascii") != 0) {
+ fprintf(ci->tx,
+ "%s NO specified charset is not supported\r\n",
+ tag);
+ return 0;
+ }
+
+ only_ascii = 1;
+ idx = 2;
+ }
+
+ /* parse the search keys */
+ while (args[idx]
+ && (result =
+ build_imap_search(args, &sk.sub_search, &idx)) >= 0);
+
+ if (result == -2) {
+ free_searchlist(&sk.sub_search);
+ fprintf(ci->tx, "* BYE server ran out of memory\r\n");
+ return -1;
+ }
+
+ if (result == -1) {
+ free_searchlist(&sk.sub_search);
+ fprintf(ci->tx, "%s BAD syntax error in search keys\r\n",
+ tag);
+ return 1;
+ }
+
+ /* check if user has the right to search in this mailbox */
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ free_searchlist(&sk.sub_search);
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to search mailbox\r\n", tag);
+ free_searchlist(&sk.sub_search);
+ return 1;
+ }
+
+ /* make it a top-level search key */
+ sk.type = IST_SUBSEARCH_AND;
+
+ i = 0;
+ do {
+ /* update mailbox info */
+ /* commented out: the search should be on the mailbox
+ as the client thinks it is (!) */
/* result = db_getmailbox(&ud->mailbox);
if (result == -1)
@@ -1937,68 +2017,72 @@ fprintf(ci->tx,"* BYE internal dbase error\r\n");
return -1;
}
*/
-
- /* allocate memory for result set */
- result_set = (unsigned*)my_malloc(sizeof(unsigned) * ud->mailbox.exists);
- if (!result_set)
- {
- free_searchlist(&sk.sub_search);
- fprintf(ci->tx,"* BYE server ran out of memory\r\n");
- return -1;
- }
-
- /* init set: select every message, this way the first search key
- * will be copied entirely (it is ANDed with this initial set), as it should
- */
-
- for (i=0; i<ud->mailbox.exists; i++)
- result_set[i] = 1;
-
- /* now perform the search operations */
- result = perform_imap_search(result_set, ud->mailbox.exists, &sk, &ud->mailbox);
-
- if (result < 0)
- {
- free_searchlist(&sk.sub_search);
- my_free(result_set);
- fprintf(ci->tx,"%s", (result == -1) ?
- "* BYE internal dbase error\r\n" :
- "* BYE server ran out of memory\r\n");
-
- trace(TRACE_ERROR, "ic_search(): fatal error [%d] from perform_imap_search()\n",result);
- return -1;
- }
- if (result == 1)
- {
- my_free(result_set);
- result_set = NULL;
- }
+ /* allocate memory for result set */
+ result_set =
+ (unsigned *) my_malloc(sizeof(unsigned) *
+ ud->mailbox.exists);
+ if (!result_set) {
+ free_searchlist(&sk.sub_search);
+ fprintf(ci->tx,
+ "* BYE server ran out of memory\r\n");
+ return -1;
+ }
- } while (result == 1 && ++i < MAX_RETRIES) ;
+ /* init set: select every message, this way the first search key
+ * will be copied entirely (it is ANDed with this initial set), as it should
+ */
- free_searchlist(&sk.sub_search);
+ for (i = 0; i < ud->mailbox.exists; i++)
+ result_set[i] = 1;
- if (result == 1)
- {
- fprintf(ci->tx,"* BYE error synchronizing dbase\r\n");
- return -1;
- }
-
- /* ok, display results */
- fprintf(ci->tx, "* SEARCH");
+ /* now perform the search operations */
+ result =
+ perform_imap_search(result_set, ud->mailbox.exists,
+ &sk, &ud->mailbox);
- for (i=0; i<ud->mailbox.exists; i++)
- {
- if (result_set[i])
- fprintf(ci->tx, " %llu", imapcommands_use_uid ? ud->mailbox.seq_list[i] : (u64_t)(i+1));
- }
+ if (result < 0) {
+ free_searchlist(&sk.sub_search);
+ my_free(result_set);
+ fprintf(ci->tx, "%s", (result == -1) ?
+ "* BYE internal dbase error\r\n" :
+ "* BYE server ran out of memory\r\n");
- fprintf(ci->tx,"\r\n");
- my_free(result_set);
-
- fprintf(ci->tx,"%s OK SEARCH completed\r\n",tag);
- return 0;
+ trace(TRACE_ERROR,
+ "ic_search(): fatal error [%d] from perform_imap_search()\n",
+ result);
+ return -1;
+ }
+
+ if (result == 1) {
+ my_free(result_set);
+ result_set = NULL;
+ }
+
+ } while (result == 1 && ++i < MAX_RETRIES);
+
+ free_searchlist(&sk.sub_search);
+
+ if (result == 1) {
+ fprintf(ci->tx, "* BYE error synchronizing dbase\r\n");
+ return -1;
+ }
+
+ /* ok, display results */
+ fprintf(ci->tx, "* SEARCH");
+
+ for (i = 0; i < ud->mailbox.exists; i++) {
+ if (result_set[i])
+ fprintf(ci->tx, " %llu",
+ imapcommands_use_uid ? ud->mailbox.
+ seq_list[i] : (u64_t) (i + 1));
+ }
+
+ fprintf(ci->tx, "\r\n");
+ my_free(result_set);
+
+ fprintf(ci->tx, "%s OK SEARCH completed\r\n", tag);
+ return 0;
}
@@ -2007,1204 +2091,1705 @@ fprintf(ci->tx,"* BYE internal dbase error\r\n");
*
* fetch message(s) from the selected mailbox
*/
-int _ic_fetch(char *tag, char **args, ClientInfo *ci)
+int _ic_fetch(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t i,fetch_start,fetch_end;
- unsigned fn;
- int result,setseen,idx,j,k;
- int only_main_header_parsing = 1, insert_rfcsize;
- int isfirstout, isfirstfetchout, uid_will_be_fetched;
- int partspeclen,only_text_from_msgpart = 0;
- int bad_response_send = 0;
- u64_t actual_cnt;
- fetch_items_t *fi,fetchitem;
- mime_message_t *msgpart;
- char date[IMAP_INTERNALDATE_LEN],*endptr;
- u64_t thisnum;
- u64_t tmpdumpsize, rfcsize=0;
- long long cnt;
- int msgflags[IMAP_NFLAGS];
- struct list fetch_list;
- mime_message_t headermsg; /* for main-header & rfcsize parsing */
- struct element *curr;
- int setSeenSet[IMAP_NFLAGS] = { 1,0,0,0,0,0 };
- msginfo_t *msginfo;
- u64_t lo,hi;
- unsigned nmatching;
- int no_parsing_at_all = 1, getrfcsize = 0, getinternaldate = 0, getflags = 0;
- char *lastchar = NULL;
- memset(&fetch_list, 0, sizeof(fetch_list));
- memset(&headermsg, 0, sizeof(headermsg));
-
- if (ud->state != IMAPCS_SELECTED)
- {
- fprintf(ci->tx,"%s BAD FETCH command received in invalid state\r\n", tag);
- return 1;
- }
-
- if (!args[0] || !args[1])
- {
- fprintf(ci->tx,"%s BAD missing argument(s) to FETCH\r\n", tag);
- return 1;
- }
-
- /* check if the user has the right to fetch messages in this mailbox */
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to fetch from mailbox\r\n", tag);
- return 1;
- }
-
- /* fetch fetch items */
- list_init(&fetch_list);
- idx = 1;
- uid_will_be_fetched = 0;
- do
- {
- idx = next_fetch_item(args, idx, &fetchitem);
- if (idx == -2)
- {
- list_freelist(&fetch_list.start);
- fprintf(ci->tx,"%s BAD invalid argument list to fetch\r\n", tag);
- return 1;
- }
-
- if (idx > 0 && !list_nodeadd(&fetch_list, &fetchitem, sizeof(fetchitem)))
- {
- list_freelist(&fetch_list.start);
- fprintf(ci->tx,"* BYE out of memory\r\n");
- return 1;
- }
-
- if (fetchitem.msgparse_needed)
- {
- no_parsing_at_all = 0;
- }
- else if (no_parsing_at_all)
- {
- if (fetchitem.getFlags) getflags = 1;
- if (fetchitem.getSize) getrfcsize = 1;
- if (fetchitem.getInternalDate) getinternaldate = 1;
- /* the msgUID will be retrieved anyway so if it is requested, it will be fetched */
- }
-
- if (fetchitem.msgparse_needed && only_main_header_parsing)
- {
- /* check to see wether all the information can be retrieved from the
- * main message header (not the entire message has to be parsed then)
- *
- * this is the case when:
- * FETCH RFC822.HEADER
- * BODY[HEADER]
- * BODY[HEADER.FIELDS ]
- * BODY[HEADER.FIELDS.NOT ]
- * BODY.PEEK[HEADER]
- * BODY.PEEK[HEADER.FIELDS ]
- * BODY.PEEK[HEADER.FIELDS.NOT ]
- *
- */
-
- if (! (fetchitem.getRFC822Header ||
- ((fetchitem.bodyfetch.itemtype == BFIT_HEADER ||
- fetchitem.bodyfetch.itemtype == BFIT_HEADER_FIELDS ||
- fetchitem.bodyfetch.itemtype == BFIT_HEADER_FIELDS_NOT)
- && fetchitem.bodyfetch.partspec[0] == 0)
- )
- )
- {
- only_main_header_parsing = 0;
- }
- }
-
- if (fetchitem.getUID)
- uid_will_be_fetched = 1;
-
- } while (idx > 0);
-
- if (!uid_will_be_fetched && imapcommands_use_uid)
- {
- /* make sure UID will be on the fetch-item list */
- memset(&fetchitem, 0, sizeof(fetchitem));
- fetchitem.getUID = 1;
- fetchitem.bodyfetch.itemtype = -1;
-
- if (!list_nodeadd(&fetch_list, &fetchitem, sizeof(fetchitem)))
- {
- list_freelist(&fetch_list.start);
- fprintf(ci->tx,"* BYE out of memory\r\n");
- return -1;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t i, fetch_start, fetch_end;
+ unsigned fn;
+ int result, setseen, idx, j, k;
+ int only_main_header_parsing = 1, insert_rfcsize;
+ int isfirstout, isfirstfetchout, uid_will_be_fetched;
+ int partspeclen, only_text_from_msgpart = 0;
+ int bad_response_send = 0;
+ u64_t actual_cnt;
+ fetch_items_t *fi, fetchitem;
+ mime_message_t *msgpart;
+ char date[IMAP_INTERNALDATE_LEN], *endptr;
+ u64_t thisnum;
+ u64_t tmpdumpsize, rfcsize = 0;
+ long long cnt;
+ int msgflags[IMAP_NFLAGS];
+ struct list fetch_list;
+ mime_message_t headermsg; /* for main-header & rfcsize parsing */
+ struct element *curr;
+ int setSeenSet[IMAP_NFLAGS] = { 1, 0, 0, 0, 0, 0 };
+ msginfo_t *msginfo;
+ u64_t lo, hi;
+ unsigned nmatching;
+ int no_parsing_at_all = 1, getrfcsize = 0, getinternaldate =
+ 0, getflags = 0;
+ char *lastchar = NULL;
+ memset(&fetch_list, 0, sizeof(fetch_list));
+ memset(&headermsg, 0, sizeof(headermsg));
+
+ if (ud->state != IMAPCS_SELECTED) {
+ fprintf(ci->tx,
+ "%s BAD FETCH command received in invalid state\r\n",
+ tag);
+ return 1;
}
- }
-
- fetch_list.start = dbmail_list_reverse(fetch_list.start);
-
- /* now fetch results for each msg */
- endptr = args[0];
- while (*endptr)
- {
- if (endptr != args[0])
- endptr++; /* skip delimiter */
-
- fetch_start = strtoull(endptr, &endptr, 10);
-
- if (fetch_start == 0 || fetch_start >
- (imapcommands_use_uid ? (ud->mailbox.msguidnext-1) : ud->mailbox.exists))
- {
- if (imapcommands_use_uid)
- fprintf(ci->tx,"%s OK FETCH completed\r\n",tag);
- else
- fprintf(ci->tx, "%s BAD invalid message range specified\r\n",tag);
-
- list_freelist(&fetch_list.start);
- return !imapcommands_use_uid;
- }
-
- switch (*endptr)
- {
- case ':':
- fetch_end = strtoull(++endptr, &lastchar, 10);
- endptr = lastchar;
-
- if (*endptr == '*')
- {
- fetch_end = (imapcommands_use_uid ?
- (ud->mailbox.msguidnext-1) : ud->mailbox.exists);
- endptr++;
- break;
- }
-
- if (fetch_end == 0 || fetch_end >
- (imapcommands_use_uid ? (ud->mailbox.msguidnext-1) : ud->mailbox.exists))
- {
- if (!imapcommands_use_uid)
- {
- fprintf(ci->tx, "%s BAD invalid message range specified\r\n",tag);
-
- list_freelist(&fetch_list.start);
- return 1;
- }
- }
- if (fetch_end < fetch_start)
- {
- i = fetch_start;
- fetch_start = fetch_end;
- fetch_end = i;
- }
- break;
+ if (!args[0] || !args[1]) {
+ fprintf(ci->tx, "%s BAD missing argument(s) to FETCH\r\n",
+ tag);
+ return 1;
+ }
- case ',':
- case 0:
- fetch_end = fetch_start;
- break;
-
- default:
- fprintf(ci->tx, "%s BAD invalid character in message range\r\n",tag);
- list_freelist(&fetch_list.start);
- return 1;
- }
-
- if (!imapcommands_use_uid)
- {
- fetch_start--;
- fetch_end--;
- }
-
- if (no_parsing_at_all)
- {
- trace(TRACE_DEBUG,"ic_fetch(): no parsing at all\n");
-
- /* all the info we need can be retrieved by a single
- * call to db_get_msginfo_range()
- */
- if (!imapcommands_use_uid)
- {
- /* find the msgUID's to use */
- lo = ud->mailbox.seq_list[fetch_start];
- hi = ud->mailbox.seq_list[fetch_end];
-
- }
- else
- {
- lo = fetch_start;
- hi = fetch_end;
- }
-
- /* (always retrieve uid) */
- result = db_get_msginfo_range(lo, hi, ud->mailbox.uid,
- getflags, getinternaldate, getrfcsize, 1,
- &msginfo, &nmatching);
-
- if (result == -1)
- {
- list_freelist(&fetch_list.start);
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
-
- if (result == -2)
- {
- list_freelist(&fetch_list.start);
- fprintf(ci->tx,"* BYE out of memory\r\n");
- return -1;
- }
-
- for (i=0; i<nmatching; i++)
- {
- if (getrfcsize && msginfo[i].rfcsize == 0)
- {
- /* parse the message to calc the size */
- result = db_fetch_headers(msginfo[i].uid, &headermsg);
- if (result == -2)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- my_free(msginfo);
- return -1;
- }
- if (result == -3)
- {
- fprintf(ci->tx,"\r\n* BYE out of memory\r\n");
- list_freelist(&fetch_list.start);
- my_free(msginfo);
- return -1;
- }
-
- msginfo[i].rfcsize = (headermsg.rfcheadersize +
- headermsg.bodysize +
- headermsg.bodylines);
-
- db_set_rfcsize(msginfo[i].rfcsize, msginfo[i].uid, ud->mailbox.uid);
- db_free_msg(&headermsg);
+ /* check if the user has the right to fetch messages in this mailbox */
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1;
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to fetch from mailbox\r\n",
+ tag);
+ return 1;
+ }
+
+ /* fetch fetch items */
+ list_init(&fetch_list);
+ idx = 1;
+ uid_will_be_fetched = 0;
+ do {
+ idx = next_fetch_item(args, idx, &fetchitem);
+ if (idx == -2) {
+ list_freelist(&fetch_list.start);
+ fprintf(ci->tx,
+ "%s BAD invalid argument list to fetch\r\n",
+ tag);
+ return 1;
}
- if (binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
- msginfo[i].uid, &fn) == -1) {
- /* this is probably some sync error:
- * the msgUID belongs to this mailbox but was not found
- * when building the mailbox info
- * let's call it fatal and let the client re-connect :)
- */
- fprintf(ci->tx, "* BYE internal syncing error\r\n");
-
- list_freelist(&fetch_list.start);
- my_free(msginfo);
- return -1;
- }
-
- fprintf(ci->tx, "* %u FETCH (", (fn+1));
-
- curr = list_getstart(&fetch_list);
- isfirstfetchout = 1;
-
- while (curr)
- {
- trace(TRACE_DEBUG, "_ic_fetch(): no parsing, into fetch loop");
-
- fi = (fetch_items_t*)curr->data;
-
- if (fi->getInternalDate)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"INTERNALDATE \"%s\"",
- date_sql2imap(msginfo[i].internaldate));
- }
-
- if (fi->getUID)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"UID %llu", msginfo[i].uid);
- }
-
- if (fi->getSize)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"RFC822.SIZE %llu", msginfo[i].rfcsize);
- }
-
- if (fi->getFlags)
- {
- isfirstout = 1;
-
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx, "FLAGS (");
- for (j=0; j<IMAP_NFLAGS; j++)
- {
- if (msginfo[i].flags[j])
- {
- fprintf(ci->tx, "%s%s", isfirstout ? "" : " ",
- imap_flag_desc_escaped[j]);
- if (isfirstout) isfirstout = 0;
- }
- }
- fprintf(ci->tx, ")");
- }
-
- curr = curr->nextnode;
+ if (idx > 0
+ && !list_nodeadd(&fetch_list, &fetchitem,
+ sizeof(fetchitem))) {
+ list_freelist(&fetch_list.start);
+ fprintf(ci->tx, "* BYE out of memory\r\n");
+ return 1;
}
- fprintf(ci->tx, ")\r\n");
- }
-
- my_free(msginfo);
- }
-
- /* if there is no parsing at all, this loop is not needed */
- for (i=fetch_start; i<=fetch_end && !no_parsing_at_all; i++)
- {
- thisnum = (imapcommands_use_uid ? i : ud->mailbox.seq_list[i]);
- insert_rfcsize = 0;
-
- if (imapcommands_use_uid)
- {
- if (i > ud->mailbox.msguidnext-1)
- {
- /* passed the last one */
- fprintf(ci->tx,"%s OK FETCH completed\r\n",tag);
- list_freelist(&fetch_list.start);
- return 0;
+ if (fetchitem.msgparse_needed) {
+ no_parsing_at_all = 0;
+ } else if (no_parsing_at_all) {
+ if (fetchitem.getFlags)
+ getflags = 1;
+ if (fetchitem.getSize)
+ getrfcsize = 1;
+ if (fetchitem.getInternalDate)
+ getinternaldate = 1;
+ /* the msgUID will be retrieved anyway so if it is requested, it will be fetched */
}
- /* check if the message with this UID belongs to this mailbox */
- if (binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
- i, &fn) == -1) {
- continue;
- }
-
- fprintf(ci->tx,"* %u FETCH (", fn+1);
-
- }
- else
- fprintf(ci->tx,"* %llu FETCH (",i+1);
-
- trace(TRACE_DEBUG, "Fetching msgID %llu (fetch num %llu)", thisnum, i+1);
-
- curr = list_getstart(&fetch_list);
- setseen = 0;
- bad_response_send = 0;
-
- isfirstfetchout = 1;
-
- while (curr && !bad_response_send)
- {
- fi = (fetch_items_t*)curr->data;
- fflush(ci->tx);
-
- only_text_from_msgpart = 0;
-
- /* check RFC822.SIZE request */
- if (fi->getSize) {
- /* ok, try to fetch size from dbase */
- if(db_get_rfcsize(thisnum, ud->mailbox.uid,
- &rfcsize) == -1) {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- return -1;
- }
-
- if (rfcsize == 0) {
- /* field is empty in dbase, message needs
- to be parsed */
- fi->msgparse_needed = 1;
- only_main_header_parsing = 0;
- insert_rfcsize = 1;
- }
- }
-
-
- /* update cache */
- if (fi->msgparse_needed && thisnum != cached_msg.num)
- {
- if (only_main_header_parsing)
- {
- /* don't update cache if only the main header is needed
- * but do retrieve this main header
- */
-
- result = db_get_main_header(thisnum, &headermsg.rfcheader);
-
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
+ if (fetchitem.msgparse_needed && only_main_header_parsing) {
+ /* check to see wether all the information can be retrieved from the
+ * main message header (not the entire message has to be parsed then)
+ *
+ * this is the case when:
+ * FETCH RFC822.HEADER
+ * BODY[HEADER]
+ * BODY[HEADER.FIELDS ]
+ * BODY[HEADER.FIELDS.NOT ]
+ * BODY.PEEK[HEADER]
+ * BODY.PEEK[HEADER.FIELDS ]
+ * BODY.PEEK[HEADER.FIELDS.NOT ]
+ *
+ */
+
+ if (!(fetchitem.getRFC822Header ||
+ ((fetchitem.bodyfetch.itemtype == BFIT_HEADER
+ || fetchitem.bodyfetch.itemtype ==
+ BFIT_HEADER_FIELDS
+ || fetchitem.bodyfetch.itemtype ==
+ BFIT_HEADER_FIELDS_NOT)
+ && fetchitem.bodyfetch.partspec[0] == 0)
+ )
+ ) {
+ only_main_header_parsing = 0;
}
+ }
- if (result == -2)
- {
- fprintf(ci->tx,"\r\n* BYE out of memory\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
+ if (fetchitem.getUID)
+ uid_will_be_fetched = 1;
- }
- else
- {
- /* parse message structure */
- if (cached_msg.msg_parsed)
- db_free_msg(&cached_msg.msg);
-
- memset(&cached_msg.msg, 0, sizeof(cached_msg.msg));
-
- cached_msg.msg_parsed = 0;
- cached_msg.num = -1;
- cached_msg.file_dumped = 0;
- mreset(cached_msg.memdump);
-
- result = db_fetch_headers(thisnum, &cached_msg.msg);
- if (result == -2)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
- if (result == -3)
- {
- fprintf(ci->tx,"\r\n* BYE out of memory\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
+ } while (idx > 0);
- cached_msg.msg_parsed = 1;
- cached_msg.num = thisnum;
-
- rfcsize = (cached_msg.msg.rfcheadersize +
- cached_msg.msg.bodysize +
- cached_msg.msg.bodylines);
-
- if (insert_rfcsize)
- {
- /* insert the rfc822 size into the dbase */
- if (db_set_rfcsize(rfcsize, thisnum,ud->mailbox.uid) == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
-
- insert_rfcsize = 0;
- }
-
- }
- }
+ if (!uid_will_be_fetched && imapcommands_use_uid) {
+ /* make sure UID will be on the fetch-item list */
+ memset(&fetchitem, 0, sizeof(fetchitem));
+ fetchitem.getUID = 1;
+ fetchitem.bodyfetch.itemtype = -1;
- if (fi->getInternalDate)
- {
- result = db_get_msgdate(ud->mailbox.uid, thisnum, date);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
-
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"INTERNALDATE \"%s\"", date_sql2imap(date));
+ if (!list_nodeadd
+ (&fetch_list, &fetchitem, sizeof(fetchitem))) {
+ list_freelist(&fetch_list.start);
+ fprintf(ci->tx, "* BYE out of memory\r\n");
+ return -1;
}
+ }
- if (fi->getUID)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
+ fetch_list.start = dbmail_list_reverse(fetch_list.start);
- fprintf(ci->tx,"UID %llu",thisnum);
- }
+ /* now fetch results for each msg */
+ endptr = args[0];
+ while (*endptr) {
+ if (endptr != args[0])
+ endptr++; /* skip delimiter */
- if (fi->getMIME_IMB)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"BODYSTRUCTURE ");
- result = retrieve_structure(ci->tx, &cached_msg.msg, 1);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE error fetching body structure\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
- }
+ fetch_start = strtoull(endptr, &endptr, 10);
- if (fi->getMIME_IMB_noextension)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"BODY ");
- result = retrieve_structure(ci->tx, &cached_msg.msg, 0);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE error fetching body\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
- }
+ if (fetch_start == 0 || fetch_start >
+ (imapcommands_use_uid ? (ud->mailbox.msguidnext - 1) :
+ ud->mailbox.exists)) {
+ if (imapcommands_use_uid)
+ fprintf(ci->tx,
+ "%s OK FETCH completed\r\n", tag);
+ else
+ fprintf(ci->tx,
+ "%s BAD invalid message range specified\r\n",
+ tag);
- if (fi->getEnvelope)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"ENVELOPE ");
- result = retrieve_envelope(ci->tx, &cached_msg.msg.rfcheader);
-
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE error fetching envelope structure\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
+ list_freelist(&fetch_list.start);
+ return !imapcommands_use_uid;
}
- if (fi->getRFC822 || fi->getRFC822Peek)
- {
- if (cached_msg.file_dumped == 0 || cached_msg.num != thisnum)
- {
- mreset(cached_msg.memdump);
-
- cached_msg.dumpsize =
- rfcheader_dump(cached_msg.memdump, &cached_msg.msg.rfcheader, args, 0, 0);
-
- cached_msg.dumpsize +=
- db_dump_range(cached_msg.memdump, cached_msg.msg.bodystart,
- cached_msg.msg.bodyend, thisnum);
-
- cached_msg.file_dumped = 1;
-
- if (cached_msg.num != thisnum)
- {
- /* if there is a parsed msg in the cache it will be invalid now */
- if (cached_msg.msg_parsed)
- {
- cached_msg.msg_parsed = 0;
- db_free_msg(&cached_msg.msg);
- }
- cached_msg.num = thisnum;
+ switch (*endptr) {
+ case ':':
+ fetch_end = strtoull(++endptr, &lastchar, 10);
+ endptr = lastchar;
+
+ if (*endptr == '*') {
+ fetch_end = (imapcommands_use_uid ?
+ (ud->mailbox.msguidnext -
+ 1) : ud->mailbox.exists);
+ endptr++;
+ break;
}
- }
-
- mseek(cached_msg.memdump, 0, SEEK_SET);
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
+ if (fetch_end == 0 || fetch_end >
+ (imapcommands_use_uid
+ ? (ud->mailbox.msguidnext -
+ 1) : ud->mailbox.exists)) {
+ if (!imapcommands_use_uid) {
+ fprintf(ci->tx,
+ "%s BAD invalid message range specified\r\n",
+ tag);
+
+ list_freelist(&fetch_list.start);
+ return 1;
+ }
+ }
- fprintf(ci->tx, "RFC822 {%llu}\r\n", cached_msg.dumpsize);
- send_data(ci->tx, cached_msg.memdump, cached_msg.dumpsize);
+ if (fetch_end < fetch_start) {
+ i = fetch_start;
+ fetch_start = fetch_end;
+ fetch_end = i;
+ }
+ break;
- if (fi->getRFC822)
- setseen = 1;
+ case ',':
+ case 0:
+ fetch_end = fetch_start;
+ break;
+ default:
+ fprintf(ci->tx,
+ "%s BAD invalid character in message range\r\n",
+ tag);
+ list_freelist(&fetch_list.start);
+ return 1;
}
-
- if (fi->getSize)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"RFC822.SIZE %llu", rfcsize);
+
+ if (!imapcommands_use_uid) {
+ fetch_start--;
+ fetch_end--;
}
- if (fi->getBodyTotal || fi->getBodyTotalPeek)
- {
- if (cached_msg.file_dumped == 0 || cached_msg.num != thisnum)
- {
- cached_msg.dumpsize =
- rfcheader_dump(cached_msg.memdump, &cached_msg.msg.rfcheader, args, 0, 0);
-
- cached_msg.dumpsize +=
- db_dump_range(cached_msg.memdump, cached_msg.msg.bodystart,
- cached_msg.msg.bodyend, thisnum);
-
-
- if (cached_msg.num != thisnum)
- {
- /* if there is a parsed msg in the cache it will be invalid now */
- if (cached_msg.msg_parsed)
- {
- cached_msg.msg_parsed = 0;
- db_free_msg(&cached_msg.msg);
- }
- cached_msg.num = thisnum;
+ if (no_parsing_at_all) {
+ trace(TRACE_DEBUG,
+ "ic_fetch(): no parsing at all\n");
+
+ /* all the info we need can be retrieved by a single
+ * call to db_get_msginfo_range()
+ */
+ if (!imapcommands_use_uid) {
+ /* find the msgUID's to use */
+ lo = ud->mailbox.seq_list[fetch_start];
+ hi = ud->mailbox.seq_list[fetch_end];
+
+ } else {
+ lo = fetch_start;
+ hi = fetch_end;
}
- cached_msg.file_dumped = 1;
- }
-
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- if (fi->bodyfetch.octetstart == -1)
- {
- mseek(cached_msg.memdump, 0, SEEK_SET);
-
- fprintf(ci->tx, "BODY[] {%llu}\r\n", cached_msg.dumpsize);
- send_data(ci->tx, cached_msg.memdump, cached_msg.dumpsize);
- }
- else
- {
- mseek(cached_msg.memdump, fi->bodyfetch.octetstart, SEEK_SET);
-
- /** \todo this next statement is ugly because of the
- casts to 'long long'. Probably, octetcnt should be
- changed to be a u64_t instead of a long long, because
- it should never be negative anyway */
- actual_cnt =
- (fi->bodyfetch.octetcnt >
- (((long long) cached_msg.dumpsize) -
- fi->bodyfetch.octetstart)) ?
- (((long long)cached_msg.dumpsize)
- - fi->bodyfetch.octetstart) :
- fi->bodyfetch.octetcnt;
+ /* (always retrieve uid) */
+ result =
+ db_get_msginfo_range(lo, hi, ud->mailbox.uid,
+ getflags, getinternaldate,
+ getrfcsize, 1, &msginfo,
+ &nmatching);
+
+ if (result == -1) {
+ list_freelist(&fetch_list.start);
+ fprintf(ci->tx,
+ "* BYE internal dbase error\r\n");
+ return -1;
+ }
- fprintf(ci->tx, "BODY[]<%llu> {%llu}\r\n", fi->bodyfetch.octetstart,
- actual_cnt);
+ if (result == -2) {
+ list_freelist(&fetch_list.start);
+ fprintf(ci->tx, "* BYE out of memory\r\n");
+ return -1;
+ }
- send_data(ci->tx, cached_msg.memdump, actual_cnt);
+ for (i = 0; i < nmatching; i++) {
+ if (getrfcsize && msginfo[i].rfcsize == 0) {
+ /* parse the message to calc the size */
+ result =
+ db_fetch_headers(msginfo[i].
+ uid,
+ &headermsg);
+ if (result == -2) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist(&fetch_list.
+ start);
+ my_free(msginfo);
+ return -1;
+ }
+ if (result == -3) {
+ fprintf(ci->tx,
+ "\r\n* BYE out of memory\r\n");
+ list_freelist(&fetch_list.
+ start);
+ my_free(msginfo);
+ return -1;
+ }
+
+ msginfo[i].rfcsize =
+ (headermsg.rfcheadersize +
+ headermsg.bodysize +
+ headermsg.bodylines);
+
+ db_set_rfcsize(msginfo[i].rfcsize,
+ msginfo[i].uid,
+ ud->mailbox.uid);
+ db_free_msg(&headermsg);
+ }
- }
+ if (binary_search
+ (ud->mailbox.seq_list,
+ ud->mailbox.exists, msginfo[i].uid,
+ &fn) == -1) {
+ /* this is probably some sync error:
+ * the msgUID belongs to this mailbox but was not found
+ * when building the mailbox info
+ * let's call it fatal and let the client re-connect :)
+ */
+ fprintf(ci->tx,
+ "* BYE internal syncing error\r\n");
+
+ list_freelist(&fetch_list.start);
+ my_free(msginfo);
+ return -1;
+ }
- if (fi->getBodyTotal)
- setseen = 1;
+ fprintf(ci->tx, "* %u FETCH (", (fn + 1));
+
+ curr = list_getstart(&fetch_list);
+ isfirstfetchout = 1;
+
+ while (curr) {
+ trace(TRACE_DEBUG,
+ "_ic_fetch(): no parsing, into fetch loop");
+
+ fi = (fetch_items_t *) curr->data;
+
+ if (fi->getInternalDate) {
+ if (isfirstfetchout)
+ isfirstfetchout =
+ 0;
+ else
+ fprintf(ci->tx,
+ " ");
+
+ fprintf(ci->tx,
+ "INTERNALDATE \"%s\"",
+ date_sql2imap
+ (msginfo[i].
+ internaldate));
+ }
+
+ if (fi->getUID) {
+ if (isfirstfetchout)
+ isfirstfetchout =
+ 0;
+ else
+ fprintf(ci->tx,
+ " ");
+
+ fprintf(ci->tx, "UID %llu",
+ msginfo[i].uid);
+ }
+
+ if (fi->getSize) {
+ if (isfirstfetchout)
+ isfirstfetchout =
+ 0;
+ else
+ fprintf(ci->tx,
+ " ");
+
+ fprintf(ci->tx,
+ "RFC822.SIZE %llu",
+ msginfo[i].
+ rfcsize);
+ }
+
+ if (fi->getFlags) {
+ isfirstout = 1;
+
+ if (isfirstfetchout)
+ isfirstfetchout =
+ 0;
+ else
+ fprintf(ci->tx,
+ " ");
+
+ fprintf(ci->tx, "FLAGS (");
+ for (j = 0;
+ j < IMAP_NFLAGS;
+ j++) {
+ if (msginfo[i].
+ flags[j]) {
+ fprintf
+ (ci->
+ tx,
+ "%s%s",
+ isfirstout
+ ? "" :
+ " ",
+ imap_flag_desc_escaped
+ [j]);
+ if (isfirstout)
+ isfirstout
+ =
+ 0;
+ }
+ }
+ fprintf(ci->tx, ")");
+ }
+
+ curr = curr->nextnode;
+ }
- }
+ fprintf(ci->tx, ")\r\n");
+ }
- if (fi->getRFC822Header)
- {
- /* here: msgparse_needed == 1
- * if this msg is in cache, retrieve it from there
- * otherwise only_main_header_parsing == 1 so retrieve direct
- * from the dbase
- */
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- if (cached_msg.num == thisnum)
- {
- mrewind(cached_msg.tmpdump);
- tmpdumpsize =
- rfcheader_dump(cached_msg.tmpdump, &cached_msg.msg.rfcheader, args, 0, 0);
-
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
-
- fprintf(ci->tx, "RFC822.HEADER {%llu}\r\n",tmpdumpsize);
- send_data(ci->tx, cached_msg.tmpdump, tmpdumpsize);
- }
- else
- {
- /* remember only_main_header_parsing == 1 here ! */
-
- /* use cached_msg.tmpdump as temporary storage */
- mrewind(cached_msg.tmpdump);
- tmpdumpsize =
- rfcheader_dump(cached_msg.tmpdump, &headermsg.rfcheader, args, 0, 0);
-
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
-
- fprintf(ci->tx, "RFC822.HEADER {%llu}\r\n",tmpdumpsize);
- send_data(ci->tx, cached_msg.tmpdump, tmpdumpsize);
- }
+ my_free(msginfo);
}
-
- if (fi->getRFC822Text)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
- mrewind(cached_msg.tmpdump);
- tmpdumpsize = db_dump_range(cached_msg.tmpdump, cached_msg.msg.bodystart,
- cached_msg.msg.bodyend, thisnum);
+ /* if there is no parsing at all, this loop is not needed */
+ for (i = fetch_start; i <= fetch_end && !no_parsing_at_all;
+ i++) {
+ thisnum =
+ (imapcommands_use_uid ? i : ud->mailbox.
+ seq_list[i]);
+ insert_rfcsize = 0;
+
+ if (imapcommands_use_uid) {
+ if (i > ud->mailbox.msguidnext - 1) {
+ /* passed the last one */
+ fprintf(ci->tx,
+ "%s OK FETCH completed\r\n",
+ tag);
+ list_freelist(&fetch_list.start);
+ return 0;
+ }
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
+ /* check if the message with this UID belongs to this mailbox */
+ if (binary_search
+ (ud->mailbox.seq_list,
+ ud->mailbox.exists, i, &fn) == -1) {
+ continue;
+ }
- fprintf(ci->tx, "RFC822.TEXT {%llu}\r\n",tmpdumpsize);
- send_data(ci->tx, cached_msg.tmpdump, tmpdumpsize);
+ fprintf(ci->tx, "* %u FETCH (", fn + 1);
+
+ } else
+ fprintf(ci->tx, "* %llu FETCH (", i + 1);
+
+ trace(TRACE_DEBUG,
+ "Fetching msgID %llu (fetch num %llu)",
+ thisnum, i + 1);
+
+ curr = list_getstart(&fetch_list);
+ setseen = 0;
+ bad_response_send = 0;
+
+ isfirstfetchout = 1;
+
+ while (curr && !bad_response_send) {
+ fi = (fetch_items_t *) curr->data;
+ fflush(ci->tx);
+
+ only_text_from_msgpart = 0;
+
+ /* check RFC822.SIZE request */
+ if (fi->getSize) {
+ /* ok, try to fetch size from dbase */
+ if (db_get_rfcsize
+ (thisnum, ud->mailbox.uid,
+ &rfcsize) == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist(&fetch_list.
+ start);
+ return -1;
+ }
+
+ if (rfcsize == 0) {
+ /* field is empty in dbase, message needs
+ to be parsed */
+ fi->msgparse_needed = 1;
+ only_main_header_parsing =
+ 0;
+ insert_rfcsize = 1;
+ }
+ }
- setseen = 1;
- }
- if (fi->bodyfetch.itemtype >= 0)
- {
- mrewind(cached_msg.tmpdump);
-
- if (fi->bodyfetch.partspec[0])
- {
- if (fi->bodyfetch.partspec[0] == '0')
- {
- fprintf(ci->tx,"\r\n%s BAD protocol error\r\n",tag);
- trace(TRACE_DEBUG,"PROTOCOL ERROR");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return 1;
- }
+ /* update cache */
+ if (fi->msgparse_needed
+ && thisnum != cached_msg.num) {
+ if (only_main_header_parsing) {
+ /* don't update cache if only the main header is needed
+ * but do retrieve this main header
+ */
+
+ result =
+ db_get_main_header
+ (thisnum,
+ &headermsg.rfcheader);
+
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist
+ (&fetch_list.
+ start);
+ db_free_msg
+ (&headermsg);
+ return -1;
+ }
+
+ if (result == -2) {
+ fprintf(ci->tx,
+ "\r\n* BYE out of memory\r\n");
+ list_freelist
+ (&fetch_list.
+ start);
+ db_free_msg
+ (&headermsg);
+ return -1;
+ }
+
+ } else {
+ /* parse message structure */
+ if (cached_msg.msg_parsed)
+ db_free_msg
+ (&cached_msg.
+ msg);
+
+ memset(&cached_msg.msg, 0,
+ sizeof(cached_msg.
+ msg));
+
+ cached_msg.msg_parsed = 0;
+ cached_msg.num = -1;
+ cached_msg.file_dumped = 0;
+ mreset(cached_msg.memdump);
+
+ result =
+ db_fetch_headers
+ (thisnum,
+ &cached_msg.msg);
+ if (result == -2) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist
+ (&fetch_list.
+ start);
+ db_free_msg
+ (&headermsg);
+ return -1;
+ }
+ if (result == -3) {
+ fprintf(ci->tx,
+ "\r\n* BYE out of memory\r\n");
+ list_freelist
+ (&fetch_list.
+ start);
+ db_free_msg
+ (&headermsg);
+ return -1;
+ }
+
+ cached_msg.msg_parsed = 1;
+ cached_msg.num = thisnum;
+
+ rfcsize =
+ (cached_msg.msg.
+ rfcheadersize +
+ cached_msg.msg.
+ bodysize +
+ cached_msg.msg.
+ bodylines);
+
+ if (insert_rfcsize) {
+ /* insert the rfc822 size into the dbase */
+ if (db_set_rfcsize
+ (rfcsize,
+ thisnum,
+ ud->mailbox.
+ uid) == -1) {
+ fprintf
+ (ci->
+ tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist
+ (&fetch_list.
+ start);
+ db_free_msg
+ (&headermsg);
+ return -1;
+ }
+
+ insert_rfcsize = 0;
+ }
+
+ }
+ }
- msgpart = get_part_by_num(&cached_msg.msg, fi->bodyfetch.partspec);
-
- if (!msgpart)
- {
- /* if the partspec ends on "1" or "1." the msg body
- * of the parent message is to be retrieved
- */
-
- partspeclen = strlen(fi->bodyfetch.partspec);
-
- if ((fi->bodyfetch.partspec[partspeclen-1] == '1' &&
- (partspeclen == 1 || fi->bodyfetch.partspec[partspeclen-2] == '.'))
- ||
- ((fi->bodyfetch.partspec[partspeclen-1] == '.' &&
- fi->bodyfetch.partspec[partspeclen-2] == '1') &&
- (partspeclen == 2 || fi->bodyfetch.partspec[partspeclen-3] == '.'))
- )
- {
- /* ok find the parent of this message */
- /* start value of k is partspeclen-2 'cause we could
- have partspec[partspeclen-1] == '.' right at the start
- */
-
- for (k = partspeclen-2; k>=0; k--)
- if (fi->bodyfetch.partspec[k] == '.')
- break;
-
- if (k>0)
- {
- fi->bodyfetch.partspec[k] = '\0';
- msgpart = get_part_by_num(&cached_msg.msg,
- fi->bodyfetch.partspec);
- fi->bodyfetch.partspec[k] = '.';
+ if (fi->getInternalDate) {
+ result =
+ db_get_msgdate(ud->mailbox.uid,
+ thisnum, date);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
+
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx,
+ "INTERNALDATE \"%s\"",
+ date_sql2imap(date));
}
- else
- msgpart = &cached_msg.msg;
- only_text_from_msgpart = 1;
- }
- }
- else
- {
- only_text_from_msgpart = 0;
- }
- }
- else
- {
- if (cached_msg.num == thisnum)
- msgpart = &cached_msg.msg;
- else
- {
- /* this will be only the case when only_main_header_parsing == 1 */
- msgpart = &headermsg;
- }
- }
-
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- if (fi->bodyfetch.noseen)
- fprintf(ci->tx, "BODY[%s", fi->bodyfetch.partspec);
- else
- {
- fprintf(ci->tx, "BODY[%s", fi->bodyfetch.partspec);
- setseen = 1;
- }
-
- switch (fi->bodyfetch.itemtype)
- {
- case BFIT_TEXT_SILENT:
- if (!msgpart)
- fprintf(ci->tx, "] NIL ");
- else
- {
- tmpdumpsize = 0;
-
- if (!only_text_from_msgpart)
- tmpdumpsize = rfcheader_dump(cached_msg.tmpdump, &msgpart->rfcheader,
- args, 0, 0);
-
- tmpdumpsize +=
- db_dump_range(cached_msg.tmpdump, msgpart->bodystart, msgpart->bodyend,
- thisnum);
-
- if (fi->bodyfetch.octetstart >= 0)
- {
- cnt = tmpdumpsize - fi->bodyfetch.octetstart;
- if (cnt<0) cnt = 0;
- if (cnt > fi->bodyfetch.octetcnt) cnt = fi->bodyfetch.octetcnt;
-
- fprintf(ci->tx, "]<%llu> {%llu}\r\n",
- fi->bodyfetch.octetstart, cnt);
-
- mseek(cached_msg.tmpdump, fi->bodyfetch.octetstart, SEEK_SET);
- }
- else
- {
- cnt = tmpdumpsize;
- fprintf(ci->tx, "] {%llu}\r\n", tmpdumpsize);
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
- }
-
- /* output data */
- send_data(ci->tx, cached_msg.tmpdump, cnt);
+ if (fi->getUID) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
- }
- break;
-
-
- case BFIT_TEXT:
- /* dump body text */
- fprintf(ci->tx, "TEXT");
- if (!msgpart)
- fprintf(ci->tx, "] NIL ");
- else
- {
- tmpdumpsize =
- db_dump_range(cached_msg.tmpdump, msgpart->bodystart, msgpart->bodyend,
- thisnum);
-
- if (fi->bodyfetch.octetstart >= 0)
- {
- cnt = tmpdumpsize - fi->bodyfetch.octetstart;
- if (cnt<0) cnt = 0;
- if (cnt > fi->bodyfetch.octetcnt) cnt = fi->bodyfetch.octetcnt;
-
- fprintf(ci->tx, "]<%llu> {%llu}\r\n",
- fi->bodyfetch.octetstart, cnt);
-
- mseek(cached_msg.tmpdump, fi->bodyfetch.octetstart, SEEK_SET);
- }
- else
- {
- cnt = tmpdumpsize;
- fprintf(ci->tx, "] {%llu}\r\n", tmpdumpsize);
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
- }
-
- /* output data */
- send_data(ci->tx, cached_msg.tmpdump, cnt);
- }
- break;
-
- case BFIT_HEADER:
- fprintf(ci->tx, "HEADER");
- if (!msgpart || only_text_from_msgpart)
- fprintf(ci->tx, "] NIL\r\n");
- else
- {
- tmpdumpsize = rfcheader_dump(cached_msg.tmpdump, &msgpart->rfcheader,
- args, 0, 0);
-
- if (!tmpdumpsize)
- {
- fprintf(ci->tx, "] NIL\r\n");
- }
- else
- {
- if (fi->bodyfetch.octetstart >= 0)
- {
- cnt = tmpdumpsize - fi->bodyfetch.octetstart;
- if (cnt<0) cnt = 0;
- if (cnt > fi->bodyfetch.octetcnt) cnt = fi->bodyfetch.octetcnt;
-
- fprintf(ci->tx, "]<%llu> {%llu}\r\n",
- fi->bodyfetch.octetstart, cnt);
-
- mseek(cached_msg.tmpdump, fi->bodyfetch.octetstart, SEEK_SET);
+ fprintf(ci->tx, "UID %llu",
+ thisnum);
+ }
+
+ if (fi->getMIME_IMB) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx, "BODYSTRUCTURE ");
+ result =
+ retrieve_structure(ci->tx,
+ &cached_msg.
+ msg, 1);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE error fetching body structure\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
}
- else
- {
- cnt = tmpdumpsize;
- fprintf(ci->tx, "] {%llu}\r\n", tmpdumpsize);
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
+
+ if (fi->getMIME_IMB_noextension) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx, "BODY ");
+ result =
+ retrieve_structure(ci->tx,
+ &cached_msg.
+ msg, 0);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE error fetching body\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
}
- /* output data */
- send_data(ci->tx, cached_msg.tmpdump, cnt);
+ if (fi->getEnvelope) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx, "ENVELOPE ");
+ result =
+ retrieve_envelope(ci->tx,
+ &cached_msg.
+ msg.
+ rfcheader);
+
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE error fetching envelope structure\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
+ }
- }
- }
- break;
-
- case BFIT_HEADER_FIELDS:
- fprintf(ci->tx, "HEADER.FIELDS (");
-
- isfirstout = 1;
- for (k=0; k<fi->bodyfetch.argcnt; k++)
- {
- if (isfirstout)
- {
- fprintf(ci->tx, "%s",args[k + fi->bodyfetch.argstart]);
- isfirstout = 0;
- }
- else
- fprintf(ci->tx, " %s",args[k + fi->bodyfetch.argstart]);
- }
+ if (fi->getRFC822 || fi->getRFC822Peek) {
+ if (cached_msg.file_dumped == 0
+ || cached_msg.num != thisnum) {
+ mreset(cached_msg.memdump);
+
+ cached_msg.dumpsize =
+ rfcheader_dump
+ (cached_msg.memdump,
+ &cached_msg.msg.
+ rfcheader, args, 0,
+ 0);
+
+ cached_msg.dumpsize +=
+ db_dump_range
+ (cached_msg.memdump,
+ cached_msg.msg.
+ bodystart,
+ cached_msg.msg.
+ bodyend, thisnum);
+
+ cached_msg.file_dumped = 1;
+
+ if (cached_msg.num !=
+ thisnum) {
+ /* if there is a parsed msg in the cache it will be invalid now */
+ if (cached_msg.
+ msg_parsed) {
+ cached_msg.
+ msg_parsed
+ = 0;
+ db_free_msg
+ (&cached_msg.
+ msg);
+ }
+ cached_msg.num =
+ thisnum;
+ }
+ }
+
+ mseek(cached_msg.memdump, 0,
+ SEEK_SET);
+
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx,
+ "RFC822 {%llu}\r\n",
+ cached_msg.dumpsize);
+ send_data(ci->tx,
+ cached_msg.memdump,
+ cached_msg.dumpsize);
+
+ if (fi->getRFC822)
+ setseen = 1;
- fprintf(ci->tx,")] ");
-
- if (!msgpart || only_text_from_msgpart)
- fprintf(ci->tx, "NIL\r\n");
- else
- {
- tmpdumpsize =
- rfcheader_dump(cached_msg.tmpdump, &msgpart->rfcheader,
- &args[fi->bodyfetch.argstart],
- fi->bodyfetch.argcnt, 1);
-
- if (!tmpdumpsize)
- {
- fprintf(ci->tx, "NIL\r\n");
- }
- else
- {
- if (fi->bodyfetch.octetstart >= 0)
- {
- cnt = tmpdumpsize - fi->bodyfetch.octetstart;
- if (cnt<0) cnt = 0;
- if (cnt > fi->bodyfetch.octetcnt) cnt = fi->bodyfetch.octetcnt;
-
- fprintf(ci->tx, "<%llu> {%llu}\r\n",
- fi->bodyfetch.octetstart, cnt);
-
- mseek(cached_msg.tmpdump, fi->bodyfetch.octetstart, SEEK_SET);
}
- else
- {
- cnt = tmpdumpsize;
- fprintf(ci->tx, "{%llu}\r\n", tmpdumpsize);
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
+
+ if (fi->getSize) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx, "RFC822.SIZE %llu",
+ rfcsize);
}
- /* output data */
- send_data(ci->tx, cached_msg.tmpdump, cnt);
+ if (fi->getBodyTotal
+ || fi->getBodyTotalPeek) {
+ if (cached_msg.file_dumped == 0
+ || cached_msg.num != thisnum) {
+ cached_msg.dumpsize =
+ rfcheader_dump
+ (cached_msg.memdump,
+ &cached_msg.msg.
+ rfcheader, args, 0,
+ 0);
+
+ cached_msg.dumpsize +=
+ db_dump_range
+ (cached_msg.memdump,
+ cached_msg.msg.
+ bodystart,
+ cached_msg.msg.
+ bodyend, thisnum);
+
+
+ if (cached_msg.num !=
+ thisnum) {
+ /* if there is a parsed msg in the cache it will be invalid now */
+ if (cached_msg.
+ msg_parsed) {
+ cached_msg.
+ msg_parsed
+ = 0;
+ db_free_msg
+ (&cached_msg.
+ msg);
+ }
+ cached_msg.num =
+ thisnum;
+ }
+
+ cached_msg.file_dumped = 1;
+ }
+
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ if (fi->bodyfetch.octetstart == -1) {
+ mseek(cached_msg.memdump,
+ 0, SEEK_SET);
+
+ fprintf(ci->tx,
+ "BODY[] {%llu}\r\n",
+ cached_msg.
+ dumpsize);
+ send_data(ci->tx,
+ cached_msg.
+ memdump,
+ cached_msg.
+ dumpsize);
+ } else {
+ mseek(cached_msg.memdump,
+ fi->bodyfetch.
+ octetstart,
+ SEEK_SET);
- }
- }
- break;
- case BFIT_HEADER_FIELDS_NOT:
- fprintf(ci->tx, "HEADER.FIELDS.NOT (");
-
- isfirstout = 1;
- for (k=0; k<fi->bodyfetch.argcnt; k++)
- {
- if (isfirstout)
- {
- fprintf(ci->tx, "%s",args[k + fi->bodyfetch.argstart]);
- isfirstout = 0;
- }
- else
- fprintf(ci->tx, " %s",args[k + fi->bodyfetch.argstart]);
- }
+ /** \todo this next statement is ugly because of the
+ casts to 'long long'. Probably, octetcnt should be
+ changed to be a u64_t instead of a long long, because
+ it should never be negative anyway */
+ actual_cnt =
+ (fi->bodyfetch.
+ octetcnt >
+ (((long long)
+ cached_msg.
+ dumpsize) -
+ fi->bodyfetch.
+ octetstart))
+ ? (((long long)
+ cached_msg.
+ dumpsize)
+ -
+ fi->bodyfetch.
+ octetstart) : fi->
+ bodyfetch.octetcnt;
+
+ fprintf(ci->tx,
+ "BODY[]<%llu> {%llu}\r\n",
+ fi->bodyfetch.
+ octetstart,
+ actual_cnt);
+
+ send_data(ci->tx,
+ cached_msg.
+ memdump,
+ actual_cnt);
+
+ }
+
+ if (fi->getBodyTotal)
+ setseen = 1;
- fprintf(ci->tx,")] ");
-
- if (!msgpart || only_text_from_msgpart)
- fprintf(ci->tx, "NIL\r\n");
- else
- {
- tmpdumpsize =
- rfcheader_dump(cached_msg.tmpdump, &msgpart->rfcheader,
- &args[fi->bodyfetch.argstart],
- fi->bodyfetch.argcnt, 0);
-
- if (!tmpdumpsize)
- {
- fprintf(ci->tx, "NIL\r\n");
- }
- else
- {
- if (fi->bodyfetch.octetstart >= 0)
- {
- cnt = tmpdumpsize - fi->bodyfetch.octetstart;
- if (cnt<0) cnt = 0;
- if (cnt > fi->bodyfetch.octetcnt) cnt = fi->bodyfetch.octetcnt;
-
- fprintf(ci->tx, "<%llu> {%llu}\r\n",
- fi->bodyfetch.octetstart, cnt);
-
- mseek(cached_msg.tmpdump, fi->bodyfetch.octetstart, SEEK_SET);
- }
- else
- {
- cnt = tmpdumpsize;
- fprintf(ci->tx, "{%llu}\r\n", tmpdumpsize);
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
}
- /* output data */
- send_data(ci->tx, cached_msg.tmpdump, cnt);
+ if (fi->getRFC822Header) {
+ /* here: msgparse_needed == 1
+ * if this msg is in cache, retrieve it from there
+ * otherwise only_main_header_parsing == 1 so retrieve direct
+ * from the dbase
+ */
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ if (cached_msg.num == thisnum) {
+ mrewind(cached_msg.
+ tmpdump);
+ tmpdumpsize =
+ rfcheader_dump
+ (cached_msg.tmpdump,
+ &cached_msg.msg.
+ rfcheader, args, 0,
+ 0);
+
+ mseek(cached_msg.tmpdump,
+ 0, SEEK_SET);
+
+ fprintf(ci->tx,
+ "RFC822.HEADER {%llu}\r\n",
+ tmpdumpsize);
+ send_data(ci->tx,
+ cached_msg.
+ tmpdump,
+ tmpdumpsize);
+ } else {
+ /* remember only_main_header_parsing == 1 here ! */
+
+ /* use cached_msg.tmpdump as temporary storage */
+ mrewind(cached_msg.
+ tmpdump);
+ tmpdumpsize =
+ rfcheader_dump
+ (cached_msg.tmpdump,
+ &headermsg.rfcheader,
+ args, 0, 0);
+
+ mseek(cached_msg.tmpdump,
+ 0, SEEK_SET);
+
+ fprintf(ci->tx,
+ "RFC822.HEADER {%llu}\r\n",
+ tmpdumpsize);
+ send_data(ci->tx,
+ cached_msg.
+ tmpdump,
+ tmpdumpsize);
+ }
+ }
- }
- }
- break;
- case BFIT_MIME:
- fprintf(ci->tx, "MIME] ");
-
- if (!msgpart)
- fprintf(ci->tx, "NIL\r\n");
- else
- {
- tmpdumpsize = mimeheader_dump(cached_msg.tmpdump, &msgpart->mimeheader);
-
- if (!tmpdumpsize)
- {
- fprintf(ci->tx, "NIL\r\n");
- }
- else
- {
- if (fi->bodyfetch.octetstart >= 0)
- {
- cnt = tmpdumpsize - fi->bodyfetch.octetstart;
- if (cnt<0) cnt = 0;
- if (cnt > fi->bodyfetch.octetcnt) cnt = fi->bodyfetch.octetcnt;
-
- fprintf(ci->tx, "<%llu> {%llu}\r\n",
- fi->bodyfetch.octetstart, cnt);
-
- mseek(cached_msg.tmpdump, fi->bodyfetch.octetstart, SEEK_SET);
+ if (fi->getRFC822Text) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ mrewind(cached_msg.tmpdump);
+ tmpdumpsize =
+ db_dump_range(cached_msg.
+ tmpdump,
+ cached_msg.msg.
+ bodystart,
+ cached_msg.msg.
+ bodyend,
+ thisnum);
+
+ mseek(cached_msg.tmpdump, 0,
+ SEEK_SET);
+
+ fprintf(ci->tx,
+ "RFC822.TEXT {%llu}\r\n",
+ tmpdumpsize);
+ send_data(ci->tx,
+ cached_msg.tmpdump,
+ tmpdumpsize);
+
+ setseen = 1;
}
- else
- {
- cnt = tmpdumpsize;
- fprintf(ci->tx, "{%llu}\r\n", tmpdumpsize);
- mseek(cached_msg.tmpdump, 0, SEEK_SET);
+
+ if (fi->bodyfetch.itemtype >= 0) {
+ mrewind(cached_msg.tmpdump);
+
+ if (fi->bodyfetch.partspec[0]) {
+ if (fi->bodyfetch.
+ partspec[0] == '0') {
+ fprintf(ci->tx,
+ "\r\n%s BAD protocol error\r\n",
+ tag);
+ trace(TRACE_DEBUG,
+ "PROTOCOL ERROR");
+ list_freelist
+ (&fetch_list.
+ start);
+ db_free_msg
+ (&headermsg);
+ return 1;
+ }
+
+ msgpart =
+ get_part_by_num
+ (&cached_msg.msg,
+ fi->bodyfetch.
+ partspec);
+
+ if (!msgpart) {
+ /* if the partspec ends on "1" or "1." the msg body
+ * of the parent message is to be retrieved
+ */
+
+ partspeclen =
+ strlen(fi->
+ bodyfetch.
+ partspec);
+
+ if ((fi->bodyfetch.
+ partspec
+ [partspeclen -
+ 1] == '1'
+ &&
+ (partspeclen
+ == 1
+ || fi->
+ bodyfetch.
+ partspec
+ [partspeclen
+ - 2] ==
+ '.'))
+ ||
+ ((fi->
+ bodyfetch.
+ partspec
+ [partspeclen
+ - 1] == '.'
+ && fi->
+ bodyfetch.
+ partspec
+ [partspeclen
+ - 2] == '1')
+ &&
+ (partspeclen
+ == 2
+ || fi->
+ bodyfetch.
+ partspec
+ [partspeclen
+ - 3] ==
+ '.'))
+ ) {
+ /* ok find the parent of this message */
+ /* start value of k is partspeclen-2 'cause we could
+ have partspec[partspeclen-1] == '.' right at the start
+ */
+
+ for (k =
+ partspeclen
+ - 2;
+ k >=
+ 0;
+ k--)
+ if (fi->bodyfetch.partspec[k] == '.')
+ break;
+
+ if (k > 0) {
+ fi->bodyfetch.partspec[k] = '\0';
+ msgpart
+ =
+ get_part_by_num
+ (&cached_msg.
+ msg,
+ fi->
+ bodyfetch.
+ partspec);
+ fi->bodyfetch.partspec[k] = '.';
+ } else
+ msgpart
+ =
+ &cached_msg.
+ msg;
+
+ only_text_from_msgpart
+ = 1;
+ }
+ } else {
+ only_text_from_msgpart
+ = 0;
+ }
+ } else {
+ if (cached_msg.num ==
+ thisnum)
+ msgpart =
+ &cached_msg.
+ msg;
+ else {
+ /* this will be only the case when only_main_header_parsing == 1 */
+ msgpart =
+ &headermsg;
+ }
+ }
+
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ if (fi->bodyfetch.noseen)
+ fprintf(ci->tx, "BODY[%s",
+ fi->bodyfetch.
+ partspec);
+ else {
+ fprintf(ci->tx, "BODY[%s",
+ fi->bodyfetch.
+ partspec);
+ setseen = 1;
+ }
+
+ switch (fi->bodyfetch.itemtype) {
+ case BFIT_TEXT_SILENT:
+ if (!msgpart)
+ fprintf(ci->tx,
+ "] NIL ");
+ else {
+ tmpdumpsize = 0;
+
+ if (!only_text_from_msgpart)
+ tmpdumpsize
+ =
+ rfcheader_dump
+ (cached_msg.
+ tmpdump,
+ &msgpart->
+ rfcheader,
+ args,
+ 0, 0);
+
+ tmpdumpsize +=
+ db_dump_range
+ (cached_msg.
+ tmpdump,
+ msgpart->
+ bodystart,
+ msgpart->
+ bodyend,
+ thisnum);
+
+ if (fi->bodyfetch.
+ octetstart >=
+ 0) {
+ cnt =
+ tmpdumpsize
+ -
+ fi->
+ bodyfetch.
+ octetstart;
+ if (cnt <
+ 0)
+ cnt = 0;
+ if (cnt >
+ fi->
+ bodyfetch.
+ octetcnt)
+ cnt = fi->bodyfetch.octetcnt;
+
+ fprintf
+ (ci->
+ tx,
+ "]<%llu> {%llu}\r\n",
+ fi->
+ bodyfetch.
+ octetstart,
+ cnt);
+
+ mseek
+ (cached_msg.
+ tmpdump,
+ fi->
+ bodyfetch.
+ octetstart,
+ SEEK_SET);
+ } else {
+ cnt =
+ tmpdumpsize;
+ fprintf
+ (ci->
+ tx,
+ "] {%llu}\r\n",
+ tmpdumpsize);
+ mseek
+ (cached_msg.
+ tmpdump,
+ 0,
+ SEEK_SET);
+ }
+
+ /* output data */
+ send_data(ci->tx,
+ cached_msg.
+ tmpdump,
+ cnt);
+
+ }
+ break;
+
+
+ case BFIT_TEXT:
+ /* dump body text */
+ fprintf(ci->tx, "TEXT");
+ if (!msgpart)
+ fprintf(ci->tx,
+ "] NIL ");
+ else {
+ tmpdumpsize =
+ db_dump_range
+ (cached_msg.
+ tmpdump,
+ msgpart->
+ bodystart,
+ msgpart->
+ bodyend,
+ thisnum);
+
+ if (fi->bodyfetch.
+ octetstart >=
+ 0) {
+ cnt =
+ tmpdumpsize
+ -
+ fi->
+ bodyfetch.
+ octetstart;
+ if (cnt <
+ 0)
+ cnt = 0;
+ if (cnt >
+ fi->
+ bodyfetch.
+ octetcnt)
+ cnt = fi->bodyfetch.octetcnt;
+
+ fprintf
+ (ci->
+ tx,
+ "]<%llu> {%llu}\r\n",
+ fi->
+ bodyfetch.
+ octetstart,
+ cnt);
+
+ mseek
+ (cached_msg.
+ tmpdump,
+ fi->
+ bodyfetch.
+ octetstart,
+ SEEK_SET);
+ } else {
+ cnt =
+ tmpdumpsize;
+ fprintf
+ (ci->
+ tx,
+ "] {%llu}\r\n",
+ tmpdumpsize);
+ mseek
+ (cached_msg.
+ tmpdump,
+ 0,
+ SEEK_SET);
+ }
+
+ /* output data */
+ send_data(ci->tx,
+ cached_msg.
+ tmpdump,
+ cnt);
+ }
+ break;
+
+ case BFIT_HEADER:
+ fprintf(ci->tx, "HEADER");
+ if (!msgpart
+ ||
+ only_text_from_msgpart)
+ fprintf(ci->tx,
+ "] NIL\r\n");
+ else {
+ tmpdumpsize =
+ rfcheader_dump
+ (cached_msg.
+ tmpdump,
+ &msgpart->
+ rfcheader,
+ args, 0, 0);
+
+ if (!tmpdumpsize) {
+ fprintf
+ (ci->
+ tx,
+ "] NIL\r\n");
+ } else {
+ if (fi->
+ bodyfetch.
+ octetstart
+ >= 0) {
+ cnt = tmpdumpsize - fi->bodyfetch.octetstart;
+ if (cnt < 0)
+ cnt = 0;
+ if (cnt > fi->bodyfetch.octetcnt)
+ cnt = fi->bodyfetch.octetcnt;
+
+ fprintf
+ (ci->
+ tx,
+ "]<%llu> {%llu}\r\n",
+ fi->
+ bodyfetch.
+ octetstart,
+ cnt);
+
+ mseek
+ (cached_msg.
+ tmpdump,
+ fi->
+ bodyfetch.
+ octetstart,
+ SEEK_SET);
+ } else {
+ cnt = tmpdumpsize;
+ fprintf
+ (ci->
+ tx,
+ "] {%llu}\r\n",
+ tmpdumpsize);
+ mseek
+ (cached_msg.
+ tmpdump,
+ 0,
+ SEEK_SET);
+ }
+
+ /* output data */
+ send_data
+ (ci->
+ tx,
+ cached_msg.
+ tmpdump,
+ cnt);
+
+ }
+ }
+ break;
+
+ case BFIT_HEADER_FIELDS:
+ fprintf(ci->tx,
+ "HEADER.FIELDS (");
+
+ isfirstout = 1;
+ for (k = 0;
+ k <
+ fi->bodyfetch.argcnt;
+ k++) {
+ if (isfirstout) {
+ fprintf
+ (ci->
+ tx,
+ "%s",
+ args[k
+ +
+ fi->
+ bodyfetch.
+ argstart]);
+ isfirstout
+ = 0;
+ } else
+ fprintf
+ (ci->
+ tx,
+ " %s",
+ args[k
+ +
+ fi->
+ bodyfetch.
+ argstart]);
+ }
+
+ fprintf(ci->tx, ")] ");
+
+ if (!msgpart
+ ||
+ only_text_from_msgpart)
+ fprintf(ci->tx,
+ "NIL\r\n");
+ else {
+ tmpdumpsize =
+ rfcheader_dump
+ (cached_msg.
+ tmpdump,
+ &msgpart->
+ rfcheader,
+ &args[fi->
+ bodyfetch.
+ argstart],
+ fi->bodyfetch.
+ argcnt, 1);
+
+ if (!tmpdumpsize) {
+ fprintf
+ (ci->
+ tx,
+ "NIL\r\n");
+ } else {
+ if (fi->
+ bodyfetch.
+ octetstart
+ >= 0) {
+ cnt = tmpdumpsize - fi->bodyfetch.octetstart;
+ if (cnt < 0)
+ cnt = 0;
+ if (cnt > fi->bodyfetch.octetcnt)
+ cnt = fi->bodyfetch.octetcnt;
+
+ fprintf
+ (ci->
+ tx,
+ "<%llu> {%llu}\r\n",
+ fi->
+ bodyfetch.
+ octetstart,
+ cnt);
+
+ mseek
+ (cached_msg.
+ tmpdump,
+ fi->
+ bodyfetch.
+ octetstart,
+ SEEK_SET);
+ } else {
+ cnt = tmpdumpsize;
+ fprintf
+ (ci->
+ tx,
+ "{%llu}\r\n",
+ tmpdumpsize);
+ mseek
+ (cached_msg.
+ tmpdump,
+ 0,
+ SEEK_SET);
+ }
+
+ /* output data */
+ send_data
+ (ci->
+ tx,
+ cached_msg.
+ tmpdump,
+ cnt);
+
+ }
+ }
+ break;
+ case BFIT_HEADER_FIELDS_NOT:
+ fprintf(ci->tx,
+ "HEADER.FIELDS.NOT (");
+
+ isfirstout = 1;
+ for (k = 0;
+ k <
+ fi->bodyfetch.argcnt;
+ k++) {
+ if (isfirstout) {
+ fprintf
+ (ci->
+ tx,
+ "%s",
+ args[k
+ +
+ fi->
+ bodyfetch.
+ argstart]);
+ isfirstout
+ = 0;
+ } else
+ fprintf
+ (ci->
+ tx,
+ " %s",
+ args[k
+ +
+ fi->
+ bodyfetch.
+ argstart]);
+ }
+
+ fprintf(ci->tx, ")] ");
+
+ if (!msgpart
+ ||
+ only_text_from_msgpart)
+ fprintf(ci->tx,
+ "NIL\r\n");
+ else {
+ tmpdumpsize =
+ rfcheader_dump
+ (cached_msg.
+ tmpdump,
+ &msgpart->
+ rfcheader,
+ &args[fi->
+ bodyfetch.
+ argstart],
+ fi->bodyfetch.
+ argcnt, 0);
+
+ if (!tmpdumpsize) {
+ fprintf
+ (ci->
+ tx,
+ "NIL\r\n");
+ } else {
+ if (fi->
+ bodyfetch.
+ octetstart
+ >= 0) {
+ cnt = tmpdumpsize - fi->bodyfetch.octetstart;
+ if (cnt < 0)
+ cnt = 0;
+ if (cnt > fi->bodyfetch.octetcnt)
+ cnt = fi->bodyfetch.octetcnt;
+
+ fprintf
+ (ci->
+ tx,
+ "<%llu> {%llu}\r\n",
+ fi->
+ bodyfetch.
+ octetstart,
+ cnt);
+
+ mseek
+ (cached_msg.
+ tmpdump,
+ fi->
+ bodyfetch.
+ octetstart,
+ SEEK_SET);
+ } else {
+ cnt = tmpdumpsize;
+ fprintf
+ (ci->
+ tx,
+ "{%llu}\r\n",
+ tmpdumpsize);
+ mseek
+ (cached_msg.
+ tmpdump,
+ 0,
+ SEEK_SET);
+ }
+
+ /* output data */
+ send_data
+ (ci->
+ tx,
+ cached_msg.
+ tmpdump,
+ cnt);
+
+ }
+ }
+ break;
+ case BFIT_MIME:
+ fprintf(ci->tx, "MIME] ");
+
+ if (!msgpart)
+ fprintf(ci->tx,
+ "NIL\r\n");
+ else {
+ tmpdumpsize =
+ mimeheader_dump
+ (cached_msg.
+ tmpdump,
+ &msgpart->
+ mimeheader);
+
+ if (!tmpdumpsize) {
+ fprintf
+ (ci->
+ tx,
+ "NIL\r\n");
+ } else {
+ if (fi->
+ bodyfetch.
+ octetstart
+ >= 0) {
+ cnt = tmpdumpsize - fi->bodyfetch.octetstart;
+ if (cnt < 0)
+ cnt = 0;
+ if (cnt > fi->bodyfetch.octetcnt)
+ cnt = fi->bodyfetch.octetcnt;
+
+ fprintf
+ (ci->
+ tx,
+ "<%llu> {%llu}\r\n",
+ fi->
+ bodyfetch.
+ octetstart,
+ cnt);
+
+ mseek
+ (cached_msg.
+ tmpdump,
+ fi->
+ bodyfetch.
+ octetstart,
+ SEEK_SET);
+ } else {
+ cnt = tmpdumpsize;
+ fprintf
+ (ci->
+ tx,
+ "{%llu}\r\n",
+ tmpdumpsize);
+ mseek
+ (cached_msg.
+ tmpdump,
+ 0,
+ SEEK_SET);
+ }
+
+ /* output data */
+ send_data
+ (ci->
+ tx,
+ cached_msg.
+ tmpdump,
+ cnt);
+
+ }
+ }
+
+ break;
+ default:
+ fprintf(ci->tx,
+ "\r\n* BYE internal server error\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
}
- /* output data */
- send_data(ci->tx, cached_msg.tmpdump, cnt);
-
- }
- }
-
- break;
- default:
- fprintf(ci->tx, "\r\n* BYE internal server error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
- }
+ /* set \Seen flag if necessary; note the absence of an error-check
+ * for db_get_msgflag()!
+ */
+ if (setseen
+ && db_get_msgflag("seen", thisnum,
+ ud->mailbox.uid) !=
+ 1) {
+ result =
+ db_set_msgflag(thisnum,
+ ud->mailbox.uid,
+ setSeenSet,
+ IMAPFA_ADD);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
+
+ fi->getFlags = 1;
+ fprintf(ci->tx, " ");
+ }
- /* set \Seen flag if necessary; note the absence of an error-check
- * for db_get_msgflag()!
- */
- if (setseen && db_get_msgflag("seen", thisnum, ud->mailbox.uid) != 1)
- {
- result = db_set_msgflag(thisnum, ud->mailbox.uid, setSeenSet, IMAPFA_ADD);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
-
- fi->getFlags = 1;
- fprintf(ci->tx," ");
- }
+ /* FLAGS ? */
+ if (fi->getFlags) {
+ if (isfirstfetchout)
+ isfirstfetchout = 0;
+ else
+ fprintf(ci->tx, " ");
+
+ fprintf(ci->tx, "FLAGS (");
+
+ isfirstout = 1;
+
+ result =
+ db_get_msgflag_all(thisnum,
+ ud->mailbox.
+ uid,
+ msgflags);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ list_freelist(&fetch_list.
+ start);
+ db_free_msg(&headermsg);
+ return -1;
+ }
+
+ for (j = 0; j < IMAP_NFLAGS; j++) {
+ if (msgflags[j]) {
+ if (isfirstout) {
+ fprintf
+ (ci->
+ tx,
+ "\\%s",
+ imap_flag_desc
+ [j]);
+ isfirstout
+ = 0;
+ } else
+ fprintf
+ (ci->
+ tx,
+ " \\%s",
+ imap_flag_desc
+ [j]);
+ }
+ }
+ fprintf(ci->tx, ")");
+ }
- /* FLAGS ? */
- if (fi->getFlags)
- {
- if (isfirstfetchout)
- isfirstfetchout = 0;
- else
- fprintf(ci->tx, " ");
-
- fprintf(ci->tx,"FLAGS (");
-
- isfirstout = 1;
-
- result = db_get_msgflag_all(thisnum, ud->mailbox.uid, msgflags);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
- return -1;
- }
-
- for (j=0; j<IMAP_NFLAGS; j++)
- {
- if (msgflags[j])
- {
- if (isfirstout)
- {
- fprintf(ci->tx,"\\%s",imap_flag_desc[j]);
- isfirstout = 0;
- }
- else
- fprintf(ci->tx," \\%s",imap_flag_desc[j]);
+ curr = curr->nextnode;
}
- }
- fprintf(ci->tx, ")");
- }
-
- curr = curr->nextnode;
- }
- if (!bad_response_send)
- fprintf(ci->tx,")\r\n");
+ if (!bad_response_send)
+ fprintf(ci->tx, ")\r\n");
+ }
}
- }
- mreset(cached_msg.tmpdump);
- list_freelist(&fetch_list.start);
- db_free_msg(&headermsg);
+ mreset(cached_msg.tmpdump);
+ list_freelist(&fetch_list.start);
+ db_free_msg(&headermsg);
- fprintf(ci->tx,"%s OK %sFETCH completed\r\n", tag, imapcommands_use_uid ? "UID " : "");
- return 0;
+ fprintf(ci->tx, "%s OK %sFETCH completed\r\n", tag,
+ imapcommands_use_uid ? "UID " : "");
+ return 0;
}
@@ -3213,296 +3798,332 @@ int _ic_fetch(char *tag, char **args, ClientInfo *ci)
*
* alter message-associated data in selected mailbox
*/
-int _ic_store(char *tag, char **args, ClientInfo *ci)
+int _ic_store(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- char *endptr, *lastchar = NULL;
- u64_t i,store_start,store_end;
- unsigned fn=0;
- int result,j,isfirstout=0;
- int be_silent=0,action=IMAPFA_NONE;
- int flaglist[IMAP_NFLAGS], msgflags[IMAP_NFLAGS];
- u64_t thisnum,lo,hi;
-
- memset(flaglist, 0, sizeof(int) * IMAP_NFLAGS);
-
- if (ud->state != IMAPCS_SELECTED)
- {
- fprintf(ci->tx,"%s BAD STORE command received in invalid state\r\n", tag);
- return 1;
- }
-
- if (!args[0] || !args[1] || !args[2])
- {
- fprintf(ci->tx,"%s BAD missing argument(s) to STORE\r\n", tag);
- return 1;
- }
-
- /* multiple flags should be parenthesed */
- if (args[3] && strcmp(args[2],"(") != 0)
- {
- fprintf(ci->tx,"%s BAD invalid argument(s) to STORE\r\n", tag);
- return 1;
- }
-
-
- /* retrieve action type */
- if (strcasecmp(args[1], "flags") == 0)
- action = IMAPFA_REPLACE;
- else if (strcasecmp(args[1], "flags.silent") == 0)
- {
- action = IMAPFA_REPLACE;
- be_silent = 1;
- }
- else if (strcasecmp(args[1], "+flags") == 0)
- action = IMAPFA_ADD;
- else if (strcasecmp(args[1], "+flags.silent") == 0)
- {
- action = IMAPFA_ADD;
- be_silent = 1;
- }
- else if (strcasecmp(args[1], "-flags") == 0)
- action = IMAPFA_REMOVE;
- else if (strcasecmp(args[1], "-flags.silent") == 0)
- {
- action = IMAPFA_REMOVE;
- be_silent = 1;
- }
-
- if (action == IMAPFA_NONE)
- {
- fprintf(ci->tx,"%s BAD invalid STORE action specified\r\n",tag);
- return 1;
- }
-
- /* now fetch flag list */
- i = (strcmp(args[2], "(") == 0) ? 3: 2;
-
- for ( ; args[i] && strcmp(args[i] ,")") != 0; i++)
- {
- for (j=0; j<IMAP_NFLAGS; j++)
- if (strcasecmp(args[i],imap_flag_desc_escaped[j]) == 0)
- {
- flaglist[j] = 1;
- break;
- }
-
- if (j == IMAP_NFLAGS)
- {
- fprintf(ci->tx,"%s BAD invalid flag list to STORE command\r\n",tag);
- return 1;
- }
- }
-
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ char *endptr, *lastchar = NULL;
+ u64_t i, store_start, store_end;
+ unsigned fn = 0;
+ int result, j, isfirstout = 0;
+ int be_silent = 0, action = IMAPFA_NONE;
+ int flaglist[IMAP_NFLAGS], msgflags[IMAP_NFLAGS];
+ u64_t thisnum, lo, hi;
+
+ memset(flaglist, 0, sizeof(int) * IMAP_NFLAGS);
+
+ if (ud->state != IMAPCS_SELECTED) {
+ fprintf(ci->tx,
+ "%s BAD STORE command received in invalid state\r\n",
+ tag);
+ return 1;
+ }
+
+ if (!args[0] || !args[1] || !args[2]) {
+ fprintf(ci->tx, "%s BAD missing argument(s) to STORE\r\n",
+ tag);
+ return 1;
+ }
+
+ /* multiple flags should be parenthesed */
+ if (args[3] && strcmp(args[2], "(") != 0) {
+ fprintf(ci->tx, "%s BAD invalid argument(s) to STORE\r\n",
+ tag);
+ return 1;
+ }
+
+
+ /* retrieve action type */
+ if (strcasecmp(args[1], "flags") == 0)
+ action = IMAPFA_REPLACE;
+ else if (strcasecmp(args[1], "flags.silent") == 0) {
+ action = IMAPFA_REPLACE;
+ be_silent = 1;
+ } else if (strcasecmp(args[1], "+flags") == 0)
+ action = IMAPFA_ADD;
+ else if (strcasecmp(args[1], "+flags.silent") == 0) {
+ action = IMAPFA_ADD;
+ be_silent = 1;
+ } else if (strcasecmp(args[1], "-flags") == 0)
+ action = IMAPFA_REMOVE;
+ else if (strcasecmp(args[1], "-flags.silent") == 0) {
+ action = IMAPFA_REMOVE;
+ be_silent = 1;
+ }
+
+ if (action == IMAPFA_NONE) {
+ fprintf(ci->tx,
+ "%s BAD invalid STORE action specified\r\n", tag);
+ return 1;
+ }
+
+ /* now fetch flag list */
+ i = (strcmp(args[2], "(") == 0) ? 3 : 2;
+
+ for (; args[i] && strcmp(args[i], ")") != 0; i++) {
+ for (j = 0; j < IMAP_NFLAGS; j++)
+ if (strcasecmp(args[i], imap_flag_desc_escaped[j])
+ == 0) {
+ flaglist[j] = 1;
+ break;
+ }
+
+ if (j == IMAP_NFLAGS) {
+ fprintf(ci->tx,
+ "%s BAD invalid flag list to STORE command\r\n",
+ tag);
+ return 1;
+ }
+ }
+
/** check ACL's for STORE */
- if (flaglist[IMAP_STORE_FLAG_SEEN] == 1) {
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_SEEN);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error");
- return -1; /* fatal */
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no right to store \\SEEN flag", tag);
- return 1;
- }
- }
- if (flaglist[IMAP_STORE_FLAG_DELETED] == 1) {
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_DELETE);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error");
- return -1; /* fatal */
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no right to store \\DELETED flag", tag);
- return 1;
- }
- }
- if (flaglist[IMAP_STORE_FLAG_ANSWERED] == 1 ||
- flaglist[IMAP_STORE_FLAG_FLAGGED] == 1 ||
- flaglist[IMAP_STORE_FLAG_DRAFT] == 1 ||
- flaglist[IMAP_STORE_FLAG_RECENT] == 1) {
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_WRITE);
- if (result < 0) {
- fprintf(ci->tx, "*BYE internal database error");
- return -1;
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no right to store flags", tag);
- return 1;
- }
- }
- /* end of ACL checking. If we get here without returning, the user has
- the right to store the flags */
-
- /* set flags & show if needed */
- endptr = args[0];
- while (*endptr)
- {
- if (endptr != args[0])
- endptr++; /* skip delimiter */
-
- store_start = strtoull(endptr, &endptr, 10);
-
- if (store_start == 0 || store_start >
- (imapcommands_use_uid ? (ud->mailbox.msguidnext-1) : ud->mailbox.exists))
- {
- fprintf(ci->tx, "%s BAD invalid message range specified\r\n",tag);
- return 1;
- }
-
- switch (*endptr)
- {
- case ':':
- store_end = strtoull(++endptr, &lastchar, 10);
- endptr = lastchar;
-
- if (*endptr == '*')
- {
- store_end = (imapcommands_use_uid ?
- (ud->mailbox.msguidnext-1) : ud->mailbox.exists);
- endptr++;
- break;
- }
-
- if (store_end == 0 || store_end >
- (imapcommands_use_uid ? (ud->mailbox.msguidnext-1) : ud->mailbox.exists))
- {
- fprintf(ci->tx, "%s BAD invalid message range specified\r\n",tag);
- return 1;
- }
-
- if (store_end < store_start)
- {
- i = store_start;
- store_start = store_end;
- store_end = i;
- }
- break;
-
- case ',':
- case 0:
- store_end = store_start;
- break;
-
- default:
- fprintf(ci->tx, "%s BAD invalid character in message range\r\n",tag);
- return 1;
- }
-
- if (!imapcommands_use_uid)
- {
- store_start--;
- store_end--;
- }
-
- if (store_start == store_end)
- {
- thisnum = (imapcommands_use_uid ? store_start : ud->mailbox.seq_list[store_start]);
-
- if (imapcommands_use_uid)
- {
- /* check if the message with this UID belongs to this mailbox */
- if (binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
- store_start, &fn) == -1)
- continue;
- }
-
- result = db_set_msgflag(thisnum, ud->mailbox.uid, flaglist, action);
-
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- return -1;
- }
-
- if (!be_silent)
- {
- result = db_get_msgflag_all(thisnum, ud->mailbox.uid, msgflags);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- return -1;
+ if (flaglist[IMAP_STORE_FLAG_SEEN] == 1) {
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid,
+ ACL_RIGHT_SEEN);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error");
+ return -1; /* fatal */
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no right to store \\SEEN flag",
+ tag);
+ return 1;
+ }
+ }
+ if (flaglist[IMAP_STORE_FLAG_DELETED] == 1) {
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid,
+ ACL_RIGHT_DELETE);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error");
+ return -1; /* fatal */
}
-
- fprintf(ci->tx, "* %llu FETCH (FLAGS (",
- imapcommands_use_uid ? (u64_t)(fn+1) : store_start+1);
-
- for (j=0,isfirstout=1; j<IMAP_NFLAGS; j++)
- {
- if (msgflags[j])
- {
- fprintf(ci->tx, "%s%s", isfirstout ? "" : " ",imap_flag_desc_escaped[j]);
- if (isfirstout) isfirstout = 0;
- }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no right to store \\DELETED flag",
+ tag);
+ return 1;
+ }
+ }
+ if (flaglist[IMAP_STORE_FLAG_ANSWERED] == 1 ||
+ flaglist[IMAP_STORE_FLAG_FLAGGED] == 1 ||
+ flaglist[IMAP_STORE_FLAG_DRAFT] == 1 ||
+ flaglist[IMAP_STORE_FLAG_RECENT] == 1) {
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid,
+ ACL_RIGHT_WRITE);
+ if (result < 0) {
+ fprintf(ci->tx, "*BYE internal database error");
+ return -1;
}
+ if (result == 0) {
+ fprintf(ci->tx, "%s NO no right to store flags",
+ tag);
+ return 1;
+ }
+ }
+ /* end of ACL checking. If we get here without returning, the user has
+ the right to store the flags */
+
+ /* set flags & show if needed */
+ endptr = args[0];
+ while (*endptr) {
+ if (endptr != args[0])
+ endptr++; /* skip delimiter */
+
+ store_start = strtoull(endptr, &endptr, 10);
+
+ if (store_start == 0 || store_start >
+ (imapcommands_use_uid ? (ud->mailbox.msguidnext - 1) :
+ ud->mailbox.exists)) {
+ fprintf(ci->tx,
+ "%s BAD invalid message range specified\r\n",
+ tag);
+ return 1;
+ }
+
+ switch (*endptr) {
+ case ':':
+ store_end = strtoull(++endptr, &lastchar, 10);
+ endptr = lastchar;
+
+ if (*endptr == '*') {
+ store_end = (imapcommands_use_uid ?
+ (ud->mailbox.msguidnext -
+ 1) : ud->mailbox.exists);
+ endptr++;
+ break;
+ }
+
+ if (store_end == 0 || store_end >
+ (imapcommands_use_uid
+ ? (ud->mailbox.msguidnext -
+ 1) : ud->mailbox.exists)) {
+ fprintf(ci->tx,
+ "%s BAD invalid message range specified\r\n",
+ tag);
+ return 1;
+ }
+
+ if (store_end < store_start) {
+ i = store_start;
+ store_start = store_end;
+ store_end = i;
+ }
+ break;
+
+ case ',':
+ case 0:
+ store_end = store_start;
+ break;
+
+ default:
+ fprintf(ci->tx,
+ "%s BAD invalid character in message range\r\n",
+ tag);
+ return 1;
+ }
+
+ if (!imapcommands_use_uid) {
+ store_start--;
+ store_end--;
+ }
+
+ if (store_start == store_end) {
+ thisnum =
+ (imapcommands_use_uid ? store_start : ud->
+ mailbox.seq_list[store_start]);
+
+ if (imapcommands_use_uid) {
+ /* check if the message with this UID belongs to this mailbox */
+ if (binary_search
+ (ud->mailbox.seq_list,
+ ud->mailbox.exists, store_start,
+ &fn) == -1)
+ continue;
+ }
+
+ result =
+ db_set_msgflag(thisnum, ud->mailbox.uid,
+ flaglist, action);
+
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ if (!be_silent) {
+ result =
+ db_get_msgflag_all(thisnum,
+ ud->mailbox.uid,
+ msgflags);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ fprintf(ci->tx, "* %llu FETCH (FLAGS (",
+ imapcommands_use_uid ? (u64_t) (fn
+ +
+ 1)
+ : store_start + 1);
+
+ for (j = 0, isfirstout = 1;
+ j < IMAP_NFLAGS; j++) {
+ if (msgflags[j]) {
+ fprintf(ci->tx, "%s%s",
+ isfirstout ? "" :
+ " ",
+ imap_flag_desc_escaped
+ [j]);
+ if (isfirstout)
+ isfirstout = 0;
+ }
+ }
- fprintf(ci->tx,"))\r\n");
- }
- }
- else
- {
- if (!imapcommands_use_uid)
- {
- /* find the msgUID's to use */
- lo = ud->mailbox.seq_list[store_start];
- hi = ud->mailbox.seq_list[store_end];
-
- }
- else
- {
- lo = store_start;
- hi = store_end;
- }
-
- result = db_set_msgflag_range(lo, hi, ud->mailbox.uid, flaglist, action);
-
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- return -1;
- }
-
- if (!be_silent)
- {
- for (i=store_start; i<=store_end; i++)
- {
- thisnum = (imapcommands_use_uid ? i : ud->mailbox.seq_list[i]);
-
- if (imapcommands_use_uid) {
- /* check if the message with this UID belongs
- to this mailbox */
- if (binary_search(ud->mailbox.seq_list,
- ud->mailbox.exists, i, &fn) == -1)
- continue;
- }
-
- result = db_get_msgflag_all(thisnum, ud->mailbox.uid, msgflags);
- if (result == -1)
- {
- fprintf(ci->tx,"\r\n* BYE internal dbase error\r\n");
- return -1;
- }
-
- fprintf(ci->tx, "* %llu FETCH (FLAGS (",
- imapcommands_use_uid ? (u64_t)(fn+1) : i+1);
-
- for (j=0,isfirstout=1; j<IMAP_NFLAGS; j++)
- {
- if (msgflags[j])
- {
- fprintf(ci->tx, "%s%s", isfirstout ? "" : " ",imap_flag_desc_escaped[j]);
- if (isfirstout) isfirstout = 0;
+ fprintf(ci->tx, "))\r\n");
+ }
+ } else {
+ if (!imapcommands_use_uid) {
+ /* find the msgUID's to use */
+ lo = ud->mailbox.seq_list[store_start];
+ hi = ud->mailbox.seq_list[store_end];
+
+ } else {
+ lo = store_start;
+ hi = store_end;
}
- }
- fprintf(ci->tx,"))\r\n");
+ result =
+ db_set_msgflag_range(lo, hi, ud->mailbox.uid,
+ flaglist, action);
+
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ if (!be_silent) {
+ for (i = store_start; i <= store_end; i++) {
+ thisnum =
+ (imapcommands_use_uid ? i :
+ ud->mailbox.seq_list[i]);
+
+ if (imapcommands_use_uid) {
+ /* check if the message with this UID belongs
+ to this mailbox */
+ if (binary_search
+ (ud->mailbox.seq_list,
+ ud->mailbox.exists, i,
+ &fn) == -1)
+ continue;
+ }
+
+ result =
+ db_get_msgflag_all(thisnum,
+ ud->mailbox.
+ uid,
+ msgflags);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "\r\n* BYE internal dbase error\r\n");
+ return -1;
+ }
+
+ fprintf(ci->tx,
+ "* %llu FETCH (FLAGS (",
+ imapcommands_use_uid
+ ? (u64_t) (fn + 1) : i +
+ 1);
+
+ for (j = 0, isfirstout = 1;
+ j < IMAP_NFLAGS; j++) {
+ if (msgflags[j]) {
+ fprintf(ci->tx,
+ "%s%s",
+ isfirstout
+ ? "" : " ",
+ imap_flag_desc_escaped
+ [j]);
+ if (isfirstout)
+ isfirstout
+ = 0;
+ }
+ }
+
+ fprintf(ci->tx, "))\r\n");
+ }
+ }
}
- }
}
- }
- fprintf(ci->tx,"%s OK %sSTORE completed\r\n", tag, imapcommands_use_uid ? "UID ":"");
- return 0;
+ fprintf(ci->tx, "%s OK %sSTORE completed\r\n", tag,
+ imapcommands_use_uid ? "UID " : "");
+ return 0;
}
@@ -3511,141 +4132,155 @@ int _ic_store(char *tag, char **args, ClientInfo *ci)
*
* copy a message to another mailbox
*/
-int _ic_copy(char *tag, char **args, ClientInfo *ci)
+int _ic_copy(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- u64_t i,copy_start,copy_end;
- unsigned fn;
- u64_t destmboxid,thisnum;
- int result;
- u64_t new_msgid;
- char *endptr, *lastchar = NULL;
-
- if (!check_state_and_args("COPY", tag, args, 2, IMAPCS_SELECTED, ci))
- return 1; /* error, return */
-
- /* check if destination mailbox exists */
- if (db_findmailbox(args[1], ud->userid, &destmboxid) == -1) {
- fprintf(ci->tx, "* BYE internal dbase error\r\n");
- return -1; /* fatal */
- }
- if (destmboxid == 0) {
- /* error: cannot select mailbox */
- fprintf(ci->tx, "%s NO [TRYCREATE] specified mailbox does not exist\r\n",tag);
- return 1;
- }
-
- // check if user has right to COPY from source mailbox
- result = acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1; /* fatal */
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to copy from mailbox\r\n", tag);
- return 1;
- }
- // check if user has right to COPY to destination mailbox
- result = acl_has_right(ud->userid, destmboxid, ACL_RIGHT_INSERT);
- if (result < 0) {
- fprintf(ci->tx, "* BYE internal database error\r\n");
- return -1; /* fatal */
- }
- if (result == 0) {
- fprintf(ci->tx, "%s NO no permission to copy to mailbox\r\n", tag);
- return 1;
- }
-
- /* ok copy msgs */
- endptr = args[0];
- while (*endptr)
- {
- if (endptr != args[0])
- endptr++; /* skip delimiter */
-
- copy_start = strtoull(endptr, &lastchar, 10);
- endptr = lastchar;
-
- if (copy_start == 0 || copy_start >
- (imapcommands_use_uid ? (ud->mailbox.msguidnext-1) : ud->mailbox.exists))
- {
- fprintf(ci->tx, "%s BAD invalid message range specified\r\n",tag);
- return 1;
- }
-
- switch (*endptr)
- {
- case ':':
- copy_end = strtoull(++endptr, &lastchar, 10);
- endptr = lastchar;
-
- if (*endptr == '*')
- {
- copy_end = (imapcommands_use_uid ?
- (ud->mailbox.msguidnext-1) : ud->mailbox.exists);
- endptr++;
- break;
- }
-
- if (copy_end == 0 || copy_end >
- (imapcommands_use_uid ? (ud->mailbox.msguidnext-1) : ud->mailbox.exists))
- {
- fprintf(ci->tx, "%s BAD invalid message range specified\r\n",tag);
- return 1;
- }
-
- if (copy_end < copy_start)
- {
- i = copy_start;
- copy_start = copy_end;
- copy_end = i;
- }
- break;
-
- case ',':
- case 0:
- copy_end = copy_start;
- break;
-
- default:
- fprintf(ci->tx, "%s BAD invalid character in message range\r\n",tag);
- return 1;
- }
-
- if (!imapcommands_use_uid)
- {
- copy_start--;
- copy_end--;
- }
-
- for (i=copy_start; i<=copy_end; i++)
- {
- thisnum = (imapcommands_use_uid ? i : ud->mailbox.seq_list[i]);
-
- if (imapcommands_use_uid)
- {
- /* check if the message with this UID belongs to this mailbox */
- if (binary_search(ud->mailbox.seq_list, ud->mailbox.exists,
- i, &fn) == -1)
- continue;
- }
-
- result = db_copymsg(thisnum, destmboxid, ud->userid, &new_msgid);
- if (result == -1)
- {
- fprintf(ci->tx,"* BYE internal dbase error\r\n");
- return -1;
- }
- if (result == -2)
- {
- fprintf(ci->tx,"%s NO quotum would exceed\r\n", tag);
- return 1;
- }
- }
- }
-
- fprintf(ci->tx,"%s OK %sCOPY completed\r\n", tag, imapcommands_use_uid?"UID ":"");
- return 0;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ u64_t i, copy_start, copy_end;
+ unsigned fn;
+ u64_t destmboxid, thisnum;
+ int result;
+ u64_t new_msgid;
+ char *endptr, *lastchar = NULL;
+
+ if (!check_state_and_args
+ ("COPY", tag, args, 2, IMAPCS_SELECTED, ci))
+ return 1; /* error, return */
+
+ /* check if destination mailbox exists */
+ if (db_findmailbox(args[1], ud->userid, &destmboxid) == -1) {
+ fprintf(ci->tx, "* BYE internal dbase error\r\n");
+ return -1; /* fatal */
+ }
+ if (destmboxid == 0) {
+ /* error: cannot select mailbox */
+ fprintf(ci->tx,
+ "%s NO [TRYCREATE] specified mailbox does not exist\r\n",
+ tag);
+ return 1;
+ }
+ // check if user has right to COPY from source mailbox
+ result =
+ acl_has_right(ud->userid, ud->mailbox.uid, ACL_RIGHT_READ);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1; /* fatal */
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to copy from mailbox\r\n",
+ tag);
+ return 1;
+ }
+ // check if user has right to COPY to destination mailbox
+ result = acl_has_right(ud->userid, destmboxid, ACL_RIGHT_INSERT);
+ if (result < 0) {
+ fprintf(ci->tx, "* BYE internal database error\r\n");
+ return -1; /* fatal */
+ }
+ if (result == 0) {
+ fprintf(ci->tx,
+ "%s NO no permission to copy to mailbox\r\n", tag);
+ return 1;
+ }
+
+ /* ok copy msgs */
+ endptr = args[0];
+ while (*endptr) {
+ if (endptr != args[0])
+ endptr++; /* skip delimiter */
+
+ copy_start = strtoull(endptr, &lastchar, 10);
+ endptr = lastchar;
+
+ if (copy_start == 0 || copy_start >
+ (imapcommands_use_uid ? (ud->mailbox.msguidnext - 1) :
+ ud->mailbox.exists)) {
+ fprintf(ci->tx,
+ "%s BAD invalid message range specified\r\n",
+ tag);
+ return 1;
+ }
+
+ switch (*endptr) {
+ case ':':
+ copy_end = strtoull(++endptr, &lastchar, 10);
+ endptr = lastchar;
+
+ if (*endptr == '*') {
+ copy_end = (imapcommands_use_uid ?
+ (ud->mailbox.msguidnext -
+ 1) : ud->mailbox.exists);
+ endptr++;
+ break;
+ }
+
+ if (copy_end == 0 || copy_end >
+ (imapcommands_use_uid
+ ? (ud->mailbox.msguidnext -
+ 1) : ud->mailbox.exists)) {
+ fprintf(ci->tx,
+ "%s BAD invalid message range specified\r\n",
+ tag);
+ return 1;
+ }
+
+ if (copy_end < copy_start) {
+ i = copy_start;
+ copy_start = copy_end;
+ copy_end = i;
+ }
+ break;
+
+ case ',':
+ case 0:
+ copy_end = copy_start;
+ break;
+
+ default:
+ fprintf(ci->tx,
+ "%s BAD invalid character in message range\r\n",
+ tag);
+ return 1;
+ }
+
+ if (!imapcommands_use_uid) {
+ copy_start--;
+ copy_end--;
+ }
+
+ for (i = copy_start; i <= copy_end; i++) {
+ thisnum =
+ (imapcommands_use_uid ? i : ud->mailbox.
+ seq_list[i]);
+
+ if (imapcommands_use_uid) {
+ /* check if the message with this UID belongs to this mailbox */
+ if (binary_search
+ (ud->mailbox.seq_list,
+ ud->mailbox.exists, i, &fn) == -1)
+ continue;
+ }
+
+ result =
+ db_copymsg(thisnum, destmboxid, ud->userid,
+ &new_msgid);
+ if (result == -1) {
+ fprintf(ci->tx,
+ "* BYE internal dbase error\r\n");
+ return -1;
+ }
+ if (result == -2) {
+ fprintf(ci->tx,
+ "%s NO quotum would exceed\r\n",
+ tag);
+ return 1;
+ }
+ }
+ }
+
+ fprintf(ci->tx, "%s OK %sCOPY completed\r\n", tag,
+ imapcommands_use_uid ? "UID " : "");
+ return 0;
}
@@ -3654,67 +4289,70 @@ int _ic_copy(char *tag, char **args, ClientInfo *ci)
*
* fetch/store/copy/search message UID's
*/
-int _ic_uid(char *tag, char **args, ClientInfo *ci)
+int _ic_uid(char *tag, char **args, ClientInfo * ci)
{
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- int result;
-
- if (ud->state != IMAPCS_SELECTED)
- {
- fprintf(ci->tx,"%s BAD UID command received in invalid state\r\n",tag);
- return 1;
- }
-
- if (!args[0])
- {
- fprintf(ci->tx,"%s BAD missing argument(s) to UID\r\n",tag);
- return 1;
- }
-
- imapcommands_use_uid = 1; /* set global var to make clear we will be using UID's */
- /* ACL rights for UID are handled by the other functions called below */
- if (strcasecmp(args[0], "fetch") == 0)
- result = _ic_fetch(tag, &args[1], ci);
- else if (strcasecmp(args[0], "copy") == 0)
- result = _ic_copy(tag, &args[1], ci);
- else if (strcasecmp(args[0], "store") == 0)
- result = _ic_store(tag, &args[1], ci);
- else if (strcasecmp(args[0], "search") == 0)
- result = _ic_search(tag, &args[1], ci);
- else
- {
- fprintf(ci->tx,"%s BAD invalid UID command\r\n",tag);
- result = 1;
- }
-
- imapcommands_use_uid = 0;
-
- return result;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ int result;
+
+ if (ud->state != IMAPCS_SELECTED) {
+ fprintf(ci->tx,
+ "%s BAD UID command received in invalid state\r\n",
+ tag);
+ return 1;
+ }
+
+ if (!args[0]) {
+ fprintf(ci->tx, "%s BAD missing argument(s) to UID\r\n",
+ tag);
+ return 1;
+ }
+
+ imapcommands_use_uid = 1; /* set global var to make clear we will be using UID's */
+ /* ACL rights for UID are handled by the other functions called below */
+ if (strcasecmp(args[0], "fetch") == 0)
+ result = _ic_fetch(tag, &args[1], ci);
+ else if (strcasecmp(args[0], "copy") == 0)
+ result = _ic_copy(tag, &args[1], ci);
+ else if (strcasecmp(args[0], "store") == 0)
+ result = _ic_store(tag, &args[1], ci);
+ else if (strcasecmp(args[0], "search") == 0)
+ result = _ic_search(tag, &args[1], ci);
+ else {
+ fprintf(ci->tx, "%s BAD invalid UID command\r\n", tag);
+ result = 1;
+ }
+
+ imapcommands_use_uid = 0;
+
+ return result;
}
/* Helper function for _ic_getquotaroot() and _ic_getquota().
* Send all resource limits in `quota'.
*/
-void send_quota(quota_t *quota, ClientInfo *ci) {
- int r;
- u64_t usage, limit;
- char *name;
-
- for (r=0; r<quota->n_resources; r++) {
- if (quota->resource[r].limit > 0) {
- switch (quota->resource[r].type) {
- case RT_STORAGE:
- name = "STORAGE";
- usage = quota->resource[r].usage/1024;
- limit = quota->resource[r].limit/1024;
- break;
- default: continue;
- }
- fprintf(ci->tx, "* QUOTA \"%s\" (%s %llu %llu)\r\n",
- quota->root, name, usage, limit);
+void send_quota(quota_t * quota, ClientInfo * ci)
+{
+ int r;
+ u64_t usage, limit;
+ char *name;
+
+ for (r = 0; r < quota->n_resources; r++) {
+ if (quota->resource[r].limit > 0) {
+ switch (quota->resource[r].type) {
+ case RT_STORAGE:
+ name = "STORAGE";
+ usage = quota->resource[r].usage / 1024;
+ limit = quota->resource[r].limit / 1024;
+ break;
+ default:
+ continue;
+ }
+ fprintf(ci->tx,
+ "* QUOTA \"%s\" (%s %llu %llu)\r\n",
+ quota->root, name, usage, limit);
+ }
}
- }
}
/*
@@ -3722,33 +4360,35 @@ void send_quota(quota_t *quota, ClientInfo *ci) {
*
* get quota root and send quota
*/
-int _ic_getquotaroot(char *tag, char **args, ClientInfo *ci) {
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- quota_t *quota;
- char *root, *errormsg;
-
- if (!check_state_and_args("GETQUOTAROOT", tag, args, 1,
- IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- root = quota_get_quotaroot(ud->userid, args[0], &errormsg);
- if (root == NULL) {
- fprintf(ci->tx, "%s NO %s\r\n", tag, errormsg);
- return 1;
- }
-
- quota = quota_get_quota(ud->userid, root, &errormsg);
- if (quota == NULL) {
- fprintf(ci->tx, "%s NO %s\r\n", tag, errormsg);
- return 1;
- }
-
- fprintf(ci->tx, "* QUOTAROOT \"%s\" \"%s\"\r\n", args[0], quota->root);
- send_quota(quota, ci);
- quota_free(quota);
-
- fprintf(ci->tx, "%s OK GETQUOTAROOT completed\r\n", tag);
- return 0;
+int _ic_getquotaroot(char *tag, char **args, ClientInfo * ci)
+{
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ quota_t *quota;
+ char *root, *errormsg;
+
+ if (!check_state_and_args("GETQUOTAROOT", tag, args, 1,
+ IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ root = quota_get_quotaroot(ud->userid, args[0], &errormsg);
+ if (root == NULL) {
+ fprintf(ci->tx, "%s NO %s\r\n", tag, errormsg);
+ return 1;
+ }
+
+ quota = quota_get_quota(ud->userid, root, &errormsg);
+ if (quota == NULL) {
+ fprintf(ci->tx, "%s NO %s\r\n", tag, errormsg);
+ return 1;
+ }
+
+ fprintf(ci->tx, "* QUOTAROOT \"%s\" \"%s\"\r\n", args[0],
+ quota->root);
+ send_quota(quota, ci);
+ quota_free(quota);
+
+ fprintf(ci->tx, "%s OK GETQUOTAROOT completed\r\n", tag);
+ return 0;
}
/*
@@ -3756,37 +4396,37 @@ int _ic_getquotaroot(char *tag, char **args, ClientInfo *ci) {
*
* get quota
*/
-int _ic_getquota(char *tag, char **args, ClientInfo *ci) {
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
- quota_t *quota;
- char *errormsg;
-
- if (!check_state_and_args("GETQUOTA", tag, args, 1,
- IMAPCS_AUTHENTICATED, ci))
- return 1; /* error, return */
-
- quota = quota_get_quota(ud->userid, args[0], &errormsg);
- if (quota == NULL) {
- fprintf(ci->tx, "%s NO %s\r\n", tag, errormsg);
- return 1;
- }
-
- send_quota(quota, ci);
- quota_free(quota);
-
- fprintf(ci->tx, "%s OK GETQUOTA completed\r\n", tag);
- return 0;
+int _ic_getquota(char *tag, char **args, ClientInfo * ci)
+{
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+ quota_t *quota;
+ char *errormsg;
+
+ if (!check_state_and_args("GETQUOTA", tag, args, 1,
+ IMAPCS_AUTHENTICATED, ci))
+ return 1; /* error, return */
+
+ quota = quota_get_quota(ud->userid, args[0], &errormsg);
+ if (quota == NULL) {
+ fprintf(ci->tx, "%s NO %s\r\n", tag, errormsg);
+ return 1;
+ }
+
+ send_quota(quota, ci);
+ quota_free(quota);
+
+ fprintf(ci->tx, "%s OK GETQUOTA completed\r\n", tag);
+ return 0;
}
/* returns -1 on error, 0 if user or mailbox not found and 1 otherwise */
static int imap_acl_pre_administer(const char *mailboxname,
- const char *username,
- u64_t executing_userid,
- u64_t *mboxid,
- u64_t *target_userid)
+ const char *username,
+ u64_t executing_userid,
+ u64_t * mboxid, u64_t * target_userid)
{
int result;
- result = db_findmailbox(mailboxname, executing_userid, mboxid);
+ result = db_findmailbox(mailboxname, executing_userid, mboxid);
if (result < 1)
return result;
@@ -3797,14 +4437,14 @@ static int imap_acl_pre_administer(const char *mailboxname,
return 1;
}
-int _ic_setacl(char *tag, char **args, ClientInfo *ci)
+int _ic_setacl(char *tag, char **args, ClientInfo * ci)
{
/* SETACL mailboxname identifier mod_rights */
- imap_userdata_t *ud = (imap_userdata_t*) ci->userData;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
int result;
u64_t mboxid;
u64_t targetuserid;
-
+
if (!check_state_and_args("SETACL", tag, args, 3,
IMAPCS_AUTHENTICATED, ci))
return 1;
@@ -3819,12 +4459,10 @@ int _ic_setacl(char *tag, char **args, ClientInfo *ci)
tag);
return 1;
}
-
// has the rights to 'administer' this mailbox?
if (acl_has_right(ud->userid, mboxid, ACL_RIGHT_ADMINISTER) != 1) {
fprintf(ci->tx, "%s NO SETACL failure: can't set acl, "
- "you don't have the proper rights\r\n",
- tag);
+ "you don't have the proper rights\r\n", tag);
return 1;
}
// set the new acl
@@ -3838,13 +4476,13 @@ int _ic_setacl(char *tag, char **args, ClientInfo *ci)
}
-int _ic_deleteacl(char *tag, char **args, ClientInfo *ci)
+int _ic_deleteacl(char *tag, char **args, ClientInfo * ci)
{
// DELETEACL mailboxname identifier
- imap_userdata_t *ud = (imap_userdata_t*) ci->userData;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
u64_t mboxid;
u64_t targetuserid;
-
+
if (!check_state_and_args("DELETEACL", tag, args, 2,
IMAPCS_AUTHENTICATED, ci))
return 1;
@@ -3854,7 +4492,6 @@ int _ic_deleteacl(char *tag, char **args, ClientInfo *ci)
fprintf(ci->tx, "* BYE internal dbase error\r\n");
return -1;
}
-
// has the rights to 'administer' this mailbox?
if (acl_has_right(ud->userid, mboxid, ACL_RIGHT_ADMINISTER) != 1) {
fprintf(ci->tx, "%s NO DELETEACL failure: can't delete "
@@ -3862,7 +4499,7 @@ int _ic_deleteacl(char *tag, char **args, ClientInfo *ci)
return 1;
}
// set the new acl
- if (acl_delete_acl(targetuserid,mboxid) < 0) {
+ if (acl_delete_acl(targetuserid, mboxid) < 0) {
fprintf(ci->tx, "* BYE internal database error\r\n");
return -1;
}
@@ -3871,10 +4508,10 @@ int _ic_deleteacl(char *tag, char **args, ClientInfo *ci)
return 0;
}
-int _ic_getacl(char *tag, char **args, ClientInfo *ci)
+int _ic_getacl(char *tag, char **args, ClientInfo * ci)
{
/* GETACL mailboxname */
- imap_userdata_t *ud = (imap_userdata_t*) ci->userData;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
int result;
u64_t mboxid;
char *acl_string;
@@ -3892,29 +4529,28 @@ int _ic_getacl(char *tag, char **args, ClientInfo *ci)
tag);
return 1;
}
-
// get acl string (string of identifier-rights pairs)
if (!(acl_string = acl_get_acl(mboxid))) {
fprintf(ci->tx, "* BYE internal database error\r\n");
return -1;
}
-
+
fprintf(ci->tx, "* ACL \"%s\" %s\r\n", args[0], acl_string);
- my_free(acl_string);
+ my_free(acl_string);
fprintf(ci->tx, "%s OK GETACL completed\r\n", tag);
return 0;
}
-
-int _ic_listrights(char *tag, char **args, ClientInfo *ci)
+
+int _ic_listrights(char *tag, char **args, ClientInfo * ci)
{
/* LISTRIGHTS mailboxname identifier */
- imap_userdata_t *ud = (imap_userdata_t*) ci->userData;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
int result;
u64_t mboxid;
u64_t targetuserid;
const char *listrights_string;
-
+
if (!check_state_and_args("LISTRIGHTS", tag, args, 2,
IMAPCS_AUTHENTICATED, ci))
return 1;
@@ -3925,14 +4561,15 @@ int _ic_listrights(char *tag, char **args, ClientInfo *ci)
fprintf(ci->tx, "* BYE internal database error\r\n");
return -1;
} else if (result == 0) {
- fprintf(ci->tx, "%s, NO LISTRIGHTS failure: can't set acl\r\n",
+ fprintf(ci->tx,
+ "%s, NO LISTRIGHTS failure: can't set acl\r\n",
tag);
return 1;
}
-
// has the rights to 'administer' this mailbox?
if (acl_has_right(ud->userid, mboxid, ACL_RIGHT_ADMINISTER) != 1) {
- fprintf(ci->tx, "%s NO LISTRIGHTS failure: can't set acl\r\n",
+ fprintf(ci->tx,
+ "%s NO LISTRIGHTS failure: can't set acl\r\n",
tag);
return 1;
}
@@ -3948,10 +4585,10 @@ int _ic_listrights(char *tag, char **args, ClientInfo *ci)
return 0;
}
-int _ic_myrights(char *tag, char **args, ClientInfo *ci)
+int _ic_myrights(char *tag, char **args, ClientInfo * ci)
{
/* MYRIGHTS mailboxname */
- imap_userdata_t *ud = (imap_userdata_t*) ci->userData;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
int result;
u64_t mboxid;
char *myrights_string;
@@ -3959,41 +4596,41 @@ int _ic_myrights(char *tag, char **args, ClientInfo *ci)
if (!check_state_and_args("LISTRIGHTS", tag, args, 1,
IMAPCS_AUTHENTICATED, ci))
return 1;
-
+
result = db_findmailbox(args[0], ud->userid, &mboxid);
if (result == -1) {
fprintf(ci->tx, "* BYE internal database error\r\n");
return -1;
} else if (result == 0) {
- fprintf(ci->tx, "%s, NO MYRIGHTS failure: unknown mailbox\r\n",
+ fprintf(ci->tx,
+ "%s, NO MYRIGHTS failure: unknown mailbox\r\n",
tag);
return 1;
}
-
+
if (!(myrights_string = acl_myrights(ud->userid, mboxid))) {
fprintf(ci->tx, "* BYE internal database error\r\n");
return -1;
}
-
- fprintf(ci->tx, "* MYRIGHTS \"%s\" %s\r\n", args[0], myrights_string);
+
+ fprintf(ci->tx, "* MYRIGHTS \"%s\" %s\r\n", args[0],
+ myrights_string);
my_free(myrights_string);
fprintf(ci->tx, "%s OK MYRIGHTS complete\r\n", tag);
return 0;
}
-int _ic_namespace(char *tag, char **args, ClientInfo *ci)
+int _ic_namespace(char *tag, char **args, ClientInfo * ci)
{
/* NAMESPACE command */
if (!check_state_and_args("NAMESPACE", tag, args, 0,
IMAPCS_AUTHENTICATED, ci))
return 1;
-
+
fprintf(ci->tx, "* NAMESPACE ((\"\" \"%s\")) ((\"%s\" \"%s\")) "
- "((\"%s\" \"%s\"))\r\n",
+ "((\"%s\" \"%s\"))\r\n",
MAILBOX_SEPERATOR, NAMESPACE_USER,
MAILBOX_SEPERATOR, NAMESPACE_PUBLIC, MAILBOX_SEPERATOR);
fprintf(ci->tx, "%s OK NAMESPACE complete\r\n", tag);
return 0;
}
-
-
diff --git a/imapcommands.h b/imapcommands.h
index ce422e8a..7d1b023f 100644
--- a/imapcommands.h
+++ b/imapcommands.h
@@ -35,65 +35,65 @@
#include "imap4.h"
/* any-state commands */
-int _ic_capability(char *tag, char **args, ClientInfo *ci);
-int _ic_noop(char *tag, char **args, ClientInfo *ci);
-int _ic_logout(char *tag, char **args, ClientInfo *ci);
+int _ic_capability(char *tag, char **args, ClientInfo * ci);
+int _ic_noop(char *tag, char **args, ClientInfo * ci);
+int _ic_logout(char *tag, char **args, ClientInfo * ci);
/* non-auth state commands */
-int _ic_login(char *tag, char **args, ClientInfo *ci);
-int _ic_authenticate(char *tag, char **args, ClientInfo *ci);
+int _ic_login(char *tag, char **args, ClientInfo * ci);
+int _ic_authenticate(char *tag, char **args, ClientInfo * ci);
/* auth state commands */
-int _ic_select(char *tag, char **args, ClientInfo *ci);
-int _ic_examine(char *tag, char **args, ClientInfo *ci);
-int _ic_create(char *tag, char **args, ClientInfo *ci);
-int _ic_delete(char *tag, char **args, ClientInfo *ci);
-int _ic_rename(char *tag, char **args, ClientInfo *ci);
-int _ic_subscribe(char *tag, char **args, ClientInfo *ci);
-int _ic_unsubscribe(char *tag, char **args, ClientInfo *ci);
-int _ic_list(char *tag, char **args, ClientInfo *ci);
-int _ic_lsub(char *tag, char **args, ClientInfo *ci);
-int _ic_status(char *tag, char **args, ClientInfo *ci);
-int _ic_append(char *tag, char **args, ClientInfo *ci);
+int _ic_select(char *tag, char **args, ClientInfo * ci);
+int _ic_examine(char *tag, char **args, ClientInfo * ci);
+int _ic_create(char *tag, char **args, ClientInfo * ci);
+int _ic_delete(char *tag, char **args, ClientInfo * ci);
+int _ic_rename(char *tag, char **args, ClientInfo * ci);
+int _ic_subscribe(char *tag, char **args, ClientInfo * ci);
+int _ic_unsubscribe(char *tag, char **args, ClientInfo * ci);
+int _ic_list(char *tag, char **args, ClientInfo * ci);
+int _ic_lsub(char *tag, char **args, ClientInfo * ci);
+int _ic_status(char *tag, char **args, ClientInfo * ci);
+int _ic_append(char *tag, char **args, ClientInfo * ci);
/* selected-state commands */
-int _ic_check(char *tag, char **args, ClientInfo *ci);
-int _ic_close(char *tag, char **args, ClientInfo *ci);
-int _ic_expunge(char *tag, char **args, ClientInfo *ci);
-int _ic_search(char *tag, char **args, ClientInfo *ci);
-int _ic_fetch(char *tag, char **args, ClientInfo *ci);
-int _ic_store(char *tag, char **args, ClientInfo *ci);
-int _ic_copy(char *tag, char **args, ClientInfo *ci);
-int _ic_uid(char *tag, char **args, ClientInfo *ci);
+int _ic_check(char *tag, char **args, ClientInfo * ci);
+int _ic_close(char *tag, char **args, ClientInfo * ci);
+int _ic_expunge(char *tag, char **args, ClientInfo * ci);
+int _ic_search(char *tag, char **args, ClientInfo * ci);
+int _ic_fetch(char *tag, char **args, ClientInfo * ci);
+int _ic_store(char *tag, char **args, ClientInfo * ci);
+int _ic_copy(char *tag, char **args, ClientInfo * ci);
+int _ic_uid(char *tag, char **args, ClientInfo * ci);
/* quota commands */
-int _ic_getquotaroot(char *tag, char **args, ClientInfo *ci);
-int _ic_getquota(char *tag, char **args, ClientInfo *ci);
+int _ic_getquotaroot(char *tag, char **args, ClientInfo * ci);
+int _ic_getquota(char *tag, char **args, ClientInfo * ci);
/* acl commands */
/**
* \brief SETACL command
*/
-int _ic_setacl(char *tag, char **args, ClientInfo *ci);
+int _ic_setacl(char *tag, char **args, ClientInfo * ci);
/**
* DELETEACL command
*/
-int _ic_deleteacl(char *tag, char **args, ClientInfo *ci);
+int _ic_deleteacl(char *tag, char **args, ClientInfo * ci);
/**
* GETACL command
*/
-int _ic_getacl(char *tag, char **args, ClientInfo *ci);
+int _ic_getacl(char *tag, char **args, ClientInfo * ci);
/**
* LISTRIGHTS command
*/
-int _ic_listrights(char *tag, char **args, ClientInfo *ci);
+int _ic_listrights(char *tag, char **args, ClientInfo * ci);
/**
* MYRIGHTS command
*/
-int _ic_myrights(char *tag, char **args, ClientInfo *ci);
+int _ic_myrights(char *tag, char **args, ClientInfo * ci);
/**
* NAMESPACE command
*/
-int _ic_namespace(char *tag, char **args, ClientInfo *ci);
+int _ic_namespace(char *tag, char **args, ClientInfo * ci);
#endif
diff --git a/imapd.c b/imapd.c
index a9fd625a..81f0c250 100644
--- a/imapd.c
+++ b/imapd.c
@@ -52,10 +52,10 @@ char *configFile = DEFAULT_CONFIG_FILE;
/* set up database login data */
extern db_param_t _db_params;
-static void SetConfigItems(serverConfig_t *config, struct list *items);
+static void SetConfigItems(serverConfig_t * config, struct list *items);
static void Daemonize(void);
static int SetMainSigHandler(void);
-static void MainSigHandler(int sig, siginfo_t *info, void *data);
+static void MainSigHandler(int sig, siginfo_t * info, void *data);
int imap_before_smtp = 0;
@@ -69,253 +69,279 @@ int main(int argc, char *argv[], char **envp)
int main(int argc, char *argv[])
#endif
{
- serverConfig_t config;
- struct list imapItems, sysItems;
- int result, status;
- pid_t pid;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- if (argc >= 2 && argv[1])
- {
- if (strcmp(argv[1],"-v") == 0)
- {
- printf ("\n*** DBMAIL: dbmail-imap version $Revision$ %s\n",COPYRIGHT);
- return 0;
+ serverConfig_t config;
+ struct list imapItems, sysItems;
+ int result, status;
+ pid_t pid;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ if (argc >= 2 && argv[1]) {
+ if (strcmp(argv[1], "-v") == 0) {
+ printf
+ ("\n*** DBMAIL: dbmail-imap version $Revision$ %s\n",
+ COPYRIGHT);
+ return 0;
+ } else if (argv[2] && (strcmp(argv[1], "-f") == 0)) {
+ configFile = argv[2];
+ }
}
- else if (argv[2] && (strcmp(argv[1],"-f") == 0))
- {
- configFile = argv[2];
- }
- }
-
- SetMainSigHandler();
- Daemonize();
- result = 0;
-
- do
- {
- mainStop = 0;
- mainRestart = 0;
-
- trace(TRACE_DEBUG, "main(): reading config");
-#ifdef PROC_TITLES
- init_set_proc_title(argc, argv, envp, PNAME);
- set_proc_title("%s", "Idle");
-#endif
- ReadConfig("IMAP", configFile, &imapItems);
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetConfigItems(&config, &imapItems);
- SetTraceLevel(&imapItems);
- GetDBParams(&_db_params, &sysItems);
-
- config.ClientHandler = IMAPClientHandler;
- config.timeoutMsg = IMAP_TIMEOUT_MSG;
-
- CreateSocket(&config);
- trace(TRACE_ERROR, "main(): socket created, starting server");
-
- switch ( (pid = fork()) )
- {
- case -1:
- close(config.listenSocket);
- trace(TRACE_FATAL, "main(): fork failed [%s]", strerror(errno));
-
- case 0:
- /* child process */
- drop_privileges(config.serverUser, config.serverGroup);
- result = StartServer(&config);
- trace(TRACE_INFO, "main(): server done, exit.");
- exit(result);
-
- default:
- /* parent process, wait for child to exit */
- while (waitpid(pid, &status, WNOHANG|WUNTRACED) == 0)
- {
- if (mainStop)
- kill(pid, SIGTERM);
-
- if (mainRestart)
- kill(pid, SIGHUP);
-
- sleep(2);
- }
-
- if (WIFEXITED(status))
- {
- /* child process terminated neatly */
- result = WEXITSTATUS(status);
- trace(TRACE_DEBUG, "main(): server has exited, exit status [%d]", result);
- }
- else
- {
- /* child stopped or signaled, don't like */
- /* make sure it is dead */
- trace(TRACE_DEBUG, "main(): server has not exited normally. Killing..");
-
- kill(pid, SIGKILL);
- result = 0;
- }
- }
+ SetMainSigHandler();
+ Daemonize();
+ result = 0;
- list_freelist(&imapItems.start);
- list_freelist(&sysItems.start);
- close(config.listenSocket);
-
- } while (result == 1 && !mainStop) ; /* 1 means reread-config and restart */
+ do {
+ mainStop = 0;
+ mainRestart = 0;
+
+ trace(TRACE_DEBUG, "main(): reading config");
+#ifdef PROC_TITLES
+ init_set_proc_title(argc, argv, envp, PNAME);
+ set_proc_title("%s", "Idle");
+#endif
- trace(TRACE_INFO, "main(): exit");
- return 0;
+ ReadConfig("IMAP", configFile, &imapItems);
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetConfigItems(&config, &imapItems);
+ SetTraceLevel(&imapItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ config.ClientHandler = IMAPClientHandler;
+ config.timeoutMsg = IMAP_TIMEOUT_MSG;
+
+ CreateSocket(&config);
+ trace(TRACE_ERROR,
+ "main(): socket created, starting server");
+
+ switch ((pid = fork())) {
+ case -1:
+ close(config.listenSocket);
+ trace(TRACE_FATAL, "main(): fork failed [%s]",
+ strerror(errno));
+
+ case 0:
+ /* child process */
+ drop_privileges(config.serverUser,
+ config.serverGroup);
+ result = StartServer(&config);
+ trace(TRACE_INFO, "main(): server done, exit.");
+ exit(result);
+
+ default:
+ /* parent process, wait for child to exit */
+ while (waitpid(pid, &status, WNOHANG | WUNTRACED)
+ == 0) {
+ if (mainStop)
+ kill(pid, SIGTERM);
+
+ if (mainRestart)
+ kill(pid, SIGHUP);
+
+ sleep(2);
+ }
+
+ if (WIFEXITED(status)) {
+ /* child process terminated neatly */
+ result = WEXITSTATUS(status);
+ trace(TRACE_DEBUG,
+ "main(): server has exited, exit status [%d]",
+ result);
+ } else {
+ /* child stopped or signaled, don't like */
+ /* make sure it is dead */
+ trace(TRACE_DEBUG,
+ "main(): server has not exited normally. Killing..");
+
+ kill(pid, SIGKILL);
+ result = 0;
+ }
+ }
+
+ list_freelist(&imapItems.start);
+ list_freelist(&sysItems.start);
+ close(config.listenSocket);
+
+ } while (result == 1 && !mainStop); /* 1 means reread-config and restart */
+
+ trace(TRACE_INFO, "main(): exit");
+ return 0;
}
-void MainSigHandler(int sig, siginfo_t *info UNUSED, void *data UNUSED)
+void MainSigHandler(int sig, siginfo_t * info UNUSED, void *data UNUSED)
{
- trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
+ trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
- if (sig == SIGHUP)
- mainRestart = 1;
- else
- mainStop = 1;
+ if (sig == SIGHUP)
+ mainRestart = 1;
+ else
+ mainStop = 1;
}
void Daemonize()
{
- if (fork())
- exit(0);
- setsid();
+ if (fork())
+ exit(0);
+ setsid();
- if (fork())
- exit(0);
-}
+ if (fork())
+ exit(0);
+}
int SetMainSigHandler()
{
- struct sigaction act;
+ struct sigaction act;
- /* init & install signal handlers */
- memset(&act, 0, sizeof(act));
+ /* init & install signal handlers */
+ memset(&act, 0, sizeof(act));
- act.sa_sigaction = MainSigHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = MainSigHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
- sigaction(SIGINT, &act, 0);
- sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
- sigaction(SIGTERM, &act, 0);
- sigaction(SIGHUP, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
- return 0;
+ return 0;
}
-void SetConfigItems(serverConfig_t *config, struct list *items)
+void SetConfigItems(serverConfig_t * config, struct list *items)
{
- field_t val;
-
- /* read items: NCHILDREN */
- GetConfigValue("NCHILDREN", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for NCHILDREN in config file");
+ field_t val;
+
+ /* read items: NCHILDREN */
+ GetConfigValue("NCHILDREN", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for NCHILDREN in config file");
+
+ if ((config->nChildren = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for NCHILDREN is invalid: [%d]",
+ config->nChildren);
+
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): server will create [%d] children",
+ config->nChildren);
+
+
+ /* read items: MAXCONNECTS */
+ GetConfigValue("MAXCONNECTS", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for MAXCONNECTS in config file");
- if ( (config->nChildren = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for NCHILDREN is invalid: [%d]", config->nChildren);
+ if ((config->childMaxConnect = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]",
+ config->childMaxConnect);
- trace(TRACE_DEBUG, "SetConfigItems(): server will create [%d] children", config->nChildren);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): children will make max. [%d] connections",
+ config->childMaxConnect);
- /* read items: MAXCONNECTS */
- GetConfigValue("MAXCONNECTS", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for MAXCONNECTS in config file");
+ /* read items: TIMEOUT */
+ GetConfigValue("TIMEOUT", items, val);
+ if (strlen(val) == 0) {
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for TIMEOUT in config file");
+ config->timeout = 0;
+ } else if ((config->timeout = atoi(val)) <= 30)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for TIMEOUT is invalid: [%d]",
+ config->timeout);
- if ( (config->childMaxConnect = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]", config->childMaxConnect);
+ trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds",
+ config->timeout);
- trace(TRACE_DEBUG, "SetConfigItems(): children will make max. [%d] connections", config->childMaxConnect);
-
- /* read items: TIMEOUT */
- GetConfigValue("TIMEOUT", items, val);
- if (strlen(val) == 0)
- {
- trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMEOUT in config file");
- config->timeout = 0;
- }
- else if ( (config->timeout = atoi(val)) <= 30)
- trace(TRACE_FATAL, "SetConfigItems(): value for TIMEOUT is invalid: [%d]", config->timeout);
+ /* read items: PORT */
+ GetConfigValue("PORT", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for PORT in config file");
- trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds", config->timeout);
-
+ if ((config->port = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for PORT is invalid: [%d]",
+ config->port);
- /* read items: PORT */
- GetConfigValue("PORT", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for PORT in config file");
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]",
+ config->port);
- if ( (config->port = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for PORT is invalid: [%d]", config->port);
- trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]", config->port);
-
+ /* read items: BINDIP */
+ GetConfigValue("BINDIP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for BINDIP in config file");
- /* read items: BINDIP */
- GetConfigValue("BINDIP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for BINDIP in config file");
+ strncpy(config->ip, val, IPLEN);
+ config->ip[IPLEN - 1] = '\0';
- strncpy(config->ip, val, IPLEN);
- config->ip[IPLEN-1] = '\0';
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]",
+ config->ip);
- trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]", config->ip);
+ /* read items: RESOLVE_IP */
+ GetConfigValue("RESOLVE_IP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for RESOLVE_IP in config file");
- /* read items: RESOLVE_IP */
- GetConfigValue("RESOLVE_IP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for RESOLVE_IP in config file");
+ config->resolveIP = (strcasecmp(val, "yes") == 0);
- config->resolveIP = (strcasecmp(val, "yes") == 0);
+ trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP",
+ config->resolveIP ? "" : "not ");
- trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP", config->resolveIP ? "" : "not ");
+ /* read items: IMAP-BEFORE-SMTP */
+ GetConfigValue("IMAP_BEFORE_SMTP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for IMAP_BEFORE_SMTP in config file");
- /* read items: IMAP-BEFORE-SMTP */
- GetConfigValue("IMAP_BEFORE_SMTP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for IMAP_BEFORE_SMTP in config file");
+ imap_before_smtp = (strcasecmp(val, "yes") == 0);
- imap_before_smtp = (strcasecmp(val, "yes") == 0);
+ trace(TRACE_DEBUG, "SetConfigItems(): %s IMAP-before-SMTP",
+ imap_before_smtp ? "Enabling" : "Disabling");
- trace(TRACE_DEBUG, "SetConfigItems(): %s IMAP-before-SMTP",
- imap_before_smtp ? "Enabling" : "Disabling");
+ /* read items: EFFECTIVE-USER */
+ GetConfigValue("EFFECTIVE_USER", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_USER in config file");
- /* read items: EFFECTIVE-USER */
- GetConfigValue("EFFECTIVE_USER", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_USER in config file");
+ strncpy(config->serverUser, val, FIELDSIZE);
+ config->serverUser[FIELDSIZE - 1] = '\0';
- strncpy(config->serverUser, val, FIELDSIZE);
- config->serverUser[FIELDSIZE-1] = '\0';
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective user shall be [%s]",
+ config->serverUser);
- trace(TRACE_DEBUG, "SetConfigItems(): effective user shall be [%s]", config->serverUser);
+ /* read items: EFFECTIVE-GROUP */
+ GetConfigValue("EFFECTIVE_GROUP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
- /* read items: EFFECTIVE-GROUP */
- GetConfigValue("EFFECTIVE_GROUP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
+ strncpy(config->serverGroup, val, FIELDSIZE);
+ config->serverGroup[FIELDSIZE - 1] = '\0';
- strncpy(config->serverGroup, val, FIELDSIZE);
- config->serverGroup[FIELDSIZE-1] = '\0';
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective group shall be [%s]",
+ config->serverGroup);
- trace(TRACE_DEBUG, "SetConfigItems(): effective group shall be [%s]", config->serverGroup);
-
}
diff --git a/imaputil.c b/imaputil.c
index 52b6d94e..571ed579 100644
--- a/imaputil.c
+++ b/imaputil.c
@@ -62,7 +62,8 @@ extern const char AcceptedMailboxnameChars[];
extern const char *month_desc[];
-char base64encodestring[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+char base64encodestring[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* returned by date_sql2imap() */
char _imapdate[IMAP_INTERNALDATE_LEN] = "03-Nov-1979 00:00:00";
@@ -70,19 +71,16 @@ char _imapdate[IMAP_INTERNALDATE_LEN] = "03-Nov-1979 00:00:00";
/* returned by date_imap2sql() */
char _sqldate[] = "1979-11-03 00:00:00";
-const int month_len[]=
-{
- 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+const int month_len[] = {
+ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
-
-const char *item_desc[] =
-{
- "TEXT", "HEADER", "MIME", "HEADER.FIELDS", "HEADER.FIELDS.NOT"
+
+const char *item_desc[] = {
+ "TEXT", "HEADER", "MIME", "HEADER.FIELDS", "HEADER.FIELDS.NOT"
};
-const char *envelope_items[] =
-{
- "from", "sender", "reply-to", "to", "cc", "bcc", NULL
+const char *envelope_items[] = {
+ "from", "sender", "reply-to", "to", "cc", "bcc", NULL
};
/*
@@ -95,221 +93,221 @@ const char *envelope_items[] =
*
* returns -1 on error, 0 on success
*/
-int retrieve_structure(FILE *outstream, mime_message_t *msg, int show_extension_data)
+int retrieve_structure(FILE * outstream, mime_message_t * msg,
+ int show_extension_data)
{
- struct mime_record *mr;
- struct element *curr;
- struct list *header_to_use;
- mime_message_t rfcmsg;
- char *subtype,*extension,*newline;
- int is_mime_multipart = 0, is_rfc_multipart = 0;
- int rfc822 = 0;
-
- fprintf(outstream,"(");
-
- mime_findfield("content-type", &msg->mimeheader, &mr);
- is_mime_multipart = (mr && strncasecmp(mr->value,"multipart", strlen("multipart")) == 0 &&
- !msg->message_has_errors);
-
- mime_findfield("content-type", &msg->rfcheader, &mr);
- is_rfc_multipart = (mr && strncasecmp(mr->value,"multipart", strlen("multipart")) == 0 &&
- !msg->message_has_errors);
-
- /* eddy */
- if (mr && strncasecmp(mr->value, "message/rfc822", strlen("message/rfc822")) == 0)
- {
- rfc822 = 1;
- }
-
-
- if (rfc822 || (!is_rfc_multipart && !is_mime_multipart) )
- {
- /* show basic fields:
- * content-type, content-subtype, (parameter list),
- * content-id, content-description, content-transfer-encoding,
- * size
- */
-
- if (msg->mimeheader.start == NULL)
- header_to_use = &msg->rfcheader; /* we're dealing with a single-part RFC msg here */
- else
- header_to_use = &msg->mimeheader; /* we're dealing with a pure-MIME header here */
-
- mime_findfield("content-type", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- show_mime_parameter_list(outstream, mr, 1, 0);
- else
- fprintf(outstream, "\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\")"); /* default */
-
- mime_findfield("content-id", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- fprintf(outstream, " ");
- quoted_string_out(outstream, mr->value);
- }
- else
- fprintf(outstream, " NIL");
-
- mime_findfield("content-description", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- fprintf(outstream, " ");
- quoted_string_out(outstream, mr->value);
- }
- else
- fprintf(outstream, " NIL");
-
- mime_findfield("content-transfer-encoding", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- fprintf(outstream, " ");
- quoted_string_out(outstream, mr->value);
- }
- else
- fprintf(outstream, " \"7BIT\"");
-
- /* now output size */
- /* add msg->bodylines because \n is dumped as \r\n */
- if (msg->mimeheader.start && msg->rfcheader.start)
- fprintf(outstream, " %llu ", msg->bodysize + msg->mimerfclines + msg->rfcheadersize
- - msg->rfcheaderlines);
- else
- fprintf(outstream, " %llu ", msg->bodysize + msg->bodylines);
-
-
- /* now check special cases, first case: message/rfc822 */
- mime_findfield("content-type", header_to_use, &mr);
- if (mr && strncasecmp(mr->value, "message/rfc822", strlen("message/rfc822")) == 0 &&
- header_to_use != &msg->rfcheader)
- {
- /* msg/rfc822 found; extra items to be displayed:
- * (a) body envelope of rfc822 msg
- * (b) body structure of rfc822 msg
- * (c) msg size (lines)
- */
-
- if (retrieve_envelope(outstream, &msg->rfcheader) == -1)
- return -1;
-
- fprintf(outstream, " ");
-
- memmove(&rfcmsg, msg, sizeof(rfcmsg));
- rfcmsg.mimeheader.start = NULL; /* forget MIME-part */
-
- if (retrieve_structure(outstream, &rfcmsg, show_extension_data) == -1)
- return -1;
-
- /* output # of lines */
- fprintf(outstream, " %llu", msg->bodylines);
- }
- /* now check second special case: text
- * NOTE: if 'content-type' is absent, TEXT is assumed
- */
- if ((mr && strncasecmp(mr->value, "text", strlen("text")) == 0) || !mr)
- {
- /* output # of lines */
- if (msg->mimeheader.start && msg->rfcheader.start)
- fprintf(outstream, "%llu", msg->mimerfclines);
- else
- fprintf(outstream, "%llu", msg->bodylines);
+ struct mime_record *mr;
+ struct element *curr;
+ struct list *header_to_use;
+ mime_message_t rfcmsg;
+ char *subtype, *extension, *newline;
+ int is_mime_multipart = 0, is_rfc_multipart = 0;
+ int rfc822 = 0;
+
+ fprintf(outstream, "(");
+
+ mime_findfield("content-type", &msg->mimeheader, &mr);
+ is_mime_multipart = (mr
+ && strncasecmp(mr->value, "multipart",
+ strlen("multipart")) == 0
+ && !msg->message_has_errors);
+
+ mime_findfield("content-type", &msg->rfcheader, &mr);
+ is_rfc_multipart = (mr
+ && strncasecmp(mr->value, "multipart",
+ strlen("multipart")) == 0
+ && !msg->message_has_errors);
+
+ /* eddy */
+ if (mr
+ && strncasecmp(mr->value, "message/rfc822",
+ strlen("message/rfc822")) == 0) {
+ rfc822 = 1;
}
- if (show_extension_data)
- {
- mime_findfield("content-md5", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- fprintf(outstream, " ");
- quoted_string_out(outstream, mr->value);
- }
- else
- fprintf(outstream, " NIL");
-
- mime_findfield("content-disposition", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- fprintf(outstream, " (");
- show_mime_parameter_list(outstream, mr, 0, 0);
- fprintf(outstream, ")");
- }
- else
- fprintf(outstream, " NIL");
-
- mime_findfield("content-language", header_to_use, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- fprintf(outstream, " ");
- quoted_string_out(outstream, mr->value);
- }
- else
- fprintf(outstream, " NIL");
- }
- }
- else
- {
- /* check for a multipart message */
- if (is_rfc_multipart || is_mime_multipart)
- {
- curr = list_getstart(&msg->children);
- while (curr)
- {
- if (retrieve_structure(outstream, (mime_message_t*)curr->data,
- show_extension_data) == -1)
- return -1;
- curr = curr->nextnode;
- }
-
- /* show multipart subtype */
- if (is_mime_multipart)
- mime_findfield("content-type", &msg->mimeheader, &mr);
- else
- mime_findfield("content-type", &msg->rfcheader, &mr);
-
- subtype = strchr(mr->value, '/');
- extension = strchr(subtype, ';');
-
- if (!subtype)
- fprintf(outstream, " NIL");
- else
- {
- if (!extension)
- {
- newline = strchr(subtype, '\n');
- if (!newline)
- return -1;
-
- *newline = 0;
- fprintf(outstream, " ");
- quoted_string_out(outstream, subtype+1);
- *newline = '\n';
+ if (rfc822 || (!is_rfc_multipart && !is_mime_multipart)) {
+ /* show basic fields:
+ * content-type, content-subtype, (parameter list),
+ * content-id, content-description, content-transfer-encoding,
+ * size
+ */
+
+ if (msg->mimeheader.start == NULL)
+ header_to_use = &msg->rfcheader; /* we're dealing with a single-part RFC msg here */
+ else
+ header_to_use = &msg->mimeheader; /* we're dealing with a pure-MIME header here */
+
+ mime_findfield("content-type", header_to_use, &mr);
+ if (mr && strlen(mr->value) > 0)
+ show_mime_parameter_list(outstream, mr, 1, 0);
+ else
+ fprintf(outstream, "\"TEXT\" \"PLAIN\" (\"CHARSET\" \"US-ASCII\")"); /* default */
+
+ mime_findfield("content-id", header_to_use, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ fprintf(outstream, " ");
+ quoted_string_out(outstream, mr->value);
+ } else
+ fprintf(outstream, " NIL");
+
+ mime_findfield("content-description", header_to_use, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ fprintf(outstream, " ");
+ quoted_string_out(outstream, mr->value);
+ } else
+ fprintf(outstream, " NIL");
+
+ mime_findfield("content-transfer-encoding", header_to_use,
+ &mr);
+ if (mr && strlen(mr->value) > 0) {
+ fprintf(outstream, " ");
+ quoted_string_out(outstream, mr->value);
+ } else
+ fprintf(outstream, " \"7BIT\"");
+
+ /* now output size */
+ /* add msg->bodylines because \n is dumped as \r\n */
+ if (msg->mimeheader.start && msg->rfcheader.start)
+ fprintf(outstream, " %llu ",
+ msg->bodysize + msg->mimerfclines +
+ msg->rfcheadersize - msg->rfcheaderlines);
+ else
+ fprintf(outstream, " %llu ",
+ msg->bodysize + msg->bodylines);
+
+
+ /* now check special cases, first case: message/rfc822 */
+ mime_findfield("content-type", header_to_use, &mr);
+ if (mr
+ && strncasecmp(mr->value, "message/rfc822",
+ strlen("message/rfc822")) == 0
+ && header_to_use != &msg->rfcheader) {
+ /* msg/rfc822 found; extra items to be displayed:
+ * (a) body envelope of rfc822 msg
+ * (b) body structure of rfc822 msg
+ * (c) msg size (lines)
+ */
+
+ if (retrieve_envelope(outstream, &msg->rfcheader)
+ == -1)
+ return -1;
+
+ fprintf(outstream, " ");
+
+ memmove(&rfcmsg, msg, sizeof(rfcmsg));
+ rfcmsg.mimeheader.start = NULL; /* forget MIME-part */
+
+ if (retrieve_structure
+ (outstream, &rfcmsg,
+ show_extension_data) == -1)
+ return -1;
+
+ /* output # of lines */
+ fprintf(outstream, " %llu", msg->bodylines);
}
- else
- {
- *extension = 0;
- fprintf(outstream, " ");
- quoted_string_out(outstream, subtype+1);
- *extension = ';';
+ /* now check second special case: text
+ * NOTE: if 'content-type' is absent, TEXT is assumed
+ */
+ if ((mr
+ && strncasecmp(mr->value, "text",
+ strlen("text")) == 0) || !mr) {
+ /* output # of lines */
+ if (msg->mimeheader.start && msg->rfcheader.start)
+ fprintf(outstream, "%llu",
+ msg->mimerfclines);
+ else
+ fprintf(outstream, "%llu", msg->bodylines);
}
- }
- /* show extension data (after subtype) */
- if (extension && show_extension_data)
- {
- show_mime_parameter_list(outstream, mr, 0, 1);
+ if (show_extension_data) {
+ mime_findfield("content-md5", header_to_use, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ fprintf(outstream, " ");
+ quoted_string_out(outstream, mr->value);
+ } else
+ fprintf(outstream, " NIL");
+
+ mime_findfield("content-disposition",
+ header_to_use, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ fprintf(outstream, " (");
+ show_mime_parameter_list(outstream, mr, 0,
+ 0);
+ fprintf(outstream, ")");
+ } else
+ fprintf(outstream, " NIL");
+
+ mime_findfield("content-language", header_to_use,
+ &mr);
+ if (mr && strlen(mr->value) > 0) {
+ fprintf(outstream, " ");
+ quoted_string_out(outstream, mr->value);
+ } else
+ fprintf(outstream, " NIL");
+ }
+ } else {
+ /* check for a multipart message */
+ if (is_rfc_multipart || is_mime_multipart) {
+ curr = list_getstart(&msg->children);
+ while (curr) {
+ if (retrieve_structure
+ (outstream,
+ (mime_message_t *) curr->data,
+ show_extension_data) == -1)
+ return -1;
- /* FIXME: should give body-disposition & body-language here */
- fprintf(outstream, " NIL NIL");
- }
- }
- else
- {
- /* ??? */
+ curr = curr->nextnode;
+ }
+
+ /* show multipart subtype */
+ if (is_mime_multipart)
+ mime_findfield("content-type",
+ &msg->mimeheader, &mr);
+ else
+ mime_findfield("content-type",
+ &msg->rfcheader, &mr);
+
+ subtype = strchr(mr->value, '/');
+ extension = strchr(subtype, ';');
+
+ if (!subtype)
+ fprintf(outstream, " NIL");
+ else {
+ if (!extension) {
+ newline = strchr(subtype, '\n');
+ if (!newline)
+ return -1;
+
+ *newline = 0;
+ fprintf(outstream, " ");
+ quoted_string_out(outstream,
+ subtype + 1);
+ *newline = '\n';
+ } else {
+ *extension = 0;
+ fprintf(outstream, " ");
+ quoted_string_out(outstream,
+ subtype + 1);
+ *extension = ';';
+ }
+ }
+
+ /* show extension data (after subtype) */
+ if (extension && show_extension_data) {
+ show_mime_parameter_list(outstream, mr, 0,
+ 1);
+
+ /* FIXME: should give body-disposition & body-language here */
+ fprintf(outstream, " NIL NIL");
+ }
+ } else {
+ /* ??? */
+ }
}
- }
- fprintf(outstream,")");
+ fprintf(outstream, ")");
- return 0;
+ return 0;
}
@@ -320,84 +318,74 @@ int retrieve_structure(FILE *outstream, mime_message_t *msg, int show_extension_
*
* returns -1 on error, 0 on success
*/
-int retrieve_envelope(FILE *outstream, struct list *rfcheader)
+int retrieve_envelope(FILE * outstream, struct list *rfcheader)
{
- struct mime_record *mr;
- int idx;
-
- fprintf(outstream,"(");
-
- mime_findfield("date", rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- quoted_string_out(outstream, mr->value);
- fprintf(outstream, " ");
- }
- else
- fprintf(outstream, "NIL ");
-
- mime_findfield("subject", rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- quoted_string_out(outstream, mr->value);
- fprintf(outstream, " ");
- }
- else
- fprintf(outstream, "NIL ");
-
- /* now from, sender, reply-to, to, cc, bcc, in-reply-to fields;
- * note that multiple mailaddresses are separated by ','
- */
-
- for (idx=0; envelope_items[idx]; idx++)
- {
- mime_findfield(envelope_items[idx], rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- show_address_list(outstream, mr);
+ struct mime_record *mr;
+ int idx;
+
+ fprintf(outstream, "(");
+
+ mime_findfield("date", rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ quoted_string_out(outstream, mr->value);
+ fprintf(outstream, " ");
+ } else
+ fprintf(outstream, "NIL ");
+
+ mime_findfield("subject", rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ quoted_string_out(outstream, mr->value);
+ fprintf(outstream, " ");
+ } else
+ fprintf(outstream, "NIL ");
+
+ /* now from, sender, reply-to, to, cc, bcc, in-reply-to fields;
+ * note that multiple mailaddresses are separated by ','
+ */
+
+ for (idx = 0; envelope_items[idx]; idx++) {
+ mime_findfield(envelope_items[idx], rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ show_address_list(outstream, mr);
+ } else if (strcasecmp(envelope_items[idx], "reply-to") ==
+ 0) {
+ /* default this field */
+ mime_findfield("from", rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0)
+ show_address_list(outstream, mr);
+ else /* no from field ??? */
+ fprintf(outstream,
+ "((NIL NIL \"nobody\" \"nowhere.nirgendwo\"))");
+ } else if (strcasecmp(envelope_items[idx], "sender") == 0) {
+ /* default this field */
+ mime_findfield("from", rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0)
+ show_address_list(outstream, mr);
+ else /* no from field ??? */
+ fprintf(outstream,
+ "((NIL NIL \"nobody\" \"nowhere.nirgendwo\"))");
+ } else
+ fprintf(outstream, "NIL");
+
+ fprintf(outstream, " ");
}
- else if (strcasecmp(envelope_items[idx], "reply-to") == 0)
- {
- /* default this field */
- mime_findfield("from", rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- show_address_list(outstream, mr);
- else /* no from field ??? */
- fprintf(outstream, "((NIL NIL \"nobody\" \"nowhere.nirgendwo\"))");
- }
- else if (strcasecmp(envelope_items[idx], "sender") == 0)
- {
- /* default this field */
- mime_findfield("from", rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- show_address_list(outstream, mr);
- else /* no from field ??? */
- fprintf(outstream, "((NIL NIL \"nobody\" \"nowhere.nirgendwo\"))");
- }
- else
- fprintf(outstream, "NIL");
-
- fprintf(outstream, " ");
- }
-
- mime_findfield("in-reply-to", rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- {
- quoted_string_out(outstream, mr->value);
- fprintf(outstream, " ");
- }
- else
- fprintf(outstream, "NIL ");
-
- mime_findfield("message-id", rfcheader, &mr);
- if (mr && strlen(mr->value) > 0)
- quoted_string_out(outstream, mr->value);
- else
- fprintf(outstream, "NIL");
-
- fprintf(outstream,")");
-
- return 0;
+
+ mime_findfield("in-reply-to", rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0) {
+ quoted_string_out(outstream, mr->value);
+ fprintf(outstream, " ");
+ } else
+ fprintf(outstream, "NIL ");
+
+ mime_findfield("message-id", rfcheader, &mr);
+ if (mr && strlen(mr->value) > 0)
+ quoted_string_out(outstream, mr->value);
+ else
+ fprintf(outstream, "NIL");
+
+ fprintf(outstream, ")");
+
+ return 0;
}
@@ -406,109 +394,107 @@ int retrieve_envelope(FILE *outstream, struct list *rfcheader)
*
* gives an address list, output to outstream
*/
-int show_address_list(FILE *outstream, struct mime_record *mr)
+int show_address_list(FILE * outstream, struct mime_record *mr)
{
- int delimiter,i,inquote,start,has_split;
- char savechar;
-
- fprintf(outstream,"(");
-
- /* find ',' to split up multiple addresses */
- delimiter = 0;
-
- do
- {
- fprintf(outstream,"(");
-
- start = delimiter;
-
- for (inquote=0; mr->value[delimiter] && !(mr->value[delimiter] == ',' && !inquote);
- delimiter++)
- if (mr->value[delimiter] == '\"') inquote ^= 1;
-
- if (mr->value[delimiter])
- mr->value[delimiter] = 0; /* replace ',' by NULL-termination */
- else
- delimiter = -1; /* this will be the last one */
-
- /* the address currently being processed is now contained within
- * &mr->value[start] 'till first '\0'
- */
-
- /* possibilities for the mail address:
- * (1) name <user@domain>
- * (2) <user@domain>
- * (3) user@domain
- * scan for '<' to determine which case we should be dealing with;
- */
-
- for (i=start, inquote=0; mr->value[i] && !(mr->value[i] == '<' && !inquote); i++)
- if (mr->value[i] == '\"') inquote ^= 1;
-
- if (mr->value[i])
- {
- if (i > start+2)
- {
- /* name is contained in &mr->value[start] untill &mr->value[i-2] */
- /* name might contain quotes */
- savechar = mr->value[i-1];
- mr->value[i-1] = '\0'; /* terminate string */
-
- quoted_string_out(outstream, &mr->value[start]);
-
- mr->value[i-1] = savechar;
-
- }
- else
- fprintf(outstream, "NIL");
-
- start = i+1; /* skip to after '<' */
- }
- else
- fprintf(outstream, "NIL");
-
- fprintf(outstream, " NIL "); /* source route ?? smtp at-domain-list ?? */
-
- /* now display user domainname; &mr->value[start] is starting point */
- fprintf(outstream, "\"");
-
- /*
- * added a check for whitespace within the address (not good)
- */
- for (i=start, has_split=0; mr->value[i] && mr->value[i] != '>' && !isspace(mr->value[i]);
- i++)
- {
- if (mr->value[i] == '@')
- {
- fprintf(outstream,"\" \"");
- has_split = 1;
- }
- else
- {
- if (mr->value[i] == '"')
- fprintf(outstream, "\\");
- fprintf(outstream,"%c",mr->value[i]);
- }
- }
+ int delimiter, i, inquote, start, has_split;
+ char savechar;
+
+ fprintf(outstream, "(");
+
+ /* find ',' to split up multiple addresses */
+ delimiter = 0;
+
+ do {
+ fprintf(outstream, "(");
+
+ start = delimiter;
+
+ for (inquote = 0;
+ mr->value[delimiter] && !(mr->value[delimiter] == ','
+ && !inquote); delimiter++)
+ if (mr->value[delimiter] == '\"')
+ inquote ^= 1;
+
+ if (mr->value[delimiter])
+ mr->value[delimiter] = 0; /* replace ',' by NULL-termination */
+ else
+ delimiter = -1; /* this will be the last one */
+
+ /* the address currently being processed is now contained within
+ * &mr->value[start] 'till first '\0'
+ */
+
+ /* possibilities for the mail address:
+ * (1) name <user@domain>
+ * (2) <user@domain>
+ * (3) user@domain
+ * scan for '<' to determine which case we should be dealing with;
+ */
+
+ for (i = start, inquote = 0;
+ mr->value[i] && !(mr->value[i] == '<' && !inquote);
+ i++)
+ if (mr->value[i] == '\"')
+ inquote ^= 1;
+
+ if (mr->value[i]) {
+ if (i > start + 2) {
+ /* name is contained in &mr->value[start] untill &mr->value[i-2] */
+ /* name might contain quotes */
+ savechar = mr->value[i - 1];
+ mr->value[i - 1] = '\0'; /* terminate string */
+
+ quoted_string_out(outstream,
+ &mr->value[start]);
+
+ mr->value[i - 1] = savechar;
+
+ } else
+ fprintf(outstream, "NIL");
+
+ start = i + 1; /* skip to after '<' */
+ } else
+ fprintf(outstream, "NIL");
+
+ fprintf(outstream, " NIL "); /* source route ?? smtp at-domain-list ?? */
+
+ /* now display user domainname; &mr->value[start] is starting point */
+ fprintf(outstream, "\"");
+
+ /*
+ * added a check for whitespace within the address (not good)
+ */
+ for (i = start, has_split = 0;
+ mr->value[i] && mr->value[i] != '>'
+ && !isspace(mr->value[i]); i++) {
+ if (mr->value[i] == '@') {
+ fprintf(outstream, "\" \"");
+ has_split = 1;
+ } else {
+ if (mr->value[i] == '"')
+ fprintf(outstream, "\\");
+ fprintf(outstream, "%c", mr->value[i]);
+ }
+ }
- if (!has_split)
- fprintf(outstream,"\" \"\""); /* '@' did not occur */
- else
- fprintf(outstream, "\"");
-
- if (delimiter > 0)
- {
- mr->value[delimiter++] = ','; /* restore & prepare for next iteration */
- while (isspace(mr->value[delimiter])) delimiter++;
- }
+ if (!has_split)
+ fprintf(outstream, "\" \"\""); /* '@' did not occur */
+ else
+ fprintf(outstream, "\"");
- fprintf(outstream, ")");
+ if (delimiter > 0) {
+ mr->value[delimiter++] = ','; /* restore & prepare for next iteration */
+ while (isspace(mr->value[delimiter]))
+ delimiter++;
+ }
+
+ fprintf(outstream, ")");
+
+ } while (delimiter > 0);
- } while (delimiter > 0) ;
-
- fprintf(outstream,")");
+ fprintf(outstream, ")");
- return 0;
+ return 0;
}
@@ -521,140 +507,149 @@ int show_address_list(FILE *outstream, struct mime_record *mr)
* if force_subtype != 0 'NIL' will be outputted if no subtype is specified
* if only_extension != 0 only extension data (after first ';') will be shown
*/
-int show_mime_parameter_list(FILE *outstream, struct mime_record *mr,
+int show_mime_parameter_list(FILE * outstream, struct mime_record *mr,
int force_subtype, int only_extension)
{
- int idx,delimiter,start,end;
-
- /* find first delimiter */
- for (delimiter = 0; mr->value[delimiter] && mr->value[delimiter] != ';'; delimiter++) ;
-
- /* are there non-whitespace chars after the delimiter? */
- /* looking for the case where the mime type ends with a ";" */
- /* if it is of type "text" it must have a default character set generated */
- end = strlen(mr->value);
- for (start = delimiter+1; (isspace(mr->value[start])==0 && start<=end) ; start++ );
- end = start - delimiter - 1;
- start = 0;
- if ( end && strstr(mr->value,"text") ) start++;
-
- if (mr->value[delimiter])
- mr->value[delimiter] = 0;
- else
- delimiter = -1;
-
- if (!only_extension)
- {
- /* find main type in value */
- for (idx = 0; mr->value[idx] && mr->value[idx] != '/'; idx++) ;
-
- if (mr->value[idx] && (idx<delimiter || delimiter == -1))
- {
- mr->value[idx] = 0;
-
- quoted_string_out(outstream, mr->value);
- fprintf(outstream, " ");
- quoted_string_out(outstream, &mr->value[idx+1]);
-
- mr->value[idx] = '/';
- }
- else
- {
- quoted_string_out(outstream, mr->value);
- fprintf(outstream," %s", force_subtype ? "NIL" : "");
+ int idx, delimiter, start, end;
+
+ /* find first delimiter */
+ for (delimiter = 0;
+ mr->value[delimiter] && mr->value[delimiter] != ';';
+ delimiter++);
+
+ /* are there non-whitespace chars after the delimiter? */
+ /* looking for the case where the mime type ends with a ";" */
+ /* if it is of type "text" it must have a default character set generated */
+ end = strlen(mr->value);
+ for (start = delimiter + 1;
+ (isspace(mr->value[start]) == 0 && start <= end); start++);
+ end = start - delimiter - 1;
+ start = 0;
+ if (end && strstr(mr->value, "text"))
+ start++;
+
+ if (mr->value[delimiter])
+ mr->value[delimiter] = 0;
+ else
+ delimiter = -1;
+
+ if (!only_extension) {
+ /* find main type in value */
+ for (idx = 0; mr->value[idx] && mr->value[idx] != '/';
+ idx++);
+
+ if (mr->value[idx] && (idx < delimiter || delimiter == -1)) {
+ mr->value[idx] = 0;
+
+ quoted_string_out(outstream, mr->value);
+ fprintf(outstream, " ");
+ quoted_string_out(outstream, &mr->value[idx + 1]);
+
+ mr->value[idx] = '/';
+ } else {
+ quoted_string_out(outstream, mr->value);
+ fprintf(outstream, " %s",
+ force_subtype ? "NIL" : "");
+ }
}
- }
-
- if (delimiter >= 0)
- {
- /* extra parameters specified */
- mr->value[delimiter] = ';';
- idx=delimiter;
-
- fprintf(outstream," (");
-
- if ( start ) fprintf(outstream,"\"CHARSET\" \"US-ASCII\"");
- /* extra params: <name>=<val> [; <name>=<val> [; ...etc...]]
- * note that both name and val may or may not be enclosed by
- * either single or double quotation marks
- */
-
- do
- {
- /* skip whitespace */
- for (idx++; isspace(mr->value[idx]); idx++) ;
-
- if (!mr->value[idx]) break; /* ?? */
-
- /* check if quotation marks are specified */
- if (mr->value[idx] == '\"' || mr->value[idx] == '\'')
- {
- start = ++idx;
- while (mr->value[idx] && mr->value[idx] != mr->value[start-1]) idx++;
-
- if (!mr->value[idx] || mr->value[idx+1] != '=') /* ?? no end quote */
- break;
- end = idx;
- idx+=2; /* skip to after '=' */
- }
- else
- {
- start = idx;
- while (mr->value[idx] && mr->value[idx] != '=') idx++;
-
- if (!mr->value[idx]) /* ?? no value specified */
- break;
-
- end = idx;
- idx++; /* skip to after '=' */
- }
+ if (delimiter >= 0) {
+ /* extra parameters specified */
+ mr->value[delimiter] = ';';
+ idx = delimiter;
+
+ fprintf(outstream, " (");
+
+ if (start)
+ fprintf(outstream, "\"CHARSET\" \"US-ASCII\"");
+ /* extra params: <name>=<val> [; <name>=<val> [; ...etc...]]
+ * note that both name and val may or may not be enclosed by
+ * either single or double quotation marks
+ */
+
+ do {
+ /* skip whitespace */
+ for (idx++; isspace(mr->value[idx]); idx++);
+
+ if (!mr->value[idx])
+ break; /* ?? */
+
+ /* check if quotation marks are specified */
+ if (mr->value[idx] == '\"'
+ || mr->value[idx] == '\'') {
+ start = ++idx;
+ while (mr->value[idx]
+ && mr->value[idx] !=
+ mr->value[start - 1])
+ idx++;
+
+ if (!mr->value[idx] || mr->value[idx + 1] != '=') /* ?? no end quote */
+ break;
+
+ end = idx;
+ idx += 2; /* skip to after '=' */
+ } else {
+ start = idx;
+ while (mr->value[idx]
+ && mr->value[idx] != '=')
+ idx++;
+
+ if (!mr->value[idx]) /* ?? no value specified */
+ break;
+
+ end = idx;
+ idx++; /* skip to after '=' */
+ }
- fprintf(outstream,"\"%.*s\" ", (end-start), &mr->value[start]);
+ fprintf(outstream, "\"%.*s\" ", (end - start),
+ &mr->value[start]);
- /* now process the value; practically same procedure */
+ /* now process the value; practically same procedure */
- if (mr->value[idx] == '\"' || mr->value[idx] == '\'')
- {
- start = ++idx;
- while (mr->value[idx] && mr->value[idx] != mr->value[start-1]) idx++;
-
- if (!mr->value[idx]) /* ?? no end quote */
- break;
+ if (mr->value[idx] == '\"'
+ || mr->value[idx] == '\'') {
+ start = ++idx;
+ while (mr->value[idx]
+ && mr->value[idx] !=
+ mr->value[start - 1])
+ idx++;
+
+ if (!mr->value[idx]) /* ?? no end quote */
+ break;
- end = idx;
- idx++;
- }
- else
- {
- start = idx;
-
- while (mr->value[idx] && !isspace(mr->value[idx]) &&
- mr->value[idx] != ';') idx++;
-
- end = idx;
- }
-
- fprintf(outstream,"\"%.*s\"", (end-start), &mr->value[start]);
-
- /* check for more name/val pairs */
- while (mr->value[idx] && mr->value[idx] != ';') idx++;
-
- if (mr->value[idx])
- fprintf(outstream," ");
-
- } while (mr->value[idx]);
-
- fprintf(outstream,")");
-
- }
- else
- {
- fprintf(outstream," NIL");
- }
-
- return 0;
+ end = idx;
+ idx++;
+ } else {
+ start = idx;
+
+ while (mr->value[idx]
+ && !isspace(mr->value[idx])
+ && mr->value[idx] != ';')
+ idx++;
+
+ end = idx;
+ }
+
+ fprintf(outstream, "\"%.*s\"", (end - start),
+ &mr->value[start]);
+
+ /* check for more name/val pairs */
+ while (mr->value[idx] && mr->value[idx] != ';')
+ idx++;
+
+ if (mr->value[idx])
+ fprintf(outstream, " ");
+
+ } while (mr->value[idx]);
+
+ fprintf(outstream, ")");
+
+ } else {
+ fprintf(outstream, " NIL");
+ }
+
+ return 0;
}
@@ -665,27 +660,28 @@ int show_mime_parameter_list(FILE *outstream, struct mime_record *mr,
* 'part' is assumed to be valid! (i.e '1.2.3.44')
* returns NULL if there is no such part
*/
-mime_message_t* get_part_by_num(mime_message_t *msg, const char *part)
+mime_message_t *get_part_by_num(mime_message_t * msg, const char *part)
{
- int nextpart,j;
- char *endptr;
- struct element *curr;
+ int nextpart, j;
+ char *endptr;
+ struct element *curr;
- if (part == NULL || strlen(part) == 0 || msg == NULL)
- return msg;
+ if (part == NULL || strlen(part) == 0 || msg == NULL)
+ return msg;
- nextpart = strtoul(part, &endptr, 10); /* strtoul() stops at '.' */
+ nextpart = strtoul(part, &endptr, 10); /* strtoul() stops at '.' */
- for (j=1, curr=list_getstart(&msg->children); j<nextpart && curr; j++, curr = curr->nextnode);
+ for (j = 1, curr = list_getstart(&msg->children);
+ j < nextpart && curr; j++, curr = curr->nextnode);
- if (!curr)
- return NULL;
+ if (!curr)
+ return NULL;
- if (*endptr)
- return get_part_by_num((mime_message_t*)curr->data, &endptr[1]); /* skip dot in part */
+ if (*endptr)
+ return get_part_by_num((mime_message_t *) curr->data, &endptr[1]); /* skip dot in part */
- return (mime_message_t*)curr->data;
-}
+ return (mime_message_t *) curr->data;
+}
/*
@@ -701,41 +697,41 @@ mime_message_t* get_part_by_num(mime_message_t *msg, const char *part)
*
* returns number of bytes written to outmem
*/
-u64_t rfcheader_dump(MEM *outmem, struct list *rfcheader, char **fieldnames, int nfields,
- int equal_type)
+u64_t rfcheader_dump(MEM * outmem, struct list * rfcheader,
+ char **fieldnames, int nfields, int equal_type)
{
- struct mime_record *mr;
- struct element *curr;
- u64_t size = 0;
-
- curr = list_getstart(rfcheader);
- if (rfcheader == NULL || curr == NULL)
- {
- /*size += fprintf(outstream, "NIL\r\n");*/
- return 0;
- }
-
- curr = list_getstart(rfcheader);
- while (curr)
- {
- mr = (struct mime_record*)curr->data;
-
- if (haystack_find(nfields, fieldnames, mr->field) == equal_type)
- {
- /* ok output this field */
- size += mwrite(mr->field, strlen(mr->field), outmem);
- size += mwrite(": ", 2, outmem);
- size += mwrite(mr->value, strlen(mr->value), outmem);
- size += mwrite("\r\n", 2, outmem);
+ struct mime_record *mr;
+ struct element *curr;
+ u64_t size = 0;
+
+ curr = list_getstart(rfcheader);
+ if (rfcheader == NULL || curr == NULL) {
+ /*size += fprintf(outstream, "NIL\r\n"); */
+ return 0;
+ }
+
+ curr = list_getstart(rfcheader);
+ while (curr) {
+ mr = (struct mime_record *) curr->data;
+
+ if (haystack_find(nfields, fieldnames, mr->field) ==
+ equal_type) {
+ /* ok output this field */
+ size +=
+ mwrite(mr->field, strlen(mr->field), outmem);
+ size += mwrite(": ", 2, outmem);
+ size +=
+ mwrite(mr->value, strlen(mr->value), outmem);
+ size += mwrite("\r\n", 2, outmem);
+ }
+
+ curr = curr->nextnode;
}
+ size += mwrite("\r\n", 2, outmem);
+
+ return size;
+}
- curr = curr->nextnode;
- }
- size += mwrite("\r\n", 2, outmem);
-
- return size;
-}
-
/*
* mimeheader_dump()
@@ -743,32 +739,30 @@ u64_t rfcheader_dump(MEM *outmem, struct list *rfcheader, char **fieldnames, int
* dumps mime-header fields belonging to mimeheader
*
*/
-u64_t mimeheader_dump(MEM *outmem, struct list *mimeheader)
+u64_t mimeheader_dump(MEM * outmem, struct list * mimeheader)
{
- struct mime_record *mr;
- struct element *curr;
- u64_t size = 0;
-
- curr = list_getstart(mimeheader);
- if (mimeheader == NULL || curr == NULL)
- {
- /*size = fprintf(outstream, "NIL\r\n");*/
- return 0;
- }
-
- while (curr)
- {
- mr = (struct mime_record*)curr->data;
- size += mwrite(mr->field, strlen(mr->field), outmem);
- size += mwrite(": ", 2, outmem);
- size += mwrite(mr->value, strlen(mr->value), outmem);
- size += mwrite("\r\n", 2, outmem);
- curr = curr->nextnode;
- }
- size += mwrite("\r\n", 2, outmem);
-
- return size;
-}
+ struct mime_record *mr;
+ struct element *curr;
+ u64_t size = 0;
+
+ curr = list_getstart(mimeheader);
+ if (mimeheader == NULL || curr == NULL) {
+ /*size = fprintf(outstream, "NIL\r\n"); */
+ return 0;
+ }
+
+ while (curr) {
+ mr = (struct mime_record *) curr->data;
+ size += mwrite(mr->field, strlen(mr->field), outmem);
+ size += mwrite(": ", 2, outmem);
+ size += mwrite(mr->value, strlen(mr->value), outmem);
+ size += mwrite("\r\n", 2, outmem);
+ curr = curr->nextnode;
+ }
+ size += mwrite("\r\n", 2, outmem);
+
+ return size;
+}
/*
@@ -776,13 +770,13 @@ u64_t mimeheader_dump(MEM *outmem, struct list *mimeheader)
*/
int haystack_find(int haystacklen, char **haystack, const char *needle)
{
- int i;
+ int i;
- for (i=0; i<haystacklen; i++)
- if (strcasecmp(haystack[i], needle) == 0)
- return 1;
+ for (i = 0; i < haystacklen; i++)
+ if (strcasecmp(haystack[i], needle) == 0)
+ return 1;
- return 0;
+ return 0;
}
@@ -794,336 +788,308 @@ int haystack_find(int haystacklen, char **haystack, const char *needle)
* arglist is supposed to be formatted according to build_args_array()
*
*/
-int next_fetch_item(char **args, int idx, fetch_items_t *fi)
+int next_fetch_item(char **args, int idx, fetch_items_t * fi)
{
- int invalidargs,indigit,ispeek,shouldclose,delimpos;
- unsigned int j = 0;
-
- memset(fi, 0, sizeof(fetch_items_t)); /* init */
- fi->bodyfetch.itemtype = -1; /* expect no body fetches (a priori) */
- invalidargs = 0;
-
- if (!args[idx])
- return -1; /* no more */
-
- if (args[idx][0] == '(')
- idx++;
-
- if (!args[idx])
- return -2; /* error */
-
- if (strcasecmp(args[idx], "flags") == 0)
- fi->getFlags = 1;
- else if (strcasecmp(args[idx], "internaldate") == 0)
- fi->getInternalDate = 1;
- else if (strcasecmp(args[idx], "uid") == 0)
- fi->getUID = 1;
- else if (strcasecmp(args[idx], "rfc822") == 0)
- {
- fi->getRFC822 = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "rfc822.peek") == 0)
- {
- fi->getRFC822Peek = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "rfc822.header") == 0)
- {
- fi->getRFC822Header = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "rfc822.size") == 0)
- {
- fi->getSize = 1;
-/* fi->msgparse_needed = 1;*/ /* after first calc, it will be in the dbase */
- }
- else if (strcasecmp(args[idx], "rfc822.text") == 0)
- {
- fi->getRFC822Text = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "body") == 0 || strcasecmp(args[idx],"body.peek") == 0)
- {
- fi->msgparse_needed = 1;
-
- if (!args[idx+1] || strcmp(args[idx+1],"[") != 0)
- {
- if (strcasecmp(args[idx],"body.peek") == 0)
- return -2; /* error DONE */
- else
- fi->getMIME_IMB_noextension = 1; /* just BODY specified */
- }
- else
- {
- /* determine wheter or not to set the seen flag */
- ispeek = (strcasecmp(args[idx],"body.peek") == 0);
-
- /* now read the argument list to body */
- idx++; /* now pointing at '[' (not the last arg, parentheses are matched) */
- idx++; /* now pointing at what should be the item type */
-
- if (strcmp(args[idx], "]") == 0)
- {
- /* specified body[] or body.peek[] */
- if (ispeek)
- fi->getBodyTotalPeek = 1;
- else
- fi->getBodyTotal = 1;
-
- /* check if octet start/cnt is specified */
- if (args[idx+1] && args[idx+1][0] == '<')
- {
- idx++; /* advance */
-
- /* check argument */
- if (args[idx][strlen(args[idx]) - 1 ] != '>')
- return -2; /* error DONE */
-
- delimpos = -1;
- for (j=1; j < strlen(args[idx])-1; j++)
- {
- if (args[idx][j] == '.')
- {
- if (delimpos != -1)
- {
- invalidargs = 1;
- break;
- }
- delimpos = j;
+ int invalidargs, indigit, ispeek, shouldclose, delimpos;
+ unsigned int j = 0;
+
+ memset(fi, 0, sizeof(fetch_items_t)); /* init */
+ fi->bodyfetch.itemtype = -1; /* expect no body fetches (a priori) */
+ invalidargs = 0;
+
+ if (!args[idx])
+ return -1; /* no more */
+
+ if (args[idx][0] == '(')
+ idx++;
+
+ if (!args[idx])
+ return -2; /* error */
+
+ if (strcasecmp(args[idx], "flags") == 0)
+ fi->getFlags = 1;
+ else if (strcasecmp(args[idx], "internaldate") == 0)
+ fi->getInternalDate = 1;
+ else if (strcasecmp(args[idx], "uid") == 0)
+ fi->getUID = 1;
+ else if (strcasecmp(args[idx], "rfc822") == 0) {
+ fi->getRFC822 = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "rfc822.peek") == 0) {
+ fi->getRFC822Peek = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "rfc822.header") == 0) {
+ fi->getRFC822Header = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "rfc822.size") == 0) {
+ fi->getSize = 1;
+/* fi->msgparse_needed = 1;*//* after first calc, it will be in the dbase */
+ } else if (strcasecmp(args[idx], "rfc822.text") == 0) {
+ fi->getRFC822Text = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "body") == 0
+ || strcasecmp(args[idx], "body.peek") == 0) {
+ fi->msgparse_needed = 1;
+
+ if (!args[idx + 1] || strcmp(args[idx + 1], "[") != 0) {
+ if (strcasecmp(args[idx], "body.peek") == 0)
+ return -2; /* error DONE */
+ else
+ fi->getMIME_IMB_noextension = 1; /* just BODY specified */
+ } else {
+ /* determine wheter or not to set the seen flag */
+ ispeek = (strcasecmp(args[idx], "body.peek") == 0);
+
+ /* now read the argument list to body */
+ idx++; /* now pointing at '[' (not the last arg, parentheses are matched) */
+ idx++; /* now pointing at what should be the item type */
+
+ if (strcmp(args[idx], "]") == 0) {
+ /* specified body[] or body.peek[] */
+ if (ispeek)
+ fi->getBodyTotalPeek = 1;
+ else
+ fi->getBodyTotal = 1;
+
+ /* check if octet start/cnt is specified */
+ if (args[idx + 1]
+ && args[idx + 1][0] == '<') {
+ idx++; /* advance */
+
+ /* check argument */
+ if (args[idx]
+ [strlen(args[idx]) - 1] != '>')
+ return -2; /* error DONE */
+
+ delimpos = -1;
+ for (j = 1;
+ j < strlen(args[idx]) - 1;
+ j++) {
+ if (args[idx][j] == '.') {
+ if (delimpos != -1) {
+ invalidargs
+ = 1;
+ break;
+ }
+ delimpos = j;
+ } else
+ if (!isdigit
+ (args[idx][j])) {
+ invalidargs = 1;
+ break;
+ }
+ }
+
+ if (invalidargs || delimpos == -1
+ || delimpos == 1
+ || delimpos ==
+ (int) (strlen(args[idx]) - 2))
+ return -2; /* no delimiter found or at first/last pos OR invalid args DONE */
+
+ /* read the numbers */
+ args[idx][strlen(args[idx]) - 1] =
+ '\0';
+ args[idx][delimpos] = '\0';
+ fi->bodyfetch.octetstart =
+ strtoll(&args[idx][1], NULL,
+ 10);
+ fi->bodyfetch.octetcnt =
+ strtoll(&args[idx]
+ [delimpos + 1], NULL,
+ 10);
+
+ /* restore argument */
+ args[idx][delimpos] = '.';
+ args[idx][strlen(args[idx]) - 1] =
+ '>';
+ } else {
+ fi->bodyfetch.octetstart = -1;
+ fi->bodyfetch.octetcnt = -1;
+ }
+
+ return idx + 1; /* DONE */
}
- else if (!isdigit(args[idx][j]))
- {
- invalidargs = 1;
- break;
+
+ if (ispeek)
+ fi->bodyfetch.noseen = 1;
+
+ /* check for a partspecifier */
+ /* first check if there is a partspecifier (numbers & dots) */
+ indigit = 0;
+
+ for (j = 0; args[idx][j]; j++) {
+ if (isdigit(args[idx][j])) {
+ indigit = 1;
+ continue;
+ } else if (args[idx][j] == '.') {
+ if (!indigit) {
+ /* error, single dot specified */
+ invalidargs = 1;
+ break;
+ }
+
+ indigit = 0;
+ continue;
+ } else
+ break; /* other char found */
}
- }
-
- if (invalidargs || delimpos == -1 || delimpos == 1 ||
- delimpos == (int) (strlen(args[idx])-2) )
- return -2; /* no delimiter found or at first/last pos OR invalid args DONE */
-
- /* read the numbers */
- args[idx][strlen(args[idx]) - 1] = '\0';
- args[idx][delimpos] = '\0';
- fi->bodyfetch.octetstart = strtoll(&args[idx][1], NULL, 10);
- fi->bodyfetch.octetcnt = strtoll(&args[idx][delimpos+1], NULL, 10);
-
- /* restore argument */
- args[idx][delimpos] = '.';
- args[idx][strlen(args[idx]) - 1] = '>';
- }
- else
- {
- fi->bodyfetch.octetstart = -1;
- fi->bodyfetch.octetcnt = -1;
- }
-
- return idx+1; /* DONE */
- }
-
- if (ispeek)
- fi->bodyfetch.noseen = 1;
-
- /* check for a partspecifier */
- /* first check if there is a partspecifier (numbers & dots) */
- indigit = 0;
-
- for (j=0; args[idx][j]; j++)
- {
- if (isdigit(args[idx][j]))
- {
- indigit = 1;
- continue;
- }
- else if (args[idx][j] == '.')
- {
- if (!indigit)
- {
- /* error, single dot specified */
- invalidargs = 1;
- break;
- }
-
- indigit = 0;
- continue;
- }
- else
- break; /* other char found */
- }
-
- if (invalidargs)
- return -2; /* error DONE */
-
- if (j > 0)
- {
- if (indigit && args[idx][j])
- return -2; /* error DONE */
-
- /* partspecifier present, save it */
- if (j >= IMAP_MAX_PARTSPEC_LEN)
- return -2; /* error DONE */
-
- strncpy(fi->bodyfetch.partspec, args[idx], j);
- }
-
- fi->bodyfetch.partspec[j] = '\0';
-
-
- shouldclose = 0;
- if (strcasecmp(&args[idx][j], "text") == 0)
- {
- fi->bodyfetch.itemtype = BFIT_TEXT;
- shouldclose = 1;
- }
- else if (strcasecmp(&args[idx][j], "header") == 0)
- {
- fi->bodyfetch.itemtype = BFIT_HEADER;
- shouldclose = 1;
- }
- else if (strcasecmp(&args[idx][j], "mime") == 0)
- {
- if (j == 0)
- return -2; /* error DONE */
-
- fi->bodyfetch.itemtype = BFIT_MIME;
- shouldclose = 1;
- }
- else if (strcasecmp(&args[idx][j], "header.fields") == 0)
- fi->bodyfetch.itemtype = BFIT_HEADER_FIELDS;
- else if (strcasecmp(&args[idx][j], "header.fields.not") == 0)
- fi->bodyfetch.itemtype = BFIT_HEADER_FIELDS_NOT;
- else if (args[idx][j] == '\0')
- {
- fi->bodyfetch.itemtype = BFIT_TEXT_SILENT;
- shouldclose = 1;
- }
- else
- return -2; /* error DONE */
-
- if (shouldclose)
- {
- if (strcmp(args[idx+1],"]") != 0)
- return -2; /* error DONE */
- }
- else
- {
- idx++; /* should be at '(' now */
- if (strcmp(args[idx],"(") != 0)
- return -2; /* error DONE */
-
- idx++; /* at first item of field list now, remember idx */
- fi->bodyfetch.argstart = idx;
-
- /* walk on untill list terminates (and it does 'cause parentheses are matched) */
- while (strcmp(args[idx],")") != 0)
- idx++;
- fi->bodyfetch.argcnt = idx - fi->bodyfetch.argstart;
-
- if (fi->bodyfetch.argcnt == 0 || strcmp(args[idx+1],"]") != 0)
- return -2; /* error DONE */
- }
-
- idx++; /* points to ']' now */
-
- /* check if octet start/cnt is specified */
- if (args[idx+1] && args[idx+1][0] == '<')
- {
- idx++; /* advance */
-
- /* check argument */
- if (args[idx][strlen(args[idx]) - 1 ] != '>')
- return -2; /* error DONE */
-
- delimpos = -1;
- for (j=1; j < strlen(args[idx])-1; j++)
- {
- if (args[idx][j] == '.')
- {
- if (delimpos != -1)
- {
- invalidargs = 1;
- break;
+ if (invalidargs)
+ return -2; /* error DONE */
+
+ if (j > 0) {
+ if (indigit && args[idx][j])
+ return -2; /* error DONE */
+
+ /* partspecifier present, save it */
+ if (j >= IMAP_MAX_PARTSPEC_LEN)
+ return -2; /* error DONE */
+
+ strncpy(fi->bodyfetch.partspec, args[idx],
+ j);
+ }
+
+ fi->bodyfetch.partspec[j] = '\0';
+
+
+ shouldclose = 0;
+ if (strcasecmp(&args[idx][j], "text") == 0) {
+ fi->bodyfetch.itemtype = BFIT_TEXT;
+ shouldclose = 1;
+ } else if (strcasecmp(&args[idx][j], "header") ==
+ 0) {
+ fi->bodyfetch.itemtype = BFIT_HEADER;
+ shouldclose = 1;
+ } else if (strcasecmp(&args[idx][j], "mime") == 0) {
+ if (j == 0)
+ return -2; /* error DONE */
+
+ fi->bodyfetch.itemtype = BFIT_MIME;
+ shouldclose = 1;
+ } else
+ if (strcasecmp(&args[idx][j], "header.fields")
+ == 0)
+ fi->bodyfetch.itemtype =
+ BFIT_HEADER_FIELDS;
+ else if (strcasecmp
+ (&args[idx][j], "header.fields.not") == 0)
+ fi->bodyfetch.itemtype =
+ BFIT_HEADER_FIELDS_NOT;
+ else if (args[idx][j] == '\0') {
+ fi->bodyfetch.itemtype = BFIT_TEXT_SILENT;
+ shouldclose = 1;
+ } else
+ return -2; /* error DONE */
+
+ if (shouldclose) {
+ if (strcmp(args[idx + 1], "]") != 0)
+ return -2; /* error DONE */
+ } else {
+ idx++; /* should be at '(' now */
+ if (strcmp(args[idx], "(") != 0)
+ return -2; /* error DONE */
+
+ idx++; /* at first item of field list now, remember idx */
+ fi->bodyfetch.argstart = idx;
+
+ /* walk on untill list terminates (and it does 'cause parentheses are matched) */
+ while (strcmp(args[idx], ")") != 0)
+ idx++;
+
+ fi->bodyfetch.argcnt =
+ idx - fi->bodyfetch.argstart;
+
+ if (fi->bodyfetch.argcnt == 0
+ || strcmp(args[idx + 1], "]") != 0)
+ return -2; /* error DONE */
}
- delimpos = j;
- }
- else if (!isdigit(args[idx][j]))
- {
- invalidargs = 1;
- break;
- }
+
+ idx++; /* points to ']' now */
+
+ /* check if octet start/cnt is specified */
+ if (args[idx + 1] && args[idx + 1][0] == '<') {
+ idx++; /* advance */
+
+ /* check argument */
+ if (args[idx][strlen(args[idx]) - 1] !=
+ '>')
+ return -2; /* error DONE */
+
+ delimpos = -1;
+ for (j = 1; j < strlen(args[idx]) - 1; j++) {
+ if (args[idx][j] == '.') {
+ if (delimpos != -1) {
+ invalidargs = 1;
+ break;
+ }
+ delimpos = j;
+ } else if (!isdigit(args[idx][j])) {
+ invalidargs = 1;
+ break;
+ }
+ }
+
+ if (invalidargs || delimpos == -1 ||
+ delimpos == 1
+ || delimpos ==
+ (int) (strlen(args[idx]) - 2))
+ return -2; /* no delimiter found or at first/last pos OR invalid args DONE */
+
+ /* read the numbers */
+ args[idx][strlen(args[idx]) - 1] = '\0';
+ args[idx][delimpos] = '\0';
+ fi->bodyfetch.octetstart =
+ strtoll(&args[idx][1], NULL, 10);
+ fi->bodyfetch.octetcnt =
+ strtoll(&args[idx][delimpos + 1], NULL,
+ 10);
+
+ /* restore argument */
+ args[idx][delimpos] = '.';
+ args[idx][strlen(args[idx]) - 1] = '>';
+ } else {
+ fi->bodyfetch.octetstart = -1;
+ fi->bodyfetch.octetcnt = -1;
+ }
+ /* ok all done for body item */
}
-
- if (invalidargs || delimpos == -1 ||
- delimpos == 1 || delimpos == (int) (strlen(args[idx])-2) )
- return -2; /* no delimiter found or at first/last pos OR invalid args DONE */
-
- /* read the numbers */
- args[idx][strlen(args[idx]) - 1] = '\0';
- args[idx][delimpos] = '\0';
- fi->bodyfetch.octetstart = strtoll(&args[idx][1], NULL, 10);
- fi->bodyfetch.octetcnt = strtoll(&args[idx][delimpos+1], NULL, 10);
-
- /* restore argument */
- args[idx][delimpos] = '.';
- args[idx][strlen(args[idx]) - 1] = '>';
- }
- else
- {
- fi->bodyfetch.octetstart = -1;
- fi->bodyfetch.octetcnt = -1;
- }
- /* ok all done for body item */
- }
- }
- else if (strcasecmp(args[idx], "all") == 0)
- {
- fi->getFlags = 1;
- fi->getInternalDate = 1;
- fi->getSize = 1;
- fi->getEnvelope = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "fast") == 0)
- {
- fi->getFlags = 1;
- fi->getInternalDate = 1;
- fi->getSize = 1;
-/* fi->msgparse_needed = 1; */ /* size will be in dbase after first calc */
- }
- else if (strcasecmp(args[idx], "full") == 0)
- {
- fi->getFlags = 1;
- fi->getInternalDate = 1;
- fi->getSize = 1;
- fi->getEnvelope = 1;
- fi->getMIME_IMB = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "bodystructure") == 0)
- {
- fi->getMIME_IMB = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcasecmp(args[idx], "envelope") == 0)
- {
- fi->getEnvelope = 1;
- fi->msgparse_needed = 1;
- }
- else if (strcmp(args[idx], ")") == 0)
- {
- /* only allowed if last arg here */
- if (args[idx+1])
- return -2; /* DONE */
- else
- return -1;
- }
- else
- return -2; /* DONE */
-
- trace(TRACE_DEBUG,"next_fetch_item(): args[idx = %d] = %s (returning %d)\n",idx,args[idx],idx+1);
- return idx+1;
+ } else if (strcasecmp(args[idx], "all") == 0) {
+ fi->getFlags = 1;
+ fi->getInternalDate = 1;
+ fi->getSize = 1;
+ fi->getEnvelope = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "fast") == 0) {
+ fi->getFlags = 1;
+ fi->getInternalDate = 1;
+ fi->getSize = 1;
+/* fi->msgparse_needed = 1; *//* size will be in dbase after first calc */
+ } else if (strcasecmp(args[idx], "full") == 0) {
+ fi->getFlags = 1;
+ fi->getInternalDate = 1;
+ fi->getSize = 1;
+ fi->getEnvelope = 1;
+ fi->getMIME_IMB = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "bodystructure") == 0) {
+ fi->getMIME_IMB = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcasecmp(args[idx], "envelope") == 0) {
+ fi->getEnvelope = 1;
+ fi->msgparse_needed = 1;
+ } else if (strcmp(args[idx], ")") == 0) {
+ /* only allowed if last arg here */
+ if (args[idx + 1])
+ return -2; /* DONE */
+ else
+ return -1;
+ } else
+ return -2; /* DONE */
+
+ trace(TRACE_DEBUG,
+ "next_fetch_item(): args[idx = %d] = %s (returning %d)\n",
+ idx, args[idx], idx + 1);
+ return idx + 1;
}
@@ -1135,53 +1101,48 @@ int next_fetch_item(char **args, int idx, fetch_items_t *fi)
*/
char **give_chunks(const char *str, char delimiter)
{
- int cnt,i;
- char **array,*cpy,*tmp;
-
- cpy = (char*)my_malloc(sizeof(char) * (strlen(str) + 1));
- if (!cpy )
- {
- trace(TRACE_ERROR, "give_chunks(): out of memory\n");
- return NULL;
- }
-
- strcpy(cpy,str);
- tmp = cpy; /* save start of cpy */
-
- for (i=0,cnt=0; str[i]; i++)
- if (str[i] == delimiter)
- {
- cnt++;
- cpy[i] = '\0';
- }
-
- cnt++; /* add last part */
-
- /* alloc mem */
- cnt++; /* for NULL termination */
- array = (char**)my_malloc(sizeof(char*) * cnt);
-
- if (!array)
- {
- trace(TRACE_ERROR, "give_chunks(): out of memory\n");
- my_free(cpy);
- return NULL;
- }
-
- for (i=0,cnt=0; str[i]; i++)
- {
- if (str[i] == delimiter)
- {
- array[cnt++] = cpy; /* save this address */
- cpy = &tmp[i+1]; /* let cpy point to next string */
+ int cnt, i;
+ char **array, *cpy, *tmp;
+
+ cpy = (char *) my_malloc(sizeof(char) * (strlen(str) + 1));
+ if (!cpy) {
+ trace(TRACE_ERROR, "give_chunks(): out of memory\n");
+ return NULL;
}
- }
- /* copy last part */
- array[cnt++] = cpy;
+ strcpy(cpy, str);
+ tmp = cpy; /* save start of cpy */
+
+ for (i = 0, cnt = 0; str[i]; i++)
+ if (str[i] == delimiter) {
+ cnt++;
+ cpy[i] = '\0';
+ }
+
+ cnt++; /* add last part */
+
+ /* alloc mem */
+ cnt++; /* for NULL termination */
+ array = (char **) my_malloc(sizeof(char *) * cnt);
+
+ if (!array) {
+ trace(TRACE_ERROR, "give_chunks(): out of memory\n");
+ my_free(cpy);
+ return NULL;
+ }
- array[cnt] = NULL;
- return array;
+ for (i = 0, cnt = 0; str[i]; i++) {
+ if (str[i] == delimiter) {
+ array[cnt++] = cpy; /* save this address */
+ cpy = &tmp[i + 1]; /* let cpy point to next string */
+ }
+ }
+
+ /* copy last part */
+ array[cnt++] = cpy;
+
+ array[cnt] = NULL;
+ return array;
}
@@ -1192,13 +1153,13 @@ char **give_chunks(const char *str, char delimiter)
*/
void free_chunks(char **chunks)
{
- if (!chunks)
- return;
+ if (!chunks)
+ return;
- if (chunks[0])
- my_free(chunks[0]); /* the entire array will be freed now */
+ if (chunks[0])
+ my_free(chunks[0]); /* the entire array will be freed now */
- my_free(chunks); /* free ptrs to strings */
+ my_free(chunks); /* free ptrs to strings */
}
@@ -1212,48 +1173,48 @@ void free_chunks(char **chunks)
*
* returns 1 on succes, 0 on failure
*/
-int check_state_and_args(const char *command, const char *tag, char **args,
- int nargs, int state, ClientInfo *ci)
+int check_state_and_args(const char *command, const char *tag, char **args,
+ int nargs, int state, ClientInfo * ci)
{
- int i;
- imap_userdata_t *ud = (imap_userdata_t*)ci->userData;
-
- /* check state */
- if (state != -1)
- {
- if (ud->state != state)
- {
- if (!(state == IMAPCS_AUTHENTICATED && ud->state == IMAPCS_SELECTED))
- {
- fprintf(ci->tx,"%s BAD %s command received in invalid state\r\n", tag, command);
- return 0;
- }
+ int i;
+ imap_userdata_t *ud = (imap_userdata_t *) ci->userData;
+
+ /* check state */
+ if (state != -1) {
+ if (ud->state != state) {
+ if (!
+ (state == IMAPCS_AUTHENTICATED
+ && ud->state == IMAPCS_SELECTED)) {
+ fprintf(ci->tx,
+ "%s BAD %s command received in invalid state\r\n",
+ tag, command);
+ return 0;
+ }
+ }
}
- }
-
- /* check args */
- for (i=0; i<nargs; i++)
- {
- if (!args[i])
- {
- /* error: need more args */
- fprintf(ci->tx,"%s BAD missing argument%s to %s\r\n", tag,
- (nargs == 1) ? "" : "(s)", command);
- return 0;
+
+ /* check args */
+ for (i = 0; i < nargs; i++) {
+ if (!args[i]) {
+ /* error: need more args */
+ fprintf(ci->tx,
+ "%s BAD missing argument%s to %s\r\n", tag,
+ (nargs == 1) ? "" : "(s)", command);
+ return 0;
+ }
}
- }
- for (i=0; args[i]; i++) ;
+ for (i = 0; args[i]; i++);
- if (i > nargs)
- {
- /* error: too many args */
- fprintf(ci->tx,"%s BAD too many arguments to %s\r\n",tag, command);
- return 0;
- }
+ if (i > nargs) {
+ /* error: too many args */
+ fprintf(ci->tx, "%s BAD too many arguments to %s\r\n", tag,
+ command);
+ return 0;
+ }
- /* succes */
- return 1;
+ /* succes */
+ return 1;
}
@@ -1284,7 +1245,7 @@ int check_state_and_args(const char *command, const char *tag, char **args,
*/
/* local defines */
-#define NORMPAR 1
+#define NORMPAR 1
#define SQUAREPAR 2
#define NOPAR 0
@@ -1292,474 +1253,457 @@ char *the_args[MAX_ARGS];
char **build_args_array(const char *s)
{
- int nargs=0,inquote=0,i,quotestart=0;
- int nnorm=0,nsquare=0,paridx=0,slen=0,argstart=0;
- char parlist[MAX_LINESIZE];
-
- if (!s)
- return NULL;
-
- /* check for empty string */
- if (!(*s))
- {
- the_args[0] = NULL;
- return the_args;
- }
-
- /* find the arguments */
- paridx = 0;
- parlist[paridx] = NOPAR;
-
- inquote = 0;
- slen = strlen(s);
-
- for (i=0,nargs=0; i<slen && nargs < MAX_ARGS-1; i++)
- {
- /* check quotes */
- if (s[i] == '"' && ((i > 0 && s[i-1] != '\\') || i == 0))
- {
- if (inquote)
- {
- /* quotation end, treat quoted string as argument */
- if (!(the_args[nargs] = (char*)my_malloc(sizeof(char) * (i-quotestart)) ))
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR,
- "IMAPD: Not enough memory while building up argument array.");
- return NULL;
- }
-
- memcpy(the_args[nargs], &s[quotestart+1], i-quotestart-1);
- the_args[nargs][i-quotestart -1] = '\0';
-
- nargs++;
- inquote = 0;
- }
- else
- {
- inquote = 1;
- quotestart = i;
- }
-
- continue;
+ int nargs = 0, inquote = 0, i, quotestart = 0;
+ int nnorm = 0, nsquare = 0, paridx = 0, slen = 0, argstart = 0;
+ char parlist[MAX_LINESIZE];
+
+ if (!s)
+ return NULL;
+
+ /* check for empty string */
+ if (!(*s)) {
+ the_args[0] = NULL;
+ return the_args;
}
- if (inquote)
- continue;
-
- /* check for (, ), [ or ] in string */
- if (s[i] == '(' || s[i] == ')' || s[i] == '[' || s[i] == ']')
- {
- /* check parenthese structure */
- if (s[i] == ')')
- {
- if (paridx < 0 || parlist[paridx] != NORMPAR)
- paridx = -1;
- else
- {
- nnorm--;
- paridx--;
- }
- }
- else if (s[i] == ']')
- {
- if (paridx < 0 || parlist[paridx] != SQUAREPAR)
- paridx = -1;
- else
- {
- paridx--;
- nsquare--;
+ /* find the arguments */
+ paridx = 0;
+ parlist[paridx] = NOPAR;
+
+ inquote = 0;
+ slen = strlen(s);
+
+ for (i = 0, nargs = 0; i < slen && nargs < MAX_ARGS - 1; i++) {
+ /* check quotes */
+ if (s[i] == '"' && ((i > 0 && s[i - 1] != '\\') || i == 0)) {
+ if (inquote) {
+ /* quotation end, treat quoted string as argument */
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(char) *
+ (i -
+ quotestart)))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "IMAPD: Not enough memory while building up argument array.");
+ return NULL;
+ }
+
+ memcpy(the_args[nargs], &s[quotestart + 1],
+ i - quotestart - 1);
+ the_args[nargs][i - quotestart - 1] = '\0';
+
+ nargs++;
+ inquote = 0;
+ } else {
+ inquote = 1;
+ quotestart = i;
+ }
+
+ continue;
}
- }
- else if (s[i] == '(')
- {
- parlist[++paridx] = NORMPAR;
- nnorm++;
- }
- else /* s[i] == '[' */
- {
- parlist[++paridx] = SQUAREPAR;
- nsquare++;
- }
-
- if (paridx < 0)
- {
- /* error in parenthesis structure */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
+
+ if (inquote)
+ continue;
+
+ /* check for (, ), [ or ] in string */
+ if (s[i] == '(' || s[i] == ')' || s[i] == '['
+ || s[i] == ']') {
+ /* check parenthese structure */
+ if (s[i] == ')') {
+ if (paridx < 0
+ || parlist[paridx] != NORMPAR)
+ paridx = -1;
+ else {
+ nnorm--;
+ paridx--;
+ }
+ } else if (s[i] == ']') {
+ if (paridx < 0
+ || parlist[paridx] != SQUAREPAR)
+ paridx = -1;
+ else {
+ paridx--;
+ nsquare--;
+ }
+ } else if (s[i] == '(') {
+ parlist[++paridx] = NORMPAR;
+ nnorm++;
+ } else { /* s[i] == '[' */
+
+ parlist[++paridx] = SQUAREPAR;
+ nsquare++;
+ }
+
+ if (paridx < 0) {
+ /* error in parenthesis structure */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+ return NULL;
+ }
+
+ /* add this parenthesis to the arg list and continue */
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(" ")))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "IMAPD: Not enough memory while building up argument array.");
+ return NULL;
+ }
+ the_args[nargs][0] = s[i];
+ the_args[nargs][1] = '\0';
+
+ nargs++;
+ continue;
}
- return NULL;
- }
-
- /* add this parenthesis to the arg list and continue */
- if (!(the_args[nargs] = (char*)my_malloc( sizeof(" ") )) )
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
+
+ if (s[i] == ' ')
+ continue;
+
+ /* at an argument start now, walk on until next delimiter
+ * and save argument
+ */
+
+ for (argstart = i; i < slen && !strchr(" []()", s[i]); i++)
+ if (s[i] == '"') {
+ if (s[i - 1] == '\\')
+ continue;
+ else
+ break;
+ }
+
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(char) *
+ (i - argstart + 1)))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "IMAPD: Not enough memory while building up argument array.");
+ return NULL;
}
-
- trace(TRACE_ERROR,
- "IMAPD: Not enough memory while building up argument array.");
- return NULL;
- }
- the_args[nargs][0] = s[i];
- the_args[nargs][1] = '\0';
-
- nargs++;
- continue;
- }
-
- if (s[i] == ' ')
- continue;
-
- /* at an argument start now, walk on until next delimiter
- * and save argument
- */
-
- for (argstart = i; i<slen && !strchr(" []()",s[i]); i++)
- if (s[i] == '"')
- {
- if (s[i-1] == '\\') continue;
- else break;
- }
-
- if (!(the_args[nargs] = (char*)my_malloc(sizeof(char) * (i-argstart +1)) ))
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR,
- "IMAPD: Not enough memory while building up argument array.");
- return NULL;
+
+ memcpy(the_args[nargs], &s[argstart], i - argstart);
+ the_args[nargs][i - argstart] = '\0';
+
+ nargs++;
+ i--; /* walked one too far */
}
-
- memcpy(the_args[nargs], &s[argstart], i-argstart);
- the_args[nargs][i-argstart] = '\0';
-
- nargs++;
- i--; /* walked one too far */
- }
-
- if (paridx != 0)
- {
- /* error in parenthesis structure */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
+
+ if (paridx != 0) {
+ /* error in parenthesis structure */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+ return NULL;
}
- return NULL;
- }
- the_args[nargs] = NULL; /* terminate */
+ the_args[nargs] = NULL; /* terminate */
- /* dump args (debug) */
- for (i=0; the_args[i]; i++)
- {
- trace(TRACE_DEBUG, "arg[%d]: '%s'\n",i,the_args[i]);
- }
+ /* dump args (debug) */
+ for (i = 0; the_args[i]; i++) {
+ trace(TRACE_DEBUG, "arg[%d]: '%s'\n", i, the_args[i]);
+ }
- return the_args;
+ return the_args;
}
/*
* as build_args_array(), but reads strings on cmd line specified by {##}\0
* (\r\n had been removed from string)
*/
-char **build_args_array_ext(const char *originalString, clientinfo_t *ci)
+char **build_args_array_ext(const char *originalString, clientinfo_t * ci)
{
- int nargs=0,inquote=0, quotestart=0;
- int nnorm=0,nsquare=0,paridx=0,argstart=0;
- unsigned int i;
- char parlist[MAX_LINESIZE];
- char s[MAX_LINESIZE];
- char *tmp, *lastchar;
- int quotedSize, cnt, dataidx;
-
- /* this is done for the possible extra lines to be read from the client:
- * the line is read into currline; s will always point to the line currently
- * being processed
- */
- strncpy(s, originalString, MAX_LINESIZE);
-
- if (!s)
- return NULL;
-
- /* check for empty string */
- if (!(*s))
- {
- the_args[0] = NULL;
- return the_args;
- }
-
- /* find the arguments */
- paridx = 0;
- parlist[paridx] = NOPAR;
-
- inquote = 0;
-
- for (i=0,nargs=0; s[i] && nargs < MAX_ARGS-1; i++)
- {
- /* check quotes */
- if (s[i] == '"' && ((i > 0 && s[i-1] != '\\') || i == 0))
- {
- if (inquote)
- {
- /* quotation end, treat quoted string as argument */
- if (!(the_args[nargs] = (char*)my_malloc(sizeof(char) * (i-quotestart)) ))
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR,
- "IMAPD: Not enough memory while building up argument array.");
- return NULL;
- }
-
- memcpy(the_args[nargs], &s[quotestart+1], i-quotestart-1);
- the_args[nargs][i-quotestart -1] = '\0';
-
- nargs++;
- inquote = 0;
- }
- else
- {
- inquote = 1;
- quotestart = i;
- }
-
- continue;
+ int nargs = 0, inquote = 0, quotestart = 0;
+ int nnorm = 0, nsquare = 0, paridx = 0, argstart = 0;
+ unsigned int i;
+ char parlist[MAX_LINESIZE];
+ char s[MAX_LINESIZE];
+ char *tmp, *lastchar;
+ int quotedSize, cnt, dataidx;
+
+ /* this is done for the possible extra lines to be read from the client:
+ * the line is read into currline; s will always point to the line currently
+ * being processed
+ */
+ strncpy(s, originalString, MAX_LINESIZE);
+
+ if (!s)
+ return NULL;
+
+ /* check for empty string */
+ if (!(*s)) {
+ the_args[0] = NULL;
+ return the_args;
}
- if (inquote)
- continue;
-
- /* check for (, ), [ or ] in string */
- if (s[i] == '(' || s[i] == ')' || s[i] == '[' || s[i] == ']')
- {
- /* check parenthese structure */
- if (s[i] == ')')
- {
- if (paridx < 0 || parlist[paridx] != NORMPAR)
- paridx = -1;
- else
- {
- nnorm--;
- paridx--;
- }
- }
- else if (s[i] == ']')
- {
- if (paridx < 0 || parlist[paridx] != SQUAREPAR)
- paridx = -1;
- else
- {
- paridx--;
- nsquare--;
- }
- }
- else if (s[i] == '(')
- {
- parlist[++paridx] = NORMPAR;
- nnorm++;
- }
- else /* s[i] == '[' */
- {
- parlist[++paridx] = SQUAREPAR;
- nsquare++;
- }
-
- if (paridx < 0)
- {
- /* error in parenthesis structure */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
- return NULL;
- }
-
- /* add this parenthesis to the arg list and continue */
- if (!(the_args[nargs] = (char*)my_malloc( sizeof(" ") )) )
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR,
- "IMAPD: Not enough memory while building up argument array.");
- return NULL;
- }
- the_args[nargs][0] = s[i];
- the_args[nargs][1] = '\0';
-
- nargs++;
- continue;
- }
-
- if (s[i] == ' ')
- continue;
-
- /* check for {number}\0 */
- if (s[i] == '{')
- {
- quotedSize = strtoul(&s[i+1], &lastchar, 10);
-
- /* only continue if the number is followed by '}\0' */
- if (*lastchar == '}' && *(lastchar+1) == '\0')
- {
- /* allocate space for this argument (could be a message when used with APPEND) */
- if (!(the_args[nargs] = (char*)my_malloc(sizeof(char) * (quotedSize+1)) ))
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR,
- "build_args_array_ext(): out of memory allocating [%u] bytes for extra string", quotedSize+1);
- return NULL;
- }
-
- fprintf(ci->tx, "+ OK gimme that string\r\n");
- alarm(ci->timeout); /* dont wait forever */
- for (cnt=0, dataidx=0; cnt<quotedSize; cnt++)
- {
- the_args[nargs][dataidx] = fgetc(ci->rx);
-
- if (the_args[nargs][dataidx] != '\r')
- dataidx++; /* only store if it is not \r */
+ /* find the arguments */
+ paridx = 0;
+ parlist[paridx] = NOPAR;
+
+ inquote = 0;
+
+ for (i = 0, nargs = 0; s[i] && nargs < MAX_ARGS - 1; i++) {
+ /* check quotes */
+ if (s[i] == '"' && ((i > 0 && s[i - 1] != '\\') || i == 0)) {
+ if (inquote) {
+ /* quotation end, treat quoted string as argument */
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(char) *
+ (i -
+ quotestart)))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "IMAPD: Not enough memory while building up argument array.");
+ return NULL;
+ }
+
+ memcpy(the_args[nargs], &s[quotestart + 1],
+ i - quotestart - 1);
+ the_args[nargs][i - quotestart - 1] = '\0';
+
+ nargs++;
+ inquote = 0;
+ } else {
+ inquote = 1;
+ quotestart = i;
+ }
+
+ continue;
}
-
- alarm(0);
- the_args[nargs][dataidx] = '\0'; /* terminate string */
- nargs++;
-
- if (!ci->rx || !ci->tx || ferror(ci->rx) || ferror(ci->tx))
- {
- /* timeout occurred or connection has gone away */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR, "build_args_array_ext(): timeout occurred");
- return NULL;
+
+ if (inquote)
+ continue;
+
+ /* check for (, ), [ or ] in string */
+ if (s[i] == '(' || s[i] == ')' || s[i] == '['
+ || s[i] == ']') {
+ /* check parenthese structure */
+ if (s[i] == ')') {
+ if (paridx < 0
+ || parlist[paridx] != NORMPAR)
+ paridx = -1;
+ else {
+ nnorm--;
+ paridx--;
+ }
+ } else if (s[i] == ']') {
+ if (paridx < 0
+ || parlist[paridx] != SQUAREPAR)
+ paridx = -1;
+ else {
+ paridx--;
+ nsquare--;
+ }
+ } else if (s[i] == '(') {
+ parlist[++paridx] = NORMPAR;
+ nnorm++;
+ } else { /* s[i] == '[' */
+
+ parlist[++paridx] = SQUAREPAR;
+ nsquare++;
+ }
+
+ if (paridx < 0) {
+ /* error in parenthesis structure */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+ return NULL;
+ }
+
+ /* add this parenthesis to the arg list and continue */
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(" ")))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "IMAPD: Not enough memory while building up argument array.");
+ return NULL;
+ }
+ the_args[nargs][0] = s[i];
+ the_args[nargs][1] = '\0';
+
+ nargs++;
+ continue;
}
- /* now read the rest of this line */
- alarm(ci->timeout);
- fgets(s, MAX_LINESIZE, ci->rx);
- alarm(0);
-
- if (!ci->rx || !ci->tx || ferror(ci->rx) || ferror(ci->tx))
- {
- /* timeout occurred */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR, "build_args_array_ext(): timeout occurred");
- return NULL;
+ if (s[i] == ' ')
+ continue;
+
+ /* check for {number}\0 */
+ if (s[i] == '{') {
+ quotedSize = strtoul(&s[i + 1], &lastchar, 10);
+
+ /* only continue if the number is followed by '}\0' */
+ if (*lastchar == '}' && *(lastchar + 1) == '\0') {
+ /* allocate space for this argument (could be a message when used with APPEND) */
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(char) *
+ (quotedSize +
+ 1)))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "build_args_array_ext(): out of memory allocating [%u] bytes for extra string",
+ quotedSize + 1);
+ return NULL;
+ }
+
+ fprintf(ci->tx,
+ "+ OK gimme that string\r\n");
+ alarm(ci->timeout); /* dont wait forever */
+ for (cnt = 0, dataidx = 0;
+ cnt < quotedSize; cnt++) {
+ the_args[nargs][dataidx] =
+ fgetc(ci->rx);
+
+ if (the_args[nargs][dataidx] !=
+ '\r')
+ dataidx++; /* only store if it is not \r */
+ }
+
+ alarm(0);
+ the_args[nargs][dataidx] = '\0'; /* terminate string */
+ nargs++;
+
+ if (!ci->rx || !ci->tx || ferror(ci->rx)
+ || ferror(ci->tx)) {
+ /* timeout occurred or connection has gone away */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "build_args_array_ext(): timeout occurred");
+ return NULL;
+ }
+
+ /* now read the rest of this line */
+ alarm(ci->timeout);
+ fgets(s, MAX_LINESIZE, ci->rx);
+ alarm(0);
+
+ if (!ci->rx || !ci->tx || ferror(ci->rx)
+ || ferror(ci->tx)) {
+ /* timeout occurred */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "build_args_array_ext(): timeout occurred");
+ return NULL;
+ }
+
+ /* remove trailing \r\n */
+ tmp = &s[strlen(s)];
+ tmp--; /* go before trailing \0; watch this with empty strings! */
+ while (tmp >= s
+ && (*tmp == '\r' || *tmp == '\n')) {
+ *tmp = '\0';
+ tmp--;
+ }
+
+ trace(TRACE_DEBUG,
+ "build_args_array_ext(): got extra line [%s]",
+ s);
+
+ /* start over! */
+ i = 0;
+ continue;
+ }
}
- /* remove trailing \r\n */
- tmp = &s[strlen(s)];
- tmp--; /* go before trailing \0; watch this with empty strings! */
- while (tmp >= s && (*tmp == '\r' || *tmp == '\n'))
- {
- *tmp = '\0';
- tmp--;
+ /* at an argument start now, walk on until next delimiter
+ * and save argument
+ */
+
+ for (argstart = i; i < strlen(s) && !strchr(" []()", s[i]);
+ i++)
+ if (s[i] == '"') {
+ if (s[i - 1] == '\\')
+ continue;
+ else
+ break;
+ }
+
+ if (!
+ (the_args[nargs] =
+ (char *) my_malloc(sizeof(char) *
+ (i - argstart + 1)))) {
+ /* out of mem */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+
+ trace(TRACE_ERROR,
+ "IMAPD: Not enough memory while building up argument array.");
+ return NULL;
}
- trace(TRACE_DEBUG, "build_args_array_ext(): got extra line [%s]", s);
+ memcpy(the_args[nargs], &s[argstart], i - argstart);
+ the_args[nargs][i - argstart] = '\0';
- /* start over! */
- i = 0;
- continue;
- }
+ nargs++;
+ i--; /* walked one too far */
}
- /* at an argument start now, walk on until next delimiter
- * and save argument
- */
-
- for (argstart = i; i<strlen(s) && !strchr(" []()",s[i]); i++)
- if (s[i] == '"')
- {
- if (s[i-1] == '\\') continue;
- else break;
- }
-
- if (!(the_args[nargs] = (char*)my_malloc(sizeof(char) * (i-argstart +1)) ))
- {
- /* out of mem */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
- }
-
- trace(TRACE_ERROR,
- "IMAPD: Not enough memory while building up argument array.");
- return NULL;
- }
-
- memcpy(the_args[nargs], &s[argstart], i-argstart);
- the_args[nargs][i-argstart] = '\0';
-
- nargs++;
- i--; /* walked one too far */
- }
-
- if (paridx != 0)
- {
- /* error in parenthesis structure */
- while (--nargs >= 0)
- {
- my_free(the_args[nargs]);
- the_args[nargs] = NULL;
+ if (paridx != 0) {
+ /* error in parenthesis structure */
+ while (--nargs >= 0) {
+ my_free(the_args[nargs]);
+ the_args[nargs] = NULL;
+ }
+ return NULL;
}
- return NULL;
- }
- the_args[nargs] = NULL; /* terminate */
+ the_args[nargs] = NULL; /* terminate */
- /* dump args (debug) */
- for (i=0; the_args[i]; i++)
- {
- trace(TRACE_DEBUG, "arg[%d]: '%s'\n",i,the_args[i]);
- }
+ /* dump args (debug) */
+ for (i = 0; the_args[i]; i++) {
+ trace(TRACE_DEBUG, "arg[%d]: '%s'\n", i, the_args[i]);
+ }
- return the_args;
+ return the_args;
}
#undef NOPAR
@@ -1775,69 +1719,64 @@ char **build_args_array_ext(const char *originalString, clientinfo_t *ci)
*/
void clarify_data(char *str)
{
- int startidx,inquote,endidx;
- unsigned int i;
-
-
- /* remove leading spaces */
- for (i=0; str[i] == ' '; i++) ;
- memmove(str, &str[i], sizeof(char) * (strlen(&str[i])+1)); /* add one for \0 */
-
- /* remove CR/LF */
- endidx = strlen(str)-1;
- if (endidx >= 0 && (str[endidx] == '\n' ||str[endidx] == '\r'))
- endidx--;
-
- if (endidx >= 0 && (str[endidx] == '\n' ||str[endidx] == '\r'))
- endidx--;
-
-
- if (endidx == 0)
- {
- /* only 1 char left and it is not a space */
- str[1] = '\0';
- return;
- }
-
- /* remove trailing spaces */
- for (i=endidx; i>0 && str[i] == ' '; i--) ;
- if (i == 0)
- {
- /* empty string remains */
- *str = '\0';
- return;
- }
-
- str[i+1] = '\0';
-
- /* scan for multiple spaces */
- inquote = 0;
- for (i=0; i < strlen(str); i++)
- {
- if (str[i] == '"')
- {
- if ((i > 0 && str[i-1]!='\\') || i == 0)
- {
- /* toggle in-quote flag */
- inquote ^= 1;
- }
+ int startidx, inquote, endidx;
+ unsigned int i;
+
+
+ /* remove leading spaces */
+ for (i = 0; str[i] == ' '; i++);
+ memmove(str, &str[i], sizeof(char) * (strlen(&str[i]) + 1)); /* add one for \0 */
+
+ /* remove CR/LF */
+ endidx = strlen(str) - 1;
+ if (endidx >= 0 && (str[endidx] == '\n' || str[endidx] == '\r'))
+ endidx--;
+
+ if (endidx >= 0 && (str[endidx] == '\n' || str[endidx] == '\r'))
+ endidx--;
+
+
+ if (endidx == 0) {
+ /* only 1 char left and it is not a space */
+ str[1] = '\0';
+ return;
+ }
+
+ /* remove trailing spaces */
+ for (i = endidx; i > 0 && str[i] == ' '; i--);
+ if (i == 0) {
+ /* empty string remains */
+ *str = '\0';
+ return;
}
- if (str[i] == ' ' && !inquote)
- {
- for (startidx = i; str[i] == ' '; i++);
-
- if (i-startidx > 1)
- {
- /* multiple non-quoted spaces found --> remove 'm */
- memmove(&str[startidx+1], &str[i], sizeof(char) * (strlen(&str[i])+1));
- /* update i */
- i = startidx+1;
- }
+ str[i + 1] = '\0';
+
+ /* scan for multiple spaces */
+ inquote = 0;
+ for (i = 0; i < strlen(str); i++) {
+ if (str[i] == '"') {
+ if ((i > 0 && str[i - 1] != '\\') || i == 0) {
+ /* toggle in-quote flag */
+ inquote ^= 1;
+ }
+ }
+
+ if (str[i] == ' ' && !inquote) {
+ for (startidx = i; str[i] == ' '; i++);
+
+ if (i - startidx > 1) {
+ /* multiple non-quoted spaces found --> remove 'm */
+ memmove(&str[startidx + 1], &str[i],
+ sizeof(char) * (strlen(&str[i]) +
+ 1));
+ /* update i */
+ i = startidx + 1;
+ }
+ }
}
- }
-}
-
+}
+
/*
* is_textplain()
@@ -1846,23 +1785,25 @@ void clarify_data(char *str)
*/
int is_textplain(struct list *hdr)
{
- struct mime_record *mr;
- int i,len;
+ struct mime_record *mr;
+ int i, len;
- if (!hdr)
- return 0;
+ if (!hdr)
+ return 0;
- mime_findfield("content-type", hdr, &mr);
+ mime_findfield("content-type", hdr, &mr);
- if (!mr)
- return 0;
+ if (!mr)
+ return 0;
- len = strlen(mr->value);
- for (i=0; len - i >= (int) sizeof("text/plain"); i++)
- if (strncasecmp(&mr->value[i], "text/plain", sizeof("text/plain")-1) == 0)
- return 1;
-
- return 0;
+ len = strlen(mr->value);
+ for (i = 0; len - i >= (int) sizeof("text/plain"); i++)
+ if (strncasecmp
+ (&mr->value[i], "text/plain",
+ sizeof("text/plain") - 1) == 0)
+ return 1;
+
+ return 0;
}
@@ -1877,39 +1818,38 @@ int is_textplain(struct list *hdr)
*/
char *date_sql2imap(const char *sqldate)
{
- int mon;
+ int mon;
- if (strlen(sqldate) != strlen("yyyy-mm-dd hh:mm:ss"))
- {
- strcpy(_imapdate, "03-Nov-1979 00:00:00");
- return _imapdate;
- }
+ if (strlen(sqldate) != strlen("yyyy-mm-dd hh:mm:ss")) {
+ strcpy(_imapdate, "03-Nov-1979 00:00:00");
+ return _imapdate;
+ }
- /* copy day */
- _imapdate[0] = sqldate[8];
- _imapdate[1] = sqldate[9];
+ /* copy day */
+ _imapdate[0] = sqldate[8];
+ _imapdate[1] = sqldate[9];
- /* find out which month */
- mon = strtoul(&sqldate[5], NULL, 10) - 1;
- if (mon < 0 || mon > 11)
- mon = 0;
+ /* find out which month */
+ mon = strtoul(&sqldate[5], NULL, 10) - 1;
+ if (mon < 0 || mon > 11)
+ mon = 0;
- /* copy month */
- _imapdate[3] = month_desc[mon][0];
- _imapdate[4] = month_desc[mon][1];
- _imapdate[5] = month_desc[mon][2];
+ /* copy month */
+ _imapdate[3] = month_desc[mon][0];
+ _imapdate[4] = month_desc[mon][1];
+ _imapdate[5] = month_desc[mon][2];
- /* copy year */
- _imapdate[7] = sqldate[0];
- _imapdate[8] = sqldate[1];
- _imapdate[9] = sqldate[2];
- _imapdate[10] = sqldate[3];
+ /* copy year */
+ _imapdate[7] = sqldate[0];
+ _imapdate[8] = sqldate[1];
+ _imapdate[9] = sqldate[2];
+ _imapdate[10] = sqldate[3];
- /* copy time */
- strcpy(&_imapdate[11], &sqldate[10]);
+ /* copy time */
+ strcpy(&_imapdate[11], &sqldate[10]);
- return _imapdate;
-}
+ return _imapdate;
+}
/*
@@ -1926,49 +1866,49 @@ char *date_sql2imap(const char *sqldate)
*/
char *date_imap2sql(const char *imapdate)
{
- int i,j;
- char sub[4];
+ int i, j;
+ char sub[4];
+
+ if (strlen(imapdate) != strlen("dd-mon-yyyy")
+ && strlen(imapdate) != strlen("d-mon-yyyy"))
+ return NULL;
- if (strlen(imapdate) != strlen("dd-mon-yyyy") && strlen(imapdate) != strlen("d-mon-yyyy"))
- return NULL;
+ j = (strlen(imapdate) == strlen("d-mon-yyyy")) ? 1 : 0;
- j = (strlen(imapdate) == strlen("d-mon-yyyy")) ? 1 : 0;
+ /* copy year */
+ _sqldate[0] = imapdate[7 - j];
+ _sqldate[1] = imapdate[8 - j];
+ _sqldate[2] = imapdate[9 - j];
+ _sqldate[3] = imapdate[10 - j];
- /* copy year */
- _sqldate[0] = imapdate[7-j];
- _sqldate[1] = imapdate[8-j];
- _sqldate[2] = imapdate[9-j];
- _sqldate[3] = imapdate[10-j];
+ _sqldate[4] = '-';
- _sqldate[4] = '-';
+ /* copy month */
+ strncpy(sub, &imapdate[3 - j], 3);
+ sub[3] = 0;
- /* copy month */
- strncpy(sub, &imapdate[3-j], 3);
- sub[3] = 0;
+ for (i = 0; i < 12; i++) {
+ if (strcasecmp(month_desc[i], sub) == 0)
+ break;
+ }
- for (i=0; i<12; i++)
- {
- if (strcasecmp(month_desc[i], sub) == 0)
- break;
- }
-
- if (i>=12)
- return NULL;
+ if (i >= 12)
+ return NULL;
- i++; /* make i in [1,12] */
- _sqldate[5] = (i<10) ? '0' : '1';
- _sqldate[6] = (i<10) ? (i+'0') : ((i-10) + '0');
+ i++; /* make i in [1,12] */
+ _sqldate[5] = (i < 10) ? '0' : '1';
+ _sqldate[6] = (i < 10) ? (i + '0') : ((i - 10) + '0');
- _sqldate[7] = '-';
-
- /* copy day */
- _sqldate[8] = j ? '0' : imapdate[0];
- _sqldate[9] = imapdate[1-j];
-
- _sqldate[10] = 0; /* terminate */
+ _sqldate[7] = '-';
- return _sqldate;
-}
+ /* copy day */
+ _sqldate[8] = j ? '0' : imapdate[0];
+ _sqldate[9] = imapdate[1 - j];
+
+ _sqldate[10] = 0; /* terminate */
+
+ return _sqldate;
+}
/*
@@ -1976,11 +1916,11 @@ char *date_imap2sql(const char *imapdate)
*/
unsigned stridx(const char *s, char ch)
{
- unsigned i;
+ unsigned i;
- for (i=0; s[i] && s[i] != ch; i++) ;
+ for (i = 0; s[i] && s[i] != ch; i++);
- return i;
+ return i;
}
@@ -1992,17 +1932,15 @@ unsigned stridx(const char *s, char ch)
*/
int checkchars(const char *s)
{
- int i;
-
- for (i=0; s[i]; i++)
- {
- if (!strchr(AcceptedChars, s[i]))
- {
- /* wrong char found */
- return 0;
+ int i;
+
+ for (i = 0; s[i]; i++) {
+ if (!strchr(AcceptedChars, s[i])) {
+ /* wrong char found */
+ return 0;
+ }
}
- }
- return 1;
+ return 1;
}
@@ -2014,17 +1952,15 @@ int checkchars(const char *s)
*/
int checktag(const char *s)
{
- int i;
-
- for (i=0; s[i]; i++)
- {
- if (!strchr(AcceptedTagChars, s[i]))
- {
- /* wrong char found */
- return 0;
+ int i;
+
+ for (i = 0; s[i]; i++) {
+ if (!strchr(AcceptedTagChars, s[i])) {
+ /* wrong char found */
+ return 0;
+ }
}
- }
- return 1;
+ return 1;
}
@@ -2036,39 +1972,36 @@ int checktag(const char *s)
*/
int checkmailboxname(const char *s)
{
- int i;
-
- if (strlen(s) == 0)
- return 0; /* empty name is not valid */
-
- if (strlen(s) >= IMAP_MAX_MAILBOX_NAMELEN)
- return 0; /* a too large string is not valid */
-
- /* check for invalid characters */
- for (i=0; s[i]; i++)
- {
- if (!strchr(AcceptedMailboxnameChars, s[i]))
- {
- /* dirty hack to allow namespaces to function */
- if (i == 0 && s[0] == '#')
- continue;
- /* wrong char found */
- return 0;
+ int i;
+
+ if (strlen(s) == 0)
+ return 0; /* empty name is not valid */
+
+ if (strlen(s) >= IMAP_MAX_MAILBOX_NAMELEN)
+ return 0; /* a too large string is not valid */
+
+ /* check for invalid characters */
+ for (i = 0; s[i]; i++) {
+ if (!strchr(AcceptedMailboxnameChars, s[i])) {
+ /* dirty hack to allow namespaces to function */
+ if (i == 0 && s[0] == '#')
+ continue;
+ /* wrong char found */
+ return 0;
+ }
}
- }
- /* check for double '/' */
- for (i=1; s[i]; i++)
- {
- if (s[i] == '/' && s[i-1] == '/')
- return 0;
- }
+ /* check for double '/' */
+ for (i = 1; s[i]; i++) {
+ if (s[i] == '/' && s[i - 1] == '/')
+ return 0;
+ }
- /* check if the name consists of a single '/' */
- if (strlen(s) == 1 && s[0] == '/')
- return 0;
+ /* check if the name consists of a single '/' */
+ if (strlen(s) == 1 && s[0] == '/')
+ return 0;
- return 1;
+ return 1;
}
@@ -2082,36 +2015,37 @@ int checkmailboxname(const char *s)
*/
int check_date(const char *date)
{
- char sub[4];
- int days,i,j;
+ char sub[4];
+ int days, i, j;
- if (strlen(date) != strlen("01-Jan-1970") && strlen(date) != strlen("1-Jan-1970"))
- return 0;
+ if (strlen(date) != strlen("01-Jan-1970")
+ && strlen(date) != strlen("1-Jan-1970"))
+ return 0;
- j = (strlen(date) == strlen("1-Jan-1970")) ? 1 : 0;
-
- if (date[2-j] != '-' || date[6-j] != '-')
- return 0;
+ j = (strlen(date) == strlen("1-Jan-1970")) ? 1 : 0;
- days = strtoul(date, NULL, 10);
- strncpy(sub, &date[3-j], 3);
- sub[3] = 0;
+ if (date[2 - j] != '-' || date[6 - j] != '-')
+ return 0;
- for (i=0; i<12; i++)
- {
- if (strcasecmp(month_desc[i], sub) == 0)
- break;
- }
+ days = strtoul(date, NULL, 10);
+ strncpy(sub, &date[3 - j], 3);
+ sub[3] = 0;
- if (i >= 12 || days > month_len[i])
- return 0;
+ for (i = 0; i < 12; i++) {
+ if (strcasecmp(month_desc[i], sub) == 0)
+ break;
+ }
+
+ if (i >= 12 || days > month_len[i])
+ return 0;
- for (i=7; i<11; i++)
- if (!isdigit(date[i-j])) return 0;
+ for (i = 7; i < 11; i++)
+ if (!isdigit(date[i - j]))
+ return 0;
- return 1;
+ return 1;
}
-
+
/*
@@ -2121,77 +2055,74 @@ int check_date(const char *date)
*/
int check_msg_set(const char *s)
{
- int i,indigit;
-
- if (!s || !isdigit(s[0]))
- return 0;
-
- for (i=1,indigit=1; s[i]; i++)
- {
- if (isdigit(s[i]))
- indigit = 1;
- else if (s[i] == ',')
- {
- if (!indigit && s[i-1] != '*')
- return 0;
-
- indigit = 0;
- }
- else if (s[i] == ':')
- {
- if (!indigit)
- return 0;
-
- indigit = 0;
- }
- else if (s[i] == '*')
- {
- if (s[i-1] != ':')
- return 0;
+ int i, indigit;
+
+ if (!s || !isdigit(s[0]))
+ return 0;
+
+ for (i = 1, indigit = 1; s[i]; i++) {
+ if (isdigit(s[i]))
+ indigit = 1;
+ else if (s[i] == ',') {
+ if (!indigit && s[i - 1] != '*')
+ return 0;
+
+ indigit = 0;
+ } else if (s[i] == ':') {
+ if (!indigit)
+ return 0;
+
+ indigit = 0;
+ } else if (s[i] == '*') {
+ if (s[i - 1] != ':')
+ return 0;
+ }
}
- }
- return 1;
+ return 1;
}
-
+
/*
* base64encode()
*
* encodes a string using base64 encoding
*/
-void base64encode(char *in,char *out)
+void base64encode(char *in, char *out)
{
- for ( ; strlen(in) >= 3; in+=3)
- {
- *out++ = base64encodestring[ (in[0] & 0xFC) >> 2U];
- *out++ = base64encodestring[ ((in[0] & 0x03) << 4U) | ((in[1] & 0xF0) >> 4U) ];
- *out++ = base64encodestring[ ((in[1] & 0x0F) << 2U) | ((in[2] & 0xC0) >> 6U) ];
- *out++ = base64encodestring[ (in[2] & 0x3F) ];
- }
-
- if (strlen(in) == 2)
- {
- /* 16 bits left to encode */
- *out++ = base64encodestring[ (in[0] & 0xFC) >> 2U];
- *out++ = base64encodestring[ ((in[0] & 0x03) << 4U) | ((in[1] & 0xF0) >> 4U) ];
- *out++ = base64encodestring[ ((in[1] & 0x0F) << 2U) ];
- *out++ = '=';
-
- return;
- }
-
- if (strlen(in) == 1)
- {
- /* 8 bits left to encode */
- *out++ = base64encodestring[ (in[0] & 0xFC) >> 2U];
- *out++ = base64encodestring[ ((in[0] & 0x03) << 4U) ];
- *out++ = '=';
- *out++ = '=';
-
- return;
- }
-}
+ for (; strlen(in) >= 3; in += 3) {
+ *out++ = base64encodestring[(in[0] & 0xFC) >> 2U];
+ *out++ =
+ base64encodestring[((in[0] & 0x03) << 4U) |
+ ((in[1] & 0xF0) >> 4U)];
+ *out++ =
+ base64encodestring[((in[1] & 0x0F) << 2U) |
+ ((in[2] & 0xC0) >> 6U)];
+ *out++ = base64encodestring[(in[2] & 0x3F)];
+ }
+
+ if (strlen(in) == 2) {
+ /* 16 bits left to encode */
+ *out++ = base64encodestring[(in[0] & 0xFC) >> 2U];
+ *out++ =
+ base64encodestring[((in[0] & 0x03) << 4U) |
+ ((in[1] & 0xF0) >> 4U)];
+ *out++ = base64encodestring[((in[1] & 0x0F) << 2U)];
+ *out++ = '=';
+
+ return;
+ }
+
+ if (strlen(in) == 1) {
+ /* 8 bits left to encode */
+ *out++ = base64encodestring[(in[0] & 0xFC) >> 2U];
+ *out++ = base64encodestring[((in[0] & 0x03) << 4U)];
+ *out++ = '=';
+ *out++ = '=';
+
+ return;
+ }
+}
/*
@@ -2199,22 +2130,21 @@ void base64encode(char *in,char *out)
*
* decodes a base64 encoded string
*/
-void base64decode(char *in,char *out)
+void base64decode(char *in, char *out)
{
- for ( ; strlen(in) >= 4; in+=4)
- {
- *out++ = (stridx(base64encodestring, in[0]) << 2U)
- | ((stridx(base64encodestring, in[1]) & 0x30) >> 4U);
+ for (; strlen(in) >= 4; in += 4) {
+ *out++ = (stridx(base64encodestring, in[0]) << 2U)
+ | ((stridx(base64encodestring, in[1]) & 0x30) >> 4U);
- *out++ = ((stridx(base64encodestring, in[1]) & 0x0F) << 4U)
- | ((stridx(base64encodestring, in[2]) & 0x3C) >> 2U);
+ *out++ = ((stridx(base64encodestring, in[1]) & 0x0F) << 4U)
+ | ((stridx(base64encodestring, in[2]) & 0x3C) >> 2U);
- *out++ = ((stridx(base64encodestring, in[2]) & 0x03) << 6U)
- | (stridx(base64encodestring, in[3]) & 0x3F);
- }
+ *out++ = ((stridx(base64encodestring, in[2]) & 0x03) << 6U)
+ | (stridx(base64encodestring, in[3]) & 0x3F);
+ }
- *out = 0;
-}
+ *out = 0;
+}
/*
@@ -2225,36 +2155,35 @@ void base64decode(char *in,char *out)
*
* returns -1 if not found. key_idx will hold key if found
*/
-int binary_search(const u64_t *array, unsigned arraysize, u64_t key,
+int binary_search(const u64_t * array, unsigned arraysize, u64_t key,
unsigned int *key_idx)
{
- unsigned low, high, mid = 1;
-
- assert(key_idx != NULL);
- *key_idx = 0;
- if (arraysize == 0)
- return -1;
-
- low = 0;
- high = arraysize-1;
-
- while (low <= high) {
- mid = (high + low) / (unsigned) 2;
- if (array[mid] < key)
- low = mid + 1;
- else if (array[mid] > key) {
- if (mid > 0)
- high = mid - 1;
- else
- break;
- }
- else {
- *key_idx = mid;
- return 1;
- }
- }
-
- return -1; /* not found */
+ unsigned low, high, mid = 1;
+
+ assert(key_idx != NULL);
+ *key_idx = 0;
+ if (arraysize == 0)
+ return -1;
+
+ low = 0;
+ high = arraysize - 1;
+
+ while (low <= high) {
+ mid = (high + low) / (unsigned) 2;
+ if (array[mid] < key)
+ low = mid + 1;
+ else if (array[mid] > key) {
+ if (mid > 0)
+ high = mid - 1;
+ else
+ break;
+ } else {
+ *key_idx = mid;
+ return 1;
+ }
+ }
+
+ return -1; /* not found */
}
/*
@@ -2266,28 +2195,29 @@ int binary_search(const u64_t *array, unsigned arraysize, u64_t key,
*
* returns the number of bytes outputted.
*/
-int quoted_string_out(FILE *outstream, const char *s)
+int quoted_string_out(FILE * outstream, const char *s)
{
- int i,cnt;
-
- // check wheter we must use literal string
- for (i = 0; s[i]; i++)
- {
- if (!(s[i] & 0xe0) || (s[i] & 0x80) || (s[i] == '"') || (s[i] == '\\'))
- {
- cnt = fprintf(outstream, "{");
- cnt += fprintf(outstream, "%lu", (unsigned long) strlen(s));
- cnt += fprintf(outstream, "}\r\n");
- cnt += fprintf(outstream, "%s", s);
- return cnt;
+ int i, cnt;
+
+ // check wheter we must use literal string
+ for (i = 0; s[i]; i++) {
+ if (!(s[i] & 0xe0) || (s[i] & 0x80) || (s[i] == '"')
+ || (s[i] == '\\')) {
+ cnt = fprintf(outstream, "{");
+ cnt +=
+ fprintf(outstream, "%lu",
+ (unsigned long) strlen(s));
+ cnt += fprintf(outstream, "}\r\n");
+ cnt += fprintf(outstream, "%s", s);
+ return cnt;
+ }
}
- }
- cnt = fprintf(outstream, "\"");
- cnt += fprintf(outstream, "%s", s);
- cnt += fprintf(outstream, "\"");
+ cnt = fprintf(outstream, "\"");
+ cnt += fprintf(outstream, "%s", s);
+ cnt += fprintf(outstream, "\"");
- return cnt;
+ return cnt;
}
@@ -2297,25 +2227,23 @@ int quoted_string_out(FILE *outstream, const char *s)
* sends cnt bytes from a MEM structure to a FILE stream
* uses a simple buffering system
*/
-void send_data(FILE *to, MEM *from, int cnt)
+void send_data(FILE * to, MEM * from, int cnt)
{
- char buf[SEND_BUF_SIZE];
+ char buf[SEND_BUF_SIZE];
- for (cnt -= SEND_BUF_SIZE; cnt >= 0; cnt -= SEND_BUF_SIZE)
- {
- mread(buf, SEND_BUF_SIZE, from);
- fwrite(buf, SEND_BUF_SIZE, 1, to);
- }
+ for (cnt -= SEND_BUF_SIZE; cnt >= 0; cnt -= SEND_BUF_SIZE) {
+ mread(buf, SEND_BUF_SIZE, from);
+ fwrite(buf, SEND_BUF_SIZE, 1, to);
+ }
- if (cnt < 0)
- {
- mread(buf, cnt+SEND_BUF_SIZE, from);
- fwrite(buf, cnt+SEND_BUF_SIZE, 1, to);
- }
+ if (cnt < 0) {
+ mread(buf, cnt + SEND_BUF_SIZE, from);
+ fwrite(buf, cnt + SEND_BUF_SIZE, 1, to);
+ }
- fflush(to);
+ fflush(to);
}
-
+
/*
@@ -2328,441 +2256,374 @@ void send_data(FILE *to, MEM *from, int cnt)
*/
int build_imap_search(char **search_keys, struct list *sl, int *idx)
{
- search_key_t key;
- int result;
-
- if (!search_keys || !search_keys[*idx])
- return 0;
-
- memset(&key, 0, sizeof(key));
-
- if (strcasecmp(search_keys[*idx], "all") == 0)
- {
- key.type = IST_SET;
- strcpy(key.search, "1:*");
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "uid") == 0)
- {
- key.type = IST_SET_UID;
- if (!search_keys[*idx+1])
- return -1;
-
- (*idx)++;
-
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- if (!check_msg_set(key.search))
- return -1;
-
- (*idx)++;
- }
-
- /*
- * FLAG search keys
- */
-
- else if (strcasecmp(search_keys[*idx], "answered") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "answered_flag=1", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "deleted") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "deleted_flag=1", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "flagged") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "flagged_flag=1", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "recent") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "recent_flag=1", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "seen") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "seen_flag=1", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "keyword") == 0)
- {
- /* no results from this one */
- if (!search_keys[(*idx)+1]) /* there should follow an argument */
- return -1;
-
- (*idx)++;
-
- key.type = IST_SET;
- strcpy(key.search, "0");
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "draft") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "draft_flag=1", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "new") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "(seen_flag=0 AND recent_flag=1)", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "old") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "recent_flag=0", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "unanswered") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "answered_flag=0", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "undeleted") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "deleted_flag=0", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "unflagged") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "flagged_flag=0", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "unseen") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "seen_flag=0", MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "unkeyword") == 0)
- {
- /* matches every msg */
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
-
- key.type = IST_SET;
- strcpy(key.search, "1:*");
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "undraft") == 0)
- {
- key.type = IST_FLAG;
- strncpy(key.search, "draft_flag=0", MAX_SEARCH_LEN);
- (*idx)++;
- }
-
- /*
- * HEADER search keys
- */
-
- else if (strcasecmp(search_keys[*idx], "bcc") == 0)
- {
- key.type = IST_HDR;
- strncpy(key.hdrfld, "bcc", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "cc") == 0)
- {
- key.type = IST_HDR;
- strncpy(key.hdrfld, "cc", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "from") == 0)
- {
- key.type = IST_HDR;
- strncpy(key.hdrfld, "from", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "to") == 0)
- {
- key.type = IST_HDR;
- strncpy(key.hdrfld, "to", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "subject") == 0)
- {
- key.type = IST_HDR;
- strncpy(key.hdrfld, "subject", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "header") == 0)
- {
- key.type = IST_HDR;
- if (!search_keys[(*idx)+1] || !search_keys[(*idx)+2])
- return -1;
-
- strncpy(key.hdrfld, search_keys[(*idx)+1], MIME_FIELD_MAX);
- strncpy(key.search, search_keys[(*idx)+2], MAX_SEARCH_LEN);
-
- (*idx) += 3;
- }
- else if (strcasecmp(search_keys[*idx], "sentbefore") == 0)
- {
- key.type = IST_HDRDATE_BEFORE;
- strncpy(key.hdrfld, "date", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "senton") == 0)
- {
- key.type = IST_HDRDATE_ON;
- strncpy(key.hdrfld, "date", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "sentsince") == 0)
- {
- key.type = IST_HDRDATE_SINCE;
- strncpy(key.hdrfld, "date", MIME_FIELD_MAX);
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
-
- /*
- * INTERNALDATE keys
- */
-
- else if (strcasecmp(search_keys[*idx], "before") == 0)
- {
- key.type = IST_IDATE;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- if (!check_date(search_keys[*idx]))
- return -1;
-
- strncpy(key.search, "internal_date<'", MAX_SEARCH_LEN);
- strncat(key.search, date_imap2sql(search_keys[*idx]),
- MAX_SEARCH_LEN - sizeof("internal_date<''"));
- strcat(key.search, "'");
-
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "on") == 0)
- {
- key.type = IST_IDATE;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- if (!check_date(search_keys[*idx]))
- return -1;
-
- strncpy(key.search, "internal_date LIKE '", MAX_SEARCH_LEN);
- strncat(key.search, date_imap2sql(search_keys[*idx]),
- MAX_SEARCH_LEN - sizeof("internal_date LIKE 'x'"));
- strcat(key.search, "%'");
-
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "since") == 0)
- {
- key.type = IST_IDATE;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- if (!check_date(search_keys[*idx]))
- return -1;
-
- strncpy(key.search, "internal_date>'", MAX_SEARCH_LEN);
- strncat(key.search, date_imap2sql(search_keys[*idx]),
- MAX_SEARCH_LEN - sizeof("internal_date>''"));
- strcat(key.search, "'");
-
- (*idx)++;
- }
-
- /*
- * DATA-keys
- */
-
- else if (strcasecmp(search_keys[*idx], "body") == 0)
- {
- key.type = IST_DATA_BODY;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "text") == 0)
- {
- key.type = IST_DATA_TEXT;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
- (*idx)++;
- }
-
- /*
- * SIZE keys
- */
-
- else if (strcasecmp(search_keys[*idx], "larger") == 0)
- {
- key.type = IST_SIZE_LARGER;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- key.size = strtoull(search_keys[(*idx)], NULL, 10);
- (*idx)++;
- }
- else if (strcasecmp(search_keys[*idx], "smaller") == 0)
- {
- key.type = IST_SIZE_SMALLER;
- if (!search_keys[(*idx)+1])
- return -1;
-
- (*idx)++;
- key.size = strtoull(search_keys[(*idx)], NULL, 10);
- (*idx)++;
- }
-
- /*
- * NOT, OR, ()
- */
- else if (strcasecmp(search_keys[*idx], "not") == 0)
- {
- key.type = IST_SUBSEARCH_NOT;
-
- (*idx)++;
- if ((result = build_imap_search(search_keys, &key.sub_search, idx)) < 0)
- {
- list_freelist(&key.sub_search.start);
- return result;
+ search_key_t key;
+ int result;
+
+ if (!search_keys || !search_keys[*idx])
+ return 0;
+
+ memset(&key, 0, sizeof(key));
+
+ if (strcasecmp(search_keys[*idx], "all") == 0) {
+ key.type = IST_SET;
+ strcpy(key.search, "1:*");
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "uid") == 0) {
+ key.type = IST_SET_UID;
+ if (!search_keys[*idx + 1])
+ return -1;
+
+ (*idx)++;
+
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ if (!check_msg_set(key.search))
+ return -1;
+
+ (*idx)++;
}
- /* a NOT should be unary */
- if (key.sub_search.total_nodes != 1)
- {
- free_searchlist(&key.sub_search);
- return -1;
+ /*
+ * FLAG search keys
+ */
+
+ else if (strcasecmp(search_keys[*idx], "answered") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "answered_flag=1", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "deleted") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "deleted_flag=1", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "flagged") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "flagged_flag=1", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "recent") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "recent_flag=1", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "seen") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "seen_flag=1", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "keyword") == 0) {
+ /* no results from this one */
+ if (!search_keys[(*idx) + 1]) /* there should follow an argument */
+ return -1;
+
+ (*idx)++;
+
+ key.type = IST_SET;
+ strcpy(key.search, "0");
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "draft") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "draft_flag=1", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "new") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "(seen_flag=0 AND recent_flag=1)",
+ MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "old") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "recent_flag=0", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "unanswered") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "answered_flag=0", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "undeleted") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "deleted_flag=0", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "unflagged") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "flagged_flag=0", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "unseen") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "seen_flag=0", MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "unkeyword") == 0) {
+ /* matches every msg */
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+
+ key.type = IST_SET;
+ strcpy(key.search, "1:*");
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "undraft") == 0) {
+ key.type = IST_FLAG;
+ strncpy(key.search, "draft_flag=0", MAX_SEARCH_LEN);
+ (*idx)++;
}
- }
- else if (strcasecmp(search_keys[*idx], "or") == 0)
- {
- key.type = IST_SUBSEARCH_OR;
-
- (*idx)++;
- if ((result = build_imap_search(search_keys, &key.sub_search, idx)) < 0)
- {
- list_freelist(&key.sub_search.start);
- return result;
+
+ /*
+ * HEADER search keys
+ */
+
+ else if (strcasecmp(search_keys[*idx], "bcc") == 0) {
+ key.type = IST_HDR;
+ strncpy(key.hdrfld, "bcc", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "cc") == 0) {
+ key.type = IST_HDR;
+ strncpy(key.hdrfld, "cc", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "from") == 0) {
+ key.type = IST_HDR;
+ strncpy(key.hdrfld, "from", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "to") == 0) {
+ key.type = IST_HDR;
+ strncpy(key.hdrfld, "to", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "subject") == 0) {
+ key.type = IST_HDR;
+ strncpy(key.hdrfld, "subject", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "header") == 0) {
+ key.type = IST_HDR;
+ if (!search_keys[(*idx) + 1] || !search_keys[(*idx) + 2])
+ return -1;
+
+ strncpy(key.hdrfld, search_keys[(*idx) + 1],
+ MIME_FIELD_MAX);
+ strncpy(key.search, search_keys[(*idx) + 2],
+ MAX_SEARCH_LEN);
+
+ (*idx) += 3;
+ } else if (strcasecmp(search_keys[*idx], "sentbefore") == 0) {
+ key.type = IST_HDRDATE_BEFORE;
+ strncpy(key.hdrfld, "date", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "senton") == 0) {
+ key.type = IST_HDRDATE_ON;
+ strncpy(key.hdrfld, "date", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "sentsince") == 0) {
+ key.type = IST_HDRDATE_SINCE;
+ strncpy(key.hdrfld, "date", MIME_FIELD_MAX);
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
}
- if ((result = build_imap_search(search_keys, &key.sub_search, idx)) < 0)
- {
- list_freelist(&key.sub_search.start);
- return result;
+ /*
+ * INTERNALDATE keys
+ */
+
+ else if (strcasecmp(search_keys[*idx], "before") == 0) {
+ key.type = IST_IDATE;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ if (!check_date(search_keys[*idx]))
+ return -1;
+
+ strncpy(key.search, "internal_date<'", MAX_SEARCH_LEN);
+ strncat(key.search, date_imap2sql(search_keys[*idx]),
+ MAX_SEARCH_LEN - sizeof("internal_date<''"));
+ strcat(key.search, "'");
+
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "on") == 0) {
+ key.type = IST_IDATE;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ if (!check_date(search_keys[*idx]))
+ return -1;
+
+ strncpy(key.search, "internal_date LIKE '",
+ MAX_SEARCH_LEN);
+ strncat(key.search, date_imap2sql(search_keys[*idx]),
+ MAX_SEARCH_LEN - sizeof("internal_date LIKE 'x'"));
+ strcat(key.search, "%'");
+
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "since") == 0) {
+ key.type = IST_IDATE;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ if (!check_date(search_keys[*idx]))
+ return -1;
+
+ strncpy(key.search, "internal_date>'", MAX_SEARCH_LEN);
+ strncat(key.search, date_imap2sql(search_keys[*idx]),
+ MAX_SEARCH_LEN - sizeof("internal_date>''"));
+ strcat(key.search, "'");
+
+ (*idx)++;
}
- /* an OR should be binary */
- if (key.sub_search.total_nodes != 2)
- {
- free_searchlist(&key.sub_search);
- return -1;
+ /*
+ * DATA-keys
+ */
+
+ else if (strcasecmp(search_keys[*idx], "body") == 0) {
+ key.type = IST_DATA_BODY;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "text") == 0) {
+ key.type = IST_DATA_TEXT;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ strncpy(key.search, search_keys[(*idx)], MAX_SEARCH_LEN);
+ (*idx)++;
}
- }
- else if (strcasecmp(search_keys[*idx], "(") == 0)
- {
- key.type = IST_SUBSEARCH_AND;
+ /*
+ * SIZE keys
+ */
+
+ else if (strcasecmp(search_keys[*idx], "larger") == 0) {
+ key.type = IST_SIZE_LARGER;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ key.size = strtoull(search_keys[(*idx)], NULL, 10);
+ (*idx)++;
+ } else if (strcasecmp(search_keys[*idx], "smaller") == 0) {
+ key.type = IST_SIZE_SMALLER;
+ if (!search_keys[(*idx) + 1])
+ return -1;
+
+ (*idx)++;
+ key.size = strtoull(search_keys[(*idx)], NULL, 10);
+ (*idx)++;
+ }
- (*idx)++;
- while ((result = build_imap_search(search_keys, &key.sub_search, idx)) == 0
- && search_keys[*idx]) ;
+ /*
+ * NOT, OR, ()
+ */
+ else if (strcasecmp(search_keys[*idx], "not") == 0) {
+ key.type = IST_SUBSEARCH_NOT;
+
+ (*idx)++;
+ if ((result =
+ build_imap_search(search_keys, &key.sub_search,
+ idx)) < 0) {
+ list_freelist(&key.sub_search.start);
+ return result;
+ }
- if (result < 0)
- {
- /* error */
- list_freelist(&key.sub_search.start);
- return result;
- }
+ /* a NOT should be unary */
+ if (key.sub_search.total_nodes != 1) {
+ free_searchlist(&key.sub_search);
+ return -1;
+ }
+ } else if (strcasecmp(search_keys[*idx], "or") == 0) {
+ key.type = IST_SUBSEARCH_OR;
+
+ (*idx)++;
+ if ((result =
+ build_imap_search(search_keys, &key.sub_search,
+ idx)) < 0) {
+ list_freelist(&key.sub_search.start);
+ return result;
+ }
+
+ if ((result =
+ build_imap_search(search_keys, &key.sub_search,
+ idx)) < 0) {
+ list_freelist(&key.sub_search.start);
+ return result;
+ }
+
+ /* an OR should be binary */
+ if (key.sub_search.total_nodes != 2) {
+ free_searchlist(&key.sub_search);
+ return -1;
+ }
- if (result == 0)
- {
- /* no ')' encountered (should not happen, parentheses are matched at the command line) */
- free_searchlist(&key.sub_search);
- return -1;
+ } else if (strcasecmp(search_keys[*idx], "(") == 0) {
+ key.type = IST_SUBSEARCH_AND;
+
+ (*idx)++;
+ while ((result =
+ build_imap_search(search_keys, &key.sub_search,
+ idx)) == 0 && search_keys[*idx]);
+
+ if (result < 0) {
+ /* error */
+ list_freelist(&key.sub_search.start);
+ return result;
+ }
+
+ if (result == 0) {
+ /* no ')' encountered (should not happen, parentheses are matched at the command line) */
+ free_searchlist(&key.sub_search);
+ return -1;
+ }
+ } else if (strcasecmp(search_keys[*idx], ")") == 0) {
+ (*idx)++;
+ return 1;
+ } else if (check_msg_set(search_keys[*idx])) {
+ key.type = IST_SET;
+ strncpy(key.search, search_keys[*idx], MAX_SEARCH_LEN);
+ (*idx)++;
+ } else {
+ /* unknown search key */
+ return -1;
}
- }
- else if (strcasecmp(search_keys[*idx], ")") == 0)
- {
- (*idx)++;
- return 1;
- }
- else if (check_msg_set(search_keys[*idx]))
- {
- key.type = IST_SET;
- strncpy(key.search, search_keys[*idx], MAX_SEARCH_LEN);
- (*idx)++;
- }
- else
- {
- /* unknown search key */
- return -1;
- }
-
- if (!list_nodeadd(sl, &key, sizeof(key)))
- return -2;
-
- return 0;
+
+ if (!list_nodeadd(sl, &key, sizeof(key)))
+ return -2;
+
+ return 0;
}
@@ -2772,105 +2633,103 @@ int build_imap_search(char **search_keys, struct list *sl, int *idx)
* returns 0 on succes, -1 on dbase error, -2 on memory error, 1 if result set is too small
* (new mail has been added to mailbox while searching, mailbox data out of sync)
*/
-int perform_imap_search(int *rset, int setlen, search_key_t *sk, mailbox_t *mb)
+int perform_imap_search(int *rset, int setlen, search_key_t * sk,
+ mailbox_t * mb)
{
- search_key_t *subsk;
- struct element *el;
- int result,*newset = NULL,i;
- int subtype = IST_SUBSEARCH_OR;
-
- if (!rset)
- return -2; /* stupidity */
-
- if (!sk)
- return 0; /* no search */
-
- newset = (int*)my_malloc(sizeof(int) * setlen);
- if (!newset)
- return -2;
-
- switch (sk->type)
- {
- case IST_SET:
- build_set(rset, setlen, sk->search);
- break;
-
- case IST_SET_UID:
- build_uid_set(rset, setlen, sk->search, mb);
- break;
-
- case IST_FLAG:
- result = db_search(rset, setlen, sk->search, mb, sk->type);
- if (result != 0)
- {
- my_free(newset);
- return result;
- }
- break;
-
- case IST_HDR:
- case IST_HDRDATE_BEFORE:
- case IST_HDRDATE_ON:
- case IST_HDRDATE_SINCE:
- case IST_DATA_BODY:
- case IST_DATA_TEXT:
- case IST_SIZE_LARGER:
- case IST_SIZE_SMALLER:
- /* these all have in common that a message should be parsed before
- matching is possible
- */
- result = db_search_parsed(rset, setlen, sk, mb);
- break;
-
- case IST_IDATE:
- result = db_search(rset, setlen, sk->search, mb, sk->type);
- if (result != 0)
- {
- my_free(newset);
- return result;
- }
- break;
-
- case IST_SUBSEARCH_NOT:
- case IST_SUBSEARCH_AND:
- subtype = IST_SUBSEARCH_AND;
-
- case IST_SUBSEARCH_OR:
- el = list_getstart(&sk->sub_search);
- while (el)
- {
- subsk = (search_key_t*)el->data;
-
- if (subsk->type == IST_SUBSEARCH_OR)
- memset(newset, 0, sizeof(int)*setlen);
- else if (subsk->type == IST_SUBSEARCH_AND || subsk->type == IST_SUBSEARCH_NOT)
- for (i=0; i<setlen; i++)
- newset[i] = 1;
-
- result = perform_imap_search(newset, setlen, subsk, mb);
- if (result < 0 || result == 1)
- {
- my_free(newset);
- return result;
- }
-
- combine_sets(rset, newset, setlen, subtype);
-
- el = el->nextnode;
- }
+ search_key_t *subsk;
+ struct element *el;
+ int result, *newset = NULL, i;
+ int subtype = IST_SUBSEARCH_OR;
+
+ if (!rset)
+ return -2; /* stupidity */
+
+ if (!sk)
+ return 0; /* no search */
+
+ newset = (int *) my_malloc(sizeof(int) * setlen);
+ if (!newset)
+ return -2;
+
+ switch (sk->type) {
+ case IST_SET:
+ build_set(rset, setlen, sk->search);
+ break;
- if (sk->type == IST_SUBSEARCH_NOT)
- invert_set(rset, setlen);
+ case IST_SET_UID:
+ build_uid_set(rset, setlen, sk->search, mb);
+ break;
+
+ case IST_FLAG:
+ result = db_search(rset, setlen, sk->search, mb, sk->type);
+ if (result != 0) {
+ my_free(newset);
+ return result;
+ }
+ break;
+
+ case IST_HDR:
+ case IST_HDRDATE_BEFORE:
+ case IST_HDRDATE_ON:
+ case IST_HDRDATE_SINCE:
+ case IST_DATA_BODY:
+ case IST_DATA_TEXT:
+ case IST_SIZE_LARGER:
+ case IST_SIZE_SMALLER:
+ /* these all have in common that a message should be parsed before
+ matching is possible
+ */
+ result = db_search_parsed(rset, setlen, sk, mb);
+ break;
- break;
+ case IST_IDATE:
+ result = db_search(rset, setlen, sk->search, mb, sk->type);
+ if (result != 0) {
+ my_free(newset);
+ return result;
+ }
+ break;
+
+ case IST_SUBSEARCH_NOT:
+ case IST_SUBSEARCH_AND:
+ subtype = IST_SUBSEARCH_AND;
+
+ case IST_SUBSEARCH_OR:
+ el = list_getstart(&sk->sub_search);
+ while (el) {
+ subsk = (search_key_t *) el->data;
+
+ if (subsk->type == IST_SUBSEARCH_OR)
+ memset(newset, 0, sizeof(int) * setlen);
+ else if (subsk->type == IST_SUBSEARCH_AND
+ || subsk->type == IST_SUBSEARCH_NOT)
+ for (i = 0; i < setlen; i++)
+ newset[i] = 1;
+
+ result =
+ perform_imap_search(newset, setlen, subsk, mb);
+ if (result < 0 || result == 1) {
+ my_free(newset);
+ return result;
+ }
+
+ combine_sets(rset, newset, setlen, subtype);
- default:
- my_free(newset);
- return -2; /* ??? */
- }
-
- my_free(newset);
- return 0;
+ el = el->nextnode;
+ }
+
+ if (sk->type == IST_SUBSEARCH_NOT)
+ invert_set(rset, setlen);
+
+ break;
+
+ default:
+ my_free(newset);
+ return -2; /* ??? */
+ }
+
+ my_free(newset);
+ return 0;
}
@@ -2880,60 +2739,56 @@ int perform_imap_search(int *rset, int setlen, search_key_t *sk, mailbox_t *mb)
*/
void free_searchlist(struct list *sl)
{
- search_key_t *sk;
- struct element *el;
-
- if (!sl)
- return;
-
- el = list_getstart(sl);
-
- while (el)
- {
- sk = (search_key_t*)el->data;
-
- free_searchlist(&sk->sub_search);
- list_freelist(&sk->sub_search.start);
-
- el = el->nextnode;
- }
-
- list_freelist(&sl->start);
- return;
+ search_key_t *sk;
+ struct element *el;
+
+ if (!sl)
+ return;
+
+ el = list_getstart(sl);
+
+ while (el) {
+ sk = (search_key_t *) el->data;
+
+ free_searchlist(&sk->sub_search);
+ list_freelist(&sk->sub_search.start);
+
+ el = el->nextnode;
+ }
+
+ list_freelist(&sl->start);
+ return;
}
void invert_set(int *set, int setlen)
{
- int i;
+ int i;
- if (!set)
- return;
+ if (!set)
+ return;
- for (i=0; i<setlen; i++)
- set[i] = !set[i];
+ for (i = 0; i < setlen; i++)
+ set[i] = !set[i];
}
void combine_sets(int *dest, int *sec, int setlen, int type)
{
- int i;
-
- if (!dest || !sec)
- return;
-
- if (type == IST_SUBSEARCH_AND)
- {
- for (i=0; i<setlen; i++)
- dest[i] = (sec[i] && dest[i]);
- }
- else if (type == IST_SUBSEARCH_OR)
- {
- for (i=0; i<setlen; i++)
- dest[i] = (sec[i] || dest[i]);
- }
+ int i;
+
+ if (!dest || !sec)
+ return;
+
+ if (type == IST_SUBSEARCH_AND) {
+ for (i = 0; i < setlen; i++)
+ dest[i] = (sec[i] && dest[i]);
+ } else if (type == IST_SUBSEARCH_OR) {
+ for (i = 0; i < setlen; i++)
+ dest[i] = (sec[i] || dest[i]);
+ }
}
-
+
/*
* build_set()
@@ -2943,77 +2798,66 @@ void combine_sets(int *dest, int *sec, int setlen, int type)
*/
void build_set(int *set, unsigned int setlen, char *cset)
{
- unsigned int i;
- u64_t num,num2;
- char *sep=NULL;
-
- if (!set)
- return;
-
- memset(set, 0, setlen * sizeof(int));
-
- if (!cset)
- return;
-
- do
- {
- num = strtoull(cset, &sep, 10);
-
- if (num <= setlen && num > 0)
- {
- if (!*sep)
- set[num-1] = 1;
- else if (*sep == ',')
- {
- set[num-1] = 1;
- cset = sep+1;
- }
- else
- {
- /* sep == ':' here */
- sep++;
- if (*sep == '*')
- {
- for (i=num-1; i<setlen; i++)
- set[i] = 1;
-
- cset = sep+1;
- }
- else
- {
- cset = sep;
- num2 = strtoull(cset, &sep, 10);
-
- if (num2 > setlen) num2 = setlen;
- if (num2 > 0)
- {
- /* NOTE: here: num2 > 0, num > 0 */
- if (num2 < num)
- {
- /* swap! */
- i = num;
- num = num2;
- num2 = i;
+ unsigned int i;
+ u64_t num, num2;
+ char *sep = NULL;
+
+ if (!set)
+ return;
+
+ memset(set, 0, setlen * sizeof(int));
+
+ if (!cset)
+ return;
+
+ do {
+ num = strtoull(cset, &sep, 10);
+
+ if (num <= setlen && num > 0) {
+ if (!*sep)
+ set[num - 1] = 1;
+ else if (*sep == ',') {
+ set[num - 1] = 1;
+ cset = sep + 1;
+ } else {
+ /* sep == ':' here */
+ sep++;
+ if (*sep == '*') {
+ for (i = num - 1; i < setlen; i++)
+ set[i] = 1;
+
+ cset = sep + 1;
+ } else {
+ cset = sep;
+ num2 = strtoull(cset, &sep, 10);
+
+ if (num2 > setlen)
+ num2 = setlen;
+ if (num2 > 0) {
+ /* NOTE: here: num2 > 0, num > 0 */
+ if (num2 < num) {
+ /* swap! */
+ i = num;
+ num = num2;
+ num2 = i;
+ }
+
+ for (i = num - 1; i < num2;
+ i++)
+ set[i] = 1;
+ }
+ if (*sep)
+ cset = sep + 1;
+ }
+ }
+ } else {
+ /* invalid num, skip it */
+ if (*sep) {
+ cset = sep + 1;
+ sep++;
}
-
- for (i=num-1; i<num2; i++)
- set[i] = 1;
- }
- if (*sep)
- cset = sep+1;
}
- }
- }
- else
- {
- /* invalid num, skip it */
- if (*sep)
- {
- cset = sep+1;
- sep++;
- }
- }
- } while (sep && *sep && cset && *cset);
+ } while (sep && *sep && cset && *cset);
}
@@ -3022,188 +2866,193 @@ void build_set(int *set, unsigned int setlen, char *cset)
*
* as build_set() but takes uid's instead of MSN's
*/
-void build_uid_set(int *set, unsigned int setlen, char *cset, mailbox_t *mb)
+void build_uid_set(int *set, unsigned int setlen, char *cset,
+ mailbox_t * mb)
{
- unsigned int i, msn, msn2;
- int result;
- int num2found = 0;
- u64_t num,num2;
- char *sep=NULL;
-
- if (!set)
- return;
-
- memset(set, 0, setlen * sizeof(int));
-
- if (!cset || setlen == 0)
- return;
-
- do
- {
- num = strtoull(cset, &sep, 10);
- result = binary_search(mb->seq_list, mb->exists, num, &msn);
-
- if (result < 0 && num < mb->seq_list[mb->exists-1])
- {
- /* ok this num is not a UID, but if a range is specified (i.e. 1:*)
- * it is valid -> check *sep
- */
- if (*sep == ':')
- {
- for (msn=0; mb->seq_list[msn] < num; msn++) ;
- if (msn >= mb->exists)
- msn = mb->exists-1;
- }
- }
-
- if (result >= 0)
- {
- if (!*sep)
- set[msn] = 1;
- else if (*sep == ',')
- {
- set[msn] = 1;
- cset = sep+1;
- }
- else
- {
- /* sep == ':' here */
- sep++;
- if (*sep == '*')
- {
- for (i=msn; i<setlen; i++)
- set[i] = 1;
-
- cset = sep+1;
+ unsigned int i, msn, msn2;
+ int result;
+ int num2found = 0;
+ u64_t num, num2;
+ char *sep = NULL;
+
+ if (!set)
+ return;
+
+ memset(set, 0, setlen * sizeof(int));
+
+ if (!cset || setlen == 0)
+ return;
+
+ do {
+ num = strtoull(cset, &sep, 10);
+ result =
+ binary_search(mb->seq_list, mb->exists, num, &msn);
+
+ if (result < 0 && num < mb->seq_list[mb->exists - 1]) {
+ /* ok this num is not a UID, but if a range is specified (i.e. 1:*)
+ * it is valid -> check *sep
+ */
+ if (*sep == ':') {
+ for (msn = 0; mb->seq_list[msn] < num;
+ msn++);
+ if (msn >= mb->exists)
+ msn = mb->exists - 1;
+ }
}
- else
- {
- /* fetch second number */
- cset = sep;
- num2 = strtoull(cset, &sep, 10);
- result = binary_search(mb->seq_list, mb->exists,
- num2, &msn2);
-
- if (result < 0)
- {
- /* in a range: (like 1:1000) so this number doesnt need to exist;
- * find the closest match below this UID value
- */
- if (mb->exists == 0)
- num2found = 0;
- else {
- for (msn2 = mb->exists - 1;; msn2--) {
- if (msn2 == 0 && mb->seq_list[msn2] > num2) {
- num2found = 0;
- break;
- } else if (mb->seq_list[msn2] <= num2) {
- /* found! */
- num2found = 1;
- break;
+
+ if (result >= 0) {
+ if (!*sep)
+ set[msn] = 1;
+ else if (*sep == ',') {
+ set[msn] = 1;
+ cset = sep + 1;
+ } else {
+ /* sep == ':' here */
+ sep++;
+ if (*sep == '*') {
+ for (i = msn; i < setlen; i++)
+ set[i] = 1;
+
+ cset = sep + 1;
+ } else {
+ /* fetch second number */
+ cset = sep;
+ num2 = strtoull(cset, &sep, 10);
+ result =
+ binary_search(mb->seq_list,
+ mb->exists, num2,
+ &msn2);
+
+ if (result < 0) {
+ /* in a range: (like 1:1000) so this number doesnt need to exist;
+ * find the closest match below this UID value
+ */
+ if (mb->exists == 0)
+ num2found = 0;
+ else {
+ for (msn2 =
+ mb->exists -
+ 1;; msn2--) {
+ if (msn2 ==
+ 0
+ && mb->
+ seq_list
+ [msn2]
+ > num2) {
+ num2found
+ =
+ 0;
+ break;
+ } else
+ if
+ (mb->
+ seq_list
+ [msn2]
+ <=
+ num2)
+ {
+ /* found! */
+ num2found
+ =
+ 1;
+ break;
+ }
+ }
+ }
+
+ } else
+ num2found = 1;
+
+ if (num2found == 1) {
+ if (msn2 < msn) {
+ /* swap! */
+ i = msn;
+ msn = msn2;
+ msn2 = i;
+ }
+
+ for (i = msn; i <= msn2;
+ i++)
+ set[i] = 1;
+ }
+
+ if (*sep)
+ cset = sep + 1;
}
- }
- }
-
- } else
- num2found = 1;
-
- if (num2found == 1)
- {
- if (msn2 < msn)
- {
- /* swap! */
- i = msn;
- msn = msn2;
- msn2 = i;
}
-
- for (i=msn; i<=msn2; i++)
- set[i] = 1;
- }
-
- if (*sep)
- cset = sep+1;
+ } else {
+ /* invalid num, skip it */
+ if (*sep) {
+ cset = sep + 1;
+ sep++;
+ }
}
- }
- }
- else
- {
- /* invalid num, skip it */
- if (*sep)
- {
- cset = sep+1;
- sep++;
- }
- }
- } while (sep && *sep && cset && *cset);
+ } while (sep && *sep && cset && *cset);
}
-void dumpsearch(search_key_t *sk, int level)
+void dumpsearch(search_key_t * sk, int level)
{
- char *spaces = (char*)my_malloc(level*3 +1);
- struct element *el;
- search_key_t *subsk;
-
- if (!spaces)
- return;
-
- memset(spaces, ' ',level*3);
- spaces[level*3] = 0;
-
- if (!sk)
- {
- trace(TRACE_DEBUG,"%s(null)\n",spaces);
- my_free(spaces);
- return;
- }
-
- switch (sk->type)
- {
- case IST_SUBSEARCH_NOT:
- trace(TRACE_DEBUG,"%sNOT\n",spaces);
-
- el = list_getstart(&sk->sub_search);
- if (el)
- subsk = (search_key_t*)el->data;
- else
- subsk = NULL;
-
- dumpsearch(subsk, level+1);
- break;
-
- case IST_SUBSEARCH_AND:
- trace(TRACE_DEBUG,"%sAND\n",spaces);
- el = list_getstart(&sk->sub_search);
-
- while (el)
- {
- subsk = (search_key_t*)el->data;
- dumpsearch(subsk, level+1);
-
- el = el->nextnode;
- }
- break;
-
- case IST_SUBSEARCH_OR:
- trace(TRACE_DEBUG,"%sOR\n",spaces);
- el = list_getstart(&sk->sub_search);
-
- while (el)
- {
- subsk = (search_key_t*)el->data;
- dumpsearch(subsk, level+1);
-
- el = el->nextnode;
+ char *spaces = (char *) my_malloc(level * 3 + 1);
+ struct element *el;
+ search_key_t *subsk;
+
+ if (!spaces)
+ return;
+
+ memset(spaces, ' ', level * 3);
+ spaces[level * 3] = 0;
+
+ if (!sk) {
+ trace(TRACE_DEBUG, "%s(null)\n", spaces);
+ my_free(spaces);
+ return;
}
- break;
- default:
- trace(TRACE_DEBUG,"%s[type %d] \"%s\"\n",spaces,sk->type,sk->search);
- }
+ switch (sk->type) {
+ case IST_SUBSEARCH_NOT:
+ trace(TRACE_DEBUG, "%sNOT\n", spaces);
- my_free(spaces);
- return;
+ el = list_getstart(&sk->sub_search);
+ if (el)
+ subsk = (search_key_t *) el->data;
+ else
+ subsk = NULL;
+
+ dumpsearch(subsk, level + 1);
+ break;
+
+ case IST_SUBSEARCH_AND:
+ trace(TRACE_DEBUG, "%sAND\n", spaces);
+ el = list_getstart(&sk->sub_search);
+
+ while (el) {
+ subsk = (search_key_t *) el->data;
+ dumpsearch(subsk, level + 1);
+
+ el = el->nextnode;
+ }
+ break;
+
+ case IST_SUBSEARCH_OR:
+ trace(TRACE_DEBUG, "%sOR\n", spaces);
+ el = list_getstart(&sk->sub_search);
+
+ while (el) {
+ subsk = (search_key_t *) el->data;
+ dumpsearch(subsk, level + 1);
+
+ el = el->nextnode;
+ }
+ break;
+
+ default:
+ trace(TRACE_DEBUG, "%s[type %d] \"%s\"\n", spaces,
+ sk->type, sk->search);
+ }
+
+ my_free(spaces);
+ return;
}
@@ -3212,15 +3061,15 @@ void dumpsearch(search_key_t *sk, int level)
*/
void close_cache()
{
- if (cached_msg.msg_parsed)
- db_free_msg(&cached_msg.msg);
+ if (cached_msg.msg_parsed)
+ db_free_msg(&cached_msg.msg);
- cached_msg.num = -1;
- cached_msg.msg_parsed = 0;
- memset(&cached_msg.msg, 0, sizeof(cached_msg.msg));
+ cached_msg.num = -1;
+ cached_msg.msg_parsed = 0;
+ memset(&cached_msg.msg, 0, sizeof(cached_msg.msg));
- mclose(&cached_msg.memdump);
- mclose(&cached_msg.tmpdump);
+ mclose(&cached_msg.memdump);
+ mclose(&cached_msg.tmpdump);
}
/*
@@ -3228,22 +3077,21 @@ void close_cache()
*/
int init_cache()
{
- cached_msg.num = -1;
- cached_msg.msg_parsed = 0;
- memset(&cached_msg.msg, 0, sizeof(cached_msg.msg));
-
- cached_msg.memdump = mopen();
- if (!cached_msg.memdump)
- return -1;
-
- cached_msg.tmpdump = mopen();
- if (!cached_msg.tmpdump)
- {
- mclose(&cached_msg.memdump);
- return -1;
- }
-
- cached_msg.file_dumped = 0;
- cached_msg.dumpsize = 0;
- return 0;
+ cached_msg.num = -1;
+ cached_msg.msg_parsed = 0;
+ memset(&cached_msg.msg, 0, sizeof(cached_msg.msg));
+
+ cached_msg.memdump = mopen();
+ if (!cached_msg.memdump)
+ return -1;
+
+ cached_msg.tmpdump = mopen();
+ if (!cached_msg.tmpdump) {
+ mclose(&cached_msg.memdump);
+ return -1;
+ }
+
+ cached_msg.file_dumped = 0;
+ cached_msg.dumpsize = 0;
+ return 0;
}
diff --git a/imaputil.h b/imaputil.h
index 93432650..d528d4b5 100644
--- a/imaputil.h
+++ b/imaputil.h
@@ -39,24 +39,24 @@
#include "clientinfo.h"
#include <stdio.h>
-int retrieve_structure(FILE *outstream, mime_message_t *msg, int show_extension_data);
-int retrieve_envelope(FILE *outstream, struct list *rfcheader);
-int show_address_list(FILE *outstream, struct mime_record *mr);
-int show_mime_parameter_list(FILE *outstream, struct mime_record *mr,
- int force_subtype,
- int only_extension);
+int retrieve_structure(FILE * outstream, mime_message_t * msg,
+ int show_extension_data);
+int retrieve_envelope(FILE * outstream, struct list *rfcheader);
+int show_address_list(FILE * outstream, struct mime_record *mr);
+int show_mime_parameter_list(FILE * outstream, struct mime_record *mr,
+ int force_subtype, int only_extension);
-mime_message_t* get_part_by_num(mime_message_t *msg, const char *part);
+mime_message_t *get_part_by_num(mime_message_t * msg, const char *part);
-u64_t rfcheader_dump(MEM *outmem, struct list *rfcheader, char **fieldnames, int nfields,
- int equal_type);
-u64_t mimeheader_dump(MEM *outmem, struct list *mimeheader);
+u64_t rfcheader_dump(MEM * outmem, struct list *rfcheader,
+ char **fieldnames, int nfields, int equal_type);
+u64_t mimeheader_dump(MEM * outmem, struct list *mimeheader);
int haystack_find(int haystacklen, char **haystack, const char *needle);
-int check_state_and_args(const char *command, const char *tag, char **args,
- int nargs, int state, ClientInfo *ci);
-int next_fetch_item(char **args, int idx, fetch_items_t *fi);
+int check_state_and_args(const char *command, const char *tag, char **args,
+ int nargs, int state, ClientInfo * ci);
+int next_fetch_item(char **args, int idx, fetch_items_t * fi);
int is_textplain(struct list *hdr);
char *date_sql2imap(const char *sqldate);
@@ -70,28 +70,30 @@ int check_msg_set(const char *s);
int check_date(const char *date);
void clarify_data(char *str);
char **build_args_array(const char *s);
-char **build_args_array_ext(const char *originalString, clientinfo_t *ci);
+char **build_args_array_ext(const char *originalString, clientinfo_t * ci);
-void base64encode(char *in,char *out);
-void base64decode(char *in,char *out);
-int binary_search(const u64_t *array, unsigned arraysize, u64_t key,
- unsigned int *key_idx);
+void base64encode(char *in, char *out);
+void base64decode(char *in, char *out);
+int binary_search(const u64_t * array, unsigned arraysize, u64_t key,
+ unsigned int *key_idx);
char **give_chunks(const char *str, char delimiter);
void free_chunks(char **chunks);
-int quoted_string_out(FILE *outstream, const char *s);
-void send_data(FILE *to, MEM *from, int cnt);
+int quoted_string_out(FILE * outstream, const char *s);
+void send_data(FILE * to, MEM * from, int cnt);
int build_imap_search(char **search_keys, struct list *sl, int *idx);
-int perform_imap_search(int *rset, int setlen, search_key_t *sk, mailbox_t *mb);
+int perform_imap_search(int *rset, int setlen, search_key_t * sk,
+ mailbox_t * mb);
void free_searchlist(struct list *sl);
void invert_set(int *set, int setlen);
void combine_sets(int *dest, int *sec, int setlen, int type);
void build_set(int *set, unsigned int setlen, char *cset);
-void build_uid_set(int *set, unsigned int setlen, char *cset, mailbox_t *mb);
-void dumpsearch(search_key_t *sk, int level);
+void build_uid_set(int *set, unsigned int setlen, char *cset,
+ mailbox_t * mb);
+void dumpsearch(search_key_t * sk, int level);
int init_cache(void);
void close_cache(void);
diff --git a/list.c b/list.c
index 17b0eec9..63e20ae7 100644
--- a/list.c
+++ b/list.c
@@ -34,8 +34,8 @@
void list_init(struct list *tlist)
{
- tlist->start=NULL;
- tlist->total_nodes=0;
+ tlist->start = NULL;
+ tlist->total_nodes = 0;
}
@@ -46,17 +46,17 @@ void list_init(struct list *tlist)
*/
void list_freelist(struct element **start)
{
- /* check if list exists */
- if (!(*start))
- return;
-
- /* free rest of list */
- list_freelist(&(*start)->nextnode);
-
- /* free this item */
- my_free((*start)->data);
- my_free(*start);
- *start = NULL;
+ /* check if list exists */
+ if (!(*start))
+ return;
+
+ /* free rest of list */
+ list_freelist(&(*start)->nextnode);
+
+ /* free this item */
+ my_free((*start)->data);
+ my_free(*start);
+ *start = NULL;
}
@@ -65,25 +65,25 @@ void list_freelist(struct element **start)
*
* reverse the order of a linked list
*/
-struct element* dbmail_list_reverse(struct element *start)
+struct element *dbmail_list_reverse(struct element *start)
{
- struct element *newstart;
+ struct element *newstart;
- if (!start)
- return NULL; /* nothing there */
+ if (!start)
+ return NULL; /* nothing there */
- if (!start->nextnode)
- return start; /* nothing to reverse */
+ if (!start->nextnode)
+ return start; /* nothing to reverse */
- newstart = dbmail_list_reverse(start->nextnode); /* reverse rest of list */
- start->nextnode->nextnode = start;
+ newstart = dbmail_list_reverse(start->nextnode); /* reverse rest of list */
+ start->nextnode->nextnode = start;
- start->nextnode = NULL; /* terminate list */
+ start->nextnode = NULL; /* terminate list */
- return newstart;
+ return newstart;
}
-
+
/*
* list_nodeadd()
*
@@ -95,41 +95,41 @@ struct element* dbmail_list_reverse(struct element *start)
struct element *list_nodeadd(struct list *tlist, const void *data,
size_t dsize)
{
- struct element *p;
-
- if (!tlist)
- return NULL; /* cannot add to non-existing list */
-
- p=tlist->start;
-
- tlist->start=(struct element *)my_malloc(sizeof(struct element));
-
- /* allocating memory */
+ struct element *p;
+
+ if (!tlist)
+ return NULL; /* cannot add to non-existing list */
+
+ p = tlist->start;
+
+ tlist->start =
+ (struct element *) my_malloc(sizeof(struct element));
+
+ /* allocating memory */
#ifdef USE_EXIT_ON_ERROR
- memtst(tlist->start==NULL);
- memtst((tlist->start->data=(void *)my_malloc(dsize))==NULL);
+ memtst(tlist->start == NULL);
+ memtst((tlist->start->data = (void *) my_malloc(dsize)) == NULL);
#else
- if (!tlist->start)
- return NULL;
-
- tlist->start->data=(void *)my_malloc(dsize);
- if (!tlist->start->data)
- {
- my_free(tlist->start);
- tlist->start = NULL;
- return NULL;
- }
+ if (!tlist->start)
+ return NULL;
+
+ tlist->start->data = (void *) my_malloc(dsize);
+ if (!tlist->start->data) {
+ my_free(tlist->start);
+ tlist->start = NULL;
+ return NULL;
+ }
#endif
-
- /* copy data */
- tlist->start->data = memcpy(tlist->start->data,data,dsize);
- tlist->start->dsize = dsize;
- tlist->start->nextnode=p;
+ /* copy data */
+ tlist->start->data = memcpy(tlist->start->data, data, dsize);
+ tlist->start->dsize = dsize;
+
+ tlist->start->nextnode = p;
/* updating node count */
- tlist->total_nodes++;
- return tlist->start;
+ tlist->total_nodes++;
+ return tlist->start;
}
@@ -141,18 +141,18 @@ struct element *list_nodeadd(struct list *tlist, const void *data,
*/
struct element *list_nodepop(struct list *list)
{
- struct element *ret;
+ struct element *ret;
+
+ if (!list || !list->start)
+ return NULL;
- if (!list || !list->start)
- return NULL;
+ ret = list->start;
- ret = list->start;
+ list->start = list->start->nextnode;
- list->start = list->start->nextnode;
-
- return ret;
+ return ret;
}
-
+
/*
@@ -162,75 +162,71 @@ struct element *list_nodepop(struct list *list)
*
* returns
*/
-struct element *list_nodedel(struct list *tlist,void *data)
+struct element *list_nodedel(struct list *tlist, void *data)
{
- struct element *temp;
- struct element *item;
- item=NULL;
-
- if (!tlist)
- return NULL;
-
- temp=tlist->start;
-
- /* checking if lists exist else return NULL*/
- if (temp==NULL) return NULL;
-
- while (temp!=NULL) /* walk the list */
- {
- if (temp->data==data)
- {
- if (item==NULL)
- {
- tlist->start=temp->nextnode;
- my_free(temp->data);
- my_free((struct element *)temp);
- break;
- }
- else
- {
- item->nextnode=temp->nextnode;
- my_free(temp->data); /* freeing memory */
- my_free((struct element *)temp);
- break;
- }
- /* updating node count */
- tlist->total_nodes--;
- }
- item=temp;
- temp=temp->nextnode;
- }
-
- return NULL;
+ struct element *temp;
+ struct element *item;
+ item = NULL;
+
+ if (!tlist)
+ return NULL;
+
+ temp = tlist->start;
+
+ /* checking if lists exist else return NULL */
+ if (temp == NULL)
+ return NULL;
+
+ while (temp != NULL) { /* walk the list */
+ if (temp->data == data) {
+ if (item == NULL) {
+ tlist->start = temp->nextnode;
+ my_free(temp->data);
+ my_free((struct element *) temp);
+ break;
+ } else {
+ item->nextnode = temp->nextnode;
+ my_free(temp->data); /* freeing memory */
+ my_free((struct element *) temp);
+ break;
+ }
+ /* updating node count */
+ tlist->total_nodes--;
+ }
+ item = temp;
+ temp = temp->nextnode;
+ }
+
+ return NULL;
}
struct element *list_getstart(struct list *tlist)
{
- return (tlist) ? tlist->start : NULL;
+ return (tlist) ? tlist->start : NULL;
}
long list_totalnodes(struct list *tlist)
{
- return (tlist) ? tlist->total_nodes : -1; /* a NULL ptr doesnt even have zero nodes (?) */
+ return (tlist) ? tlist->total_nodes : -1; /* a NULL ptr doesnt even have zero nodes (?) */
}
void list_showlist(struct list *tlist)
{
- struct element *temp;
-
- if (!tlist)
- {
- trace(TRACE_MESSAGE,"list_showlist(): NULL ptr received\n");
- return;
- }
-
- temp=tlist->start;
- while (temp!=NULL)
- {
- trace (TRACE_MESSAGE,"list_showlist():item found [%s]\n",(char *)temp->data);
- temp=temp->nextnode;
- }
-}
+ struct element *temp;
+
+ if (!tlist) {
+ trace(TRACE_MESSAGE,
+ "list_showlist(): NULL ptr received\n");
+ return;
+ }
+
+ temp = tlist->start;
+ while (temp != NULL) {
+ trace(TRACE_MESSAGE, "list_showlist():item found [%s]\n",
+ (char *) temp->data);
+ temp = temp->nextnode;
+ }
+}
diff --git a/list.h b/list.h
index bbbd45de..2f2802e2 100644
--- a/list.h
+++ b/list.h
@@ -34,23 +34,21 @@
/*
* list data types
*/
-struct element
-{
- void *data;
- size_t dsize;
- struct element *nextnode;
+struct element {
+ void *data;
+ size_t dsize;
+ struct element *nextnode;
};
-struct list
-{
- struct element *start;
- long total_nodes;
+struct list {
+ struct element *start;
+ long total_nodes;
};
struct element *list_nodeadd(struct list *tlist, const void *data,
- size_t dsize);
+ size_t dsize);
struct element *list_nodedel(struct list *tlist, void *data);
struct element *list_nodepop(struct list *list);
@@ -64,6 +62,6 @@ void list_init(struct list *tlist);
* export a function with the name list_reverse(). Nice of them,
* but a pretty "strange" way to pollute the global namespace
*/
-struct element* dbmail_list_reverse(struct element *start);
+struct element *dbmail_list_reverse(struct element *start);
-#endif
+#endif
diff --git a/lmtp.c b/lmtp.c
index 8e8a8d4e..e2ed9e6a 100644
--- a/lmtp.c
+++ b/lmtp.c
@@ -42,639 +42,668 @@ struct list rcpt;
char *envelopefrom = NULL;
/* allowed lmtp commands */
-const char * const commands [] =
-{
- "LHLO", "QUIT", "RSET", "DATA", "MAIL",
- "VRFY", "EXPN", "HELP", "NOOP", "RCPT"
+const char *const commands[] = {
+ "LHLO", "QUIT", "RSET", "DATA", "MAIL",
+ "VRFY", "EXPN", "HELP", "NOOP", "RCPT"
};
const char validchars[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-"_.!@#$%^&*()-+=~[]{}<>:;\\/ ";
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "_.!@#$%^&*()-+=~[]{}<>:;\\/ ";
char myhostname[64];
-int lmtp_reset(PopSession_t *session)
- {
- /* Free the lists and reinitialize
- * but only if they were previously
- * initialized by LMTP_LHLO... */
- if( session->state == LHLO )
- {
- list_freelist( &rcpt.start );
- list_init( &rcpt );
- }
-
- if( envelopefrom != NULL )
- {
- my_free( envelopefrom );
- }
- envelopefrom = NULL;
-
- session->state = LHLO;
-
- return 1;
- }
-
-
-int lmtp_handle_connection(clientinfo_t *ci)
+int lmtp_reset(PopSession_t * session)
{
- /*
- Handles connection and calls
- lmtp command handler
- */
-
- int done = 1; /* loop state */
- char *buffer = NULL; /* connection buffer */
- int cnt; /* counter */
-
- PopSession_t session; /* current connection session */
-
- /* setting Session variables */
- session.error_count = 0;
-
- session.username = NULL;
- session.password = NULL;
-
- session.SessionResult = 0;
-
- /* reset counters */
- session.totalsize = 0;
- session.virtual_totalsize = 0;
- session.totalmessages = 0;
- session.virtual_totalmessages = 0;
-
-
- /* getting hostname */
- gethostname(myhostname,64);
- myhostname[63] = 0; /* make sure string is terminated */
-
- buffer=(char *)my_malloc(INCOMING_BUFFER_SIZE*sizeof(char));
-
- if (!buffer)
- {
- trace(TRACE_MESSAGE,"lmtp_handle_connection(): Could not allocate buffer");
- return 0;
- }
-
- if (ci->tx)
- {
- /* sending greeting */
- fprintf(ci->tx,"220 %s DBMail LMTP service ready to rock\r\n",
- myhostname);
- fflush(ci->tx);
- }
- else
- {
- trace(TRACE_MESSAGE,"lmtp_handle_connection(): TX stream is null!");
- return 0;
- }
-
- lmtp_reset(&session);
- while (done > 0)
- {
- /* set the timeout counter */
- alarm(ci->timeout);
-
- /* clear the buffer */
- memset(buffer, 0, INCOMING_BUFFER_SIZE);
-
- for (cnt=0; cnt < INCOMING_BUFFER_SIZE-1; cnt++)
- {
- do
- {
- clearerr(ci->rx);
- fread(&buffer[cnt], 1, 1, ci->rx);
-
- /* leave, an alarm has occured during fread */
- if (!ci->rx) return 0;
- } while (ferror(ci->rx) && errno == EINTR);
-
- if (buffer[cnt] == '\n' || feof(ci->rx) || ferror(ci->rx))
- {
- buffer[cnt+1] = '\0';
- break;
- }
- }
-
- if (feof(ci->rx) || ferror(ci->rx))
- {
- /* check client eof */
- done = -1;
- }
- else
- {
- /* reset function handle timeout */
- alarm(0);
- /* handle lmtp commands */
- done = lmtp(ci->tx, ci->rx, buffer, ci->ip, &session);
- }
- fflush(ci->tx);
- }
-
- /* memory cleanup */
- lmtp_reset(&session);
- my_free(buffer);
- buffer = NULL;
-
- /* reset timers */
- alarm(0);
- __debug_dumpallocs();
-
- return 0;
+ /* Free the lists and reinitialize
+ * but only if they were previously
+ * initialized by LMTP_LHLO... */
+ if (session->state == LHLO) {
+ list_freelist(&rcpt.start);
+ list_init(&rcpt);
+ }
+
+ if (envelopefrom != NULL) {
+ my_free(envelopefrom);
+ }
+ envelopefrom = NULL;
+
+ session->state = LHLO;
+
+ return 1;
}
-int lmtp_error(PopSession_t *session, void *stream, const char *formatstring, ...)
- __attribute__((format(printf, 3, 4)));
-int lmtp_error(PopSession_t *session, void *stream, const char *formatstring, ...)
+int lmtp_handle_connection(clientinfo_t * ci)
{
- va_list argp;
-
- if (session->error_count>=MAX_ERRORS)
- {
- trace(TRACE_MESSAGE,"lmtp_error(): too many errors (MAX_ERRORS is %d)",MAX_ERRORS);
- fprintf((FILE *)stream, "500 Too many errors, closing connection.\r\n");
- session->SessionResult = 2; /* possible flood */
- lmtp_reset(session);
- return -3;
- }
- else
- {
- va_start(argp, formatstring);
- vfprintf((FILE *)stream, formatstring, argp);
- va_end(argp);
- }
-
- trace(TRACE_DEBUG,"lmtp_error(): an invalid command was issued");
- session->error_count++;
- return 1;
+ /*
+ Handles connection and calls
+ lmtp command handler
+ */
+
+ int done = 1; /* loop state */
+ char *buffer = NULL; /* connection buffer */
+ int cnt; /* counter */
+
+ PopSession_t session; /* current connection session */
+
+ /* setting Session variables */
+ session.error_count = 0;
+
+ session.username = NULL;
+ session.password = NULL;
+
+ session.SessionResult = 0;
+
+ /* reset counters */
+ session.totalsize = 0;
+ session.virtual_totalsize = 0;
+ session.totalmessages = 0;
+ session.virtual_totalmessages = 0;
+
+
+ /* getting hostname */
+ gethostname(myhostname, 64);
+ myhostname[63] = 0; /* make sure string is terminated */
+
+ buffer = (char *) my_malloc(INCOMING_BUFFER_SIZE * sizeof(char));
+
+ if (!buffer) {
+ trace(TRACE_MESSAGE,
+ "lmtp_handle_connection(): Could not allocate buffer");
+ return 0;
+ }
+
+ if (ci->tx) {
+ /* sending greeting */
+ fprintf(ci->tx,
+ "220 %s DBMail LMTP service ready to rock\r\n",
+ myhostname);
+ fflush(ci->tx);
+ } else {
+ trace(TRACE_MESSAGE,
+ "lmtp_handle_connection(): TX stream is null!");
+ return 0;
+ }
+
+ lmtp_reset(&session);
+ while (done > 0) {
+ /* set the timeout counter */
+ alarm(ci->timeout);
+
+ /* clear the buffer */
+ memset(buffer, 0, INCOMING_BUFFER_SIZE);
+
+ for (cnt = 0; cnt < INCOMING_BUFFER_SIZE - 1; cnt++) {
+ do {
+ clearerr(ci->rx);
+ fread(&buffer[cnt], 1, 1, ci->rx);
+
+ /* leave, an alarm has occured during fread */
+ if (!ci->rx)
+ return 0;
+ } while (ferror(ci->rx) && errno == EINTR);
+
+ if (buffer[cnt] == '\n' || feof(ci->rx)
+ || ferror(ci->rx)) {
+ buffer[cnt + 1] = '\0';
+ break;
+ }
+ }
+
+ if (feof(ci->rx) || ferror(ci->rx)) {
+ /* check client eof */
+ done = -1;
+ } else {
+ /* reset function handle timeout */
+ alarm(0);
+ /* handle lmtp commands */
+ done =
+ lmtp(ci->tx, ci->rx, buffer, ci->ip, &session);
+ }
+ fflush(ci->tx);
+ }
+
+ /* memory cleanup */
+ lmtp_reset(&session);
+ my_free(buffer);
+ buffer = NULL;
+
+ /* reset timers */
+ alarm(0);
+ __debug_dumpallocs();
+
+ return 0;
}
-int lmtp(void *stream, void *instream, char *buffer, char *client_ip UNUSED, PopSession_t *session)
+int lmtp_error(PopSession_t * session, void *stream,
+ const char *formatstring, ...)
+ __attribute__ ((format(printf, 3, 4)));
+int lmtp_error(PopSession_t * session, void *stream,
+ const char *formatstring, ...)
{
- /* returns values:
- * 0 to quit
- * -1 on failure
- * 1 on success */
- char *command, *value;
- int cmdtype;
- int indx=0;
-
- /* buffer overflow attempt */
- if (strlen(buffer) > MAX_IN_BUFFER)
- {
- trace(TRACE_DEBUG, "lmtp(): buffer overflow attempt");
- return -3;
- }
-
- /* check for command issued */
- while (strchr(validchars, buffer[indx]))
- indx++;
-
- /* end buffer */
- buffer[indx]='\0';
-
- trace(TRACE_DEBUG,"lmtp(): incoming buffer: [%s]",buffer);
-
- command = buffer;
-
- value = strstr(command," "); /* look for the separator */
-
- if (value!=NULL)
- {
- *value = '\0'; /* set a \0 on the command end */
- value++; /* skip space */
-
- if (strlen(value) == 0)
- {
- value=NULL; /* no value specified */
- }
- else
- {
- trace(TRACE_DEBUG,"lmtp(): command issued :cmd [%s], value [%s]\n",command, value);
- }
- }
-
- for (cmdtype = LMTP_STRT; cmdtype < LMTP_END; cmdtype ++)
- if (strcasecmp(command, commands[cmdtype]) == 0) break;
-
- trace(TRACE_DEBUG,"lmtp(): command looked up as commandtype %d", cmdtype);
-
- /* commands that are allowed to have no arguments */
- if ((value==NULL) &&
- !(
- (cmdtype==LMTP_LHLO) || (cmdtype==LMTP_DATA) ||
- (cmdtype==LMTP_RSET) || (cmdtype==LMTP_QUIT) ||
- (cmdtype==LMTP_NOOP) || (cmdtype==LMTP_HELP)
- ))
- {
- trace(TRACE_ERROR, "ARGUMENT %d", cmdtype);
- return lmtp_error(session, stream, "500 This command requires an argument.\r\n");
- }
-
- switch (cmdtype)
- {
- case LMTP_QUIT :
- {
- fprintf((FILE *)stream, "221 %s BYE\r\n", myhostname);
- lmtp_reset(session);
- return 0; /* return 0 to cause the connection to close */
- }
- case LMTP_NOOP :
- {
- fprintf((FILE *)stream, "250 OK\r\n");
- return 1;
- }
- case LMTP_RSET :
- {
- fprintf((FILE *)stream, "250 OK\r\n");
- lmtp_reset(session);
- return 1;
- }
- case LMTP_LHLO :
- {
- /* Reply wth our hostname and a list of features.
- * The RFC requires a couple of SMTP extensions
- * with a MUST statement, so just hardcode them.
- * */
- fprintf((FILE *)stream,
- "250-%s\r\n"
- "250-PIPELINING\r\n"
- "250-ENHANCEDSTATUSCODES\r\n"
- /* This is a SHOULD implement:
- * "250-8BITMIME\r\n"
- * Might as well do these, too:
- * "250-CHUNKING\r\n"
- * "250-BINARYMIME\r\n"
- * */
- "250 SIZE\r\n", myhostname );
- /* Free the recipients list and reinitialize it */
- // list_freelist( &rcpt.start );
- list_init( &rcpt );
-
- session->state = LHLO;
- return 1;
- }
- case LMTP_HELP :
- {
- int helpcmd;
-
- if (value == NULL)
- helpcmd = LMTP_END;
- else
- for (helpcmd = LMTP_STRT; helpcmd < LMTP_END; helpcmd++)
- if (strcasecmp(value, commands[helpcmd]) == 0) break;
-
- trace(TRACE_DEBUG,"lmtp(): LMTP_HELP requested for commandtype %d", helpcmd);
-
- if( (helpcmd==LMTP_LHLO) || (helpcmd==LMTP_DATA) ||
- (helpcmd==LMTP_RSET) || (helpcmd==LMTP_QUIT) ||
- (helpcmd==LMTP_NOOP) || (helpcmd==LMTP_HELP) )
- {
- fprintf((FILE *)stream, "%s", LMTP_HELP_TEXT[helpcmd]);
- }
- else
- {
- fprintf((FILE *)stream, "%s", LMTP_HELP_TEXT[LMTP_END]);
- }
-
- return 1;
- }
- case LMTP_VRFY :
- {
- /* RFC 2821 says this SHOULD be implemented...
- * and the goal is to say if the given address
- * is a valid delivery address at this server. */
- fprintf((FILE *)stream, "502 Command not implemented\r\n" );
- return 1;
- }
- case LMTP_EXPN:
- {
- /* RFC 2821 says this SHOULD be implemented...
- * and the goal is to return the membership
- * of the specified mailing list. */
- fprintf((FILE *)stream, "502 Command not implemented\r\n" );
- return 1;
- }
- case LMTP_MAIL:
- {
- /* We need to LHLO first because the client
- * needs to know what extensions we support.
- * */
- if (session->state != LHLO)
- {
- fprintf((FILE *)stream, "550 Command out of sequence.\r\n");
- }
- else if (envelopefrom != NULL)
- {
- fprintf((FILE *)stream, "500 Sender already received. Use RSET to clear.\r\n");
- }
- else
- {
- /* First look for an email address.
- * Don't bother verifying or whatever,
- * just find something between angle brackets!
- * */
- int goodtogo=1;
- size_t tmplen = 0, tmppos = 0;
- char *tmpaddr = NULL, *tmpbody = NULL;
-
- find_bounded(value, '<', '>', &tmpaddr, &tmplen, &tmppos);
-
- /* Second look for a BODY keyword.
- * See if it has an argument, and if we
- * support that feature. Don't give an OK
- * if we can't handle it yet, like 8BIT!
- * */
-
- /* Find the '=' following the address
- * then advance one character past it
- * (but only if there's more string!)
- * */
- tmpbody = strstr(value+tmppos, "=");
- if (tmpbody != NULL)
- if (strlen(tmpbody))
- tmpbody++;
-
- /* This is all a bit nested now... */
- if (tmplen < 1 && tmpaddr == NULL)
- {
- fprintf((FILE *)stream,"500 No address found.\r\n" );
- goodtogo = 0;
- }
- else if (tmpbody != NULL)
- {
- /* See RFC 3030 for the best
- * description of this stuff.
- * */
- if (strlen(tmpbody) < 4)
- {
- /* Caught */
- }
- else if (0 == strcasecmp(tmpbody, "7BIT"))
- {
- /* Sure fine go ahead. */
- goodtogo = 1; // Not that it wasn't 1 already ;-)
- }
- /* 8BITMIME corresponds to RFC 1652,
- * BINARYMIME corresponds to RFC 3030.
- * */
- else if (strlen(tmpbody) < 8)
- {
- /* Caught */
- }
- else if (0 == strcasecmp(tmpbody, "8BITMIME"))
- {
- /* We can't do this yet. */
- /* session->state = BIT8;
- * */
- fprintf((FILE *)stream,"500 Please use 7BIT MIME only.\r\n");
- goodtogo = 0;
- }
- else if (strlen(tmpbody) < 10)
- {
- /* Caught */
- }
- else if (0 == strcasecmp(tmpbody, "BINARYMIME"))
- {
- /* We can't do this yet. */
- /* session->state = BDAT;
- * */
- fprintf((FILE *)stream,"500 Please use 7BIT MIME only.\r\n" );
- goodtogo = 0;
- }
- }
-
- if (goodtogo)
- {
- /* Sure fine go ahead. */
- envelopefrom = tmpaddr;
- fprintf((FILE *)stream,"250 Sender <%s> OK\r\n", envelopefrom );
- }
- else
- {
- if (tmpaddr != NULL)
- my_free(tmpaddr);
- }
- }
- return 1;
- }
- case LMTP_RCPT :
- {
- if (session->state != LHLO)
- {
- fprintf((FILE *)stream, "550 Command out of sequence.\r\n");
- }
- else
- {
- size_t tmplen = 0, tmppos = 0;
- char *tmpaddr = NULL;
-
- find_bounded(value, '<', '>', &tmpaddr, &tmplen, &tmppos);
-
- if (tmplen < 1)
- {
- fprintf((FILE *)stream,"500 No address found.\r\n" );
- }
- else
- {
- /* Note that this is not a pointer, but really is on the stack!
- * Because list_nodeadd() memcpy's the structure, we don't need
- * it to live any longer than the duration of this stack frame. */
- deliver_to_user_t dsnuser;
-
- dsnuser_init(&dsnuser);
-
- /* find_bounded() allocated tmpaddr for us, and that's ok
- * since dsnuser_free() will free it for us later on. */
- dsnuser.address = tmpaddr;
-
- /* Queue up the potential recipients. We can use one call to
- * dsnuser_resolve_list() to look them up. This should not
- * be a problem because the client is required to pipeline
- * the commands, i.e. not wait for a reply to each command. */
- list_nodeadd(&rcpt, &dsnuser, sizeof(deliver_to_user_t));
- }
- }
- return 1;
- }
- /* Here's where it gets really exciting! */
- case LMTP_DATA:
- {
- // if (session->state != DATA || session->state != BIT8)
- if (session->state != LHLO)
- {
- fprintf((FILE *)stream, "550 Command out of sequence\r\n" );
- }
- else if (list_totalnodes(&rcpt) < 1)
- {
- fprintf((FILE *)stream, "503 No valid recipients\r\n" );
- }
- else
- {
- int has_recipients = 0;
- struct element *element;
-
- /* The replies MUST be in the order received */
- rcpt.start = dbmail_list_reverse(rcpt.start);
-
- /* Resolve the addresses into deliverable / non-deliverable form. */
- if (dsnuser_resolve_list(&rcpt) == -1)
- {
- trace(TRACE_ERROR, "main(): dsnuser_resolve_list failed");
- fprintf((FILE *)stream, "430 Temporary failure in recipient lookup\r\n" );
- return 1;
- }
-
- for(element = list_getstart(&rcpt);
- element != NULL; element = element->nextnode)
- {
- deliver_to_user_t *dsnuser = (deliver_to_user_t *)element->data;
-
- /* Class 2 means the address was deliverable in some way. */
- switch (dsnuser->dsn.class)
- {
- case DSN_CLASS_OK:
- fprintf((FILE *)stream, "250 Recipient <%s> OK\r\n",
- dsnuser->address);
- has_recipients = 1;
- break;
- default:
- fprintf((FILE *)stream, "550 Recipient <%s> FAIL\r\n",
- dsnuser->address);
- /* Remove the failed user from the potential recipients list
- * so that we do not report a failed delivery later on. */
- list_nodedel(&rcpt, dsnuser);
- break;
- }
- }
-
- /* Now we have a list of recipients! */
- /* Let the client know if they should continue... */
-
- if (has_recipients && envelopefrom != NULL)
- {
- trace(TRACE_DEBUG,"main(): requesting sender to begin message.");
- fprintf((FILE *)stream, "354 Start mail input; end with <CRLF>.<CRLF>\r\n" );
- }
- else
- {
- if (!has_recipients)
- {
- trace(TRACE_DEBUG,"main(): no valid recipients found, cancel message.");
- fprintf((FILE *)stream, "503 No valid recipients\r\n" );
- }
- if (!envelopefrom)
- {
- trace(TRACE_DEBUG,"main(): envelopefrom is empty, cancel message.");
- fprintf((FILE *)stream, "554 No valid sender.\r\n" );
- }
- return 1;
- }
-
- /* Anonymous Block */
- {
- char *header = NULL;
- u64_t headersize=0, headerrfcsize=0;
- u64_t dummyidx=0,dummysize=0;
- struct list fromlist, headerfields;
- struct element *element;
-
- list_init(&mimelist);
- list_init(&fromlist);
- list_init(&headerfields);
-
- /* if (envelopefrom != NULL) */
- /* We know this to be true from the 354 code, above. */
- list_nodeadd(&fromlist, envelopefrom, strlen(envelopefrom));
-
- if (!read_header((FILE *)instream, &headerrfcsize, &headersize, &header))
- {
- trace(TRACE_ERROR,"main(): fatal error from read_header()");
- discard_client_input((FILE*) instream);
- fprintf((FILE *)stream, "500 Error reading header.\r\n" );
- return 1;
- }
-
- if (header != NULL)
- {
- trace(TRACE_ERROR,"main(): size of read_header() header "
- "is [%llu]", headersize);
- if (headersize > READ_BLOCK_SIZE) {
- trace(TRACE_ERROR, "main(): header is too "
- "big");
- discard_client_input((FILE *)instream);
- fprintf((FILE*)stream, "500 Error reading header, "
- "header too big.\r\n");
- return 1;
- }
- }
- else
- {
- trace(TRACE_ERROR,"main(): read_header() returned a null header [%s]", header);
- discard_client_input((FILE*) instream);
- fprintf((FILE *)stream, "500 Error reading header.\r\n" );
- return 1;
- }
-
-
- /* Parse the list and scan for field and content */
- if (mime_readheader(header, &dummyidx, &mimelist, &dummysize) < 0)
- {
- trace(TRACE_ERROR,"main(): fatal error from mime_readheader()");
- discard_client_input((FILE*) instream);
- fprintf((FILE *)stream, "500 Error reading header.\r\n" );
- return 1;
- }
-
- if (insert_messages((FILE *)instream,
- header, headersize, headerrfcsize,
- &headerfields, &rcpt, &fromlist) == -1)
- {
- fprintf((FILE *)stream, "503 Message not received\r\n");
- }
- else
- {
- /* The DATA command itself it not given a reply except
- * that of the status of each of the remaining recipients. */
-
- for (element = list_getstart(&rcpt);
- element != NULL; element = element->nextnode)
- {
- deliver_to_user_t *dsnuser = (deliver_to_user_t *)element->data;
-
- switch (dsnuser->dsn.class)
- {
- case DSN_CLASS_OK:
- fprintf((FILE *)stream, "250 Recipient <%s> OK\r\n",
- dsnuser->address);
- break;
- case DSN_CLASS_TEMP:
- fprintf((FILE *)stream, "450 Recipient <%s> TEMP FAIL\r\n",
- dsnuser->address);
- break;
- case DSN_CLASS_FAIL:
- default:
- fprintf((FILE *)stream, "550 Recipient <%s> PERM FAIL\r\n",
- dsnuser->address);
- break;
- }
- }
- }
- if (header != NULL)
- my_free(header);
- }
- }
- return 1;
- }
- default :
- {
- return lmtp_error(session, stream,"500 What are you trying to say here?\r\n");
- }
- }
- return 1;
+ va_list argp;
+
+ if (session->error_count >= MAX_ERRORS) {
+ trace(TRACE_MESSAGE,
+ "lmtp_error(): too many errors (MAX_ERRORS is %d)",
+ MAX_ERRORS);
+ fprintf((FILE *) stream,
+ "500 Too many errors, closing connection.\r\n");
+ session->SessionResult = 2; /* possible flood */
+ lmtp_reset(session);
+ return -3;
+ } else {
+ va_start(argp, formatstring);
+ vfprintf((FILE *) stream, formatstring, argp);
+ va_end(argp);
+ }
+
+ trace(TRACE_DEBUG, "lmtp_error(): an invalid command was issued");
+ session->error_count++;
+ return 1;
}
+
+int lmtp(void *stream, void *instream, char *buffer,
+ char *client_ip UNUSED, PopSession_t * session)
+{
+ /* returns values:
+ * 0 to quit
+ * -1 on failure
+ * 1 on success */
+ char *command, *value;
+ int cmdtype;
+ int indx = 0;
+
+ /* buffer overflow attempt */
+ if (strlen(buffer) > MAX_IN_BUFFER) {
+ trace(TRACE_DEBUG, "lmtp(): buffer overflow attempt");
+ return -3;
+ }
+
+ /* check for command issued */
+ while (strchr(validchars, buffer[indx]))
+ indx++;
+
+ /* end buffer */
+ buffer[indx] = '\0';
+
+ trace(TRACE_DEBUG, "lmtp(): incoming buffer: [%s]", buffer);
+
+ command = buffer;
+
+ value = strstr(command, " "); /* look for the separator */
+
+ if (value != NULL) {
+ *value = '\0'; /* set a \0 on the command end */
+ value++; /* skip space */
+
+ if (strlen(value) == 0) {
+ value = NULL; /* no value specified */
+ } else {
+ trace(TRACE_DEBUG,
+ "lmtp(): command issued :cmd [%s], value [%s]\n",
+ command, value);
+ }
+ }
+
+ for (cmdtype = LMTP_STRT; cmdtype < LMTP_END; cmdtype++)
+ if (strcasecmp(command, commands[cmdtype]) == 0)
+ break;
+
+ trace(TRACE_DEBUG, "lmtp(): command looked up as commandtype %d",
+ cmdtype);
+
+ /* commands that are allowed to have no arguments */
+ if ((value == NULL) &&
+ !((cmdtype == LMTP_LHLO) || (cmdtype == LMTP_DATA) ||
+ (cmdtype == LMTP_RSET) || (cmdtype == LMTP_QUIT) ||
+ (cmdtype == LMTP_NOOP) || (cmdtype == LMTP_HELP)
+ )) {
+ trace(TRACE_ERROR, "ARGUMENT %d", cmdtype);
+ return lmtp_error(session, stream,
+ "500 This command requires an argument.\r\n");
+ }
+
+ switch (cmdtype) {
+ case LMTP_QUIT:
+ {
+ fprintf((FILE *) stream, "221 %s BYE\r\n",
+ myhostname);
+ lmtp_reset(session);
+ return 0; /* return 0 to cause the connection to close */
+ }
+ case LMTP_NOOP:
+ {
+ fprintf((FILE *) stream, "250 OK\r\n");
+ return 1;
+ }
+ case LMTP_RSET:
+ {
+ fprintf((FILE *) stream, "250 OK\r\n");
+ lmtp_reset(session);
+ return 1;
+ }
+ case LMTP_LHLO:
+ {
+ /* Reply wth our hostname and a list of features.
+ * The RFC requires a couple of SMTP extensions
+ * with a MUST statement, so just hardcode them.
+ * */
+ fprintf((FILE *) stream,
+ "250-%s\r\n"
+ "250-PIPELINING\r\n"
+ "250-ENHANCEDSTATUSCODES\r\n"
+ /* This is a SHOULD implement:
+ * "250-8BITMIME\r\n"
+ * Might as well do these, too:
+ * "250-CHUNKING\r\n"
+ * "250-BINARYMIME\r\n"
+ * */
+ "250 SIZE\r\n", myhostname);
+ /* Free the recipients list and reinitialize it */
+ // list_freelist( &rcpt.start );
+ list_init(&rcpt);
+
+ session->state = LHLO;
+ return 1;
+ }
+ case LMTP_HELP:
+ {
+ int helpcmd;
+
+ if (value == NULL)
+ helpcmd = LMTP_END;
+ else
+ for (helpcmd = LMTP_STRT;
+ helpcmd < LMTP_END; helpcmd++)
+ if (strcasecmp
+ (value,
+ commands[helpcmd]) == 0)
+ break;
+
+ trace(TRACE_DEBUG,
+ "lmtp(): LMTP_HELP requested for commandtype %d",
+ helpcmd);
+
+ if ((helpcmd == LMTP_LHLO)
+ || (helpcmd == LMTP_DATA)
+ || (helpcmd == LMTP_RSET)
+ || (helpcmd == LMTP_QUIT)
+ || (helpcmd == LMTP_NOOP)
+ || (helpcmd == LMTP_HELP)) {
+ fprintf((FILE *) stream, "%s",
+ LMTP_HELP_TEXT[helpcmd]);
+ } else {
+ fprintf((FILE *) stream, "%s",
+ LMTP_HELP_TEXT[LMTP_END]);
+ }
+
+ return 1;
+ }
+ case LMTP_VRFY:
+ {
+ /* RFC 2821 says this SHOULD be implemented...
+ * and the goal is to say if the given address
+ * is a valid delivery address at this server. */
+ fprintf((FILE *) stream,
+ "502 Command not implemented\r\n");
+ return 1;
+ }
+ case LMTP_EXPN:
+ {
+ /* RFC 2821 says this SHOULD be implemented...
+ * and the goal is to return the membership
+ * of the specified mailing list. */
+ fprintf((FILE *) stream,
+ "502 Command not implemented\r\n");
+ return 1;
+ }
+ case LMTP_MAIL:
+ {
+ /* We need to LHLO first because the client
+ * needs to know what extensions we support.
+ * */
+ if (session->state != LHLO) {
+ fprintf((FILE *) stream,
+ "550 Command out of sequence.\r\n");
+ } else if (envelopefrom != NULL) {
+ fprintf((FILE *) stream,
+ "500 Sender already received. Use RSET to clear.\r\n");
+ } else {
+ /* First look for an email address.
+ * Don't bother verifying or whatever,
+ * just find something between angle brackets!
+ * */
+ int goodtogo = 1;
+ size_t tmplen = 0, tmppos = 0;
+ char *tmpaddr = NULL, *tmpbody = NULL;
+
+ find_bounded(value, '<', '>', &tmpaddr,
+ &tmplen, &tmppos);
+
+ /* Second look for a BODY keyword.
+ * See if it has an argument, and if we
+ * support that feature. Don't give an OK
+ * if we can't handle it yet, like 8BIT!
+ * */
+
+ /* Find the '=' following the address
+ * then advance one character past it
+ * (but only if there's more string!)
+ * */
+ tmpbody = strstr(value + tmppos, "=");
+ if (tmpbody != NULL)
+ if (strlen(tmpbody))
+ tmpbody++;
+
+ /* This is all a bit nested now... */
+ if (tmplen < 1 && tmpaddr == NULL) {
+ fprintf((FILE *) stream,
+ "500 No address found.\r\n");
+ goodtogo = 0;
+ } else if (tmpbody != NULL) {
+ /* See RFC 3030 for the best
+ * description of this stuff.
+ * */
+ if (strlen(tmpbody) < 4) {
+ /* Caught */
+ } else if (0 ==
+ strcasecmp(tmpbody,
+ "7BIT")) {
+ /* Sure fine go ahead. */
+ goodtogo = 1; // Not that it wasn't 1 already ;-)
+ }
+ /* 8BITMIME corresponds to RFC 1652,
+ * BINARYMIME corresponds to RFC 3030.
+ * */
+ else if (strlen(tmpbody) < 8) {
+ /* Caught */
+ } else if (0 ==
+ strcasecmp(tmpbody,
+ "8BITMIME"))
+ {
+ /* We can't do this yet. */
+ /* session->state = BIT8;
+ * */
+ fprintf((FILE *) stream,
+ "500 Please use 7BIT MIME only.\r\n");
+ goodtogo = 0;
+ } else if (strlen(tmpbody) < 10) {
+ /* Caught */
+ } else if (0 ==
+ strcasecmp(tmpbody,
+ "BINARYMIME"))
+ {
+ /* We can't do this yet. */
+ /* session->state = BDAT;
+ * */
+ fprintf((FILE *) stream,
+ "500 Please use 7BIT MIME only.\r\n");
+ goodtogo = 0;
+ }
+ }
+
+ if (goodtogo) {
+ /* Sure fine go ahead. */
+ envelopefrom = tmpaddr;
+ fprintf((FILE *) stream,
+ "250 Sender <%s> OK\r\n",
+ envelopefrom);
+ } else {
+ if (tmpaddr != NULL)
+ my_free(tmpaddr);
+ }
+ }
+ return 1;
+ }
+ case LMTP_RCPT:
+ {
+ if (session->state != LHLO) {
+ fprintf((FILE *) stream,
+ "550 Command out of sequence.\r\n");
+ } else {
+ size_t tmplen = 0, tmppos = 0;
+ char *tmpaddr = NULL;
+
+ find_bounded(value, '<', '>', &tmpaddr,
+ &tmplen, &tmppos);
+
+ if (tmplen < 1) {
+ fprintf((FILE *) stream,
+ "500 No address found.\r\n");
+ } else {
+ /* Note that this is not a pointer, but really is on the stack!
+ * Because list_nodeadd() memcpy's the structure, we don't need
+ * it to live any longer than the duration of this stack frame. */
+ deliver_to_user_t dsnuser;
+
+ dsnuser_init(&dsnuser);
+
+ /* find_bounded() allocated tmpaddr for us, and that's ok
+ * since dsnuser_free() will free it for us later on. */
+ dsnuser.address = tmpaddr;
+
+ /* Queue up the potential recipients. We can use one call to
+ * dsnuser_resolve_list() to look them up. This should not
+ * be a problem because the client is required to pipeline
+ * the commands, i.e. not wait for a reply to each command. */
+ list_nodeadd(&rcpt, &dsnuser,
+ sizeof
+ (deliver_to_user_t));
+ }
+ }
+ return 1;
+ }
+ /* Here's where it gets really exciting! */
+ case LMTP_DATA:
+ {
+ // if (session->state != DATA || session->state != BIT8)
+ if (session->state != LHLO) {
+ fprintf((FILE *) stream,
+ "550 Command out of sequence\r\n");
+ } else if (list_totalnodes(&rcpt) < 1) {
+ fprintf((FILE *) stream,
+ "503 No valid recipients\r\n");
+ } else {
+ int has_recipients = 0;
+ struct element *element;
+
+ /* The replies MUST be in the order received */
+ rcpt.start =
+ dbmail_list_reverse(rcpt.start);
+
+ /* Resolve the addresses into deliverable / non-deliverable form. */
+ if (dsnuser_resolve_list(&rcpt) == -1) {
+ trace(TRACE_ERROR,
+ "main(): dsnuser_resolve_list failed");
+ fprintf((FILE *) stream,
+ "430 Temporary failure in recipient lookup\r\n");
+ return 1;
+ }
+
+ for (element = list_getstart(&rcpt);
+ element != NULL;
+ element = element->nextnode) {
+ deliver_to_user_t *dsnuser =
+ (deliver_to_user_t *) element->
+ data;
+
+ /* Class 2 means the address was deliverable in some way. */
+ switch (dsnuser->dsn.class) {
+ case DSN_CLASS_OK:
+ fprintf((FILE *) stream,
+ "250 Recipient <%s> OK\r\n",
+ dsnuser->address);
+ has_recipients = 1;
+ break;
+ default:
+ fprintf((FILE *) stream,
+ "550 Recipient <%s> FAIL\r\n",
+ dsnuser->address);
+ /* Remove the failed user from the potential recipients list
+ * so that we do not report a failed delivery later on. */
+ list_nodedel(&rcpt,
+ dsnuser);
+ break;
+ }
+ }
+
+ /* Now we have a list of recipients! */
+ /* Let the client know if they should continue... */
+
+ if (has_recipients && envelopefrom != NULL) {
+ trace(TRACE_DEBUG,
+ "main(): requesting sender to begin message.");
+ fprintf((FILE *) stream,
+ "354 Start mail input; end with <CRLF>.<CRLF>\r\n");
+ } else {
+ if (!has_recipients) {
+ trace(TRACE_DEBUG,
+ "main(): no valid recipients found, cancel message.");
+ fprintf((FILE *) stream,
+ "503 No valid recipients\r\n");
+ }
+ if (!envelopefrom) {
+ trace(TRACE_DEBUG,
+ "main(): envelopefrom is empty, cancel message.");
+ fprintf((FILE *) stream,
+ "554 No valid sender.\r\n");
+ }
+ return 1;
+ }
+
+ /* Anonymous Block */
+ {
+ char *header = NULL;
+ u64_t headersize =
+ 0, headerrfcsize = 0;
+ u64_t dummyidx = 0, dummysize = 0;
+ struct list fromlist, headerfields;
+ struct element *element;
+
+ list_init(&mimelist);
+ list_init(&fromlist);
+ list_init(&headerfields);
+
+ /* if (envelopefrom != NULL) */
+ /* We know this to be true from the 354 code, above. */
+ list_nodeadd(&fromlist,
+ envelopefrom,
+ strlen(envelopefrom));
+
+ if (!read_header
+ ((FILE *) instream,
+ &headerrfcsize, &headersize,
+ &header)) {
+ trace(TRACE_ERROR,
+ "main(): fatal error from read_header()");
+ discard_client_input((FILE
+ *)
+ instream);
+ fprintf((FILE *) stream,
+ "500 Error reading header.\r\n");
+ return 1;
+ }
+
+ if (header != NULL) {
+ trace(TRACE_ERROR,
+ "main(): size of read_header() header "
+ "is [%llu]",
+ headersize);
+ if (headersize >
+ READ_BLOCK_SIZE) {
+ trace(TRACE_ERROR,
+ "main(): header is too "
+ "big");
+ discard_client_input
+ ((FILE *)
+ instream);
+ fprintf((FILE *)
+ stream,
+ "500 Error reading header, "
+ "header too big.\r\n");
+ return 1;
+ }
+ } else {
+ trace(TRACE_ERROR,
+ "main(): read_header() returned a null header [%s]",
+ header);
+ discard_client_input((FILE
+ *)
+ instream);
+ fprintf((FILE *) stream,
+ "500 Error reading header.\r\n");
+ return 1;
+ }
+
+
+ /* Parse the list and scan for field and content */
+ if (mime_readheader
+ (header, &dummyidx, &mimelist,
+ &dummysize) < 0) {
+ trace(TRACE_ERROR,
+ "main(): fatal error from mime_readheader()");
+ discard_client_input((FILE
+ *)
+ instream);
+ fprintf((FILE *) stream,
+ "500 Error reading header.\r\n");
+ return 1;
+ }
+
+ if (insert_messages
+ ((FILE *) instream, header,
+ headersize, headerrfcsize,
+ &headerfields, &rcpt,
+ &fromlist) == -1) {
+ fprintf((FILE *) stream,
+ "503 Message not received\r\n");
+ } else {
+ /* The DATA command itself it not given a reply except
+ * that of the status of each of the remaining recipients. */
+
+ for (element =
+ list_getstart(&rcpt);
+ element != NULL;
+ element =
+ element->nextnode) {
+ deliver_to_user_t
+ * dsnuser =
+ (deliver_to_user_t
+ *) element->
+ data;
+
+ switch (dsnuser->
+ dsn.
+ class) {
+ case DSN_CLASS_OK:
+ fprintf((FILE *) stream, "250 Recipient <%s> OK\r\n", dsnuser->address);
+ break;
+ case DSN_CLASS_TEMP:
+ fprintf((FILE *) stream, "450 Recipient <%s> TEMP FAIL\r\n", dsnuser->address);
+ break;
+ case DSN_CLASS_FAIL:
+ default:
+ fprintf((FILE *) stream, "550 Recipient <%s> PERM FAIL\r\n", dsnuser->address);
+ break;
+ }
+ }
+ }
+ if (header != NULL)
+ my_free(header);
+ }
+ }
+ return 1;
+ }
+ default:
+ {
+ return lmtp_error(session, stream,
+ "500 What are you trying to say here?\r\n");
+ }
+ }
+ return 1;
+}
diff --git a/lmtp.h b/lmtp.h
index 02730699..f080f64f 100644
--- a/lmtp.h
+++ b/lmtp.h
@@ -38,7 +38,7 @@
/* processes */
#define MAXCHILDREN 5
-#define DEFAULT_CHILDREN 5
+#define DEFAULT_CHILDREN 5
#define LMTP_DEF_MAXCONNECT 1500
@@ -57,21 +57,22 @@ const char *commands [] =
"VRFY", "EXPN", "HELP", "NOOP", "RCPT"
}; */
-#define LMTP_STRT 0 /* lower bound of array - 0 */
+#define LMTP_STRT 0 /* lower bound of array - 0 */
#define LMTP_LHLO 0
#define LMTP_QUIT 1
#define LMTP_RSET 2
-#define LMTP_DATA 3
+#define LMTP_DATA 3
#define LMTP_MAIL 4
#define LMTP_VRFY 5
#define LMTP_EXPN 6
#define LMTP_HELP 7
#define LMTP_NOOP 8
#define LMTP_RCPT 9
-#define LMTP_END 10 /* upper bound of array + 1 */
+#define LMTP_END 10 /* upper bound of array + 1 */
-int lmtp(void *stream, void *instream, char *buffer, char *client_ip, PopSession_t *session);
-int lmtp_handle_connection(clientinfo_t *ci);
+int lmtp(void *stream, void *instream, char *buffer, char *client_ip,
+ PopSession_t * session);
+int lmtp_handle_connection(clientinfo_t * ci);
/*
* Enhanced Status Codes
@@ -140,66 +141,66 @@ int lmtp_handle_connection(clientinfo_t *ci);
*/
/* Help */
-static const char * const LMTP_HELP_TEXT[] = {
+static const char *const LMTP_HELP_TEXT[] = {
/* LMTP_LHLO 0 */
- "214-The LHLO command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The LHLO command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_QUIT 1 */ ,
- "214-The QUIT command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The QUIT command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_RSET 2 */ ,
- "214-The RSET command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The RSET command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_DATA 3 */ ,
- "214-The DATA command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The DATA command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_MAIL 4 */ ,
- "214-The MAIL command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The MAIL command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_VRFY 5 */ ,
- "214-The VRFY command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The VRFY command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_EXPN 6 */ ,
- "214-The EXPN command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The EXPN command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_HELP 7 */ ,
- "214-The HELP command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The HELP command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_NOOP 8 */ ,
- "214-The NOOP command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The NOOP command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_RCPT 9 */ ,
- "214-The RCPT command begins a client/server\r\n"
- "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
- "214-may only be issued after a successful LHLO.\r\n"
- "214 Syntax: LHLO [your hostname]\r\n"
+ "214-The RCPT command begins a client/server\r\n"
+ "214-dialogue. The commands MAIL, RCPT and DATA\r\n"
+ "214-may only be issued after a successful LHLO.\r\n"
+ "214 Syntax: LHLO [your hostname]\r\n"
/* LMTP_END 10 */ ,
- "214-This is DBMail-LMTP.\r\n"
- "214-The following commands are supported:\r\n"
- "214-LHLO, RSET, NOOP, QUIT, HELP.\r\n"
- "214-VRFY, EXPN, MAIL, RCPT, DATA.\r\n"
- "214-For more information about a command:\r\n"
- "214 Use HELP <command>.\r\n"
+ "214-This is DBMail-LMTP.\r\n"
+ "214-The following commands are supported:\r\n"
+ "214-LHLO, RSET, NOOP, QUIT, HELP.\r\n"
+ "214-VRFY, EXPN, MAIL, RCPT, DATA.\r\n"
+ "214-For more information about a command:\r\n"
+ "214 Use HELP <command>.\r\n"
/* For good measure... */ ,
- NULL
+ NULL
};
#endif
diff --git a/lmtpd.c b/lmtpd.c
index 9567bee3..fe3aaecb 100644
--- a/lmtpd.c
+++ b/lmtpd.c
@@ -42,10 +42,10 @@ char *configFile = DEFAULT_CONFIG_FILE;
/* set up database login data */
extern db_param_t _db_params;
-void SetConfigItems(serverConfig_t *config, struct list *items);
+void SetConfigItems(serverConfig_t * config, struct list *items);
void Daemonize(void);
int SetMainSigHandler(void);
-void MainSigHandler(int sig, siginfo_t *info, void *data);
+void MainSigHandler(int sig, siginfo_t * info, void *data);
int lmtp_before_smtp = 0;
int mainRestart = 0;
@@ -58,256 +58,282 @@ char *timeout_setting;
#ifdef PROC_TITLES
int main(int argc, char *argv[], char **envp)
#else
- int main(int argc, char *argv[])
+int main(int argc, char *argv[])
#endif
{
- serverConfig_t config;
- int result, status;
- pid_t pid;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- if (argc >= 2 && (argv[1]))
- {
- if (strcmp (argv[1],"-v") == 0)
- {
- printf ("\n*** DBMAIL: dbmail-lmtpd version $Revision$ %s\n\n",COPYRIGHT);
- return 0;
- }
- else
- if (strcmp(argv[1],"-f")==0 && (argv[2]))
- configFile = argv[2];
- }
-
- SetMainSigHandler();
- Daemonize();
- result = 0;
-
- do
- {
- mainStop = 0;
- mainRestart = 0;
-
- trace(TRACE_DEBUG, "main(): reading config");
-#ifdef PROC_TITLES
- init_set_proc_title(argc, argv, envp, PNAME);
- set_proc_title("%s", "Idle");
-#endif
-
- /* We need smtp config for bounce.c and forward.c */
- ReadConfig("SMTP", configFile, &smtpItems);
- ReadConfig("LMTP", configFile, &lmtpItems);
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetConfigItems(&config, &lmtpItems);
- SetTraceLevel(&lmtpItems);
- GetDBParams(&_db_params, &sysItems);
-
- config.ClientHandler = lmtp_handle_connection;
- config.timeoutMsg = LMTP_TIMEOUT_MSG;
-
- CreateSocket(&config);
- trace(TRACE_DEBUG, "main(): socket created, starting server");
-
- switch ( (pid = fork()) )
- {
- case -1:
- close(config.listenSocket);
- trace(TRACE_FATAL, "main(): fork failed [%s]", strerror(errno));
-
- case 0:
- /* child process */
- drop_privileges(config.serverUser, config.serverGroup);
- result = StartServer(&config);
-
- trace(TRACE_INFO, "main(): server done, exit.");
- exit(result);
-
- default:
- /* parent process, wait for child to exit */
- while (waitpid(pid, &status, WNOHANG|WUNTRACED) == 0)
- {
- if (mainStop)
- kill(pid, SIGTERM);
-
- if (mainRestart)
- kill(pid, SIGHUP);
-
- sleep(2);
- }
-
- if (WIFEXITED(status))
- {
- /* child process terminated neatly */
- result = WEXITSTATUS(status);
- trace(TRACE_DEBUG, "main(): server has exited, exit status [%d]", result);
- }
- else
- {
- /* child stopped or signaled, don't like */
- /* make sure it is dead */
- trace(TRACE_DEBUG, "main(): server has not exited normally. Killing..");
-
- kill(pid, SIGKILL);
- result = 0;
- }
+ serverConfig_t config;
+ int result, status;
+ pid_t pid;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ if (argc >= 2 && (argv[1])) {
+ if (strcmp(argv[1], "-v") == 0) {
+ printf
+ ("\n*** DBMAIL: dbmail-lmtpd version $Revision$ %s\n\n",
+ COPYRIGHT);
+ return 0;
+ } else if (strcmp(argv[1], "-f") == 0 && (argv[2]))
+ configFile = argv[2];
}
- list_freelist(&smtpItems.start);
- list_freelist(&lmtpItems.start);
- list_freelist(&sysItems.start);
- close(config.listenSocket);
+ SetMainSigHandler();
+ Daemonize();
+ result = 0;
- } while (result == 1 && !mainStop) ; /* 1 means reread-config and restart */
+ do {
+ mainStop = 0;
+ mainRestart = 0;
+
+ trace(TRACE_DEBUG, "main(): reading config");
+#ifdef PROC_TITLES
+ init_set_proc_title(argc, argv, envp, PNAME);
+ set_proc_title("%s", "Idle");
+#endif
- trace(TRACE_INFO, "main(): exit");
- return 0;
+ /* We need smtp config for bounce.c and forward.c */
+ ReadConfig("SMTP", configFile, &smtpItems);
+ ReadConfig("LMTP", configFile, &lmtpItems);
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetConfigItems(&config, &lmtpItems);
+ SetTraceLevel(&lmtpItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ config.ClientHandler = lmtp_handle_connection;
+ config.timeoutMsg = LMTP_TIMEOUT_MSG;
+
+ CreateSocket(&config);
+ trace(TRACE_DEBUG,
+ "main(): socket created, starting server");
+
+ switch ((pid = fork())) {
+ case -1:
+ close(config.listenSocket);
+ trace(TRACE_FATAL, "main(): fork failed [%s]",
+ strerror(errno));
+
+ case 0:
+ /* child process */
+ drop_privileges(config.serverUser,
+ config.serverGroup);
+ result = StartServer(&config);
+
+ trace(TRACE_INFO, "main(): server done, exit.");
+ exit(result);
+
+ default:
+ /* parent process, wait for child to exit */
+ while (waitpid(pid, &status, WNOHANG | WUNTRACED)
+ == 0) {
+ if (mainStop)
+ kill(pid, SIGTERM);
+
+ if (mainRestart)
+ kill(pid, SIGHUP);
+
+ sleep(2);
+ }
+
+ if (WIFEXITED(status)) {
+ /* child process terminated neatly */
+ result = WEXITSTATUS(status);
+ trace(TRACE_DEBUG,
+ "main(): server has exited, exit status [%d]",
+ result);
+ } else {
+ /* child stopped or signaled, don't like */
+ /* make sure it is dead */
+ trace(TRACE_DEBUG,
+ "main(): server has not exited normally. Killing..");
+
+ kill(pid, SIGKILL);
+ result = 0;
+ }
+ }
+
+ list_freelist(&smtpItems.start);
+ list_freelist(&lmtpItems.start);
+ list_freelist(&sysItems.start);
+ close(config.listenSocket);
+
+ } while (result == 1 && !mainStop); /* 1 means reread-config and restart */
+
+ trace(TRACE_INFO, "main(): exit");
+ return 0;
}
-void MainSigHandler(int sig, siginfo_t *info UNUSED, void *data UNUSED)
+void MainSigHandler(int sig, siginfo_t * info UNUSED, void *data UNUSED)
{
- trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
+ trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
- if (sig == SIGHUP)
- mainRestart = 1;
- else
- mainStop = 1;
+ if (sig == SIGHUP)
+ mainRestart = 1;
+ else
+ mainStop = 1;
}
void Daemonize()
{
- if (fork())
- exit(0);
- setsid();
+ if (fork())
+ exit(0);
+ setsid();
- if (fork())
- exit(0);
+ if (fork())
+ exit(0);
}
int SetMainSigHandler()
{
- struct sigaction act;
+ struct sigaction act;
- /* init & install signal handlers */
- memset(&act, 0, sizeof(act));
+ /* init & install signal handlers */
+ memset(&act, 0, sizeof(act));
- act.sa_sigaction = MainSigHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = MainSigHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
- sigaction(SIGINT, &act, 0);
- sigaction(SIGQUIT, &act, 0);
- sigaction(SIGTERM, &act, 0);
- sigaction(SIGHUP, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
- return 0;
+ return 0;
}
-void SetConfigItems(serverConfig_t *config, struct list *items)
+void SetConfigItems(serverConfig_t * config, struct list *items)
{
- field_t val;
+ field_t val;
- /* read items: NCHILDREN */
- GetConfigValue("NCHILDREN", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for NCHILDREN in config file");
+ /* read items: NCHILDREN */
+ GetConfigValue("NCHILDREN", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for NCHILDREN in config file");
- if ( (config->nChildren = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for NCHILDREN is invalid: [%d]", config->nChildren);
+ if ((config->nChildren = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for NCHILDREN is invalid: [%d]",
+ config->nChildren);
- trace(TRACE_DEBUG, "SetConfigItems(): server will create [%d] children", config->nChildren);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): server will create [%d] children",
+ config->nChildren);
- /* read items: MAXCONNECTS */
- GetConfigValue("MAXCONNECTS", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for MAXCONNECTS in config file");
+ /* read items: MAXCONNECTS */
+ GetConfigValue("MAXCONNECTS", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for MAXCONNECTS in config file");
- if ( (config->childMaxConnect = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]", config->childMaxConnect);
+ if ((config->childMaxConnect = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]",
+ config->childMaxConnect);
- trace(TRACE_DEBUG, "SetConfigItems(): children will make max. [%d] connections", config->childMaxConnect);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): children will make max. [%d] connections",
+ config->childMaxConnect);
- /* read items: TIMEOUT */
- GetConfigValue("TIMEOUT", items, val);
- if (strlen(val) == 0)
- {
- trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMEOUT in config file");
- config->timeout = 0;
- }
- else if ( (config->timeout = atoi(val)) <= 30)
- trace(TRACE_FATAL, "SetConfigItems(): value for TIMEOUT is invalid: [%d]", config->timeout);
+ /* read items: TIMEOUT */
+ GetConfigValue("TIMEOUT", items, val);
+ if (strlen(val) == 0) {
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for TIMEOUT in config file");
+ config->timeout = 0;
+ } else if ((config->timeout = atoi(val)) <= 30)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for TIMEOUT is invalid: [%d]",
+ config->timeout);
- trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds", config->timeout);
+ trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds",
+ config->timeout);
- /* read items: PORT */
- GetConfigValue("PORT", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for PORT in config file");
+ /* read items: PORT */
+ GetConfigValue("PORT", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for PORT in config file");
- if ( (config->port = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for PORT is invalid: [%d]", config->port);
+ if ((config->port = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for PORT is invalid: [%d]",
+ config->port);
- trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]", config->port);
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]",
+ config->port);
- /* read items: BINDIP */
- GetConfigValue("BINDIP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for BINDIP in config file");
+ /* read items: BINDIP */
+ GetConfigValue("BINDIP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for BINDIP in config file");
- strncpy(config->ip, val, IPLEN);
- config->ip[IPLEN-1] = '\0';
+ strncpy(config->ip, val, IPLEN);
+ config->ip[IPLEN - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]", config->ip);
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]",
+ config->ip);
- /* read items: RESOLVE_IP */
- GetConfigValue("RESOLVE_IP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for RESOLVE_IP in config file");
+ /* read items: RESOLVE_IP */
+ GetConfigValue("RESOLVE_IP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for RESOLVE_IP in config file");
- config->resolveIP = (strcasecmp(val, "yes") == 0);
+ config->resolveIP = (strcasecmp(val, "yes") == 0);
- trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP", config->resolveIP ? "" : "not ");
+ trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP",
+ config->resolveIP ? "" : "not ");
- /* read items: IMAP-BEFORE-SMTP */
- GetConfigValue("LMTP_BEFORE_SMTP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for LMTP_BEFORE_SMTP in config file");
+ /* read items: IMAP-BEFORE-SMTP */
+ GetConfigValue("LMTP_BEFORE_SMTP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for LMTP_BEFORE_SMTP in config file");
- lmtp_before_smtp = (strcasecmp(val, "yes") == 0);
+ lmtp_before_smtp = (strcasecmp(val, "yes") == 0);
- trace(TRACE_DEBUG, "SetConfigItems(): %s LMTP-before-SMTP",
- lmtp_before_smtp ? "Enabling" : "Disabling");
+ trace(TRACE_DEBUG, "SetConfigItems(): %s LMTP-before-SMTP",
+ lmtp_before_smtp ? "Enabling" : "Disabling");
- /* read items: EFFECTIVE-USER */
- GetConfigValue("EFFECTIVE_USER", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_USER in config file");
+ /* read items: EFFECTIVE-USER */
+ GetConfigValue("EFFECTIVE_USER", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_USER in config file");
- strncpy(config->serverUser, val, FIELDSIZE);
- config->serverUser[FIELDSIZE-1] = '\0';
+ strncpy(config->serverUser, val, FIELDSIZE);
+ config->serverUser[FIELDSIZE - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): effective user shall be [%s]", config->serverUser);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective user shall be [%s]",
+ config->serverUser);
- /* read items: EFFECTIVE-GROUP */
- GetConfigValue("EFFECTIVE_GROUP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
+ /* read items: EFFECTIVE-GROUP */
+ GetConfigValue("EFFECTIVE_GROUP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
- strncpy(config->serverGroup, val, FIELDSIZE);
- config->serverGroup[FIELDSIZE-1] = '\0';
+ strncpy(config->serverGroup, val, FIELDSIZE);
+ config->serverGroup[FIELDSIZE - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): effective group shall be [%s]", config->serverGroup);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective group shall be [%s]",
+ config->serverGroup);
diff --git a/main.c b/main.c
index 40b808a9..72fbff47 100644
--- a/main.c
+++ b/main.c
@@ -49,17 +49,17 @@
/* syslog */
#define PNAME "dbmail/smtp"
-struct list returnpath; /* returnpath (should aways be just 1 hop) */
-struct list mimelist; /* raw unformatted mimefields and values */
-struct list dsnusers; /* list of deliver_to_user_t structs */
-struct list users; /* list of email addresses in message */
+struct list returnpath; /* returnpath (should aways be just 1 hop) */
+struct list mimelist; /* raw unformatted mimefields and values */
+struct list dsnusers; /* list of deliver_to_user_t structs */
+struct list users; /* list of email addresses in message */
struct element *tmp;
-struct list sysItems, smtpItems; /* config item lists */
+struct list sysItems, smtpItems; /* config item lists */
char *configFile = DEFAULT_CONFIG_FILE;
-extern db_param_t _db_params; /* set up database login data */
+extern db_param_t _db_params; /* set up database login data */
deliver_to_user_t dsnuser;
@@ -70,282 +70,286 @@ u64_t headersize, headerrfcsize;
void print_usage(const char *progname)
{
- printf("\n*** DBMAIL: dbmail-smtp version $Revision$ %s\n",
- COPYRIGHT);
- printf("\nUsage: %s -n [headerfield] for normal deliveries (default: \"deliver-to\")\n",
- progname);
- printf(" %s -m \"mailbox\" -u [username] for delivery to mailbox (name)\n",
- progname);
- printf(" %s -d [addresses] for delivery without using scanner\n",
- progname);
- printf(" %s -u [usernames] for direct delivery to users\n\n",
- progname);
+ printf("\n*** DBMAIL: dbmail-smtp version $Revision$ %s\n",
+ COPYRIGHT);
+ printf
+ ("\nUsage: %s -n [headerfield] for normal deliveries (default: \"deliver-to\")\n",
+ progname);
+ printf
+ (" %s -m \"mailbox\" -u [username] for delivery to mailbox (name)\n",
+ progname);
+ printf
+ (" %s -d [addresses] for delivery without using scanner\n",
+ progname);
+ printf
+ (" %s -u [usernames] for direct delivery to users\n\n",
+ progname);
}
-int main(int argc, char *argv[])
+int main(int argc, char *argv[])
{
- int exitcode = 0;
- int c, c_prev = 0, usage_error = 0;
- u64_t dummyidx = 0, dummysize = 0;
-
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- ReadConfig("DBMAIL", configFile, &sysItems);
- ReadConfig("SMTP", configFile, &smtpItems);
- SetTraceLevel(&smtpItems);
- GetDBParams(&_db_params, &sysItems);
-
- list_init(&users);
- list_init(&dsnusers);
- list_init(&mimelist);
- list_init(&returnpath);
-
- /* Check for commandline options.
- * The initial '-' means that arguments which are not associated
- * with an immediately preceding option are return with option
- * value '1'. We will use this to allow for multiple values to
- * follow after each of the supported options. */
- while ((c = getopt(argc, argv, "-n::m:u:d:f:")) != EOF)
- {
- /* Received an n-th value following the last option,
- * so recall the last known option to be used in the switch. */
- if (c == '1')
- c = c_prev;
- c_prev = c;
- /* Do something with this option. */
- switch (c)
- {
- case 'n':
- trace(TRACE_INFO, "main(): using NORMAL_DELIVERY");
-
- if (optarg)
- {
- if (deliver_to_header)
- {
- printf("Only one header field may be specified.\n");
- usage_error = 1;
- }
- else
- deliver_to_header = optarg;
- }
- else
- deliver_to_header = "deliver-to";
-
- break;
- case 'm':
- trace(TRACE_INFO, "main(): using SPECIAL_DELIVERY to mailbox");
-
- if (deliver_to_mailbox)
- {
- printf("Only one header field may be specified.\n");
- usage_error = 1;
- }
- else
- deliver_to_mailbox = optarg;
-
- break;
- case 'f':
- trace(TRACE_INFO, "main(): using RETURN_PATH for bounces");
-
- /* Add argument onto the returnpath list. */
- if (list_nodeadd(&returnpath, optarg, strlen(optarg) + 1) == 0)
- {
- trace(TRACE_ERROR, "main(): list_nodeadd reports out of memory"
- " while adding to returnpath");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- break;
- case 'u':
- trace(TRACE_INFO, "main(): using SPECIAL_DELIVERY to usernames");
-
- dsnuser_init(&dsnuser);
- dsnuser.address = strdup(optarg);
-
- /* Add argument onto the users list. */
- if (list_nodeadd(&dsnusers, &dsnuser, sizeof(deliver_to_user_t)) == 0)
- {
- trace(TRACE_ERROR, "main(): list_nodeadd reports out of memory"
- " while adding usernames");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- break;
- case 'd':
- trace(TRACE_INFO, "main(): using SPECIAL_DELIVERY to email addresses");
-
- dsnuser_init(&dsnuser);
- dsnuser.address = strdup(optarg);
-
- /* Add argument onto the users list. */
- if (list_nodeadd(&dsnusers, &dsnuser, sizeof(deliver_to_user_t)) == 0)
- {
- trace(TRACE_ERROR, "main(): list_nodeadd reports out of memory"
- " while adding email addresses");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- break;
- default:
- usage_error = 1;
- break;
- }
-
- /* At the end of each round of options, check
- * to see if there were any errors worth stopping for. */
- if (usage_error)
- {
- print_usage(argv[0]);
- trace(TRACE_DEBUG, "main(): usage error; setting EX_USAGE and aborting");
- exitcode = EX_USAGE;
- goto freeall;
- }
- }
-
- /* ...or if there weren't any command line arguments at all. */
- if (argc < 2)
- {
- print_usage(argv[0]);
- trace(TRACE_DEBUG, "main(): no arguments; setting EX_USAGE and aborting");
- exitcode = EX_USAGE;
- goto freeall;
- }
-
- if (db_connect() != 0)
- {
- trace(TRACE_ERROR, "main(): database connection failed");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- if (auth_connect() != 0)
- {
- trace(TRACE_ERROR, "main(): authentication connection failed");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- /* first we need to read the header */
- if (!read_header(stdin, &headerrfcsize, &headersize, &header))
- {
- trace(TRACE_ERROR, "main(): read_header failed to read a header");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- if (headersize > READ_BLOCK_SIZE) {
- trace(TRACE_ERROR, "%s,%s: failed to read header because header is "
- "too big (bigger than READ_BLOCK_SIZE (%llu))",
- __FILE__, __FUNCTION__, (u64_t)READ_BLOCK_SIZE);
- exitcode = EX_DATAERR;
- goto freeall;
- }
-
- /* parse the list and scan for field and content */
- if (mime_readheader(header, &dummyidx, &mimelist, &dummysize) < 0)
- {
- trace(TRACE_ERROR, "main(): mime_readheader failed to read a header list");
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- /* parse returnpath from header */
- if (returnpath.total_nodes == 0)
- mail_adr_list("Return-Path", &returnpath, &mimelist);
- if (returnpath.total_nodes == 0)
- mail_adr_list("From", &returnpath, &mimelist);
- if (returnpath.total_nodes == 0)
- trace(TRACE_DEBUG, "main(): no return path found.");
-
- /* If the NORMAL delivery mode has been selected... */
- if (deliver_to_header != NULL)
- {
- /* parse for destination addresses */
- trace(TRACE_DEBUG, "main(): scanning for [%s]",
- deliver_to_header);
- if (mail_adr_list(deliver_to_header, &users, &mimelist) !=0)
- {
- trace(TRACE_STOP, "main(): scanner found no email addresses (scanned for %s)",
- deliver_to_header);
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- /* Loop through the users list, moving the entries into the dsnusers list. */
- for(tmp = list_getstart(&users); tmp != NULL; tmp = tmp->nextnode)
- {
- deliver_to_user_t dsnuser;
-
- dsnuser_init(&dsnuser);
- dsnuser.address = strdup((char *)tmp->data);
-
- list_nodeadd(&dsnusers, &dsnuser, sizeof(deliver_to_user_t));
- }
- }
-
- if (dsnuser_resolve_list(&dsnusers) == -1)
- {
- trace(TRACE_ERROR, "main(): dsnuser_resolve_list failed");
- /* Most likely a random failure... */
- exitcode = EX_TEMPFAIL;
- goto freeall;
- }
-
- /* inserting messages into the database */
- if (insert_messages(stdin,
- header, headersize, headerrfcsize,
- &mimelist, &dsnusers, &returnpath) == -1)
- {
- trace(TRACE_ERROR, "main(): insert_messages failed");
- /* Most likely a random failure... */
- exitcode = EX_TEMPFAIL;
- }
-
-freeall: /* Goto's here! */
-
- /* If there wasn't already an EX_TEMPFAIL from insert_messages(),
- * then see if one of the status flags was marked with an error. */
- if (!exitcode)
- {
- /* Get one reasonable error code for everyone. */
- switch (dsnuser_worstcase_list(&dsnusers))
- {
- case DSN_CLASS_OK:
- exitcode = EX_OK;
- break;
- case DSN_CLASS_TEMP:
- exitcode = EX_TEMPFAIL;
- break;
- case DSN_CLASS_FAIL:
- exitcode = EX_NOUSER;
- break;
- }
- }
-
- trace(TRACE_DEBUG, "main(): freeing dsnuser list");
- dsnuser_free_list(&dsnusers);
-
- trace(TRACE_DEBUG, "main(): freeing all other lists");
- list_freelist(&sysItems.start);
- list_freelist(&smtpItems.start);
- list_freelist(&mimelist.start);
- list_freelist(&returnpath.start);
- list_freelist(&users.start);
-
- trace(TRACE_DEBUG, "main(): freeing memory blocks");
- if (header != NULL)
- my_free(header);
-
- trace(TRACE_DEBUG, "main(): they're all free. we're done.");
-
- db_disconnect();
- auth_disconnect();
-
- trace(TRACE_DEBUG, "main(): exit code is [%d].", exitcode);
- return exitcode;
+ int exitcode = 0;
+ int c, c_prev = 0, usage_error = 0;
+ u64_t dummyidx = 0, dummysize = 0;
+
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ ReadConfig("SMTP", configFile, &smtpItems);
+ SetTraceLevel(&smtpItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ list_init(&users);
+ list_init(&dsnusers);
+ list_init(&mimelist);
+ list_init(&returnpath);
+
+ /* Check for commandline options.
+ * The initial '-' means that arguments which are not associated
+ * with an immediately preceding option are return with option
+ * value '1'. We will use this to allow for multiple values to
+ * follow after each of the supported options. */
+ while ((c = getopt(argc, argv, "-n::m:u:d:f:")) != EOF) {
+ /* Received an n-th value following the last option,
+ * so recall the last known option to be used in the switch. */
+ if (c == '1')
+ c = c_prev;
+ c_prev = c;
+ /* Do something with this option. */
+ switch (c) {
+ case 'n':
+ trace(TRACE_INFO, "main(): using NORMAL_DELIVERY");
+
+ if (optarg) {
+ if (deliver_to_header) {
+ printf
+ ("Only one header field may be specified.\n");
+ usage_error = 1;
+ } else
+ deliver_to_header = optarg;
+ } else
+ deliver_to_header = "deliver-to";
+
+ break;
+ case 'm':
+ trace(TRACE_INFO,
+ "main(): using SPECIAL_DELIVERY to mailbox");
+
+ if (deliver_to_mailbox) {
+ printf
+ ("Only one header field may be specified.\n");
+ usage_error = 1;
+ } else
+ deliver_to_mailbox = optarg;
+
+ break;
+ case 'f':
+ trace(TRACE_INFO,
+ "main(): using RETURN_PATH for bounces");
+
+ /* Add argument onto the returnpath list. */
+ if (list_nodeadd
+ (&returnpath, optarg,
+ strlen(optarg) + 1) == 0) {
+ trace(TRACE_ERROR,
+ "main(): list_nodeadd reports out of memory"
+ " while adding to returnpath");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ break;
+ case 'u':
+ trace(TRACE_INFO,
+ "main(): using SPECIAL_DELIVERY to usernames");
+
+ dsnuser_init(&dsnuser);
+ dsnuser.address = strdup(optarg);
+
+ /* Add argument onto the users list. */
+ if (list_nodeadd
+ (&dsnusers, &dsnuser,
+ sizeof(deliver_to_user_t)) == 0) {
+ trace(TRACE_ERROR,
+ "main(): list_nodeadd reports out of memory"
+ " while adding usernames");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ break;
+ case 'd':
+ trace(TRACE_INFO,
+ "main(): using SPECIAL_DELIVERY to email addresses");
+
+ dsnuser_init(&dsnuser);
+ dsnuser.address = strdup(optarg);
+
+ /* Add argument onto the users list. */
+ if (list_nodeadd
+ (&dsnusers, &dsnuser,
+ sizeof(deliver_to_user_t)) == 0) {
+ trace(TRACE_ERROR,
+ "main(): list_nodeadd reports out of memory"
+ " while adding email addresses");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ break;
+ default:
+ usage_error = 1;
+ break;
+ }
+
+ /* At the end of each round of options, check
+ * to see if there were any errors worth stopping for. */
+ if (usage_error) {
+ print_usage(argv[0]);
+ trace(TRACE_DEBUG,
+ "main(): usage error; setting EX_USAGE and aborting");
+ exitcode = EX_USAGE;
+ goto freeall;
+ }
+ }
+
+ /* ...or if there weren't any command line arguments at all. */
+ if (argc < 2) {
+ print_usage(argv[0]);
+ trace(TRACE_DEBUG,
+ "main(): no arguments; setting EX_USAGE and aborting");
+ exitcode = EX_USAGE;
+ goto freeall;
+ }
+
+ if (db_connect() != 0) {
+ trace(TRACE_ERROR, "main(): database connection failed");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ if (auth_connect() != 0) {
+ trace(TRACE_ERROR,
+ "main(): authentication connection failed");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ /* first we need to read the header */
+ if (!read_header(stdin, &headerrfcsize, &headersize, &header)) {
+ trace(TRACE_ERROR,
+ "main(): read_header failed to read a header");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ if (headersize > READ_BLOCK_SIZE) {
+ trace(TRACE_ERROR,
+ "%s,%s: failed to read header because header is "
+ "too big (bigger than READ_BLOCK_SIZE (%llu))",
+ __FILE__, __FUNCTION__, (u64_t) READ_BLOCK_SIZE);
+ exitcode = EX_DATAERR;
+ goto freeall;
+ }
+
+ /* parse the list and scan for field and content */
+ if (mime_readheader(header, &dummyidx, &mimelist, &dummysize) < 0) {
+ trace(TRACE_ERROR,
+ "main(): mime_readheader failed to read a header list");
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ /* parse returnpath from header */
+ if (returnpath.total_nodes == 0)
+ mail_adr_list("Return-Path", &returnpath, &mimelist);
+ if (returnpath.total_nodes == 0)
+ mail_adr_list("From", &returnpath, &mimelist);
+ if (returnpath.total_nodes == 0)
+ trace(TRACE_DEBUG, "main(): no return path found.");
+
+ /* If the NORMAL delivery mode has been selected... */
+ if (deliver_to_header != NULL) {
+ /* parse for destination addresses */
+ trace(TRACE_DEBUG, "main(): scanning for [%s]",
+ deliver_to_header);
+ if (mail_adr_list(deliver_to_header, &users, &mimelist) !=
+ 0) {
+ trace(TRACE_STOP,
+ "main(): scanner found no email addresses (scanned for %s)",
+ deliver_to_header);
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ /* Loop through the users list, moving the entries into the dsnusers list. */
+ for (tmp = list_getstart(&users); tmp != NULL;
+ tmp = tmp->nextnode) {
+ deliver_to_user_t dsnuser;
+
+ dsnuser_init(&dsnuser);
+ dsnuser.address = strdup((char *) tmp->data);
+
+ list_nodeadd(&dsnusers, &dsnuser,
+ sizeof(deliver_to_user_t));
+ }
+ }
+
+ if (dsnuser_resolve_list(&dsnusers) == -1) {
+ trace(TRACE_ERROR, "main(): dsnuser_resolve_list failed");
+ /* Most likely a random failure... */
+ exitcode = EX_TEMPFAIL;
+ goto freeall;
+ }
+
+ /* inserting messages into the database */
+ if (insert_messages(stdin,
+ header, headersize, headerrfcsize,
+ &mimelist, &dsnusers, &returnpath) == -1) {
+ trace(TRACE_ERROR, "main(): insert_messages failed");
+ /* Most likely a random failure... */
+ exitcode = EX_TEMPFAIL;
+ }
+
+ freeall: /* Goto's here! */
+
+ /* If there wasn't already an EX_TEMPFAIL from insert_messages(),
+ * then see if one of the status flags was marked with an error. */
+ if (!exitcode) {
+ /* Get one reasonable error code for everyone. */
+ switch (dsnuser_worstcase_list(&dsnusers)) {
+ case DSN_CLASS_OK:
+ exitcode = EX_OK;
+ break;
+ case DSN_CLASS_TEMP:
+ exitcode = EX_TEMPFAIL;
+ break;
+ case DSN_CLASS_FAIL:
+ exitcode = EX_NOUSER;
+ break;
+ }
+ }
+
+ trace(TRACE_DEBUG, "main(): freeing dsnuser list");
+ dsnuser_free_list(&dsnusers);
+
+ trace(TRACE_DEBUG, "main(): freeing all other lists");
+ list_freelist(&sysItems.start);
+ list_freelist(&smtpItems.start);
+ list_freelist(&mimelist.start);
+ list_freelist(&returnpath.start);
+ list_freelist(&users.start);
+
+ trace(TRACE_DEBUG, "main(): freeing memory blocks");
+ if (header != NULL)
+ my_free(header);
+
+ trace(TRACE_DEBUG, "main(): they're all free. we're done.");
+
+ db_disconnect();
+ auth_disconnect();
+
+ trace(TRACE_DEBUG, "main(): exit code is [%d].", exitcode);
+ return exitcode;
}
-
diff --git a/maintenance.c b/maintenance.c
index 7dea9168..a2cdbf07 100644
--- a/maintenance.c
+++ b/maintenance.c
@@ -53,441 +53,453 @@ static void find_time(char *timestr, const char *timespec);
int main(int argc, char *argv[])
{
- int should_fix = 0, check_integrity = 0, check_iplog = 0;
- int check_null_messages=0;
- int show_help=0, purge_deleted=0, set_deleted=0;
- int vacuum_db = 0;
- int do_nothing=1;
- struct list sysItems;
-
- time_t start,stop;
-
- char timespec[LEN],timestr[LEN];
- int opt;
- struct list lostlist;
- struct element *el;
- u64_t id;
-
- u64_t deleted_messages;
- u64_t messages_set_to_delete;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetTraceLevel(&sysItems);
- GetDBParams(&_db_params, &sysItems);
-
- setvbuf(stdout,0,_IONBF,0);
- printf ("*** dbmail-maintenance ***\n");
-
- /* get options */
- opterr = 0; /* suppress error message from getopt() */
- while ((opt = getopt(argc, argv, "cfvinl:phd")) != -1)
- {
- switch (opt)
- {
- case 'c':
- vacuum_db = 1;
- do_nothing = 0;
- break;
+ int should_fix = 0, check_integrity = 0, check_iplog = 0;
+ int check_null_messages = 0;
+ int show_help = 0, purge_deleted = 0, set_deleted = 0;
+ int vacuum_db = 0;
+ int do_nothing = 1;
+ struct list sysItems;
+
+ time_t start, stop;
+
+ char timespec[LEN], timestr[LEN];
+ int opt;
+ struct list lostlist;
+ struct element *el;
+ u64_t id;
+
+ u64_t deleted_messages;
+ u64_t messages_set_to_delete;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetTraceLevel(&sysItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ setvbuf(stdout, 0, _IONBF, 0);
+ printf("*** dbmail-maintenance ***\n");
+
+ /* get options */
+ opterr = 0; /* suppress error message from getopt() */
+ while ((opt = getopt(argc, argv, "cfvinl:phd")) != -1) {
+ switch (opt) {
+ case 'c':
+ vacuum_db = 1;
+ do_nothing = 0;
+ break;
+
+ case 'h':
+ show_help = 1;
+ do_nothing = 0;
+ break;
+
+ case 'p':
+ purge_deleted = 1;
+ do_nothing = 0;
+ break;
+
+ case 'd':
+ set_deleted = 1;
+ do_nothing = 0;
+ break;
+
+ case 'f':
+ check_integrity = 1;
+ should_fix = 1;
+ do_nothing = 0;
+ break;
+
+ case 'i':
+ check_integrity = 1;
+ do_nothing = 0;
+ break;
+
+ case 'n':
+ check_null_messages = 1;
+ do_nothing = 0;
+ break;
+
+ case 'v':
+ printf
+ ("\n*** DBMAIL: dbmail-maintenance version $Revision$ %s\n",
+ COPYRIGHT);
+ return 0;
+
+
+ case 'l':
+ check_iplog = 1;
+ do_nothing = 0;
+ if (optarg)
+ strncpy(timespec, optarg, LEN);
+ else
+ timespec[0] = 0;
+
+ timespec[LEN] = 0;
+ break;
+
+ default:
+ /*printf("unrecognized option [%c], continuing...\n",optopt); */
+ break;
+ }
+ }
- case 'h':
- show_help = 1;
- do_nothing = 0;
- break;
-
- case 'p':
- purge_deleted = 1;
- do_nothing = 0;
- break;
-
- case 'd':
- set_deleted = 1;
- do_nothing = 0;
- break;
-
- case 'f':
- check_integrity = 1;
- should_fix = 1;
- do_nothing = 0;
- break;
-
- case 'i':
- check_integrity = 1;
- do_nothing = 0;
- break;
-
- case 'n':
- check_null_messages = 1;
- do_nothing = 0;
- break;
-
- case 'v':
- printf ("\n*** DBMAIL: dbmail-maintenance version $Revision$ %s\n",COPYRIGHT);
+ if (show_help) {
+ printf("\ndbmail maintenance utility\n\n");
+ printf
+ ("Performs maintenance tasks on the dbmail-databases\n");
+ printf("Use: dbmail-maintenance -[cfiphdl]\n");
+ printf("See the man page for more info\n\n");
return 0;
+ }
- case 'l':
- check_iplog = 1;
- do_nothing = 0;
- if (optarg)
- strncpy(timespec, optarg, LEN);
- else
- timespec[0] = 0;
-
- timespec[LEN] = 0;
- break;
+ if (do_nothing) {
+ printf("Ok. Nothing requested, nothing done. "
+ "Try adding a command-line option to perform maintenance.\n");
+ return 0;
+ }
- default:
- /*printf("unrecognized option [%c], continuing...\n",optopt);*/
- break;
+ printf("Opening connection to database... ");
+ if (db_connect() != 0) {
+ printf("Failed. An error occured. Please check log.\n");
+ return -1;
}
- }
-
- if (show_help)
- {
- printf("\ndbmail maintenance utility\n\n");
- printf("Performs maintenance tasks on the dbmail-databases\n");
- printf("Use: dbmail-maintenance -[cfiphdl]\n");
- printf("See the man page for more info\n\n");
- return 0;
- }
-
-
- if (do_nothing)
- {
- printf("Ok. Nothing requested, nothing done. "
- "Try adding a command-line option to perform maintenance.\n");
- return 0;
- }
-
- printf ("Opening connection to database... ");
- if (db_connect() != 0)
- {
- printf ("Failed. An error occured. Please check log.\n");
- return -1;
- }
-
- printf ("Opening connection to authentication... ");
- if (auth_connect() != 0)
- {
- printf ("Failed. An error occured. Please check log.\n");
- return -1;
- }
-
- printf ("Ok. Connected\n");
-
- if (purge_deleted)
- {
- printf ("Deleting messages with DELETE status... ");
- if (db_deleted_purge(&deleted_messages) < 0) {
- printf ("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
- }
- printf ("Ok. [%llu] messages deleted.\n",deleted_messages);
- }
-
-
- if (set_deleted)
- {
- printf ("Setting DELETE status for deleted messages... ");
- if (db_set_deleted(&messages_set_to_delete) == -1) {
- printf ("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
- }
- printf ("Ok. [%llu] messages set for deletion.\n",messages_set_to_delete);
- printf("Re-calculating used quota for all users... ");
- if (db_calculate_quotum_all() < 0) {
- printf("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
- }
- printf("Ok. Used quota updated for all users.\n");
- }
-
- if (check_null_messages)
- {
- printf ("Now checking DBMAIL for NULL messages.. ");
- time(&start);
-
- if (db_icheck_null_messages(&lostlist) < 0)
- {
- printf ("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
+
+ printf("Opening connection to authentication... ");
+ if (auth_connect() != 0) {
+ printf("Failed. An error occured. Please check log.\n");
+ return -1;
}
-
- if (lostlist.total_nodes > 0)
- {
- printf ("Ok. Found [%ld] null messages:\n", lostlist.total_nodes);
-
- el = lostlist.start;
- while (el)
- {
- id = *((u64_t*)el->data);
- if (db_set_message_status(id, 6) < 0)
- printf("Warning: could not set message status #%llu. Check log.\n", id);
- else
- printf("%llu (status update to 6)\n", id);
-
- el = el->nextnode;
- }
-
- list_freelist(&lostlist.start);
-
- printf ("\n");
+
+ printf("Ok. Connected\n");
+
+ if (purge_deleted) {
+ printf("Deleting messages with DELETE status... ");
+ if (db_deleted_purge(&deleted_messages) < 0) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+ printf("Ok. [%llu] messages deleted.\n", deleted_messages);
}
- else
- printf ("Ok. Found 0 NULL messages.\n");
-
- time(&stop);
- printf("--- checking NULL messages took %g seconds\n", difftime(stop, start));
- printf("Now checking DBMAIL for NULL physmessages..");
- time(&start);
- if (db_icheck_null_physmessages(&lostlist) < 0) {
- printf("Failed, an error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
- }
-
- if (lostlist.total_nodes > 0) {
- printf("found %ld physmessages without messageblocks\n",
- lostlist.total_nodes);
- el = lostlist.start;
- while(el) {
- id = *((u64_t*)el->data);
- if (db_delete_physmessage(id) < 0)
- printf("Warning: couldn't delete physmessage");
- else
- printf("deleted physmessage [%llu]\n", id);
- el = el->nextnode;
- }
- list_freelist(&lostlist.start);
- printf("\n");
- } else
- printf("found 0 physmessages without messageblks");
-
- time(&stop);
- fprintf(stderr, "--- checking NULL physmessages took %g seconds\n",
- difftime(stop,start));
- }
-
- if (check_integrity)
- {
- printf ("Now checking DBMAIL messageblocks integrity.. ");
- time(&start);
-
- /* this is what we do:
- * First we're checking for loose messageblocks
- * Secondly we're chekcing for loose messages
- * Third we're checking for loose mailboxes
- */
-
- /* first part */
- if (db_icheck_messageblks(&lostlist) < 0)
- {
- printf ("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
+
+
+ if (set_deleted) {
+ printf("Setting DELETE status for deleted messages... ");
+ if (db_set_deleted(&messages_set_to_delete) == -1) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+ printf("Ok. [%llu] messages set for deletion.\n",
+ messages_set_to_delete);
+ printf("Re-calculating used quota for all users... ");
+ if (db_calculate_quotum_all() < 0) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+ printf("Ok. Used quota updated for all users.\n");
}
-
- if (lostlist.total_nodes > 0)
- {
- printf ("Ok. Found [%ld] unconnected messageblks:\n", lostlist.total_nodes);
-
- el = lostlist.start;
- while (el)
- {
- id = *((u64_t*)el->data);
- if (should_fix == 0)
- printf("%llu ", id);
- else
- {
- if (db_delete_messageblk(id) < 0)
- printf("Warning: could not delete messageblock #%llu. Check log.\n", id);
- else
- printf("%llu (removed from dbase)\n",id);
+
+ if (check_null_messages) {
+ printf("Now checking DBMAIL for NULL messages.. ");
+ time(&start);
+
+ if (db_icheck_null_messages(&lostlist) < 0) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
}
- el = el->nextnode;
- }
-
- list_freelist(&lostlist.start);
-
- printf ("\n");
- if (should_fix == 0)
- {
- printf("Try running dbmail-maintenance with the '-f' option "
- "in order to fix these problems\n\n");
- }
- }
- else
- printf ("Ok. Found 0 unconnected messageblks.\n");
-
-
- time(&stop);
- printf("--- checking block integrity took %g seconds\n",
- difftime(stop, start));
- fprintf(stderr, "--- checking block integrity took %g seconds\n",
- difftime(stop,start));
-
- /* second part */
- start = stop;
- printf ("Now checking DBMAIL message integrity.. ");
-
- if (db_icheck_messages(&lostlist) < 0)
- {
- printf ("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
+ if (lostlist.total_nodes > 0) {
+ printf("Ok. Found [%ld] null messages:\n",
+ lostlist.total_nodes);
+
+ el = lostlist.start;
+ while (el) {
+ id = *((u64_t *) el->data);
+ if (db_set_message_status(id, 6) < 0)
+ printf
+ ("Warning: could not set message status #%llu. Check log.\n",
+ id);
+ else
+ printf
+ ("%llu (status update to 6)\n",
+ id);
+
+ el = el->nextnode;
+ }
+
+ list_freelist(&lostlist.start);
+
+ printf("\n");
+ } else
+ printf("Ok. Found 0 NULL messages.\n");
+
+ time(&stop);
+ printf("--- checking NULL messages took %g seconds\n",
+ difftime(stop, start));
+ printf("Now checking DBMAIL for NULL physmessages..");
+ time(&start);
+ if (db_icheck_null_physmessages(&lostlist) < 0) {
+ printf
+ ("Failed, an error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+
+ if (lostlist.total_nodes > 0) {
+ printf
+ ("found %ld physmessages without messageblocks\n",
+ lostlist.total_nodes);
+ el = lostlist.start;
+ while (el) {
+ id = *((u64_t *) el->data);
+ if (db_delete_physmessage(id) < 0)
+ printf
+ ("Warning: couldn't delete physmessage");
+ else
+ printf
+ ("deleted physmessage [%llu]\n",
+ id);
+ el = el->nextnode;
+ }
+ list_freelist(&lostlist.start);
+ printf("\n");
+ } else
+ printf("found 0 physmessages without messageblks");
+
+ time(&stop);
+ fprintf(stderr,
+ "--- checking NULL physmessages took %g seconds\n",
+ difftime(stop, start));
}
-
- if (lostlist.total_nodes > 0)
- {
- printf ("Ok. Found [%ld] unconnected messages:\n", lostlist.total_nodes);
-
- el = lostlist.start;
- while (el)
- {
- id = *((u64_t*)el->data);
-
- if (should_fix == 0)
- printf("%llu ", id);
- else
- {
- if (db_delete_message(id) < 0)
- printf("Warning: could not delete message #%llu. Check log.\n", id);
- else
- printf("%llu (removed from dbase)\n", id);
+
+ if (check_integrity) {
+ printf("Now checking DBMAIL messageblocks integrity.. ");
+ time(&start);
+
+ /* this is what we do:
+ * First we're checking for loose messageblocks
+ * Secondly we're chekcing for loose messages
+ * Third we're checking for loose mailboxes
+ */
+
+ /* first part */
+ if (db_icheck_messageblks(&lostlist) < 0) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+
+ if (lostlist.total_nodes > 0) {
+ printf
+ ("Ok. Found [%ld] unconnected messageblks:\n",
+ lostlist.total_nodes);
+
+ el = lostlist.start;
+ while (el) {
+ id = *((u64_t *) el->data);
+ if (should_fix == 0)
+ printf("%llu ", id);
+ else {
+ if (db_delete_messageblk(id) < 0)
+ printf
+ ("Warning: could not delete messageblock #%llu. Check log.\n",
+ id);
+ else
+ printf
+ ("%llu (removed from dbase)\n",
+ id);
+ }
+
+ el = el->nextnode;
+ }
+
+ list_freelist(&lostlist.start);
+
+ printf("\n");
+ if (should_fix == 0) {
+ printf
+ ("Try running dbmail-maintenance with the '-f' option "
+ "in order to fix these problems\n\n");
+ }
+ } else
+ printf("Ok. Found 0 unconnected messageblks.\n");
+
+
+ time(&stop);
+ printf("--- checking block integrity took %g seconds\n",
+ difftime(stop, start));
+ fprintf(stderr,
+ "--- checking block integrity took %g seconds\n",
+ difftime(stop, start));
+
+ /* second part */
+ start = stop;
+ printf("Now checking DBMAIL message integrity.. ");
+
+ if (db_icheck_messages(&lostlist) < 0) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
}
- el = el->nextnode;
- }
-
- printf ("\n");
- if (should_fix == 0)
- {
- printf("Try running dbmail-maintenance with the '-f' option "
- "in order to fix these problems\n\n");
- }
- list_freelist(&lostlist.start);
+ if (lostlist.total_nodes > 0) {
+ printf("Ok. Found [%ld] unconnected messages:\n",
+ lostlist.total_nodes);
+
+ el = lostlist.start;
+ while (el) {
+ id = *((u64_t *) el->data);
+
+ if (should_fix == 0)
+ printf("%llu ", id);
+ else {
+ if (db_delete_message(id) < 0)
+ printf
+ ("Warning: could not delete message #%llu. Check log.\n",
+ id);
+ else
+ printf
+ ("%llu (removed from dbase)\n",
+ id);
+ }
+
+ el = el->nextnode;
+ }
+
+ printf("\n");
+ if (should_fix == 0) {
+ printf
+ ("Try running dbmail-maintenance with the '-f' option "
+ "in order to fix these problems\n\n");
+ }
+ list_freelist(&lostlist.start);
+
+ } else
+ printf("Ok. Found 0 unconnected messages.\n");
+
+ time(&stop);
+ printf("--- checking message integrity took %g seconds\n",
+ difftime(stop, start));
+ fprintf(stderr,
+ "--- checking message integrity took %g seconds\n",
+ difftime(stop, start));
+
+
+ /* third part */
+ printf("Now checking DBMAIL mailbox integrity.. ");
+ start = stop;
+
+ if (db_icheck_mailboxes(&lostlist) < 0) {
+ printf
+ ("Failed. An error occured. Please check log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+ if (lostlist.total_nodes) {
+ printf("Ok. Found [%ld] unconnected mailboxes:\n",
+ lostlist.total_nodes);
+
+ el = lostlist.start;
+ while (el) {
+ id = *((u64_t *) el->data);
+
+ if (should_fix == 0)
+ printf("%llu ", id);
+ else {
+ if (db_delete_mailbox(id, 0, 0) <
+ 0)
+ printf
+ ("Warning: could not delete mailbox #%llu. Check log.\n",
+ id);
+ else
+ printf
+ ("%llu (removed from dbase)\n",
+ id);
+ }
+
+ el = el->nextnode;
+ }
+
+ printf("\n");
+ if (should_fix == 0) {
+ printf
+ ("Try running dbmail-maintenance with the '-f' option "
+ "in order to fix these problems\n\n");
+ }
+
+ list_freelist(&lostlist.start);
+ } else
+ printf("Ok. Found 0 unconnected mailboxes.\n");
+
+ time(&stop);
+ printf("--- checking mailbox integrity took %g seconds\n",
+ difftime(stop, start));
+ fprintf(stderr,
+ "--- checking mailbox integrity took %g seconds\n",
+ difftime(stop, start));
}
- else
- printf ("Ok. Found 0 unconnected messages.\n");
-
- time(&stop);
- printf("--- checking message integrity took %g seconds\n",
- difftime(stop, start));
- fprintf(stderr, "--- checking message integrity took %g seconds\n",
- difftime(stop, start));
-
-
- /* third part */
- printf ("Now checking DBMAIL mailbox integrity.. ");
- start = stop;
-
- if (db_icheck_mailboxes(&lostlist) < 0)
- {
- printf ("Failed. An error occured. Please check log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
- }
-
- if (lostlist.total_nodes)
- {
- printf ("Ok. Found [%ld] unconnected mailboxes:\n", lostlist.total_nodes);
-
- el = lostlist.start;
- while (el)
- {
- id = *((u64_t*)el->data);
-
- if (should_fix == 0)
- printf("%llu ", id);
- else
- {
- if (db_delete_mailbox(id, 0, 0) < 0)
- printf("Warning: could not delete mailbox #%llu. Check log.\n", id);
- else
- printf("%llu (removed from dbase)\n",id);
+
+ if (check_iplog) {
+ find_time(timestr, timespec);
+ printf("Cleaning up IP log... ");
+
+ if (timestr[0] == 0) {
+ printf("Failed. Invalid argument [%s] specified\n",
+ timespec);
+ db_disconnect();
+ auth_disconnect();
+ return -1;
}
- el = el->nextnode;
- }
-
- printf ("\n");
- if (should_fix == 0)
- {
- printf("Try running dbmail-maintenance with the '-f' option "
- "in order to fix these problems\n\n");
- }
-
- list_freelist(&lostlist.start);
- }
- else
- printf ("Ok. Found 0 unconnected mailboxes.\n");
-
- time(&stop);
- printf("--- checking mailbox integrity took %g seconds\n",
- difftime(stop, start));
- fprintf(stderr, "--- checking mailbox integrity took %g seconds\n",
- difftime(stop, start));
- }
-
- if (check_iplog)
- {
- find_time(timestr, timespec);
- printf("Cleaning up IP log... ");
-
- if (timestr[0] == 0)
- {
- printf("Failed. Invalid argument [%s] specified\n",timespec);
- db_disconnect();
- auth_disconnect();
- return -1;
- }
+ if (db_cleanup_iplog(timestr) < 0) {
+ printf("Failed. Please check the log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
- if (db_cleanup_iplog(timestr) < 0)
- {
- printf("Failed. Please check the log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
+ printf("Ok. All entries before [%s] have been removed.\n",
+ timestr);
}
-
- printf("Ok. All entries before [%s] have been removed.\n",timestr);
- }
-
- if (vacuum_db)
- {
- printf("Cleaning up database structure... "); fflush(stdout);
- if (db_cleanup() < 0)
- {
- printf("Failed. Please check the log.\n");
- db_disconnect();
- auth_disconnect();
- return -1;
+
+ if (vacuum_db) {
+ printf("Cleaning up database structure... ");
+ fflush(stdout);
+ if (db_cleanup() < 0) {
+ printf("Failed. Please check the log.\n");
+ db_disconnect();
+ auth_disconnect();
+ return -1;
+ }
+
+ printf("Ok. Database cleaned up.\n");
}
-
- printf("Ok. Database cleaned up.\n");
- }
-
- printf ("Maintenance done.\n\n");
-
- db_disconnect();
- auth_disconnect();
- return 0;
+
+ printf("Maintenance done.\n\n");
+
+ db_disconnect();
+ auth_disconnect();
+ return 0;
}
/*
@@ -500,79 +512,71 @@ int main(int argc, char *argv[])
*/
void find_time(char *timestr, const char *timespec)
{
- time_t td;
- struct tm tm;
- int min=-1,hour=-1;
- long tmp;
- char *end;
-
- time(&td); /* get time */
-
- timestr[0] = 0;
- if (!timespec)
- return;
-
- /* find first num */
- tmp = strtol(timespec, &end, 10);
- if (!end)
- return;
-
- if (tmp < 0)
- return;
-
- switch (*end)
- {
- case 'h':
- case 'H':
- hour = tmp;
- break;
-
- case 'm':
- case 'M':
- hour = 0;
- min = tmp;
- if (end[1]) /* should end here */
- return;
+ time_t td;
+ struct tm tm;
+ int min = -1, hour = -1;
+ long tmp;
+ char *end;
+
+ time(&td); /* get time */
- break;
+ timestr[0] = 0;
+ if (!timespec)
+ return;
- default:
- return;
- }
+ /* find first num */
+ tmp = strtol(timespec, &end, 10);
+ if (!end)
+ return;
+ if (tmp < 0)
+ return;
- /* find second num */
- if (timespec[end-timespec+1])
- {
- tmp = strtol(&timespec[end-timespec+1], &end, 10);
- if (end)
- {
- if ((*end != 'm' && *end != 'M') || end[1])
- return;
+ switch (*end) {
+ case 'h':
+ case 'H':
+ hour = tmp;
+ break;
- if (tmp < 0)
- return;
+ case 'm':
+ case 'M':
+ hour = 0;
+ min = tmp;
+ if (end[1]) /* should end here */
+ return;
- if (min >= 0) /* already specified minutes */
- return;
+ break;
- min = tmp;
+ default:
+ return;
}
- }
- if (min < 0)
- min = 0;
- /* adjust time */
- td -= (hour * 3600L + min * 60L);
-
- tm = *localtime(&td); /* get components */
- strftime(timestr, LEN, "%Y-%m-%d %H:%M:%S", &tm);
+ /* find second num */
+ if (timespec[end - timespec + 1]) {
+ tmp = strtol(&timespec[end - timespec + 1], &end, 10);
+ if (end) {
+ if ((*end != 'm' && *end != 'M') || end[1])
+ return;
- return;
-}
+ if (tmp < 0)
+ return;
+ if (min >= 0) /* already specified minutes */
+ return;
+ min = tmp;
+ }
+ }
+
+ if (min < 0)
+ min = 0;
+ /* adjust time */
+ td -= (hour * 3600L + min * 60L);
+ tm = *localtime(&td); /* get components */
+ strftime(timestr, LEN, "%Y-%m-%d %H:%M:%S", &tm);
+ return;
+}
diff --git a/maintenance.h b/maintenance.h
index fdeb9dee..ba2c76e5 100644
--- a/maintenance.h
+++ b/maintenance.h
@@ -31,4 +31,3 @@
#define PNAME "dbmail/maintenance"
#endif
-
diff --git a/mbox2dbmail.c b/mbox2dbmail.c
index 61ccd59e..89659236 100644
--- a/mbox2dbmail.c
+++ b/mbox2dbmail.c
@@ -42,87 +42,73 @@ const char *mbox_delimiter_pattern = "^From .*@.* ";
int main(int argc, char *argv[])
{
- regex_t preg;
- int result;
- int in_msg;
- char line[MAX_LINESIZE],cmdstr[MAX_LINESIZE];
- FILE *smtp = 0;
- unsigned long long uid;
-
- if ((result = regcomp(&preg, mbox_delimiter_pattern, REG_NOSUB)) != 0)
- {
- fprintf(stderr,"Regex compilation failed.\n");
- return 1;
- }
-
- if (argc >= 2)
- {
- /* user ID specified as an argument */
- snprintf(cmdstr, MAX_LINESIZE, "%s %s", SMTP_INJECTOR, argv[1]);
- }
- else
- {
- /* first line should be user ID */
- if (fgets(line, MAX_LINESIZE, stdin) == 0)
- {
- fprintf(stderr, "Error reading from stdin\n");
- return -1;
+ regex_t preg;
+ int result;
+ int in_msg;
+ char line[MAX_LINESIZE], cmdstr[MAX_LINESIZE];
+ FILE *smtp = 0;
+ unsigned long long uid;
+
+ if ((result =
+ regcomp(&preg, mbox_delimiter_pattern, REG_NOSUB)) != 0) {
+ fprintf(stderr, "Regex compilation failed.\n");
+ return 1;
}
-
- uid = strtoull(line, NULL, 10);
- snprintf(cmdstr, MAX_LINESIZE, "%s %llu", SMTP_INJECTOR, uid);
- }
- in_msg = 0;
-
- while (!feof(stdin) && !ferror(stdin))
- {
- if (fgets(line, MAX_LINESIZE, stdin) == 0)
- break;
-
- /* check if this is a mbox delimiter */
- if (regexec(&preg, line, 0, NULL, 0) == 0)
- {
- if (!in_msg)
- {
- /* ok start of a new msg */
- /* this code will only be reached if it concerns the first msg */
- if ((smtp = popen(cmdstr, "w")) == 0)
- {
- perror("Error opening pipe");
- break;
- }
-
- in_msg = 1;
- }
- else
- {
- /* close current pipe */
- pclose(smtp);
-
- /* open new pipe */
- if ((smtp = popen(cmdstr, "w")) == 0)
- {
- perror("Error opening pipe");
- break;
+
+ if (argc >= 2) {
+ /* user ID specified as an argument */
+ snprintf(cmdstr, MAX_LINESIZE, "%s %s", SMTP_INJECTOR,
+ argv[1]);
+ } else {
+ /* first line should be user ID */
+ if (fgets(line, MAX_LINESIZE, stdin) == 0) {
+ fprintf(stderr, "Error reading from stdin\n");
+ return -1;
}
- }
+
+ uid = strtoull(line, NULL, 10);
+ snprintf(cmdstr, MAX_LINESIZE, "%s %llu", SMTP_INJECTOR,
+ uid);
}
- else
- {
- /* write data to pipe */
- if (smtp)
- fputs(line, smtp);
- else
- {
- fprintf(stderr,"Tried to write to an unopened pipe!\n");
- return 1;
- }
+ in_msg = 0;
+
+ while (!feof(stdin) && !ferror(stdin)) {
+ if (fgets(line, MAX_LINESIZE, stdin) == 0)
+ break;
+
+ /* check if this is a mbox delimiter */
+ if (regexec(&preg, line, 0, NULL, 0) == 0) {
+ if (!in_msg) {
+ /* ok start of a new msg */
+ /* this code will only be reached if it concerns the first msg */
+ if ((smtp = popen(cmdstr, "w")) == 0) {
+ perror("Error opening pipe");
+ break;
+ }
+
+ in_msg = 1;
+ } else {
+ /* close current pipe */
+ pclose(smtp);
+
+ /* open new pipe */
+ if ((smtp = popen(cmdstr, "w")) == 0) {
+ perror("Error opening pipe");
+ break;
+ }
+ }
+ } else {
+ /* write data to pipe */
+ if (smtp)
+ fputs(line, smtp);
+ else {
+ fprintf(stderr,
+ "Tried to write to an unopened pipe!\n");
+ return 1;
+ }
+ }
}
- }
- return 0;
+ return 0;
}
-
-
-
diff --git a/md5.c b/md5.c
index 7b45de55..b77899b5 100644
--- a/md5.c
+++ b/md5.c
@@ -62,13 +62,13 @@ void byteReverse(unsigned char *buf, unsigned longs);
*/
void byteReverse(unsigned char *buf, unsigned longs)
{
- uint32 t;
- do {
- t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
- ((unsigned) buf[1] << 8 | buf[0]);
- *(uint32 *) buf = t;
- buf += 4;
- } while (--longs);
+ uint32 t;
+ do {
+ t = (uint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(uint32 *) buf = t;
+ buf += 4;
+ } while (--longs);
}
#endif
@@ -77,112 +77,111 @@ void byteReverse(unsigned char *buf, unsigned longs)
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
-void
-gdm_md5_init (struct GdmMD5Context *ctx)
+void gdm_md5_init(struct GdmMD5Context *ctx)
{
- ctx->buf[0] = 0x67452301;
- ctx->buf[1] = 0xefcdab89;
- ctx->buf[2] = 0x98badcfe;
- ctx->buf[3] = 0x10325476;
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
- ctx->bits[0] = 0;
- ctx->bits[1] = 0;
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
-void
-gdm_md5_update (struct GdmMD5Context *ctx, unsigned char const *buf, unsigned len)
+void
+gdm_md5_update(struct GdmMD5Context *ctx, unsigned char const *buf,
+ unsigned len)
{
- uint32 t;
+ uint32 t;
- /* Update bitcount */
+ /* Update bitcount */
- t = ctx->bits[0];
- if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
- ctx->bits[1]++; /* Carry from low to high */
- ctx->bits[1] += len >> 29;
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((uint32) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
- t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
- /* Handle any leading odd-sized chunks */
+ /* Handle any leading odd-sized chunks */
- if (t) {
- unsigned char *p = (unsigned char *) ctx->in + t;
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
- t = 64 - t;
- if (len < t) {
- memcpy (p, buf, len);
- return;
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ gdm_md5_transform(ctx->buf, (uint32 *) ctx->in);
+ buf += t;
+ len -= t;
}
- memcpy (p, buf, t);
- byteReverse (ctx->in, 16);
- gdm_md5_transform (ctx->buf, (uint32 *) ctx->in);
- buf += t;
- len -= t;
- }
-
- /* Process data in 64-byte chunks */
-
- while (len >= 64) {
- memcpy (ctx->in, buf, 64);
- byteReverse (ctx->in, 16);
- gdm_md5_transform (ctx->buf, (uint32 *) ctx->in);
- buf += 64;
- len -= 64;
- }
-
- /* Handle any remaining bytes of data. */
-
- memcpy(ctx->in, buf, len);
+
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ gdm_md5_transform(ctx->buf, (uint32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
-void
-gdm_md5_final (unsigned char digest[16], struct GdmMD5Context *ctx)
+void gdm_md5_final(unsigned char digest[16], struct GdmMD5Context *ctx)
{
- unsigned count;
- unsigned char *p;
-
- /* Compute number of bytes mod 64 */
- count = (ctx->bits[0] >> 3) & 0x3F;
-
- /* Set the first char of padding to 0x80. This is safe since there is
- always at least one byte free */
- p = ctx->in + count;
- *p++ = 0x80;
-
- /* Bytes of padding needed to make 64 bytes */
- count = 64 - 1 - count;
-
- /* Pad out to 56 mod 64 */
- if (count < 8) {
- /* Two lots of padding: Pad the first block to 64 bytes */
- memset (p, 0, count);
- byteReverse (ctx->in, 16);
- gdm_md5_transform (ctx->buf, (uint32 *) ctx->in);
-
- /* Now fill the next block with 56 bytes */
- memset(ctx->in, 0, 56);
- } else {
- /* Pad block to 56 bytes */
- memset(p, 0, count - 8);
- }
- byteReverse(ctx->in, 14);
-
- /* Append length in bits and transform */
- ((uint32 *) ctx->in)[14] = ctx->bits[0];
- ((uint32 *) ctx->in)[15] = ctx->bits[1];
-
- gdm_md5_transform (ctx->buf, (uint32 *) ctx->in);
- byteReverse ((unsigned char *) ctx->buf, 4);
- memcpy (digest, ctx->buf, 16);
- memset (ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+ unsigned count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ gdm_md5_transform(ctx->buf, (uint32 *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((uint32 *) ctx->in)[14] = ctx->bits[0];
+ ((uint32 *) ctx->in)[15] = ctx->bits[1];
+
+ gdm_md5_transform(ctx->buf, (uint32 *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
}
@@ -202,89 +201,85 @@ gdm_md5_final (unsigned char digest[16], struct GdmMD5Context *ctx)
* reflect the addition of 16 longwords of new data. GdmMD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
-void
-gdm_md5_transform (uint32 buf[4], uint32 const in[16])
+void gdm_md5_transform(uint32 buf[4], uint32 const in[16])
{
- register uint32 a, b, c, d;
-
- a = buf[0];
- b = buf[1];
- c = buf[2];
- d = buf[3];
-
- gdm_md5_step(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
- gdm_md5_step(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
- gdm_md5_step(F1, c, d, a, b, in[2] + 0x242070db, 17);
- gdm_md5_step(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
- gdm_md5_step(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
- gdm_md5_step(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
- gdm_md5_step(F1, c, d, a, b, in[6] + 0xa8304613, 17);
- gdm_md5_step(F1, b, c, d, a, in[7] + 0xfd469501, 22);
- gdm_md5_step(F1, a, b, c, d, in[8] + 0x698098d8, 7);
- gdm_md5_step(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
- gdm_md5_step(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
- gdm_md5_step(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
- gdm_md5_step(F1, a, b, c, d, in[12] + 0x6b901122, 7);
- gdm_md5_step(F1, d, a, b, c, in[13] + 0xfd987193, 12);
- gdm_md5_step(F1, c, d, a, b, in[14] + 0xa679438e, 17);
- gdm_md5_step(F1, b, c, d, a, in[15] + 0x49b40821, 22);
-
- gdm_md5_step(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
- gdm_md5_step(F2, d, a, b, c, in[6] + 0xc040b340, 9);
- gdm_md5_step(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
- gdm_md5_step(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
- gdm_md5_step(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
- gdm_md5_step(F2, d, a, b, c, in[10] + 0x02441453, 9);
- gdm_md5_step(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
- gdm_md5_step(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
- gdm_md5_step(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
- gdm_md5_step(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
- gdm_md5_step(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
- gdm_md5_step(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
- gdm_md5_step(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
- gdm_md5_step(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
- gdm_md5_step(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
- gdm_md5_step(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
-
- gdm_md5_step(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
- gdm_md5_step(F3, d, a, b, c, in[8] + 0x8771f681, 11);
- gdm_md5_step(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
- gdm_md5_step(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
- gdm_md5_step(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
- gdm_md5_step(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
- gdm_md5_step(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
- gdm_md5_step(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
- gdm_md5_step(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
- gdm_md5_step(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
- gdm_md5_step(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
- gdm_md5_step(F3, b, c, d, a, in[6] + 0x04881d05, 23);
- gdm_md5_step(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
- gdm_md5_step(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
- gdm_md5_step(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
- gdm_md5_step(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
-
- gdm_md5_step(F4, a, b, c, d, in[0] + 0xf4292244, 6);
- gdm_md5_step(F4, d, a, b, c, in[7] + 0x432aff97, 10);
- gdm_md5_step(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
- gdm_md5_step(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
- gdm_md5_step(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
- gdm_md5_step(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
- gdm_md5_step(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
- gdm_md5_step(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
- gdm_md5_step(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
- gdm_md5_step(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
- gdm_md5_step(F4, c, d, a, b, in[6] + 0xa3014314, 15);
- gdm_md5_step(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
- gdm_md5_step(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
- gdm_md5_step(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
- gdm_md5_step(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
- gdm_md5_step(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
-
- buf[0] += a;
- buf[1] += b;
- buf[2] += c;
- buf[3] += d;
+ register uint32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ gdm_md5_step(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ gdm_md5_step(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ gdm_md5_step(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ gdm_md5_step(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ gdm_md5_step(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ gdm_md5_step(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ gdm_md5_step(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ gdm_md5_step(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ gdm_md5_step(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ gdm_md5_step(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ gdm_md5_step(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ gdm_md5_step(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ gdm_md5_step(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ gdm_md5_step(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ gdm_md5_step(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ gdm_md5_step(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ gdm_md5_step(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ gdm_md5_step(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ gdm_md5_step(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ gdm_md5_step(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ gdm_md5_step(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ gdm_md5_step(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ gdm_md5_step(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ gdm_md5_step(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ gdm_md5_step(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ gdm_md5_step(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ gdm_md5_step(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ gdm_md5_step(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ gdm_md5_step(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ gdm_md5_step(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ gdm_md5_step(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ gdm_md5_step(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ gdm_md5_step(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ gdm_md5_step(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ gdm_md5_step(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ gdm_md5_step(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ gdm_md5_step(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ gdm_md5_step(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ gdm_md5_step(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ gdm_md5_step(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ gdm_md5_step(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ gdm_md5_step(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ gdm_md5_step(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ gdm_md5_step(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ gdm_md5_step(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ gdm_md5_step(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ gdm_md5_step(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ gdm_md5_step(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ gdm_md5_step(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ gdm_md5_step(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ gdm_md5_step(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ gdm_md5_step(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ gdm_md5_step(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ gdm_md5_step(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ gdm_md5_step(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ gdm_md5_step(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ gdm_md5_step(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ gdm_md5_step(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ gdm_md5_step(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ gdm_md5_step(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ gdm_md5_step(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ gdm_md5_step(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ gdm_md5_step(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ gdm_md5_step(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
}
-
-
-
diff --git a/md5.h b/md5.h
index 07883c53..8847f414 100644
--- a/md5.h
+++ b/md5.h
@@ -34,15 +34,16 @@ struct GdmMD5Context {
unsigned char in[64];
};
-void gdm_md5_init (struct GdmMD5Context *context);
-void gdm_md5_update (struct GdmMD5Context *context, unsigned char const *buf,
- unsigned len);
-void gdm_md5_final (unsigned char digest[16], struct GdmMD5Context *context);
-void gdm_md5_transform (uint32 buf[4], uint32 const in[16]);
+void gdm_md5_init(struct GdmMD5Context *context);
+void gdm_md5_update(struct GdmMD5Context *context,
+ unsigned char const *buf, unsigned len);
+void gdm_md5_final(unsigned char digest[16],
+ struct GdmMD5Context *context);
+void gdm_md5_transform(uint32 buf[4], uint32 const in[16]);
/*
* This is needed to make RSAREF happy on some MS-DOS compilers.
*/
/* typedef struct gdm_md5_Context gdm_md5__CTX; */
-#endif /* !GdmMD5_H */
+#endif /* !GdmMD5_H */
diff --git a/memblock.c b/memblock.c
index 6172c0c7..1d2e4f6b 100644
--- a/memblock.c
+++ b/memblock.c
@@ -36,19 +36,19 @@
#define MAX_ERROR_SIZE 128
-enum __M_ERRORS { M_NOERROR, M_NOMEM, M_BADMEM, M_BADDATA, M_BADWHENCE, M_LASTERR };
+enum __M_ERRORS { M_NOERROR, M_NOMEM, M_BADMEM, M_BADDATA, M_BADWHENCE,
+ M_LASTERR };
-const char *__m_error_desc[M_LASTERR] =
-{
- "no error", "not enough memory", "bad memory structure specified",
- "bad data block specified", "bad whence indicator specified"
+const char *__m_error_desc[M_LASTERR] = {
+ "no error", "not enough memory", "bad memory structure specified",
+ "bad data block specified", "bad whence indicator specified"
};
int __m_errno;
char __m_error_str[MAX_ERROR_SIZE];
/* internal use only */
-int __m_blkadd(MEM *m);
+int __m_blkadd(MEM * m);
/*
@@ -56,36 +56,34 @@ int __m_blkadd(MEM *m);
*
* opens a mem-structure
*/
-MEM* mopen()
+MEM *mopen()
{
- MEM *mp = (MEM*)my_malloc(sizeof(MEM));
-
- if (!mp)
- {
- __m_errno = M_NOMEM;
- return NULL;
- }
-
- memset(mp, 0, sizeof(*mp));
-
- mp->firstblk = (memblock_t*)my_malloc(sizeof(memblock_t));
- if (!mp->firstblk)
- {
- __m_errno = M_NOMEM;
- my_free(mp);
- return NULL;
- }
-
- mp->firstblk->nextblk = NULL;
- mp->firstblk->prevblk = NULL;
-
- mp->lastblk = mp->firstblk;
- mp->currblk = mp->firstblk;
-
- mp->nblocks = 1;
-
- __m_errno = M_NOERROR;
- return mp;
+ MEM *mp = (MEM *) my_malloc(sizeof(MEM));
+
+ if (!mp) {
+ __m_errno = M_NOMEM;
+ return NULL;
+ }
+
+ memset(mp, 0, sizeof(*mp));
+
+ mp->firstblk = (memblock_t *) my_malloc(sizeof(memblock_t));
+ if (!mp->firstblk) {
+ __m_errno = M_NOMEM;
+ my_free(mp);
+ return NULL;
+ }
+
+ mp->firstblk->nextblk = NULL;
+ mp->firstblk->prevblk = NULL;
+
+ mp->lastblk = mp->firstblk;
+ mp->currblk = mp->firstblk;
+
+ mp->nblocks = 1;
+
+ __m_errno = M_NOERROR;
+ return mp;
}
@@ -95,103 +93,95 @@ MEM* mopen()
* closes a mem structure
*
*/
-void mclose(MEM **m)
+void mclose(MEM ** m)
{
- memblock_t *tmp,*next;
+ memblock_t *tmp, *next;
- __m_errno = M_NOERROR;
+ __m_errno = M_NOERROR;
- if (!m || !(*m))
- return;
+ if (!m || !(*m))
+ return;
- tmp = (*m)->firstblk;
- while (tmp)
- {
- next = tmp->nextblk; /* save address */
- my_free(tmp);
- tmp = next;
- }
+ tmp = (*m)->firstblk;
+ while (tmp) {
+ next = tmp->nextblk; /* save address */
+ my_free(tmp);
+ tmp = next;
+ }
- my_free(*m);
- *m = NULL;
+ my_free(*m);
+ *m = NULL;
- return;
+ return;
}
-
+
/*
* mwrite()
*
* writes size bytes of data to the memory associated with m
*/
-int mwrite(const void *data, int size, MEM *m)
+int mwrite(const void *data, int size, MEM * m)
{
- long left;
-
- if (!m)
- {
- __m_errno = M_BADMEM;
- return 0;
- }
-
- if (!data)
- {
- __m_errno = M_BADDATA;
- return 0;
- }
-
- if (size <= 0)
- return 0;
-
-
- left = _MEMBLOCK_SIZE - m->mpos;
-
- if (size <= left)
- {
- /* entire fit */
- memmove(&m->currblk->data[m->mpos], data, size);
- m->mpos += size;
-
- if (size == left)
- {
- /* update */
- if (m->currblk == m->lastblk)
- {
- if (!__m_blkadd(m))
- {
- m->mpos--;
- m->eom = m->mpos;
- return size-1;
+ long left;
+
+ if (!m) {
+ __m_errno = M_BADMEM;
+ return 0;
+ }
+
+ if (!data) {
+ __m_errno = M_BADDATA;
+ return 0;
+ }
+
+ if (size <= 0)
+ return 0;
+
+
+ left = _MEMBLOCK_SIZE - m->mpos;
+
+ if (size <= left) {
+ /* entire fit */
+ memmove(&m->currblk->data[m->mpos], data, size);
+ m->mpos += size;
+
+ if (size == left) {
+ /* update */
+ if (m->currblk == m->lastblk) {
+ if (!__m_blkadd(m)) {
+ m->mpos--;
+ m->eom = m->mpos;
+ return size - 1;
+ }
+ }
+
+ m->currblk = m->currblk->nextblk;
+ m->mpos = 0;
}
- }
- m->currblk = m->currblk->nextblk;
- m->mpos = 0;
+ if (m->currblk == m->lastblk && m->mpos > m->eom)
+ m->eom = m->mpos;
+
+ return size;
}
- if (m->currblk == m->lastblk && m->mpos > m->eom)
- m->eom = m->mpos;
-
- return size;
- }
-
- /* copy everything that can be placed */
- memmove(&m->currblk->data[m->mpos], data, left);
- m->mpos += left;
-
- if (m->currblk == m->lastblk)
- {
- /* need a new block */
- if (!__m_blkadd(m))
- return left;
-
- m->eom = 0;
- }
-
- m->currblk = m->currblk->nextblk; /* advance current block */
- m->mpos = 0;
-
- return left + mwrite(&((char*)data)[left], size - left, m);
+ /* copy everything that can be placed */
+ memmove(&m->currblk->data[m->mpos], data, left);
+ m->mpos += left;
+
+ if (m->currblk == m->lastblk) {
+ /* need a new block */
+ if (!__m_blkadd(m))
+ return left;
+
+ m->eom = 0;
+ }
+
+ m->currblk = m->currblk->nextblk; /* advance current block */
+ m->mpos = 0;
+
+ return left + mwrite(&((char *) data)[left], size - left, m);
}
@@ -202,58 +192,54 @@ int mwrite(const void *data, int size, MEM *m)
*
* returns the number of bytes actually read
*/
-int mread(void *data, int size, MEM *m)
+int mread(void *data, int size, MEM * m)
{
- long left;
-
- if (!m)
- {
- __m_errno = M_BADMEM;
- return 0;
- }
-
- if (!data)
- {
- __m_errno = M_BADDATA;
- return 0;
- }
-
- if (size <= 0)
- return 0;
-
- if (m->lastblk == m->currblk)
- left = m->eom - m->mpos;
- else
- left = _MEMBLOCK_SIZE - m->mpos;
-
- if (left <= 0)
- return 0;
-
- if (size < left)
- {
- /* entire fit */
- memmove(data, &m->currblk->data[m->mpos], size);
- m->mpos += size;
-
- return size;
- }
-
- /* copy everything that can be placed */
- memmove(data, &m->currblk->data[m->mpos], left);
- m->mpos += left;
-
- if (m->currblk == m->lastblk)
- {
- /* no more data */
- return left;
- }
-
- m->currblk = m->currblk->nextblk; /* advance current block */
- m->mpos = 0;
-
- return left + mread(&((char*)data)[left], size - left, m);
+ long left;
+
+ if (!m) {
+ __m_errno = M_BADMEM;
+ return 0;
+ }
+
+ if (!data) {
+ __m_errno = M_BADDATA;
+ return 0;
+ }
+
+ if (size <= 0)
+ return 0;
+
+ if (m->lastblk == m->currblk)
+ left = m->eom - m->mpos;
+ else
+ left = _MEMBLOCK_SIZE - m->mpos;
+
+ if (left <= 0)
+ return 0;
+
+ if (size < left) {
+ /* entire fit */
+ memmove(data, &m->currblk->data[m->mpos], size);
+ m->mpos += size;
+
+ return size;
+ }
+
+ /* copy everything that can be placed */
+ memmove(data, &m->currblk->data[m->mpos], left);
+ m->mpos += left;
+
+ if (m->currblk == m->lastblk) {
+ /* no more data */
+ return left;
+ }
+
+ m->currblk = m->currblk->nextblk; /* advance current block */
+ m->mpos = 0;
+
+ return left + mread(&((char *) data)[left], size - left, m);
}
-
+
/*
* mseek()
@@ -265,95 +251,83 @@ int mread(void *data, int size, MEM *m)
*
* returns 0 on succes, -1 on error
*/
-int mseek(MEM *m, long offset, int whence)
+int mseek(MEM * m, long offset, int whence)
{
- long left;
-
- if (!m)
- {
- __m_errno = M_BADMEM;
- return -1;
- }
-
- switch (whence)
- {
- case SEEK_SET:
- m->currblk = m->firstblk;
- m->mpos = 0;
-
- if (offset <= 0)
- return 0;
+ long left;
- return mseek(m, offset, SEEK_CUR);
+ if (!m) {
+ __m_errno = M_BADMEM;
+ return -1;
+ }
- case SEEK_CUR:
- if (offset == 0)
- return 0;
-
- if (offset > 0)
- {
- left = _MEMBLOCK_SIZE - m->mpos;
- if (offset >= left)
- {
- if (m->currblk == m->lastblk)
- {
- m->mpos = m->eom;
- return 0;
+ switch (whence) {
+ case SEEK_SET:
+ m->currblk = m->firstblk;
+ m->mpos = 0;
+
+ if (offset <= 0)
+ return 0;
+
+ return mseek(m, offset, SEEK_CUR);
+
+ case SEEK_CUR:
+ if (offset == 0)
+ return 0;
+
+ if (offset > 0) {
+ left = _MEMBLOCK_SIZE - m->mpos;
+ if (offset >= left) {
+ if (m->currblk == m->lastblk) {
+ m->mpos = m->eom;
+ return 0;
+ }
+
+ m->currblk = m->currblk->nextblk;
+ m->mpos = 0;
+ return mseek(m, offset - left, SEEK_CUR);
+ } else {
+ m->mpos += offset;
+
+ if (m->currblk == m->lastblk
+ && m->mpos > m->eom)
+ m->mpos = m->eom;
+
+ return 0;
+ }
+ } else {
+ /* offset < 0, walk backwards */
+ left = -m->mpos;
+
+ if (offset <= left) {
+ if (m->currblk == m->firstblk) {
+ m->mpos = 0;
+ return 0;
+ }
+
+ m->currblk = m->currblk->prevblk;
+ m->mpos = _MEMBLOCK_SIZE;
+ return mseek(m, offset - left, SEEK_CUR);
+ } else {
+ m->mpos += offset; /* remember: offset<0 */
+ return 0;
+ }
}
-
- m->currblk = m->currblk->nextblk;
- m->mpos = 0;
- return mseek(m, offset - left, SEEK_CUR);
- }
- else
- {
- m->mpos += offset;
-
- if (m->currblk == m->lastblk && m->mpos > m->eom)
+
+ case SEEK_END:
+ m->currblk = m->lastblk;
m->mpos = m->eom;
- return 0;
- }
- }
- else
- {
- /* offset < 0, walk backwards */
- left = - m->mpos;
-
- if (offset <= left)
- {
- if (m->currblk == m->firstblk)
- {
- m->mpos = 0;
- return 0;
- }
-
- m->currblk = m->currblk->prevblk;
- m->mpos = _MEMBLOCK_SIZE;
- return mseek(m, offset - left, SEEK_CUR);
- }
- else
- {
- m->mpos += offset; /* remember: offset<0 */
- return 0;
- }
- }
-
- case SEEK_END:
- m->currblk = m->lastblk;
- m->mpos = m->eom;
-
- if (offset >= 0)
- return 0;
+ if (offset >= 0)
+ return 0;
- return mseek(m, offset, SEEK_CUR);
+ return mseek(m, offset, SEEK_CUR);
- default:
- __m_errno = M_BADWHENCE;
- return -1;
- }
+ default:
+ __m_errno = M_BADWHENCE;
+ return -1;
+ }
- return 0;
+ return 0;
}
@@ -362,32 +336,29 @@ int mseek(MEM *m, long offset, int whence)
*
* gives the current position in bytes (absolute cnt)
*/
-long mtell(MEM *m)
+long mtell(MEM * m)
{
- memblock_t *tmp;
- long pos = 0;
-
- if (!m)
- {
- __m_errno = M_BADMEM;
- return -1;
- }
-
- tmp = m->firstblk;
- while (tmp && tmp != m->currblk)
- {
- pos += _MEMBLOCK_SIZE;
- tmp = tmp->nextblk;
- }
-
- if (!tmp)
- {
- __m_errno = M_BADMEM;
- return -1;
- }
-
- pos += m->mpos;
- return pos;
+ memblock_t *tmp;
+ long pos = 0;
+
+ if (!m) {
+ __m_errno = M_BADMEM;
+ return -1;
+ }
+
+ tmp = m->firstblk;
+ while (tmp && tmp != m->currblk) {
+ pos += _MEMBLOCK_SIZE;
+ tmp = tmp->nextblk;
+ }
+
+ if (!tmp) {
+ __m_errno = M_BADMEM;
+ return -1;
+ }
+
+ pos += m->mpos;
+ return pos;
}
@@ -396,10 +367,10 @@ long mtell(MEM *m)
*
* equivalent to mseek(m, 0, SEEK_SET)
*/
-void mrewind(MEM *m)
+void mrewind(MEM * m)
{
- mseek(m, 0, SEEK_SET);
- __m_errno = M_NOERROR;
+ mseek(m, 0, SEEK_SET);
+ __m_errno = M_NOERROR;
}
@@ -408,15 +379,14 @@ void mrewind(MEM *m)
*
* returns a ptr to a string describing the status of the last operation
*/
-char* merror()
+char *merror()
{
- if (__m_errno >= 0 && __m_errno < M_LASTERR)
- {
- strncpy(__m_error_str, __m_error_desc[__m_errno], MAX_ERROR_SIZE);
- return __m_error_str;
- }
- else
- return NULL;
+ if (__m_errno >= 0 && __m_errno < M_LASTERR) {
+ strncpy(__m_error_str, __m_error_desc[__m_errno],
+ MAX_ERROR_SIZE);
+ return __m_error_str;
+ } else
+ return NULL;
}
@@ -425,33 +395,32 @@ char* merror()
*
* restores a memory block to the state just after it was created with mopen()
*/
-void mreset(MEM *m)
+void mreset(MEM * m)
{
- memblock_t *tmp,*next;
-
- __m_errno = M_NOERROR;
-
- if (!m)
- return;
-
- tmp = m->firstblk;
- if (tmp)
- tmp = tmp->nextblk;
-
- while (tmp)
- {
- next = tmp->nextblk; /* save address */
- my_free(tmp);
- tmp = next;
- m->nblocks--;
- }
-
- m->firstblk->nextblk = NULL;
- m->mpos = 0;
- m->eom = 0;
-
- m->currblk = m->firstblk;
- m->lastblk = m->firstblk;
+ memblock_t *tmp, *next;
+
+ __m_errno = M_NOERROR;
+
+ if (!m)
+ return;
+
+ tmp = m->firstblk;
+ if (tmp)
+ tmp = tmp->nextblk;
+
+ while (tmp) {
+ next = tmp->nextblk; /* save address */
+ my_free(tmp);
+ tmp = next;
+ m->nblocks--;
+ }
+
+ m->firstblk->nextblk = NULL;
+ m->mpos = 0;
+ m->eom = 0;
+
+ m->currblk = m->firstblk;
+ m->lastblk = m->firstblk;
}
@@ -460,28 +429,26 @@ void mreset(MEM *m)
* adds a block to m
* returns 0 on failure, 1 on succes
*/
-int __m_blkadd(MEM *m)
+int __m_blkadd(MEM * m)
{
- memblock_t *newblk;
-
- if (!m)
- {
- __m_errno = M_BADMEM;
- return 0;
- }
-
- newblk = (memblock_t*)my_malloc(sizeof(memblock_t));
- if (!newblk)
- {
- __m_errno = M_NOMEM;
- return 0;
- }
-
- newblk->prevblk = m->lastblk;
- newblk->nextblk = NULL;
-
- m->nblocks++;
- m->lastblk->nextblk = newblk;
- m->lastblk = newblk;
- return 1;
+ memblock_t *newblk;
+
+ if (!m) {
+ __m_errno = M_BADMEM;
+ return 0;
+ }
+
+ newblk = (memblock_t *) my_malloc(sizeof(memblock_t));
+ if (!newblk) {
+ __m_errno = M_NOMEM;
+ return 0;
+ }
+
+ newblk->prevblk = m->lastblk;
+ newblk->nextblk = NULL;
+
+ m->nblocks++;
+ m->lastblk->nextblk = newblk;
+ m->lastblk = newblk;
+ return 1;
}
diff --git a/memblock.h b/memblock.h
index b2525c8f..3eeff4c4 100644
--- a/memblock.h
+++ b/memblock.h
@@ -34,34 +34,32 @@
#define _MEMBLOCK_SIZE (512ul*1024ul)
-struct memblock
-{
- char data[_MEMBLOCK_SIZE];
- struct memblock *nextblk,*prevblk;
+struct memblock {
+ char data[_MEMBLOCK_SIZE];
+ struct memblock *nextblk, *prevblk;
};
typedef struct memblock memblock_t;
-struct MEM_TYPE
-{
- int nblocks;
- long mpos,eom; /* eom = end-of-mem; these positions are relative to
- * currblk (mpos) and lastblk (eom)
- */
+struct MEM_TYPE {
+ int nblocks;
+ long mpos, eom; /* eom = end-of-mem; these positions are relative to
+ * currblk (mpos) and lastblk (eom)
+ */
- memblock_t *firstblk,*currblk,*lastblk;
+ memblock_t *firstblk, *currblk, *lastblk;
};
-
+
typedef struct MEM_TYPE MEM;
-MEM* mopen(void);
-void mclose(MEM **m);
-int mwrite(const void *data, int size, MEM *m);
-int mread(void *data, int size, MEM *m);
-int mseek(MEM *m, long offset, int whence);
-long mtell(MEM *m);
-void mrewind(MEM *m);
-void mreset(MEM *m);
-char* merror(void);
+MEM *mopen(void);
+void mclose(MEM ** m);
+int mwrite(const void *data, int size, MEM * m);
+int mread(void *data, int size, MEM * m);
+int mseek(MEM * m, long offset, int whence);
+long mtell(MEM * m);
+void mrewind(MEM * m);
+void mreset(MEM * m);
+char *merror(void);
#endif
diff --git a/mime.h b/mime.h
index 79ede52e..c58b474c 100644
--- a/mime.h
+++ b/mime.h
@@ -31,19 +31,21 @@
#define MEM_BLOCK 1024
-struct mime_record
-{
+struct mime_record {
/* if these are to be changed to ptrs, the following has to be updated:
mime.c (duh)
db_parse_as_text
a cleanup for all the memory allocated
*/
- char field[MIME_FIELD_MAX];
- char value[MIME_VALUE_MAX];
+ char field[MIME_FIELD_MAX];
+ char value[MIME_VALUE_MAX];
};
-void mime_findfield(const char *fname, struct list *mimelist, struct mime_record **mr);
-int mail_adr_list(char *scan_for_field, struct list *targetlist, struct list *mimelist);
-int mime_readheader(char *blkdata, u64_t *blkidx, struct list *mimelist, u64_t *headersize);
+void mime_findfield(const char *fname, struct list *mimelist,
+ struct mime_record **mr);
+int mail_adr_list(char *scan_for_field, struct list *targetlist,
+ struct list *mimelist);
+int mime_readheader(char *blkdata, u64_t * blkidx, struct list *mimelist,
+ u64_t * headersize);
#endif
diff --git a/misc.c b/misc.c
index 573df4a9..de55bb7e 100644
--- a/misc.c
+++ b/misc.c
@@ -37,85 +37,87 @@
#include "misc.h"
-int drop_privileges (char *newuser, char *newgroup)
+int drop_privileges(char *newuser, char *newgroup)
{
- /* will drop running program's priviledges to newuser and newgroup */
- struct passwd *pwd;
- struct group *grp;
-
- grp = getgrnam(newgroup);
-
- if (grp == NULL) {
- trace (TRACE_ERROR,"%s,%s: could not find group %s\n",
- __FILE__, __FUNCTION__, newgroup);
- return -1;
- }
-
- pwd = getpwnam(newuser);
- if (pwd == NULL) {
- trace (TRACE_ERROR,"%s,%s: could not find user %s\n",
- __FILE__, __FUNCTION__, newuser);
- return -1;
- }
-
- if (setgid (grp->gr_gid) !=0) {
- trace (TRACE_ERROR,"%s,%s: could not set gid to %s\n",
- __FILE__, __FUNCTION__, newgroup);
- return -1;
- }
-
- if (setuid (pwd->pw_uid) != 0) {
- trace (TRACE_ERROR,"%s,%s: could not set uid to %s\n",
- __FILE__, __FUNCTION__, newuser);
- return -1;
- }
- return 0;
+ /* will drop running program's priviledges to newuser and newgroup */
+ struct passwd *pwd;
+ struct group *grp;
+
+ grp = getgrnam(newgroup);
+
+ if (grp == NULL) {
+ trace(TRACE_ERROR, "%s,%s: could not find group %s\n",
+ __FILE__, __FUNCTION__, newgroup);
+ return -1;
+ }
+
+ pwd = getpwnam(newuser);
+ if (pwd == NULL) {
+ trace(TRACE_ERROR, "%s,%s: could not find user %s\n",
+ __FILE__, __FUNCTION__, newuser);
+ return -1;
+ }
+
+ if (setgid(grp->gr_gid) != 0) {
+ trace(TRACE_ERROR, "%s,%s: could not set gid to %s\n",
+ __FILE__, __FUNCTION__, newgroup);
+ return -1;
+ }
+
+ if (setuid(pwd->pw_uid) != 0) {
+ trace(TRACE_ERROR, "%s,%s: could not set uid to %s\n",
+ __FILE__, __FUNCTION__, newuser);
+ return -1;
+ }
+ return 0;
}
char *itoa(int i)
{
- char *s=(char *) malloc(42); /* Enough for a 128 bit integer */
- if (s) sprintf(s,"%d",i);
- return s;
+ char *s = (char *) malloc(42); /* Enough for a 128 bit integer */
+ if (s)
+ sprintf(s, "%d", i);
+ return s;
}
void create_unique_id(char *target, u64_t message_idnr)
{
- char *a_message_idnr, *a_rand;
- char *md5_str;
-
- a_message_idnr = itoa(message_idnr);
- a_rand = itoa(rand());
-
- if (message_idnr != 0)
- snprintf(target, UID_SIZE, "%s:%s",
- a_message_idnr, a_rand);
- else
- snprintf(target, UID_SIZE, "%s", a_rand);
- md5_str = makemd5(target);
- snprintf(target, UID_SIZE, "%s", md5_str);
- trace(TRACE_DEBUG,"%s,%s: created: %s", __FILE__, __FUNCTION__, target);
- my_free(md5_str);
- my_free(a_message_idnr);
- my_free(a_rand);
+ char *a_message_idnr, *a_rand;
+ char *md5_str;
+
+ a_message_idnr = itoa(message_idnr);
+ a_rand = itoa(rand());
+
+ if (message_idnr != 0)
+ snprintf(target, UID_SIZE, "%s:%s",
+ a_message_idnr, a_rand);
+ else
+ snprintf(target, UID_SIZE, "%s", a_rand);
+ md5_str = makemd5(target);
+ snprintf(target, UID_SIZE, "%s", md5_str);
+ trace(TRACE_DEBUG, "%s,%s: created: %s", __FILE__, __FUNCTION__,
+ target);
+ my_free(md5_str);
+ my_free(a_message_idnr);
+ my_free(a_rand);
}
-void create_current_timestring(timestring_t *timestring)
+void create_current_timestring(timestring_t * timestring)
{
time_t td;
struct tm tm;
-
+
if (time(&td) == -1)
trace(TRACE_FATAL, "%s,%s: error getting time from OS",
__FILE__, __FUNCTION__);
- tm = *localtime(&td); /* get components */
- strftime((char*)timestring, sizeof(timestring_t),
+ tm = *localtime(&td); /* get components */
+ strftime((char *) timestring, sizeof(timestring_t),
"%Y-%m-%d %H:%M:%S", &tm);
}
-char *mailbox_add_namespace(const char *mailbox_name, u64_t owner_idnr,
- u64_t user_idnr)
+char *mailbox_add_namespace(const char *mailbox_name, u64_t owner_idnr,
+ u64_t user_idnr)
{
char *fq_name;
char *owner_name;
@@ -126,42 +128,45 @@ char *mailbox_add_namespace(const char *mailbox_name, u64_t owner_idnr,
"NULL.", __FILE__, __FUNCTION__);
return NULL;
}
-
+
if (user_idnr == owner_idnr) {
/* mailbox owned by current user */
return strdup(mailbox_name);
} else {
owner_name = auth_get_userid(owner_idnr);
if (owner_name == NULL) {
- trace(TRACE_ERROR, "%s,%s: error owner_name is NULL",
- __FILE__, __FUNCTION__);
+ trace(TRACE_ERROR,
+ "%s,%s: error owner_name is NULL", __FILE__,
+ __FUNCTION__);
return NULL;
}
trace(TRACE_ERROR, "%s,%s: owner name = %s", __FILE__,
__FUNCTION__, owner_name);
if (strcmp(owner_name, PUBLIC_FOLDER_USER) == 0) {
fq_name_len = strlen(NAMESPACE_PUBLIC) +
- strlen(MAILBOX_SEPERATOR) +
- strlen(mailbox_name) + 1;
- if (!(fq_name = my_malloc(fq_name_len *
+ strlen(MAILBOX_SEPERATOR) +
+ strlen(mailbox_name) + 1;
+ if (!(fq_name = my_malloc(fq_name_len *
sizeof(char)))) {
- trace(TRACE_ERROR, "%s,%s: not enough memory",
- __FILE__, __FUNCTION__);
+ trace(TRACE_ERROR,
+ "%s,%s: not enough memory", __FILE__,
+ __FUNCTION__);
return NULL;
}
snprintf(fq_name, fq_name_len, "%s%s%s",
- NAMESPACE_PUBLIC, MAILBOX_SEPERATOR,
+ NAMESPACE_PUBLIC, MAILBOX_SEPERATOR,
mailbox_name);
} else {
fq_name_len = strlen(NAMESPACE_USER) +
- strlen(MAILBOX_SEPERATOR) +
- strlen(owner_name) +
- strlen(MAILBOX_SEPERATOR) +
- strlen(mailbox_name) + 1;
+ strlen(MAILBOX_SEPERATOR) +
+ strlen(owner_name) +
+ strlen(MAILBOX_SEPERATOR) +
+ strlen(mailbox_name) + 1;
if (!(fq_name = my_malloc(fq_name_len *
sizeof(char)))) {
- trace(TRACE_ERROR, "%s,%s: not enough memory",
- __FILE__, __FUNCTION__);
+ trace(TRACE_ERROR,
+ "%s,%s: not enough memory", __FILE__,
+ __FUNCTION__);
return NULL;
}
snprintf(fq_name, fq_name_len, "%s%s%s%s%s",
@@ -186,24 +191,27 @@ const char *mailbox_remove_namespace(const char *fq_name)
if (strcmp(fq_name, NAMESPACE_USER) == 0) {
temp = strstr(fq_name, MAILBOX_SEPERATOR);
if (temp == NULL || strlen(temp) <= 1) {
- trace(TRACE_ERROR, "%s,%s wronly constructed mailbox "
- "name", __FILE__, __FUNCTION__);
+ trace(TRACE_ERROR,
+ "%s,%s wronly constructed mailbox " "name",
+ __FILE__, __FUNCTION__);
return NULL;
}
temp = strstr(&temp[1], MAILBOX_SEPERATOR);
if (temp == NULL || strlen(temp) <= 1) {
- trace(TRACE_ERROR, "%s,%s wronly constructed mailbox "
- "name", __FILE__, __FUNCTION__);
+ trace(TRACE_ERROR,
+ "%s,%s wronly constructed mailbox " "name",
+ __FILE__, __FUNCTION__);
return NULL;
}
return &temp[1];
}
if (strcmp(fq_name, NAMESPACE_PUBLIC) == 0) {
temp = strstr(fq_name, MAILBOX_SEPERATOR);
-
+
if (temp == NULL || strlen(temp) <= 1) {
- trace(TRACE_ERROR, "%s,%s wronly constructed mailbox "
- "name", __FILE__, __FUNCTION__);
+ trace(TRACE_ERROR,
+ "%s,%s wronly constructed mailbox " "name",
+ __FILE__, __FUNCTION__);
return NULL;
}
return &temp[1];
@@ -223,186 +231,188 @@ const char *mailbox_remove_namespace(const char *fq_name)
#define BAD -1
static const char base64val[] = {
- BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
- BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD,
- BAD,BAD,BAD,BAD, BAD,BAD,BAD,BAD, BAD,BAD,BAD, 62, BAD,BAD,BAD, 63,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,BAD,BAD, BAD,BAD,BAD,BAD,
- BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,BAD, BAD,BAD,BAD,BAD,
- BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,BAD, BAD,BAD,BAD,BAD
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
+ BAD, BAD, BAD,
+ BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, 62, BAD,
+ BAD, BAD, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, BAD, BAD, BAD, BAD, BAD,
+ BAD,
+ BAD, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, BAD, BAD, BAD, BAD,
+ BAD,
+ BAD, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, BAD, BAD, BAD, BAD, BAD
};
#define DECODE64(c) (isascii(c) ? base64val[c] : BAD)
/* Base64 to raw bytes in quasi-big-endian order */
/* Returns 0 on success, -1 on failure */
-int base64_decode_internal(const char *in, size_t inlen, size_t maxlen, char *out, size_t *outlen)
+int base64_decode_internal(const char *in, size_t inlen, size_t maxlen,
+ char *out, size_t * outlen)
{
- size_t pos = 0;
- size_t len = 0;
- register unsigned char digit1, digit2, digit3, digit4;
-
- /* Don't even bother if the string is too short */
- if (inlen < 4)
- return -1;
-
- do
- {
- digit1 = in[0];
- if (DECODE64(digit1) == BAD)
- return -1;
- digit2 = in[1];
- if (DECODE64(digit2) == BAD)
- return -1;
- digit3 = in[2];
- if (digit3 != '=' && DECODE64(digit3) == BAD)
- return -1;
- digit4 = in[3];
- if (digit4 != '=' && DECODE64(digit4) == BAD)
- return -1;
- in += 4;
- pos += 4;
- ++len;
- if (maxlen && len > maxlen)
- return -1;
- *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
- if (digit3 != '=')
- {
- ++len;
- if (maxlen && len > maxlen)
- return -1;
- *out++ = ((DECODE64(digit2) << 4) & 0xf0) | (DECODE64(digit3) >> 2);
- if (digit4 != '=')
- {
- ++len;
- if (maxlen && len > maxlen)
- return -1;
- *out++ = ((DECODE64(digit3) << 6) & 0xc0) | DECODE64(digit4);
- }
- }
- } while ( pos < inlen && digit4 != '=');
-
- *out = '\0';
-
- *outlen = len;
- return 0;
+ size_t pos = 0;
+ size_t len = 0;
+ register unsigned char digit1, digit2, digit3, digit4;
+
+ /* Don't even bother if the string is too short */
+ if (inlen < 4)
+ return -1;
+
+ do {
+ digit1 = in[0];
+ if (DECODE64(digit1) == BAD)
+ return -1;
+ digit2 = in[1];
+ if (DECODE64(digit2) == BAD)
+ return -1;
+ digit3 = in[2];
+ if (digit3 != '=' && DECODE64(digit3) == BAD)
+ return -1;
+ digit4 = in[3];
+ if (digit4 != '=' && DECODE64(digit4) == BAD)
+ return -1;
+ in += 4;
+ pos += 4;
+ ++len;
+ if (maxlen && len > maxlen)
+ return -1;
+ *out++ = (DECODE64(digit1) << 2) | (DECODE64(digit2) >> 4);
+ if (digit3 != '=') {
+ ++len;
+ if (maxlen && len > maxlen)
+ return -1;
+ *out++ =
+ ((DECODE64(digit2) << 4) & 0xf0) |
+ (DECODE64(digit3) >> 2);
+ if (digit4 != '=') {
+ ++len;
+ if (maxlen && len > maxlen)
+ return -1;
+ *out++ =
+ ((DECODE64(digit3) << 6) & 0xc0) |
+ DECODE64(digit4);
+ }
+ }
+ } while (pos < inlen && digit4 != '=');
+
+ *out = '\0';
+
+ *outlen = len;
+ return 0;
}
/* A frontend to the base64_decode_internal() that deals with embedded strings */
char **base64_decode(char *str, size_t len)
{
- size_t i, j, n, maxlen;
- size_t numstrings = 0;
- char *str_decoded = NULL;
- size_t len_decoded = 0;
- char **ret = NULL;
-
- /* Base64 encoding required about 40% more space.
- * So we'll allocate 50% more space. */
- maxlen = 3 * len / 2;
- str_decoded = (char *)malloc(sizeof(char) * maxlen);
- if (str_decoded == NULL)
- return NULL;
-
- if (0 != base64_decode_internal(str, len, maxlen, str_decoded, &len_decoded))
- return NULL;
- if (str_decoded == NULL)
- return NULL;
-
- /* Count up the number of embedded strings... */
- for (i = 0; i <= len_decoded; i++)
- {
- if (str_decoded[i] == '\0')
- {
- numstrings++;
- }
- }
-
- /* Allocate an array of arrays large enough
- * for the strings and a terminating NULL */
- ret = (char **)malloc(sizeof(char *) * (numstrings + 1));
- if (ret == NULL)
- return NULL;
-
- /* If there are more strings, copy those, too */
- for (i = j = n = 0; i <= len_decoded; i++)
- {
- if (str_decoded[i] == '\0')
- {
- ret[n] = strdup(str_decoded + j);
- j = i + 1;
- n++;
- }
- }
-
- /* Put that final NULL on the end of the array */
- ret[n] = NULL;
-
- my_free(str_decoded);
-
- return ret;
+ size_t i, j, n, maxlen;
+ size_t numstrings = 0;
+ char *str_decoded = NULL;
+ size_t len_decoded = 0;
+ char **ret = NULL;
+
+ /* Base64 encoding required about 40% more space.
+ * So we'll allocate 50% more space. */
+ maxlen = 3 * len / 2;
+ str_decoded = (char *) malloc(sizeof(char) * maxlen);
+ if (str_decoded == NULL)
+ return NULL;
+
+ if (0 !=
+ base64_decode_internal(str, len, maxlen, str_decoded,
+ &len_decoded))
+ return NULL;
+ if (str_decoded == NULL)
+ return NULL;
+
+ /* Count up the number of embedded strings... */
+ for (i = 0; i <= len_decoded; i++) {
+ if (str_decoded[i] == '\0') {
+ numstrings++;
+ }
+ }
+
+ /* Allocate an array of arrays large enough
+ * for the strings and a terminating NULL */
+ ret = (char **) malloc(sizeof(char *) * (numstrings + 1));
+ if (ret == NULL)
+ return NULL;
+
+ /* If there are more strings, copy those, too */
+ for (i = j = n = 0; i <= len_decoded; i++) {
+ if (str_decoded[i] == '\0') {
+ ret[n] = strdup(str_decoded + j);
+ j = i + 1;
+ n++;
+ }
+ }
+
+ /* Put that final NULL on the end of the array */
+ ret[n] = NULL;
+
+ my_free(str_decoded);
+
+ return ret;
}
void base64_free(char **ret)
{
- size_t i;
+ size_t i;
- if (ret == NULL)
- return;
+ if (ret == NULL)
+ return;
- for (i = 0; ret[i] != NULL; i++)
- {
- my_free(ret[i]);
- }
+ for (i = 0; ret[i] != NULL; i++) {
+ my_free(ret[i]);
+ }
- my_free(ret);
+ my_free(ret);
}
/* Return 0 is all's well. Returns something else if not... */
-int read_from_stream(FILE *instream, char **m_buf, size_t maxlen)
+int read_from_stream(FILE * instream, char **m_buf, size_t maxlen)
{
- size_t f_len = 0;
- size_t f_pos = 0;
- char *tmp_buf = NULL;
- char *f_buf = NULL;
-
- /* Give up on a zero length request */
- if (maxlen < 1)
- {
- *m_buf = NULL;
- return 0;
- }
-
- tmp_buf = malloc(sizeof(char) * (f_len+=512));
- if (tmp_buf != NULL)
- f_buf = tmp_buf;
- else
- return -2;
-
- /* Shouldn't this also check for ferror() or feof() ?? */
- while (f_pos < maxlen)
- {
- if (f_pos + 1 >= f_len)
- {
- /* Per suggestion of my CS instructor, double the
- * buffer every time it is too small. This yields
- * a logarithmic number of reallocations. */
- tmp_buf = realloc(f_buf, sizeof(char) * (f_len*=2));
- if (tmp_buf != NULL)
- f_buf = tmp_buf;
- else
- return -2;
- }
- f_buf[f_pos] = fgetc(instream);
- f_pos++;
- }
-
- if (f_pos)
- f_buf[f_pos] = '\0';
-
- *m_buf = f_buf;
-
- return 0;
+ size_t f_len = 0;
+ size_t f_pos = 0;
+ char *tmp_buf = NULL;
+ char *f_buf = NULL;
+
+ /* Give up on a zero length request */
+ if (maxlen < 1) {
+ *m_buf = NULL;
+ return 0;
+ }
+
+ tmp_buf = malloc(sizeof(char) * (f_len += 512));
+ if (tmp_buf != NULL)
+ f_buf = tmp_buf;
+ else
+ return -2;
+
+ /* Shouldn't this also check for ferror() or feof() ?? */
+ while (f_pos < maxlen) {
+ if (f_pos + 1 >= f_len) {
+ /* Per suggestion of my CS instructor, double the
+ * buffer every time it is too small. This yields
+ * a logarithmic number of reallocations. */
+ tmp_buf =
+ realloc(f_buf, sizeof(char) * (f_len *= 2));
+ if (tmp_buf != NULL)
+ f_buf = tmp_buf;
+ else
+ return -2;
+ }
+ f_buf[f_pos] = fgetc(instream);
+ f_pos++;
+ }
+
+ if (f_pos)
+ f_buf[f_pos] = '\0';
+
+ *m_buf = f_buf;
+
+ return 0;
}
/* Finds what lurks between two bounding symbols.
@@ -415,53 +425,54 @@ int read_from_stream(FILE *instream, char **m_buf, size_t maxlen)
*
* The caller is responsible for free()ing *retchar.
* */
-int find_bounded(char *value, char left, char right, char **retchar, size_t *retsize, size_t *retlast)
+int find_bounded(char *value, char left, char right, char **retchar,
+ size_t * retsize, size_t * retlast)
{
- char *tmpleft;
- char *tmpright;
- size_t tmplen;
-
- tmpleft = value;
- tmpright = value + strlen(value);
-
- while (tmpleft[0] != left && tmpleft < tmpright)
- tmpleft++;
- while (tmpright[0] != right && tmpright > tmpleft)
- tmpright--;
-
- if (tmpleft[0] != left || tmpright[0] != right)
- {
- trace(TRACE_INFO, "%s, %s: Found nothing between '%c' and '%c'",
- __FILE__, __FUNCTION__, left, right);
- *retchar = NULL;
- *retsize = 0;
- *retlast = 0;
- return -1;
- }
- else
- {
- /* Step left up to skip the actual left thinger */
- if (tmpright != tmpleft)
- tmpleft++;
-
- tmplen = tmpright - tmpleft;
- *retchar = my_malloc(sizeof(char) * (tmplen + 1));
- if (*retchar == NULL)
- {
- *retchar = NULL;
- *retsize = 0;
- *retlast = 0;
- trace(TRACE_INFO, "%s, %s: Found [%s] of length [%zd] between '%c' and '%c' so next skip [%zd]",
- __FILE__, __FUNCTION__, *retchar, *retsize, left, right, *retlast);
- return -2;
- }
- strncpy(*retchar, tmpleft, tmplen);
- (*retchar)[tmplen] = '\0';
- *retsize = tmplen;
- *retlast = tmpright - value;
- trace(TRACE_INFO, "%s, %s: Found [%s] of length [%zd] between '%c' and '%c' so next skip [%zd]",
- __FILE__, __FUNCTION__, *retchar, *retsize, left, right, *retlast);
- return 0;
- }
+ char *tmpleft;
+ char *tmpright;
+ size_t tmplen;
+
+ tmpleft = value;
+ tmpright = value + strlen(value);
+
+ while (tmpleft[0] != left && tmpleft < tmpright)
+ tmpleft++;
+ while (tmpright[0] != right && tmpright > tmpleft)
+ tmpright--;
+
+ if (tmpleft[0] != left || tmpright[0] != right) {
+ trace(TRACE_INFO,
+ "%s, %s: Found nothing between '%c' and '%c'",
+ __FILE__, __FUNCTION__, left, right);
+ *retchar = NULL;
+ *retsize = 0;
+ *retlast = 0;
+ return -1;
+ } else {
+ /* Step left up to skip the actual left thinger */
+ if (tmpright != tmpleft)
+ tmpleft++;
+
+ tmplen = tmpright - tmpleft;
+ *retchar = my_malloc(sizeof(char) * (tmplen + 1));
+ if (*retchar == NULL) {
+ *retchar = NULL;
+ *retsize = 0;
+ *retlast = 0;
+ trace(TRACE_INFO,
+ "%s, %s: Found [%s] of length [%zd] between '%c' and '%c' so next skip [%zd]",
+ __FILE__, __FUNCTION__, *retchar, *retsize,
+ left, right, *retlast);
+ return -2;
+ }
+ strncpy(*retchar, tmpleft, tmplen);
+ (*retchar)[tmplen] = '\0';
+ *retsize = tmplen;
+ *retlast = tmpright - value;
+ trace(TRACE_INFO,
+ "%s, %s: Found [%s] of length [%zd] between '%c' and '%c' so next skip [%zd]",
+ __FILE__, __FUNCTION__, *retchar, *retsize, left,
+ right, *retlast);
+ return 0;
+ }
}
-
diff --git a/misc.h b/misc.h
index ee13389f..d5c7cbd9 100644
--- a/misc.h
+++ b/misc.h
@@ -44,7 +44,7 @@
- -1 on error
- 0 on success
*/
-int drop_privileges (char *newuser, char *newgroup);
+int drop_privileges(char *newuser, char *newgroup);
/**
* \brief convert integer to string (length 42, long enough for
@@ -52,7 +52,7 @@ int drop_privileges (char *newuser, char *newgroup);
* \param i the integer
* \return string
*/
-char * itoa (int i);
+char *itoa(int i);
/**
* \brief create a unique id for a message (used for pop, stored per message)
@@ -65,7 +65,7 @@ void create_unique_id(char *target, u64_t message_idnr);
* \brief create a timestring with the current time.
* \param timestring an allocated timestring object.
*/
-void create_current_timestring(timestring_t *timestring);
+void create_current_timestring(timestring_t * timestring);
/**
* \brief decorate a mailbox name with a namespace if needed
@@ -91,8 +91,10 @@ const char *mailbox_remove_namespace(const char *fq_name);
char **base64_decode(char *str, size_t len);
void base64_free(char **ret);
-int read_from_stream(FILE *instream, char **m_buf, size_t maxlen);
-int find_bounded(char *value, char left, char right, char **retchar, size_t *retsize, size_t *retlast);
-int base64_grow_ret(char ***inchar, size_t **inint, size_t newcount, size_t newchar);
+int read_from_stream(FILE * instream, char **m_buf, size_t maxlen);
+int find_bounded(char *value, char left, char right, char **retchar,
+ size_t * retsize, size_t * retlast);
+int base64_grow_ret(char ***inchar, size_t ** inint, size_t newcount,
+ size_t newchar);
#endif
diff --git a/mysql/dbmysql.c b/mysql/dbmysql.c
index 21876fdc..1d0e85ac 100644
--- a/mysql/dbmysql.c
+++ b/mysql/dbmysql.c
@@ -47,7 +47,7 @@ static MYSQL conn; /**< MySQL database connection */
static MYSQL_RES *res = NULL; /**< MySQL result set */
static MYSQL_RES *msgbuf_res = NULL; /**< MySQL result set for msgbuf */
static MYSQL_RES *auth_res = NULL; /**< MySQL result set for authentication */
-static MYSQL_RES *stored_res = NULL; /**< MySQL result set backup */
+static MYSQL_RES *stored_res = NULL; /**< MySQL result set backup */
static unsigned last_row_nr = -1; /**< number of last row that was used */
static MYSQL_ROW last_row; /**< last result set */
@@ -65,12 +65,12 @@ db_param_t _db_params;
*/
static int db_check_connection(void);
-int db_connect()
-{
+int db_connect()
+{
char *sock = NULL;
- /* connect */
+ /* connect */
mysql_init(&conn);
-
+
/* auto re-connect */
conn.reconnect = 1;
@@ -88,27 +88,26 @@ int db_connect()
"will be attempted using the default socket.",
__FILE__, __FUNCTION__);
sock = NULL;
- } else
+ } else
sock = _db_params.sock;
}
-
-
- if (mysql_real_connect (&conn, _db_params.host, _db_params.user,
- _db_params.pass, _db_params.db,
- _db_params.port, sock,
- 0) == NULL) {
- trace(TRACE_ERROR,"%s,%s: mysql_real_connect failed: %s",
- __FILE__, __FUNCTION__, mysql_error(&conn));
- return -1;
- }
-#ifdef mysql_errno
- if (mysql_errno(&conn)) {
- trace(TRACE_ERROR,"%s,%s: mysql_real_connect failed: %s",
- __FILE__, __FUNCTION__, mysql_error(&conn));
- return -1;
- }
-#endif
- return 0;
+
+
+ if (mysql_real_connect(&conn, _db_params.host, _db_params.user,
+ _db_params.pass, _db_params.db,
+ _db_params.port, sock, 0) == NULL) {
+ trace(TRACE_ERROR, "%s,%s: mysql_real_connect failed: %s",
+ __FILE__, __FUNCTION__, mysql_error(&conn));
+ return -1;
+ }
+#ifdef mysql_errno
+ if (mysql_errno(&conn)) {
+ trace(TRACE_ERROR, "%s,%s: mysql_real_connect failed: %s",
+ __FILE__, __FUNCTION__, mysql_error(&conn));
+ return -1;
+ }
+#endif
+ return 0;
}
unsigned db_num_rows()
@@ -118,7 +117,7 @@ unsigned db_num_rows()
* should return 0 */
if (!res)
return 0;
-
+
return mysql_num_rows(res);
}
@@ -144,38 +143,38 @@ char *db_get_result(unsigned row, unsigned field)
if (!res) {
trace(TRACE_WARNING, "%s,%s: result set is null\n",
- __FILE__, __FUNCTION__);
- return NULL;
- }
-
- if ((row >= db_num_rows()) ||
- (field >= db_num_fields())) {
- trace(TRACE_WARNING, "%s, %s: "
- "row = %u, field = %u, bigger than size of result set", __FILE__, __FUNCTION__,row, field);
- return NULL;
- }
+ __FILE__, __FUNCTION__);
+ return NULL;
+ }
+
+ if ((row >= db_num_rows()) || (field >= db_num_fields())) {
+ trace(TRACE_WARNING, "%s, %s: "
+ "row = %u, field = %u, bigger than size of result set",
+ __FILE__, __FUNCTION__, row, field);
+ return NULL;
+ }
/* get the right row */
- if(last_row_nr == row) {
- } else if((last_row_nr + 1) == row) {
+ if (last_row_nr == row) {
+ } else if ((last_row_nr + 1) == row) {
last_row = mysql_fetch_row(res);
} else {
- mysql_data_seek(res, row);
+ mysql_data_seek(res, row);
last_row = mysql_fetch_row(res);
}
- result = last_row[field];
- if (result == NULL)
+ result = last_row[field];
+ if (result == NULL)
trace(TRACE_WARNING, "%s,%s: result is null\n",
__FILE__, __FUNCTION__);
last_row_nr = row;
- return result;
-}
+ return result;
+}
int db_disconnect()
-{
- db_free_result();
- mysql_close(&conn);
- return 0;
-}
+{
+ db_free_result();
+ mysql_close(&conn);
+ return 0;
+}
int db_check_connection()
{
@@ -191,66 +190,69 @@ int db_check_connection()
return 0;
}
-u64_t db_insert_result(const char *sequence_identifier UNUSED)
-{
- u64_t insert_result;
- insert_result = mysql_insert_id(&conn);
- return insert_result;
-}
+u64_t db_insert_result(const char *sequence_identifier UNUSED)
+{
+ u64_t insert_result;
+ insert_result = mysql_insert_id(&conn);
+ return insert_result;
+}
-int db_query(const char *the_query)
-{
+int db_query(const char *the_query)
+{
unsigned int querysize = 0;
last_row_nr = -1;
if (db_check_connection() < 0) {
trace(TRACE_ERROR, "%s,%s: no database connection",
- __FILE__, __FUNCTION__);
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+ if (the_query != NULL) {
+ querysize = strlen(the_query);
+ if (querysize > 0) {
+ trace(TRACE_DEBUG, "%s,%s: "
+ "executing query [%s]",
+ __FILE__, __FUNCTION__, the_query);
+ if (mysql_real_query(&conn,
+ the_query, querysize) < 0) {
+ trace(TRACE_ERROR, "%s,%s: "
+ "query [%s] failed",
+ __FILE__, __FUNCTION__, the_query);
+ trace(TRACE_ERROR, "%s,%s: "
+ "mysql_real_query failed: %s",
+ __FILE__, __FUNCTION__,
+ mysql_error(&conn));
+ return -1;
+ }
+ } else {
+ trace(TRACE_ERROR, "%s,%s: "
+ "querysize is wrong: [%d]", __FILE__,
+ __FUNCTION__, querysize);
+ return -1;
+ }
+ } else {
+ trace(TRACE_ERROR, "%s,%s: "
+ "query buffer is NULL, this is not supposed to happen\n",
+ __FILE__, __FUNCTION__);
return -1;
}
- if (the_query != NULL) {
- querysize = strlen(the_query);
- if (querysize > 0) {
- trace(TRACE_DEBUG, "%s,%s: "
- "executing query [%s]",
- __FILE__, __FUNCTION__, the_query);
- if (mysql_real_query(&conn,
- the_query, querysize) < 0) {
- trace(TRACE_ERROR, "%s,%s: "
- "query [%s] failed",
- __FILE__, __FUNCTION__, the_query);
- trace(TRACE_ERROR, "%s,%s: "
- "mysql_real_query failed: %s",
- __FILE__, __FUNCTION__, mysql_error(&conn));
- return -1;
- }
- } else {
- trace(TRACE_ERROR, "%s,%s: "
- "querysize is wrong: [%d]", __FILE__, __FUNCTION__,querysize);
- return -1;
- }
- } else {
- trace (TRACE_ERROR,"%s,%s: "
- "query buffer is NULL, this is not supposed to happen\n",
- __FILE__, __FUNCTION__);
- return -1;
- }
/* mysql_store_result is only needed if a SELECT or
an OPTIMIZE is done */
if (strncasecmp(the_query, "SELECT", 6) == 0 ||
- strncasecmp(the_query, "OPTIMIZE", 8) == 0) {
- res = mysql_store_result(&conn);
- if (res == NULL) {
- trace(TRACE_ERROR, "%s,%s: could not store query result",
- __FILE__, __FUNCTION__);
- return -1;
- }
- }
- return 0;
+ strncasecmp(the_query, "OPTIMIZE", 8) == 0) {
+ res = mysql_store_result(&conn);
+ if (res == NULL) {
+ trace(TRACE_ERROR,
+ "%s,%s: could not store query result",
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+ }
+ return 0;
}
-unsigned long db_escape_string(char *to,
- const char *from, unsigned long length)
+unsigned long db_escape_string(char *to,
+ const char *from, unsigned long length)
{
return mysql_real_escape_string(&conn, to, from, length);
}
@@ -262,11 +264,13 @@ int db_do_cleanup(const char **tables, int num)
int result = 0;
for (i = 0; i < num; i++) {
- snprintf(query, DEF_QUERYSIZE, "OPTIMIZE TABLE %s", tables[i]);
+ snprintf(query, DEF_QUERYSIZE, "OPTIMIZE TABLE %s",
+ tables[i]);
if (db_query(query) == -1) {
- trace(TRACE_ERROR, "%s,%s: error optimizing table [%s]",
- __FILE__, __FUNCTION__, tables[i]);
+ trace(TRACE_ERROR,
+ "%s,%s: error optimizing table [%s]",
+ __FILE__, __FUNCTION__, tables[i]);
result = -1;
}
db_free_result();
@@ -280,19 +284,19 @@ u64_t db_get_length(unsigned row, unsigned field)
if (!res) {
trace(TRACE_WARNING, "%s,%s: result set is null\n",
__FILE__, __FUNCTION__);
- return -1;
- }
-
- if ((row >= db_num_rows()) ||
- (field >= db_num_fields())) {
- trace(TRACE_ERROR, "%s, %s: "
- "row = %u, field = %u, bigger than size of result set", __FILE__, __FUNCTION__,row, field);
- return -1;
- }
+ return -1;
+ }
+
+ if ((row >= db_num_rows()) || (field >= db_num_fields())) {
+ trace(TRACE_ERROR, "%s, %s: "
+ "row = %u, field = %u, bigger than size of result set",
+ __FILE__, __FUNCTION__, row, field);
+ return -1;
+ }
/* get the right row */
if (last_row_nr == row) {
// Don't do anything, we're already there
- } else if(last_row_nr + 1 == row) {
+ } else if (last_row_nr + 1 == row) {
// Get the next row
last_row = mysql_fetch_row(res);
} else {
@@ -305,7 +309,7 @@ u64_t db_get_length(unsigned row, unsigned field)
u64_t db_get_affected_rows()
{
- return (u64_t) mysql_affected_rows(&conn);
+ return (u64_t) mysql_affected_rows(&conn);
}
void db_use_msgbuf_result()
@@ -332,13 +336,12 @@ void db_store_auth_result()
res = stored_res;
}
-void* db_get_result_set()
+void *db_get_result_set()
{
- return (void*) res;
+ return (void *) res;
}
void db_set_result_set(void *the_result_set)
{
- res = (MYSQL_RES*) the_result_set;
+ res = (MYSQL_RES *) the_result_set;
}
-
diff --git a/pgsql/dbpgsql.c b/pgsql/dbpgsql.c
index 5e776f7f..192cc1f9 100644
--- a/pgsql/dbpgsql.c
+++ b/pgsql/dbpgsql.c
@@ -28,7 +28,7 @@
#endif
#include "db.h"
-#include "libpq-fe.h" /* PostgreSQL header */
+#include "libpq-fe.h" /* PostgreSQL header */
#include "dbmail.h"
#include "dbmailtypes.h"
@@ -60,287 +60,292 @@ static int db_check_connection(void);
int db_connect()
{
- char connectionstring[255];
-
- /* use the standard port for postgresql if none is given. This looks a bit
- dirty.. can't we get this info from somewhere else? */
- if (_db_params.port != 0)
- snprintf (connectionstring, 255,
- "host='%s' user='%s' password='%s' dbname='%s' "
- "port='%u'",
- _db_params.host, _db_params.user, _db_params.pass,
- _db_params.db, _db_params.port);
- else
- snprintf (connectionstring, 255,
- "host='%s' user='%s' password='%s' dbname='%s' ",
- _db_params.host, _db_params.user, _db_params.pass,
- _db_params.db);
-
- conn = PQconnectdb(connectionstring);
-
- if (PQstatus(conn) == CONNECTION_BAD) {
- trace(TRACE_ERROR,
- "%si,%s: PQconnectdb failed: %s",
- __FILE__, __FUNCTION__,
- PQerrorMessage(conn));
- return -1;
- }
-
- return 0;
+ char connectionstring[255];
+
+ /* use the standard port for postgresql if none is given. This looks a bit
+ dirty.. can't we get this info from somewhere else? */
+ if (_db_params.port != 0)
+ snprintf(connectionstring, 255,
+ "host='%s' user='%s' password='%s' dbname='%s' "
+ "port='%u'",
+ _db_params.host, _db_params.user, _db_params.pass,
+ _db_params.db, _db_params.port);
+ else
+ snprintf(connectionstring, 255,
+ "host='%s' user='%s' password='%s' dbname='%s' ",
+ _db_params.host, _db_params.user, _db_params.pass,
+ _db_params.db);
+
+ conn = PQconnectdb(connectionstring);
+
+ if (PQstatus(conn) == CONNECTION_BAD) {
+ trace(TRACE_ERROR,
+ "%si,%s: PQconnectdb failed: %s",
+ __FILE__, __FUNCTION__, PQerrorMessage(conn));
+ return -1;
+ }
+
+ return 0;
}
int db_disconnect()
{
- db_free_result();
- PQfinish(conn);
- conn = NULL;
+ db_free_result();
+ PQfinish(conn);
+ conn = NULL;
- return 0;
+ return 0;
}
int db_check_connection()
{
- /* if there is no connection, try making one */
- if (!conn) {
- trace(TRACE_DEBUG, "%s,%s: no database connection, trying "
- "to establish one", __FILE__, __FUNCTION__);
- if (db_connect() < 0) {
- trace(TRACE_ERROR, "%s,%s: unable to connect to database",
- __FILE__, __FUNCTION__);
- return -1;
- }
- return 0;
- }
-
- /* check status of current connection */
- if (PQstatus(conn) != CONNECTION_OK) {
- trace(TRACE_DEBUG, "%s,%s: connection lost, trying to reset",
- __FILE__, __FUNCTION__);
- PQreset(conn);
-
- if (PQstatus(conn) != CONNECTION_OK) {
- trace(TRACE_ERROR, "%s,%s: Connection failed: [%s]",
- __FILE__, __FUNCTION__, PQerrorMessage(conn));
- trace(TRACE_ERROR, "%s,%s: Could not establish dbase "
- "connection", __FILE__, __FUNCTION__);
- conn = NULL;
- return -1;
- }
- }
- return 0;
+ /* if there is no connection, try making one */
+ if (!conn) {
+ trace(TRACE_DEBUG, "%s,%s: no database connection, trying "
+ "to establish one", __FILE__, __FUNCTION__);
+ if (db_connect() < 0) {
+ trace(TRACE_ERROR,
+ "%s,%s: unable to connect to database",
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+ return 0;
+ }
+
+ /* check status of current connection */
+ if (PQstatus(conn) != CONNECTION_OK) {
+ trace(TRACE_DEBUG,
+ "%s,%s: connection lost, trying to reset", __FILE__,
+ __FUNCTION__);
+ PQreset(conn);
+
+ if (PQstatus(conn) != CONNECTION_OK) {
+ trace(TRACE_ERROR,
+ "%s,%s: Connection failed: [%s]", __FILE__,
+ __FUNCTION__, PQerrorMessage(conn));
+ trace(TRACE_ERROR,
+ "%s,%s: Could not establish dbase "
+ "connection", __FILE__, __FUNCTION__);
+ conn = NULL;
+ return -1;
+ }
+ }
+ return 0;
}
-
+
unsigned db_num_rows()
{
- int num_rows;
- if (!res)
- return 0;
-
- num_rows = PQntuples(res);
- if (num_rows < 0)
- return 0;
- else
- return (unsigned) num_rows;
+ int num_rows;
+ if (!res)
+ return 0;
+
+ num_rows = PQntuples(res);
+ if (num_rows < 0)
+ return 0;
+ else
+ return (unsigned) num_rows;
}
unsigned db_num_fields()
{
- int num_fields;
-
- if (!res)
- return 0;
- num_fields = PQnfields(res);
- if (num_fields < 0)
- return 0;
- else
- return (unsigned) num_fields;
+ int num_fields;
+
+ if (!res)
+ return 0;
+ num_fields = PQnfields(res);
+ if (num_fields < 0)
+ return 0;
+ else
+ return (unsigned) num_fields;
}
void db_free_result()
{
- if (res != NULL)
- PQclear(res);
- res = NULL;
+ if (res != NULL)
+ PQclear(res);
+ res = NULL;
}
char *db_get_result(unsigned row, unsigned field)
{
- if (!res) {
- trace(TRACE_WARNING, "%s,%s: result set is NULL",
- __FILE__, __FUNCTION__);
- return NULL;
- }
-
- if ((row >= db_num_rows()) ||
- (field >= db_num_fields())) {
- trace(TRACE_WARNING, "%s,%s: "
- "(row = %u,field = %u) bigger then size of result set",
- __FILE__, __FUNCTION__, row, field);
- return NULL;
- }
- return PQgetvalue(res, row, field);
+ if (!res) {
+ trace(TRACE_WARNING, "%s,%s: result set is NULL",
+ __FILE__, __FUNCTION__);
+ return NULL;
+ }
+
+ if ((row >= db_num_rows()) || (field >= db_num_fields())) {
+ trace(TRACE_WARNING, "%s,%s: "
+ "(row = %u,field = %u) bigger then size of result set",
+ __FILE__, __FUNCTION__, row, field);
+ return NULL;
+ }
+ return PQgetvalue(res, row, field);
}
u64_t db_insert_result(const char *sequence_identifier)
{
- char query[DEF_QUERYSIZE];
- u64_t insert_result;
-
- /* postgres uses the currval call on a sequence to determine
- * the result value of an insert query */
- snprintf(query, DEF_QUERYSIZE,
- "SELECT currval('%s_seq')", sequence_identifier);
-
- db_query(query);
- if (db_num_rows() == 0) {
- db_free_result();
- return 0;
- }
- insert_result = strtoull(db_get_result(0, 0), NULL, 10);
- db_free_result();
- return insert_result;
+ char query[DEF_QUERYSIZE];
+ u64_t insert_result;
+
+ /* postgres uses the currval call on a sequence to determine
+ * the result value of an insert query */
+ snprintf(query, DEF_QUERYSIZE,
+ "SELECT currval('%s_seq')", sequence_identifier);
+
+ db_query(query);
+ if (db_num_rows() == 0) {
+ db_free_result();
+ return 0;
+ }
+ insert_result = strtoull(db_get_result(0, 0), NULL, 10);
+ db_free_result();
+ return insert_result;
}
int db_query(const char *the_query)
{
- int PQresultStatusVar;
- char *result_string;
- PGresult *temp_res; /**< temp_res is used as a temporary result set. If
+ int PQresultStatusVar;
+ char *result_string;
+ PGresult *temp_res;
+ /**< temp_res is used as a temporary result set. If
the query succeeds, and needs to return a
result set (i.e. it is a SELECT query)
the global res is
set to this temp_res result set */
- if (db_check_connection() < 0) {
- trace(TRACE_ERROR, "%s,%s: No database connection",
- __FILE__, __FUNCTION__);
- return -1;
- }
-
- if (the_query != NULL) {
- trace(TRACE_DEBUG, "%s,%s: "
- "executing query [%s]", __FILE__, __FUNCTION__, the_query);
- temp_res = PQexec (conn, the_query);
- if (!temp_res)
- return -1;
-
- PQresultStatusVar = PQresultStatus(temp_res);
-
- if (PQresultStatusVar != PGRES_COMMAND_OK &&
- PQresultStatusVar != PGRES_TUPLES_OK)
- {
- trace(TRACE_ERROR,"%s, %s: "
- "Error executing query [%s] : [%s]\n",
- __FILE__, __FUNCTION__,
- the_query, PQresultErrorMessage(temp_res));
- return -1;
- }
-
- /* get the number of rows affected by the query */
- result_string = PQcmdTuples(temp_res);
- if (result_string)
- affected_rows = strtoull(result_string, NULL, 10);
- else
- affected_rows = 0;
-
- /* only keep the result set if this was a SELECT
- * query */
- if (strncasecmp(the_query, "SELECT", 6) != 0) {
- if (temp_res != NULL)
- PQclear(temp_res);
- }
-
- else {
- if (res)
- trace(TRACE_WARNING, "%s,%s: previous result set is possibly "
- "not freed.", __FILE__, __FUNCTION__);
- res = temp_res;
- }
- } else {
- trace (TRACE_ERROR,"%s,%s: "
- "query buffer is NULL, this is not supposed to happen\n",
- __FILE__,__FUNCTION__);
- return -1;
- }
- return 0;
+ if (db_check_connection() < 0) {
+ trace(TRACE_ERROR, "%s,%s: No database connection",
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+
+ if (the_query != NULL) {
+ trace(TRACE_DEBUG, "%s,%s: "
+ "executing query [%s]", __FILE__, __FUNCTION__,
+ the_query);
+ temp_res = PQexec(conn, the_query);
+ if (!temp_res)
+ return -1;
+
+ PQresultStatusVar = PQresultStatus(temp_res);
+
+ if (PQresultStatusVar != PGRES_COMMAND_OK &&
+ PQresultStatusVar != PGRES_TUPLES_OK) {
+ trace(TRACE_ERROR, "%s, %s: "
+ "Error executing query [%s] : [%s]\n",
+ __FILE__, __FUNCTION__,
+ the_query, PQresultErrorMessage(temp_res));
+ return -1;
+ }
+
+ /* get the number of rows affected by the query */
+ result_string = PQcmdTuples(temp_res);
+ if (result_string)
+ affected_rows = strtoull(result_string, NULL, 10);
+ else
+ affected_rows = 0;
+
+ /* only keep the result set if this was a SELECT
+ * query */
+ if (strncasecmp(the_query, "SELECT", 6) != 0) {
+ if (temp_res != NULL)
+ PQclear(temp_res);
+ }
+
+ else {
+ if (res)
+ trace(TRACE_WARNING,
+ "%s,%s: previous result set is possibly "
+ "not freed.", __FILE__,
+ __FUNCTION__);
+ res = temp_res;
+ }
+ } else {
+ trace(TRACE_ERROR, "%s,%s: "
+ "query buffer is NULL, this is not supposed to happen\n",
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+ return 0;
}
unsigned long db_escape_string(char *to,
const char *from, unsigned long length)
{
- return PQescapeString(to, from, length);
+ return PQescapeString(to, from, length);
}
int db_do_cleanup(const char **tables, int num_tables)
{
- int result = 0;
- int i;
- char query[DEF_QUERYSIZE];
-
- for (i = 0; i < num_tables; i++) {
- snprintf(query, DEF_QUERYSIZE, "VACUUM %s", tables[i]);
- if (db_query(query) == -1) {
- trace(TRACE_ERROR, "%s,%s: error vacuuming table [%s]",
- __FILE__, __FUNCTION__, tables[i]);
- result = -1;
- }
- }
- return result;
+ int result = 0;
+ int i;
+ char query[DEF_QUERYSIZE];
+
+ for (i = 0; i < num_tables; i++) {
+ snprintf(query, DEF_QUERYSIZE, "VACUUM %s", tables[i]);
+ if (db_query(query) == -1) {
+ trace(TRACE_ERROR,
+ "%s,%s: error vacuuming table [%s]",
+ __FILE__, __FUNCTION__, tables[i]);
+ result = -1;
+ }
+ }
+ return result;
}
u64_t db_get_length(unsigned row, unsigned field)
{
- if (!res) {
- trace(TRACE_WARNING, "%s,%s: result set is NULL",
- __FILE__, __FUNCTION__);
- return -1;
- }
-
- if ((row >= db_num_rows()) ||
- (field >= db_num_fields())) {
- trace(TRACE_ERROR, "%s,%s: "
- "(row = %u,field = %u) bigger then size of result set",
- __FILE__, __FUNCTION__, row, field);
- return -1;
- }
- return PQgetlength(res, row, field);
+ if (!res) {
+ trace(TRACE_WARNING, "%s,%s: result set is NULL",
+ __FILE__, __FUNCTION__);
+ return -1;
+ }
+
+ if ((row >= db_num_rows()) || (field >= db_num_fields())) {
+ trace(TRACE_ERROR, "%s,%s: "
+ "(row = %u,field = %u) bigger then size of result set",
+ __FILE__, __FUNCTION__, row, field);
+ return -1;
+ }
+ return PQgetlength(res, row, field);
}
u64_t db_get_affected_rows()
{
- return affected_rows;
+ return affected_rows;
}
-
+
void db_use_msgbuf_result()
{
- stored_res = res;
- res = msgbuf_res;
+ stored_res = res;
+ res = msgbuf_res;
}
void db_store_msgbuf_result()
{
- msgbuf_res = res;
- res = stored_res;
+ msgbuf_res = res;
+ res = stored_res;
}
void db_use_auth_result()
{
- stored_res = res;
- res = auth_res;
+ stored_res = res;
+ res = auth_res;
}
void db_store_auth_result()
{
- auth_res = res;
- res = stored_res;
+ auth_res = res;
+ res = stored_res;
}
-void* db_get_result_set()
+
+void *db_get_result_set()
{
- return (void*) res;
+ return (void *) res;
}
void db_set_result_set(void *the_result_set)
{
- res = (PGresult*) the_result_set;
+ res = (PGresult *) the_result_set;
}
-
diff --git a/pipe.c b/pipe.c
index eaef53a0..210e3547 100644
--- a/pipe.c
+++ b/pipe.c
@@ -68,56 +68,61 @@ extern struct list smtpItems, sysItems;
/*
* Send an automatic notification using sendmail
*/
-static int send_notification(const char *to, const char *from, const char *subject)
+static int send_notification(const char *to, const char *from,
+ const char *subject)
{
- FILE *mailpipe = NULL;
- char *sendmail_command = NULL;
- field_t sendmail;
- int result;
+ FILE *mailpipe = NULL;
+ char *sendmail_command = NULL;
+ field_t sendmail;
+ int result;
- GetConfigValue("SENDMAIL", &smtpItems, sendmail);
- if (sendmail[0] == '\0')
- trace(TRACE_FATAL, "send_notification(): SENDMAIL not configured (see config file). Stop.");
+ GetConfigValue("SENDMAIL", &smtpItems, sendmail);
+ if (sendmail[0] == '\0')
+ trace(TRACE_FATAL,
+ "send_notification(): SENDMAIL not configured (see config file). Stop.");
- trace(TRACE_DEBUG, "send_notification(): found sendmail command to be [%s]", sendmail);
+ trace(TRACE_DEBUG,
+ "send_notification(): found sendmail command to be [%s]",
+ sendmail);
-
- sendmail_command = (char *)my_malloc(strlen((char *)(to))+
- strlen(sendmail)+2); /* +2 for extra space and \0 */
- if (!sendmail_command)
- {
- trace(TRACE_ERROR,"send_notification(): out of memory");
- return -1;
- }
- trace (TRACE_DEBUG,"send_notification(): allocated memory for"
- " external command call");
- sprintf (sendmail_command, "%s %s",sendmail, to);
+ sendmail_command = (char *) my_malloc(strlen((char *) (to)) + strlen(sendmail) + 2); /* +2 for extra space and \0 */
+ if (!sendmail_command) {
+ trace(TRACE_ERROR, "send_notification(): out of memory");
+ return -1;
+ }
+
+ trace(TRACE_DEBUG, "send_notification(): allocated memory for"
+ " external command call");
+ sprintf(sendmail_command, "%s %s", sendmail, to);
- trace (TRACE_INFO,"send_notification(): opening pipe to command "
- "%s",sendmail_command);
+ trace(TRACE_INFO, "send_notification(): opening pipe to command "
+ "%s", sendmail_command);
- if (! (mailpipe = popen(sendmail_command, "w")) )
- {
- trace(TRACE_ERROR, "send_notification(): could not open pipe to sendmail using cmd [%s]", sendmail);
- return 1;
- }
+ if (!(mailpipe = popen(sendmail_command, "w"))) {
+ trace(TRACE_ERROR,
+ "send_notification(): could not open pipe to sendmail using cmd [%s]",
+ sendmail);
+ return 1;
+ }
- trace(TRACE_DEBUG, "send_notification(): pipe opened, sending data");
+ trace(TRACE_DEBUG,
+ "send_notification(): pipe opened, sending data");
- fprintf(mailpipe, "To: %s\n", to);
- fprintf(mailpipe, "From: %s\n", from);
- fprintf(mailpipe, "Subject: %s\n", subject);
- fprintf(mailpipe, "\n");
+ fprintf(mailpipe, "To: %s\n", to);
+ fprintf(mailpipe, "From: %s\n", from);
+ fprintf(mailpipe, "Subject: %s\n", subject);
+ fprintf(mailpipe, "\n");
- result = pclose(mailpipe);
- trace(TRACE_DEBUG, "send_notification(): pipe closed");
+ result = pclose(mailpipe);
+ trace(TRACE_DEBUG, "send_notification(): pipe closed");
- if (result != 0)
- trace(TRACE_ERROR,"send_notification(): reply could not be sent: sendmail error");
+ if (result != 0)
+ trace(TRACE_ERROR,
+ "send_notification(): reply could not be sent: sendmail error");
- return 0;
+ return 0;
}
@@ -126,166 +131,175 @@ static int send_notification(const char *to, const char *from, const char *subje
*/
static int send_reply(struct list *headerfields, const char *body)
{
- struct element *el;
- struct mime_record *record;
- char *from = NULL, *to = NULL, *replyto = NULL, *subject = NULL;
- FILE *mailpipe = NULL;
- char *send_address;
- char *escaped_send_address;
- char comm[MAX_COMM_SIZE]; /**< command sent to sendmail (needs to escaped) */
- field_t sendmail;
- int result;
- unsigned int i,j;
-
- GetConfigValue("SENDMAIL", &smtpItems, sendmail);
- if (sendmail[0] == '\0')
- trace(TRACE_FATAL, "send_reply(): SENDMAIL not configured (see config file). Stop.");
-
- trace(TRACE_DEBUG, "send_reply(): found sendmail command to be [%s]", sendmail);
-
- /* find To: and Reply-To:/From: field */
- el = list_getstart(headerfields);
-
- while (el)
- {
- record = (struct mime_record*)el->data;
-
- if (strcasecmp(record->field, "from") == 0)
- {
- from = record->value;
- trace(TRACE_DEBUG, "send_reply(): found FROM [%s]", from);
- }
- else if (strcasecmp(record->field, "reply-to") == 0)
- {
- replyto = record->value;
- trace(TRACE_DEBUG, "send_reply(): found REPLY-TO [%s]", replyto);
- }
- else if (strcasecmp(record->field, "subject") == 0)
- {
- subject = record->value;
- trace(TRACE_DEBUG, "send_reply(): found SUBJECT [%s]", subject);
- }
- else if (strcasecmp(record->field, "deliver-to") == 0)
- {
- to = record->value;
- trace(TRACE_DEBUG, "send_reply(): found TO [%s]", to);
- }
-
- el = el->nextnode;
- }
-
- if (!from && !replyto)
- {
- trace(TRACE_ERROR, "send_reply(): no address to send to");
- return 0;
- }
-
-
- trace(TRACE_DEBUG, "send_reply(): header fields scanned; opening pipe to sendmail");
- send_address = replyto ? replyto : from;
- /* allocate a string twice the size of send_address */
- escaped_send_address = (char*) my_malloc(strlen((send_address) + 1)
- * 2 * sizeof(char));
- i = 0;
- j = 0;
- /* get all characters from send_address, and escape every ' */
- while (i < (strlen(send_address) + 1)) {
- if (send_address[i] == '\'')
- escaped_send_address[j++] = '\\';
- escaped_send_address[j++] = send_address[i++];
- }
- snprintf(comm, MAX_COMM_SIZE, "%s '%s'", sendmail, escaped_send_address);
-
- if (! (mailpipe = popen(comm, "w")) )
- {
- trace(TRACE_ERROR, "send_reply(): could not open pipe to sendmail using cmd [%s]", comm);
- return 1;
- }
-
- trace(TRACE_DEBUG, "send_reply(): sending data");
-
- fprintf(mailpipe, "To: %s\n", replyto ? replyto : from);
- fprintf(mailpipe, "From: %s\n", to ? to : "(unknown)");
- fprintf(mailpipe, "Subject: AW: %s\n", subject ? subject : "<no subject>");
- fprintf(mailpipe, "\n");
- fprintf(mailpipe, "%s\n", body ? body : "--");
-
- result = pclose(mailpipe);
- trace(TRACE_DEBUG, "send_reply(): pipe closed");
- if (result != 0)
- trace(TRACE_ERROR,"send_reply(): reply could not be sent: sendmail error");
-
- return 0;
+ struct element *el;
+ struct mime_record *record;
+ char *from = NULL, *to = NULL, *replyto = NULL, *subject = NULL;
+ FILE *mailpipe = NULL;
+ char *send_address;
+ char *escaped_send_address;
+ char comm[MAX_COMM_SIZE];
+ /**< command sent to sendmail (needs to escaped) */
+ field_t sendmail;
+ int result;
+ unsigned int i, j;
+
+ GetConfigValue("SENDMAIL", &smtpItems, sendmail);
+ if (sendmail[0] == '\0')
+ trace(TRACE_FATAL,
+ "send_reply(): SENDMAIL not configured (see config file). Stop.");
+
+ trace(TRACE_DEBUG,
+ "send_reply(): found sendmail command to be [%s]", sendmail);
+
+ /* find To: and Reply-To:/From: field */
+ el = list_getstart(headerfields);
+
+ while (el) {
+ record = (struct mime_record *) el->data;
+
+ if (strcasecmp(record->field, "from") == 0) {
+ from = record->value;
+ trace(TRACE_DEBUG, "send_reply(): found FROM [%s]",
+ from);
+ } else if (strcasecmp(record->field, "reply-to") == 0) {
+ replyto = record->value;
+ trace(TRACE_DEBUG,
+ "send_reply(): found REPLY-TO [%s]",
+ replyto);
+ } else if (strcasecmp(record->field, "subject") == 0) {
+ subject = record->value;
+ trace(TRACE_DEBUG,
+ "send_reply(): found SUBJECT [%s]", subject);
+ } else if (strcasecmp(record->field, "deliver-to") == 0) {
+ to = record->value;
+ trace(TRACE_DEBUG, "send_reply(): found TO [%s]",
+ to);
+ }
+
+ el = el->nextnode;
+ }
+
+ if (!from && !replyto) {
+ trace(TRACE_ERROR, "send_reply(): no address to send to");
+ return 0;
+ }
+
+
+ trace(TRACE_DEBUG,
+ "send_reply(): header fields scanned; opening pipe to sendmail");
+ send_address = replyto ? replyto : from;
+ /* allocate a string twice the size of send_address */
+ escaped_send_address =
+ (char *) my_malloc(strlen((send_address) + 1)
+ * 2 * sizeof(char));
+ i = 0;
+ j = 0;
+ /* get all characters from send_address, and escape every ' */
+ while (i < (strlen(send_address) + 1)) {
+ if (send_address[i] == '\'')
+ escaped_send_address[j++] = '\\';
+ escaped_send_address[j++] = send_address[i++];
+ }
+ snprintf(comm, MAX_COMM_SIZE, "%s '%s'", sendmail,
+ escaped_send_address);
+
+ if (!(mailpipe = popen(comm, "w"))) {
+ trace(TRACE_ERROR,
+ "send_reply(): could not open pipe to sendmail using cmd [%s]",
+ comm);
+ return 1;
+ }
+
+ trace(TRACE_DEBUG, "send_reply(): sending data");
+
+ fprintf(mailpipe, "To: %s\n", replyto ? replyto : from);
+ fprintf(mailpipe, "From: %s\n", to ? to : "(unknown)");
+ fprintf(mailpipe, "Subject: AW: %s\n",
+ subject ? subject : "<no subject>");
+ fprintf(mailpipe, "\n");
+ fprintf(mailpipe, "%s\n", body ? body : "--");
+
+ result = pclose(mailpipe);
+ trace(TRACE_DEBUG, "send_reply(): pipe closed");
+ if (result != 0)
+ trace(TRACE_ERROR,
+ "send_reply(): reply could not be sent: sendmail error");
+
+ return 0;
}
/* Yeah, RAN. That's Reply And Notify ;-) */
static int execute_auto_ran(u64_t useridnr, struct list *headerfields)
{
- field_t val;
- int do_auto_notify = 0, do_auto_reply = 0;
- char *reply_body = NULL;
- char *notify_address = NULL;
-
- /* message has been succesfully inserted, perform auto-notification & auto-reply */
- GetConfigValue("AUTO_NOTIFY", &smtpItems, val);
- if (strcasecmp(val, "yes") == 0)
- do_auto_notify = 1;
-
- GetConfigValue("AUTO_REPLY", &smtpItems, val);
- if (strcasecmp(val, "yes") == 0)
- do_auto_reply = 1;
-
- if (do_auto_notify)
- {
- trace(TRACE_DEBUG, "execute_auto_ran(): starting auto-notification procedure");
-
- if (db_get_notify_address(useridnr, &notify_address) != 0)
- trace(TRACE_ERROR, "execute_auto_ran(): error fetching notification address");
- else
- {
- if (notify_address == NULL)
- trace(TRACE_DEBUG, "execute_auto_ran(): no notification address specified, skipping");
- else
- {
- trace(TRACE_DEBUG, "execute_auto_ran(): sending notifcation to [%s]", notify_address);
- send_notification(notify_address, AUTO_NOTIFY_SENDER, AUTO_NOTIFY_SUBJECT);
- my_free(notify_address);
- }
- }
- }
-
- if (do_auto_reply)
- {
- trace(TRACE_DEBUG, "execute_auto_ran(): starting auto-reply procedure");
-
- if (db_get_reply_body(useridnr, &reply_body) != 0)
- trace(TRACE_ERROR, "execute_auto_ran(): error fetching reply body");
- else
- {
- if (reply_body == NULL || reply_body[0] == '\0')
- trace(TRACE_DEBUG, "execute_auto_ran(): no reply body specified, skipping");
- else
- {
- send_reply(headerfields, reply_body);
- my_free(reply_body);
- }
- }
- }
-
- return 0;
+ field_t val;
+ int do_auto_notify = 0, do_auto_reply = 0;
+ char *reply_body = NULL;
+ char *notify_address = NULL;
+
+ /* message has been succesfully inserted, perform auto-notification & auto-reply */
+ GetConfigValue("AUTO_NOTIFY", &smtpItems, val);
+ if (strcasecmp(val, "yes") == 0)
+ do_auto_notify = 1;
+
+ GetConfigValue("AUTO_REPLY", &smtpItems, val);
+ if (strcasecmp(val, "yes") == 0)
+ do_auto_reply = 1;
+
+ if (do_auto_notify) {
+ trace(TRACE_DEBUG,
+ "execute_auto_ran(): starting auto-notification procedure");
+
+ if (db_get_notify_address(useridnr, &notify_address) != 0)
+ trace(TRACE_ERROR,
+ "execute_auto_ran(): error fetching notification address");
+ else {
+ if (notify_address == NULL)
+ trace(TRACE_DEBUG,
+ "execute_auto_ran(): no notification address specified, skipping");
+ else {
+ trace(TRACE_DEBUG,
+ "execute_auto_ran(): sending notifcation to [%s]",
+ notify_address);
+ send_notification(notify_address,
+ AUTO_NOTIFY_SENDER,
+ AUTO_NOTIFY_SUBJECT);
+ my_free(notify_address);
+ }
+ }
+ }
+
+ if (do_auto_reply) {
+ trace(TRACE_DEBUG,
+ "execute_auto_ran(): starting auto-reply procedure");
+
+ if (db_get_reply_body(useridnr, &reply_body) != 0)
+ trace(TRACE_ERROR,
+ "execute_auto_ran(): error fetching reply body");
+ else {
+ if (reply_body == NULL || reply_body[0] == '\0')
+ trace(TRACE_DEBUG,
+ "execute_auto_ran(): no reply body specified, skipping");
+ else {
+ send_reply(headerfields, reply_body);
+ my_free(reply_body);
+ }
+ }
+ }
+
+ return 0;
}
/* read from instream, but simply discard all input! */
-void discard_client_input(FILE *instream)
+void discard_client_input(FILE * instream)
{
char *tmpline;
- memtst ((tmpline= (char *)my_malloc(MAX_LINE_SIZE+1))==NULL);
- while(!feof(instream)) {
+ memtst((tmpline = (char *) my_malloc(MAX_LINE_SIZE + 1)) == NULL);
+ while (!feof(instream)) {
fgets(tmpline, MAX_LINE_SIZE, instream);
-
+
if (!tmpline)
break;
@@ -305,164 +319,168 @@ void discard_client_input(FILE *instream)
*
* returns a message id number, or -1 on error.
* */
-static int store_message_temp(FILE *instream,
- char *header, u64_t headersize, u64_t headerrfcsize,
- u64_t *msgsize, u64_t *rfcsize, u64_t *temp_message_idnr)
+static int store_message_temp(FILE * instream,
+ char *header, u64_t headersize,
+ u64_t headerrfcsize, u64_t * msgsize,
+ u64_t * rfcsize, u64_t * temp_message_idnr)
{
- int myeof=0;
- u64_t msgidnr=0;
- size_t i=0, usedmem=0, linemem=0;
- u64_t totalmem = 0, rfclines=0;
- char *strblock=NULL, *tmpline=NULL;
- char unique_id[UID_SIZE];
- u64_t messageblk_idnr;
- u64_t user_idnr;
- int result;
-
- result = auth_user_exists(DBMAIL_DELIVERY_USERNAME, &user_idnr);
- if (result < 0) {
- trace(TRACE_ERROR, "%s,%s: unable to find user_idnr for user "
- "[%s]\n", __FILE__, __FUNCTION__, DBMAIL_DELIVERY_USERNAME);
- return -1;
- }
- if (result == 0) {
- trace(TRACE_ERROR, "%s,%s: unable to find user_idnr for user "
- "[%s]. Make sure this system user is in the database!\n",
- __FILE__, __FUNCTION__, DBMAIL_DELIVERY_USERNAME);
- return -1;
- }
-
- create_unique_id(unique_id, user_idnr);
-
- /* create a message record */
- switch (db_insert_message(user_idnr, DBMAIL_TEMPMBOX,
- CREATE_IF_MBOX_NOT_FOUND, unique_id, &msgidnr))
- {
- case -1:
- trace(TRACE_ERROR, "store_message_temp(): returned -1, aborting");
- return -1;
- }
-
- switch (db_insert_message_block(header, headersize, msgidnr, &messageblk_idnr))
- {
- case -1:
- trace(TRACE_ERROR, "store_message_temp(): error inserting msgblock [header]");
- return -1;
- }
-
- trace(TRACE_DEBUG, "store_message_temp(): allocating [%ld] bytes of memory for readblock",
- READ_BLOCK_SIZE);
-
- memtst ((strblock = (char *)my_malloc(READ_BLOCK_SIZE+1))==NULL);
- memset((void*) strblock, '\0', READ_BLOCK_SIZE+1);
- memtst ((tmpline= (char *)my_malloc(MAX_LINE_SIZE+1))==NULL);
- memset((void*) tmpline, '\0', MAX_LINE_SIZE+1);
-
- while ((!feof(instream) && (!myeof)) || (linemem != 0))
- {
- /* Copy the line that didn't fit before */
- if (linemem > 0)
- {
- strncpy(strblock, tmpline, linemem);
- usedmem += linemem;
-
- /* Resetting strlen for tmpline */
- tmpline[0] = '\0';
- linemem = 0;
- }
-
- /* We want to fill up each block if possible,
- * unless of course we're at the end of the file */
- while (!feof(instream) && (usedmem +linemem < READ_BLOCK_SIZE))
- {
- fgets(tmpline, MAX_LINE_SIZE, instream);
- linemem = strlen(tmpline);
- /* The RFC size assumes all lines end in \r\n,
- * so if we have a newline (\n) but don't have
- * a carriage return (\r), count it in rfcsize. */
- if (linemem > 0 && tmpline[linemem-1] == '\n')
- if (linemem == 1 || (linemem > 1 && tmpline[linemem-2] != '\r'))
- rfclines++;
-
- if (ferror(instream))
- {
- trace(TRACE_ERROR,"store_message_temp(): error on instream: [%s]", strerror(errno));
- /* FIXME: Umm, don't we need to free a few things?! */
- return -1;
- }
-
- /* This should be the one and only valid
- * end to a message over SMTP/LMTP...
- * FIXME: If there's a compatibility problem, it's probably here! */
- if (strcmp(tmpline, ".\r\n") == 0)
- {
- /* This is the end of the message! */
- myeof = 1;
- linemem = 0;
- break;
- }
- else
- {
- /* See if the line fits into this block */
- if (usedmem + linemem < READ_BLOCK_SIZE)
- {
- strncpy(strblock+usedmem, tmpline, linemem);
- usedmem += linemem;
-
- /* Resetting strlen for tmpline */
- tmpline[0] = '\0';
- linemem = 0;
- }
- /* Don't need an else, see above this while loop for more */
- }
- }
-
- /* replace all errorneous '\0' by ' ' (space) */
- for (i = 0; i < usedmem; i++)
- {
- if (strblock[i] == '\0')
- {
- strblock[i] = ' ';
- }
- }
-
- /* fread won't do this for us! */
- strblock[usedmem] = '\0';
-
- if (usedmem > 0) /* usedmem is 0 with an EOF */
- {
- totalmem += usedmem;
-
- switch (db_insert_message_block(strblock, usedmem, msgidnr, &messageblk_idnr))
- {
- case -1:
- trace(TRACE_STOP, "store_message_temp(): error inserting msgblock");
- return -1;
- }
- }
-
- /* resetting strlen for strblock */
- strblock[0] = '\0';
- usedmem = 0;
- }
-
- trace(TRACE_DEBUG, "store_message_temp(): end of instream");
-
- my_free (tmpline);
- trace(TRACE_DEBUG, "store_message_temp(): tmpline freed");
-
- my_free (strblock);
- trace(TRACE_DEBUG, "store_message_temp(): strblock freed");
-
- db_update_message(msgidnr, unique_id, (totalmem+headersize),
- (totalmem+rfclines+headerrfcsize));
-
- /* Pass the message id out to the caller. */
- *temp_message_idnr = msgidnr;
- *rfcsize = totalmem + rfclines + headerrfcsize;
- *msgsize = totalmem + headersize;
-
- return 0;
+ int myeof = 0;
+ u64_t msgidnr = 0;
+ size_t i = 0, usedmem = 0, linemem = 0;
+ u64_t totalmem = 0, rfclines = 0;
+ char *strblock = NULL, *tmpline = NULL;
+ char unique_id[UID_SIZE];
+ u64_t messageblk_idnr;
+ u64_t user_idnr;
+ int result;
+
+ result = auth_user_exists(DBMAIL_DELIVERY_USERNAME, &user_idnr);
+ if (result < 0) {
+ trace(TRACE_ERROR,
+ "%s,%s: unable to find user_idnr for user " "[%s]\n",
+ __FILE__, __FUNCTION__, DBMAIL_DELIVERY_USERNAME);
+ return -1;
+ }
+ if (result == 0) {
+ trace(TRACE_ERROR,
+ "%s,%s: unable to find user_idnr for user "
+ "[%s]. Make sure this system user is in the database!\n",
+ __FILE__, __FUNCTION__, DBMAIL_DELIVERY_USERNAME);
+ return -1;
+ }
+
+ create_unique_id(unique_id, user_idnr);
+
+ /* create a message record */
+ switch (db_insert_message(user_idnr, DBMAIL_TEMPMBOX,
+ CREATE_IF_MBOX_NOT_FOUND, unique_id,
+ &msgidnr)) {
+ case -1:
+ trace(TRACE_ERROR,
+ "store_message_temp(): returned -1, aborting");
+ return -1;
+ }
+
+ switch (db_insert_message_block
+ (header, headersize, msgidnr, &messageblk_idnr)) {
+ case -1:
+ trace(TRACE_ERROR,
+ "store_message_temp(): error inserting msgblock [header]");
+ return -1;
+ }
+
+ trace(TRACE_DEBUG,
+ "store_message_temp(): allocating [%ld] bytes of memory for readblock",
+ READ_BLOCK_SIZE);
+
+ memtst((strblock =
+ (char *) my_malloc(READ_BLOCK_SIZE + 1)) == NULL);
+ memset((void *) strblock, '\0', READ_BLOCK_SIZE + 1);
+ memtst((tmpline = (char *) my_malloc(MAX_LINE_SIZE + 1)) == NULL);
+ memset((void *) tmpline, '\0', MAX_LINE_SIZE + 1);
+
+ while ((!feof(instream) && (!myeof)) || (linemem != 0)) {
+ /* Copy the line that didn't fit before */
+ if (linemem > 0) {
+ strncpy(strblock, tmpline, linemem);
+ usedmem += linemem;
+
+ /* Resetting strlen for tmpline */
+ tmpline[0] = '\0';
+ linemem = 0;
+ }
+
+ /* We want to fill up each block if possible,
+ * unless of course we're at the end of the file */
+ while (!feof(instream)
+ && (usedmem + linemem < READ_BLOCK_SIZE)) {
+ fgets(tmpline, MAX_LINE_SIZE, instream);
+ linemem = strlen(tmpline);
+ /* The RFC size assumes all lines end in \r\n,
+ * so if we have a newline (\n) but don't have
+ * a carriage return (\r), count it in rfcsize. */
+ if (linemem > 0 && tmpline[linemem - 1] == '\n')
+ if (linemem == 1
+ || (linemem > 1
+ && tmpline[linemem - 2] != '\r'))
+ rfclines++;
+
+ if (ferror(instream)) {
+ trace(TRACE_ERROR,
+ "store_message_temp(): error on instream: [%s]",
+ strerror(errno));
+ /* FIXME: Umm, don't we need to free a few things?! */
+ return -1;
+ }
+
+ /* This should be the one and only valid
+ * end to a message over SMTP/LMTP...
+ * FIXME: If there's a compatibility problem, it's probably here! */
+ if (strcmp(tmpline, ".\r\n") == 0) {
+ /* This is the end of the message! */
+ myeof = 1;
+ linemem = 0;
+ break;
+ } else {
+ /* See if the line fits into this block */
+ if (usedmem + linemem < READ_BLOCK_SIZE) {
+ strncpy(strblock + usedmem,
+ tmpline, linemem);
+ usedmem += linemem;
+
+ /* Resetting strlen for tmpline */
+ tmpline[0] = '\0';
+ linemem = 0;
+ }
+ /* Don't need an else, see above this while loop for more */
+ }
+ }
+
+ /* replace all errorneous '\0' by ' ' (space) */
+ for (i = 0; i < usedmem; i++) {
+ if (strblock[i] == '\0') {
+ strblock[i] = ' ';
+ }
+ }
+
+ /* fread won't do this for us! */
+ strblock[usedmem] = '\0';
+
+ if (usedmem > 0) { /* usedmem is 0 with an EOF */
+ totalmem += usedmem;
+
+ switch (db_insert_message_block
+ (strblock, usedmem, msgidnr,
+ &messageblk_idnr)) {
+ case -1:
+ trace(TRACE_STOP,
+ "store_message_temp(): error inserting msgblock");
+ return -1;
+ }
+ }
+
+ /* resetting strlen for strblock */
+ strblock[0] = '\0';
+ usedmem = 0;
+ }
+
+ trace(TRACE_DEBUG, "store_message_temp(): end of instream");
+
+ my_free(tmpline);
+ trace(TRACE_DEBUG, "store_message_temp(): tmpline freed");
+
+ my_free(strblock);
+ trace(TRACE_DEBUG, "store_message_temp(): strblock freed");
+
+ db_update_message(msgidnr, unique_id, (totalmem + headersize),
+ (totalmem + rfclines + headerrfcsize));
+
+ /* Pass the message id out to the caller. */
+ *temp_message_idnr = msgidnr;
+ *rfcsize = totalmem + rfclines + headerrfcsize;
+ *msgsize = totalmem + headersize;
+
+ return 0;
}
/* Here's the real *meat* of this source file!
@@ -498,117 +516,129 @@ static int store_message_temp(FILE *instream,
* - 0 on success
* - -1 on full failure
*/
-int insert_messages(FILE *instream, char *header, u64_t headersize, u64_t headerrfcsize,
- struct list *headerfields, struct list *dsnusers, struct list *returnpath)
+int insert_messages(FILE * instream, char *header, u64_t headersize,
+ u64_t headerrfcsize, struct list *headerfields,
+ struct list *dsnusers, struct list *returnpath)
{
- struct element *element, *ret_path;
- u64_t msgsize, rfcsize, tmpmsgidnr;
-
- /* Read in the rest of the stream and store it into a temporary message */
- switch (store_message_temp(instream, header, headersize, headerrfcsize,
- &msgsize, &rfcsize, &tmpmsgidnr))
- {
- case -1:
- /* Major trouble. Bail out immediately. */
- trace(TRACE_ERROR, "%s, %s: failed to store temporary message.",
- __FILE__, __FUNCTION__ );
- return -1;
- default:
- trace(TRACE_DEBUG, "%s, %s: temporary msgidnr is [%llu]",
- __FILE__, __FUNCTION__, tmpmsgidnr );
- break;
- }
-
- /* Loop through the users list. */
- for (element = list_getstart(dsnusers); element != NULL; element = element->nextnode)
- {
- struct element *userid_elem;
- int has_2 = 0, has_4 = 0, has_5 = 0;
- deliver_to_user_t *delivery = (deliver_to_user_t *)element->data;
-
- /* Each user may have a list of user_idnr's for local delivery. */
- for (userid_elem = list_getstart(delivery->userids);
- userid_elem != NULL; userid_elem = userid_elem->nextnode)
- {
- u64_t useridnr = *(u64_t *)userid_elem->data;
- trace(TRACE_DEBUG, "%s, %s: calling sort_and_deliver for useridnr [%llu]",
- __FILE__, __FUNCTION__, useridnr);
-
- switch (sort_and_deliver(tmpmsgidnr,
- header, headersize, msgsize, rfcsize,
- useridnr, delivery->mailbox))
- {
- case DSN_CLASS_OK:
- /* Indicate success. */
- trace(TRACE_DEBUG, "%s, %s: successful sort_and_deliver for useridnr [%llu]",
- __FILE__, __FUNCTION__, useridnr);
- has_2 = 1;
- break;
- case DSN_CLASS_FAIL:
- /* Indicate permanent failure. */
- trace(TRACE_ERROR, "%s, %s: permanent failure sort_and_deliver for useridnr [%llu]",
- __FILE__, __FUNCTION__, useridnr);
- has_5 = 1;
- break;
- case DSN_CLASS_TEMP:
- case -1:
- default:
- /* Assume a temporary failure */
- trace(TRACE_ERROR, "%s, %s: temporary failure sort_and_deliver for useridnr [%llu]",
- __FILE__, __FUNCTION__, useridnr);
- has_4 = 1;
- break;
- }
-
- /* Automatic reply and notification */
- execute_auto_ran(useridnr, headerfields);
- } /* from: the useridnr for loop */
-
- switch (dsnuser_worstcase_int(has_2, has_4, has_5))
- {
- case DSN_CLASS_OK:
- delivery->dsn.class = DSN_CLASS_OK; /* Success. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 5; /* Valid. */
- break;
- case DSN_CLASS_TEMP:
- delivery->dsn.class = DSN_CLASS_TEMP; /* Temporary transient failure. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 5; /* Valid. */
- break;
- case DSN_CLASS_FAIL:
- delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
- delivery->dsn.subject = 1; /* Address related. */
- delivery->dsn.detail = 1; /* Does not exist. */
- break;
- }
-
- trace(TRACE_DEBUG,"insert_messages(): we need to deliver [%ld] "
- "messages to external addresses", list_totalnodes(delivery->forwards));
-
- /* Each user may also have a list of external forwarding addresses. */
- if (list_totalnodes(delivery->forwards) > 0)
- {
-
- trace(TRACE_DEBUG, "insert_messages(): delivering to external addresses");
-
- /* Only the last step of the returnpath is used. */
- ret_path = list_getstart(returnpath);
-
- /* Forward using the temporary stored message. */
- forward(tmpmsgidnr, delivery->forwards, (ret_path ? ret_path->data : "DBMAIL-MAILER"), header, headersize);
- }
-
- } /* from: the delivery for loop */
-
- /* Always delete the temporary message, even if the delivery failed.
- * It is the MTA's job to requeue or bounce the message,
- * and our job to keep a tidy database ;-) */
- db_delete_message(tmpmsgidnr);
- trace(TRACE_DEBUG, "insert_messages(): temporary message deleted from database");
-
- trace(TRACE_DEBUG, "insert_messages(): End of function");
-
- return 0;
-}
+ struct element *element, *ret_path;
+ u64_t msgsize, rfcsize, tmpmsgidnr;
+
+ /* Read in the rest of the stream and store it into a temporary message */
+ switch (store_message_temp
+ (instream, header, headersize, headerrfcsize, &msgsize,
+ &rfcsize, &tmpmsgidnr)) {
+ case -1:
+ /* Major trouble. Bail out immediately. */
+ trace(TRACE_ERROR,
+ "%s, %s: failed to store temporary message.",
+ __FILE__, __FUNCTION__);
+ return -1;
+ default:
+ trace(TRACE_DEBUG, "%s, %s: temporary msgidnr is [%llu]",
+ __FILE__, __FUNCTION__, tmpmsgidnr);
+ break;
+ }
+ /* Loop through the users list. */
+ for (element = list_getstart(dsnusers); element != NULL;
+ element = element->nextnode) {
+ struct element *userid_elem;
+ int has_2 = 0, has_4 = 0, has_5 = 0;
+ deliver_to_user_t *delivery =
+ (deliver_to_user_t *) element->data;
+
+ /* Each user may have a list of user_idnr's for local delivery. */
+ for (userid_elem = list_getstart(delivery->userids);
+ userid_elem != NULL;
+ userid_elem = userid_elem->nextnode) {
+ u64_t useridnr = *(u64_t *) userid_elem->data;
+ trace(TRACE_DEBUG,
+ "%s, %s: calling sort_and_deliver for useridnr [%llu]",
+ __FILE__, __FUNCTION__, useridnr);
+
+ switch (sort_and_deliver(tmpmsgidnr,
+ header, headersize,
+ msgsize, rfcsize,
+ useridnr,
+ delivery->mailbox)) {
+ case DSN_CLASS_OK:
+ /* Indicate success. */
+ trace(TRACE_DEBUG,
+ "%s, %s: successful sort_and_deliver for useridnr [%llu]",
+ __FILE__, __FUNCTION__, useridnr);
+ has_2 = 1;
+ break;
+ case DSN_CLASS_FAIL:
+ /* Indicate permanent failure. */
+ trace(TRACE_ERROR,
+ "%s, %s: permanent failure sort_and_deliver for useridnr [%llu]",
+ __FILE__, __FUNCTION__, useridnr);
+ has_5 = 1;
+ break;
+ case DSN_CLASS_TEMP:
+ case -1:
+ default:
+ /* Assume a temporary failure */
+ trace(TRACE_ERROR,
+ "%s, %s: temporary failure sort_and_deliver for useridnr [%llu]",
+ __FILE__, __FUNCTION__, useridnr);
+ has_4 = 1;
+ break;
+ }
+
+ /* Automatic reply and notification */
+ execute_auto_ran(useridnr, headerfields);
+ } /* from: the useridnr for loop */
+
+ switch (dsnuser_worstcase_int(has_2, has_4, has_5)) {
+ case DSN_CLASS_OK:
+ delivery->dsn.class = DSN_CLASS_OK; /* Success. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 5; /* Valid. */
+ break;
+ case DSN_CLASS_TEMP:
+ delivery->dsn.class = DSN_CLASS_TEMP; /* Temporary transient failure. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 5; /* Valid. */
+ break;
+ case DSN_CLASS_FAIL:
+ delivery->dsn.class = DSN_CLASS_FAIL; /* Permanent failure. */
+ delivery->dsn.subject = 1; /* Address related. */
+ delivery->dsn.detail = 1; /* Does not exist. */
+ break;
+ }
+
+ trace(TRACE_DEBUG,
+ "insert_messages(): we need to deliver [%ld] "
+ "messages to external addresses",
+ list_totalnodes(delivery->forwards));
+
+ /* Each user may also have a list of external forwarding addresses. */
+ if (list_totalnodes(delivery->forwards) > 0) {
+
+ trace(TRACE_DEBUG,
+ "insert_messages(): delivering to external addresses");
+
+ /* Only the last step of the returnpath is used. */
+ ret_path = list_getstart(returnpath);
+
+ /* Forward using the temporary stored message. */
+ forward(tmpmsgidnr, delivery->forwards,
+ (ret_path ? ret_path->
+ data : "DBMAIL-MAILER"), header,
+ headersize);
+ }
+
+ } /* from: the delivery for loop */
+
+ /* Always delete the temporary message, even if the delivery failed.
+ * It is the MTA's job to requeue or bounce the message,
+ * and our job to keep a tidy database ;-) */
+ db_delete_message(tmpmsgidnr);
+ trace(TRACE_DEBUG,
+ "insert_messages(): temporary message deleted from database");
+
+ trace(TRACE_DEBUG, "insert_messages(): End of function");
+
+ return 0;
+}
diff --git a/pipe.h b/pipe.h
index d6da169d..5062f245 100644
--- a/pipe.h
+++ b/pipe.h
@@ -45,14 +45,15 @@
* \param headerfields list of header fields
* \return 0
*/
-int insert_messages(FILE *instream,
- char *header, u64_t headersize, u64_t headerrfcsize,
- struct list *headerfields, struct list *dsnusers, struct list *returnpath);
+int insert_messages(FILE * instream,
+ char *header, u64_t headersize, u64_t headerrfcsize,
+ struct list *headerfields, struct list *dsnusers,
+ struct list *returnpath);
/**
* \brief discards all input coming from instream
* \param instream FILE stream holding input from a client
*/
-void discard_client_input(FILE *instream);
+void discard_client_input(FILE * instream);
#endif
diff --git a/pop3.c b/pop3.c
index 0c3f1bfb..273f6867 100644
--- a/pop3.c
+++ b/pop3.c
@@ -55,809 +55,972 @@
extern int pop_before_smtp;
-int pop3 (void *stream, char *buffer, char *client_ip, PopSession_t *session);
+int pop3(void *stream, char *buffer, char *client_ip,
+ PopSession_t * session);
/* allowed pop3 commands */
-const char *commands [] =
-{
- "quit", /**< POP3_QUIT */
- "user", /**< POP3_USER */
- "pass", /**< POP3_PASS */
- "stat", /**< POP3_STAT */
- "list", /**< POP3_LIST */
- "retr", /**< POP3_RETR */
- "dele", /**< POP3_DELE */
- "noop", /**< POP3_NOOP */
- "last", /**< POP3_LAST */
- "rset", /**< POP3_RSET */
- "uidl", /**< POP3_UIDL */
- "apop", /**< POP3_APOP */
- "auth", /**< POP3_AUTH */
- "top", /**< POP3_TOP */
- "capa" /**< POP3_CAPA */
+const char *commands[] = {
+ "quit",
+ /**< POP3_QUIT */
+ "user",
+ /**< POP3_USER */
+ "pass",
+ /**< POP3_PASS */
+ "stat",
+ /**< POP3_STAT */
+ "list",
+ /**< POP3_LIST */
+ "retr",
+ /**< POP3_RETR */
+ "dele",
+ /**< POP3_DELE */
+ "noop",
+ /**< POP3_NOOP */
+ "last",
+ /**< POP3_LAST */
+ "rset",
+ /**< POP3_RSET */
+ "uidl",
+ /**< POP3_UIDL */
+ "apop",
+ /**< POP3_APOP */
+ "auth",
+ /**< POP3_AUTH */
+ "top",
+ /**< POP3_TOP */
+ "capa"
+ /**< POP3_CAPA */
};
const char validchars[] =
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
- "_.!@#$%^&*()-+=~[]{}<>:;\\/ ";
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "_.!@#$%^&*()-+=~[]{}<>:;\\/ ";
-int pop3_handle_connection (clientinfo_t *ci)
+int pop3_handle_connection(clientinfo_t * ci)
{
- /*
- Handles connection and calls
- pop command handler
- */
-
- int done = 1; /* loop state */
- char *buffer = NULL; /* connection buffer */
- char myhostname[64];
- int cnt; /* counter */
- PopSession_t session; /* current connection session */
- char unique_id[UID_SIZE];
-
- /* setting Session variables */
- session.error_count = 0;
- session.was_apop = 0;
-
- session.username = NULL;
- session.password = NULL;
-
- session.apop_stamp = NULL;
-
- session.SessionResult = 0;
-
- /* reset counters */
- session.totalsize = 0;
- session.virtual_totalsize = 0;
- session.totalmessages = 0;
- session.virtual_totalmessages = 0;
-
- /* getting hostname */
- gethostname (myhostname,64);
- myhostname[63] = '\0'; /* make sure string is terminated */
-
- buffer=(char *)my_malloc(INCOMING_BUFFER_SIZE*sizeof(char));
-
- if (!buffer)
- {
- trace (TRACE_MESSAGE,"pop3_handle_connection(): Could not allocate buffer");
- return 0;
- }
-
- /* create an unique timestamp + processid for APOP authentication */
- session.apop_stamp = (char *)my_malloc(APOP_STAMP_SIZE*sizeof(char));
- if (!session.apop_stamp)
- {
- trace (TRACE_MESSAGE,"pop3_handle_connection(): Could not allocate buffer for apop");
- return 0;
- }
- /* create an unique timestamp + processid for APOP authentication */
- create_unique_id(unique_id, 0);
- snprintf(session.apop_stamp, APOP_STAMP_SIZE,
- "<%s@%s>", unique_id, myhostname);
-
- if (ci->tx)
- {
- /* sending greeting */
- fprintf (ci->tx,"+OK DBMAIL pop3 server ready to rock %s\r\n",
- session.apop_stamp);
- fflush (ci->tx);
- }
- else
- {
- trace (TRACE_MESSAGE,"pop3_handle_connection(): TX stream is null!");
- return 0;
- }
-
- /* set authorization state */
- session.state = POP3_AUTHORIZATION_STATE;
-
- while (done > 0)
- {
- /* set the timeout counter */
- alarm (ci->timeout);
-
- /* clear the buffer */
- memset(buffer, 0, INCOMING_BUFFER_SIZE);
-
- for (cnt=0; cnt < INCOMING_BUFFER_SIZE-1; cnt++)
- {
- do
- {
- clearerr(ci->rx);
- fread(&buffer[cnt], 1, 1, ci->rx);
-
- /* leave, an alarm has occured during fread */
- if (!ci->rx) return 0;
-
- } while (ferror(ci->rx) && errno == EINTR);
-
- if (buffer[cnt] == '\n' || feof(ci->rx) || ferror(ci->rx))
- {
- buffer[cnt+1] = '\0';
- break;
- }
- }
-
- if (feof(ci->rx) || ferror(ci->rx))
- done = -1; /* check client eof */
- else
- {
- alarm (0); /* reset function handle timeout */
- done = pop3(ci->tx, buffer, ci->ip, &session); /* handle pop3 commands */
- }
- fflush (ci->tx);
- }
-
- /* we've reached the state */
- session.state = POP3_UPDATE_STATE;
-
- /* memory cleanup */
- my_free(buffer);
- buffer = NULL;
-
- my_free(session.apop_stamp);
- session.apop_stamp = NULL;
-
- if (session.username != NULL && (session.was_apop || session.password != NULL))
- {
- switch (session.SessionResult)
- {
- case 0:
- {
- trace (TRACE_MESSAGE, "pop3_handle_connection(): user %s logging out"
- " [messages=%llu, octets=%llu]",
- session.username, session.virtual_totalmessages,
- session.virtual_totalsize);
-
- /* if everything went well, write down everything and do a cleanup */
- db_update_pop(&session);
- break;
- }
-
- case 1: trace (TRACE_ERROR, "pop3_handle_connection(): EOF from client, "
- " connection terminated"); break;
-
- case 2: trace (TRACE_ERROR, "pop3_handle_connection(): alert! possible flood attempt,"
- " closing connection"); break;
-
- case 3: trace (TRACE_ERROR, "pop3_handle_connection(): authorization layer failure"); break;
- case 4: trace (TRACE_ERROR, "pop3_handle_connection(): storage layer failure"); break;
- }
- }
- else
- trace (TRACE_ERROR, "pop3_handle_connection(): error, uncomplete session");
-
- if (session.username != NULL)
- {
- /* username cleanup */
- my_free(session.username);
- session.username = NULL;
- }
-
- if (session.password != NULL)
- {
- /* password cleanup */
- my_free(session.password);
- session.password = NULL;
- }
-
- /* reset timers */
- alarm (0);
- __debug_dumpallocs();
-
- return 0;
+ /*
+ Handles connection and calls
+ pop command handler
+ */
+
+ int done = 1; /* loop state */
+ char *buffer = NULL; /* connection buffer */
+ char myhostname[64];
+ int cnt; /* counter */
+ PopSession_t session; /* current connection session */
+ char unique_id[UID_SIZE];
+
+ /* setting Session variables */
+ session.error_count = 0;
+ session.was_apop = 0;
+
+ session.username = NULL;
+ session.password = NULL;
+
+ session.apop_stamp = NULL;
+
+ session.SessionResult = 0;
+
+ /* reset counters */
+ session.totalsize = 0;
+ session.virtual_totalsize = 0;
+ session.totalmessages = 0;
+ session.virtual_totalmessages = 0;
+
+ /* getting hostname */
+ gethostname(myhostname, 64);
+ myhostname[63] = '\0'; /* make sure string is terminated */
+
+ buffer = (char *) my_malloc(INCOMING_BUFFER_SIZE * sizeof(char));
+
+ if (!buffer) {
+ trace(TRACE_MESSAGE,
+ "pop3_handle_connection(): Could not allocate buffer");
+ return 0;
+ }
+
+ /* create an unique timestamp + processid for APOP authentication */
+ session.apop_stamp =
+ (char *) my_malloc(APOP_STAMP_SIZE * sizeof(char));
+ if (!session.apop_stamp) {
+ trace(TRACE_MESSAGE,
+ "pop3_handle_connection(): Could not allocate buffer for apop");
+ return 0;
+ }
+ /* create an unique timestamp + processid for APOP authentication */
+ create_unique_id(unique_id, 0);
+ snprintf(session.apop_stamp, APOP_STAMP_SIZE,
+ "<%s@%s>", unique_id, myhostname);
+
+ if (ci->tx) {
+ /* sending greeting */
+ fprintf(ci->tx,
+ "+OK DBMAIL pop3 server ready to rock %s\r\n",
+ session.apop_stamp);
+ fflush(ci->tx);
+ } else {
+ trace(TRACE_MESSAGE,
+ "pop3_handle_connection(): TX stream is null!");
+ return 0;
+ }
+
+ /* set authorization state */
+ session.state = POP3_AUTHORIZATION_STATE;
+
+ while (done > 0) {
+ /* set the timeout counter */
+ alarm(ci->timeout);
+
+ /* clear the buffer */
+ memset(buffer, 0, INCOMING_BUFFER_SIZE);
+
+ for (cnt = 0; cnt < INCOMING_BUFFER_SIZE - 1; cnt++) {
+ do {
+ clearerr(ci->rx);
+ fread(&buffer[cnt], 1, 1, ci->rx);
+
+ /* leave, an alarm has occured during fread */
+ if (!ci->rx)
+ return 0;
+
+ } while (ferror(ci->rx) && errno == EINTR);
+
+ if (buffer[cnt] == '\n' || feof(ci->rx)
+ || ferror(ci->rx)) {
+ buffer[cnt + 1] = '\0';
+ break;
+ }
+ }
+
+ if (feof(ci->rx) || ferror(ci->rx))
+ done = -1; /* check client eof */
+ else {
+ alarm(0); /* reset function handle timeout */
+ done = pop3(ci->tx, buffer, ci->ip, &session); /* handle pop3 commands */
+ }
+ fflush(ci->tx);
+ }
+
+ /* we've reached the state */
+ session.state = POP3_UPDATE_STATE;
+
+ /* memory cleanup */
+ my_free(buffer);
+ buffer = NULL;
+
+ my_free(session.apop_stamp);
+ session.apop_stamp = NULL;
+
+ if (session.username != NULL
+ && (session.was_apop || session.password != NULL)) {
+ switch (session.SessionResult) {
+ case 0:
+ {
+ trace(TRACE_MESSAGE,
+ "pop3_handle_connection(): user %s logging out"
+ " [messages=%llu, octets=%llu]",
+ session.username,
+ session.virtual_totalmessages,
+ session.virtual_totalsize);
+
+ /* if everything went well, write down everything and do a cleanup */
+ db_update_pop(&session);
+ break;
+ }
+
+ case 1:
+ trace(TRACE_ERROR,
+ "pop3_handle_connection(): EOF from client, "
+ " connection terminated");
+ break;
+
+ case 2:
+ trace(TRACE_ERROR,
+ "pop3_handle_connection(): alert! possible flood attempt,"
+ " closing connection");
+ break;
+
+ case 3:
+ trace(TRACE_ERROR,
+ "pop3_handle_connection(): authorization layer failure");
+ break;
+ case 4:
+ trace(TRACE_ERROR,
+ "pop3_handle_connection(): storage layer failure");
+ break;
+ }
+ } else
+ trace(TRACE_ERROR,
+ "pop3_handle_connection(): error, uncomplete session");
+
+ if (session.username != NULL) {
+ /* username cleanup */
+ my_free(session.username);
+ session.username = NULL;
+ }
+
+ if (session.password != NULL) {
+ /* password cleanup */
+ my_free(session.password);
+ session.password = NULL;
+ }
+
+ /* reset timers */
+ alarm(0);
+ __debug_dumpallocs();
+
+ return 0;
}
-int pop3_error(PopSession_t *session, void *stream, const char *formatstring, ...)
- __attribute__((format(printf, 3, 4)));
-int pop3_error(PopSession_t *session, void *stream, const char *formatstring, ...)
+int pop3_error(PopSession_t * session, void *stream,
+ const char *formatstring, ...)
+ __attribute__ ((format(printf, 3, 4)));
+int pop3_error(PopSession_t * session, void *stream,
+ const char *formatstring, ...)
{
- va_list argp;
-
- if (session->error_count>=MAX_ERRORS)
- {
- trace(TRACE_MESSAGE, "pop3_error(): too many errors (MAX_ERRORS is %d)", MAX_ERRORS);
- fprintf((FILE *)stream, "-ERR loser, go play somewhere else\r\n");
- session->SessionResult = 2; /* possible flood */
- return -3;
- }
- else
- {
- va_start(argp, formatstring);
- vfprintf((FILE *)stream, formatstring, argp);
- va_end(argp);
- }
-
- trace(TRACE_DEBUG, "pop3_error(): an invalid command was issued");
- session->error_count++;
- return 1;
+ va_list argp;
+
+ if (session->error_count >= MAX_ERRORS) {
+ trace(TRACE_MESSAGE,
+ "pop3_error(): too many errors (MAX_ERRORS is %d)",
+ MAX_ERRORS);
+ fprintf((FILE *) stream,
+ "-ERR loser, go play somewhere else\r\n");
+ session->SessionResult = 2; /* possible flood */
+ return -3;
+ } else {
+ va_start(argp, formatstring);
+ vfprintf((FILE *) stream, formatstring, argp);
+ va_end(argp);
+ }
+
+ trace(TRACE_DEBUG, "pop3_error(): an invalid command was issued");
+ session->error_count++;
+ return 1;
}
-int pop3 (void *stream, char *buffer, char *client_ip, PopSession_t *session)
+int pop3(void *stream, char *buffer, char *client_ip,
+ PopSession_t * session)
{
- /* returns a 0 on a quit
- * -1 on a failure
- * 1 on a success */
- char *command, *value;
- Pop3Cmd_t cmdtype;
- int found=0;
- int indx=0;
- u64_t result;
- int validate_result;
- u64_t top_lines, top_messageid;
- struct element *tmpelement;
- char *md5_apop_he;
- char *searchptr;
- u64_t user_idnr;
-
- /* buffer overflow attempt */
- if (strlen(buffer)>MAX_IN_BUFFER)
- {
- trace(TRACE_DEBUG, "pop3(): buffer overflow attempt");
- return -3;
- }
-
- /* check for command issued */
- while (strchr(validchars, buffer[indx]))
- indx++;
-
- /* end buffer */
- buffer[indx]='\0';
-
- trace(TRACE_DEBUG,"pop3(): incoming buffer: [%s]",buffer);
-
- command=buffer;
-
- value=strstr (command," "); /* look for the separator */
-
- if (value!=NULL)
- {
- *value = '\0'; /* set a \0 on the command end */
- value++; /* skip space */
-
- if (strlen(value) == 0)
- value=NULL; /* no value specified */
- else
- {
- trace (TRACE_DEBUG,"pop3(): command issued :cmd [%s], value [%s]\n",command, value);
- }
- }
-
- /* find command that was issued */
- for (cmdtype = POP3_QUIT; cmdtype <= POP3_CAPA; cmdtype ++)
- if (strcasecmp(command, commands[cmdtype]) == 0) {
- session->was_apop = 1;
- break;
- }
-
- trace (TRACE_DEBUG,"pop3(): command looked up as commandtype %d", cmdtype);
-
- /* commands that are allowed to have no arguments */
- if ((value==NULL) && (cmdtype!=POP3_QUIT) && (cmdtype!=POP3_LIST) &&
- (cmdtype!=POP3_STAT) && (cmdtype!=POP3_RSET) &&
- (cmdtype!=POP3_NOOP) && (cmdtype!=POP3_LAST) &&
- (cmdtype!=POP3_UIDL) && (cmdtype!=POP3_AUTH) &&
- (cmdtype!=POP3_CAPA))
- {
- return pop3_error(session, stream, "-ERR your command does not compute\r\n");
- }
-
- switch (cmdtype)
- {
- case POP3_QUIT :
- {
- fprintf ((FILE *)stream, "+OK see ya later\r\n");
- return 0;
- }
- case POP3_USER :
- {
- if (session->state != POP3_AUTHORIZATION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- if (session->username != NULL)
- {
- /* reset username */
- my_free(session->username);
- session->username = NULL;
- }
-
- if (session->username == NULL)
- {
- if (strlen(value)>MAX_USERID_SIZE)
- return pop3_error(session, stream,"-ERR userid is too long\r\n");
-
- /* create memspace for username */
- memtst((session->username = (char *)my_malloc(strlen(value)+1))==NULL);
- strncpy (session->username, value, strlen(value)+1);
- }
-
- fprintf ((FILE *)stream, "+OK Password required for %s\r\n",
- session->username);
- return 1;
- }
-
- case POP3_PASS :
- {
- if (session->state != POP3_AUTHORIZATION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- if (session->password != NULL)
- {
- my_free(session->password);
- session->password = NULL;
- }
-
- if (session->password == NULL)
- {
- /* create memspace for password */
- memtst((session->password = (char *)my_malloc(strlen(value)+1))==NULL);
- strncpy (session->password, value, strlen(value)+1);
- }
-
- /* check in authorization layer if these credentials are correct */
- validate_result = auth_validate(session->username,
- session->password,
- &result);
- switch (validate_result) {
- case -1:
- session->SessionResult = 3; return -1;
- case 0:
- {
- trace (TRACE_ERROR,"pop3(): user [%s] tried to "
- "login with wrong password",
- session->username);
-
- /* clear username, must be re-entered according to RFC */
- my_free (session->username);
- session->username = NULL;
-
- /* also, if the password is set, clear it */
- if (session->password != NULL)
- {
- my_free (session->password);
- session->password = NULL;
- }
- return pop3_error (session, stream,"-ERR username/password incorrect\r\n");
- }
- default:
- {
- /* user logged in OK */
- session->state = POP3_TRANSACTION_STATE;
-
- /* now we're going to build up a session for this user */
- trace(TRACE_DEBUG,"pop3(): validation OK, building a session for user [%s]",
- session->username);
-
- /* if pop_before_smtp is active, log this ip */
- if (pop_before_smtp)
- db_log_ip(client_ip);
-
- result = db_createsession (result, session);
- if (result == 1)
- {
- fprintf ((FILE *)stream, "+OK %s has %llu messages (%llu octets)\r\n",
- session->username, session->virtual_totalmessages,
- session->virtual_totalsize);
- trace(TRACE_MESSAGE,
- "pop3(): user %s logged in [messages=%llu, octets=%llu]",
- session->username, session->virtual_totalmessages,
- session->virtual_totalsize);
+ /* returns a 0 on a quit
+ * -1 on a failure
+ * 1 on a success */
+ char *command, *value;
+ Pop3Cmd_t cmdtype;
+ int found = 0;
+ int indx = 0;
+ u64_t result;
+ int validate_result;
+ u64_t top_lines, top_messageid;
+ struct element *tmpelement;
+ char *md5_apop_he;
+ char *searchptr;
+ u64_t user_idnr;
+
+ /* buffer overflow attempt */
+ if (strlen(buffer) > MAX_IN_BUFFER) {
+ trace(TRACE_DEBUG, "pop3(): buffer overflow attempt");
+ return -3;
+ }
+
+ /* check for command issued */
+ while (strchr(validchars, buffer[indx]))
+ indx++;
+
+ /* end buffer */
+ buffer[indx] = '\0';
+
+ trace(TRACE_DEBUG, "pop3(): incoming buffer: [%s]", buffer);
+
+ command = buffer;
+
+ value = strstr(command, " "); /* look for the separator */
+
+ if (value != NULL) {
+ *value = '\0'; /* set a \0 on the command end */
+ value++; /* skip space */
+
+ if (strlen(value) == 0)
+ value = NULL; /* no value specified */
+ else {
+ trace(TRACE_DEBUG,
+ "pop3(): command issued :cmd [%s], value [%s]\n",
+ command, value);
+ }
+ }
+
+ /* find command that was issued */
+ for (cmdtype = POP3_QUIT; cmdtype <= POP3_CAPA; cmdtype++)
+ if (strcasecmp(command, commands[cmdtype]) == 0) {
+ session->was_apop = 1;
+ break;
+ }
+
+ trace(TRACE_DEBUG, "pop3(): command looked up as commandtype %d",
+ cmdtype);
+
+ /* commands that are allowed to have no arguments */
+ if ((value == NULL) && (cmdtype != POP3_QUIT)
+ && (cmdtype != POP3_LIST) && (cmdtype != POP3_STAT)
+ && (cmdtype != POP3_RSET) && (cmdtype != POP3_NOOP)
+ && (cmdtype != POP3_LAST) && (cmdtype != POP3_UIDL)
+ && (cmdtype != POP3_AUTH) && (cmdtype != POP3_CAPA)) {
+ return pop3_error(session, stream,
+ "-ERR your command does not compute\r\n");
+ }
+
+ switch (cmdtype) {
+ case POP3_QUIT:
+ {
+ fprintf((FILE *) stream, "+OK see ya later\r\n");
+ return 0;
+ }
+ case POP3_USER:
+ {
+ if (session->state != POP3_AUTHORIZATION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ if (session->username != NULL) {
+ /* reset username */
+ my_free(session->username);
+ session->username = NULL;
+ }
+
+ if (session->username == NULL) {
+ if (strlen(value) > MAX_USERID_SIZE)
+ return pop3_error(session, stream,
+ "-ERR userid is too long\r\n");
+
+ /* create memspace for username */
+ memtst((session->username =
+ (char *) my_malloc(strlen(value) +
+ 1)) == NULL);
+ strncpy(session->username, value,
+ strlen(value) + 1);
+ }
+
+ fprintf((FILE *) stream,
+ "+OK Password required for %s\r\n",
+ session->username);
+ return 1;
+ }
+
+ case POP3_PASS:
+ {
+ if (session->state != POP3_AUTHORIZATION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ if (session->password != NULL) {
+ my_free(session->password);
+ session->password = NULL;
+ }
+
+ if (session->password == NULL) {
+ /* create memspace for password */
+ memtst((session->password =
+ (char *) my_malloc(strlen(value) +
+ 1)) == NULL);
+ strncpy(session->password, value,
+ strlen(value) + 1);
+ }
+
+ /* check in authorization layer if these credentials are correct */
+ validate_result = auth_validate(session->username,
+ session->password,
+ &result);
+ switch (validate_result) {
+ case -1:
+ session->SessionResult = 3;
+ return -1;
+ case 0:
+ {
+ trace(TRACE_ERROR,
+ "pop3(): user [%s] tried to "
+ "login with wrong password",
+ session->username);
+
+ /* clear username, must be re-entered according to RFC */
+ my_free(session->username);
+ session->username = NULL;
+
+ /* also, if the password is set, clear it */
+ if (session->password != NULL) {
+ my_free(session->password);
+ session->password = NULL;
+ }
+ return pop3_error(session, stream,
+ "-ERR username/password incorrect\r\n");
+ }
+ default:
+ {
+ /* user logged in OK */
+ session->state =
+ POP3_TRANSACTION_STATE;
+
+ /* now we're going to build up a session for this user */
+ trace(TRACE_DEBUG,
+ "pop3(): validation OK, building a session for user [%s]",
+ session->username);
+
+ /* if pop_before_smtp is active, log this ip */
+ if (pop_before_smtp)
+ db_log_ip(client_ip);
+
+ result =
+ db_createsession(result,
+ session);
+ if (result == 1) {
+ fprintf((FILE *) stream,
+ "+OK %s has %llu messages (%llu octets)\r\n",
+ session->username,
+ session->
+ virtual_totalmessages,
+ session->
+ virtual_totalsize);
+ trace(TRACE_MESSAGE,
+ "pop3(): user %s logged in [messages=%llu, octets=%llu]",
+ session->username,
+ session->
+ virtual_totalmessages,
+ session->
+ virtual_totalsize);
#ifdef PROC_TITLES
- /* sets the program ARGV's with username */
- set_proc_title("USER %s [%s]", session->username, client_ip);
+ /* sets the program ARGV's with username */
+ set_proc_title
+ ("USER %s [%s]",
+ session->username,
+ client_ip);
#endif
- }
- else
- session->SessionResult = 4; /* something went wrong on DB layer */
- return result;
- }
- }
- return 1;
- }
-
- case POP3_LIST :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream, "-ERR wrong command mode, sir\r\n");
-
- tmpelement = list_getstart (&session->messagelst);
- if (value != NULL)
- {
- /* they're asking for a specific message */
- while (tmpelement != NULL)
- {
- if (((struct message *)tmpelement->data)->messageid==strtoull(value, NULL, 10) &&
- ((struct message *)tmpelement->data)->virtual_messagestatus<2)
- {
- fprintf ((FILE *)stream,"+OK %llu %llu\r\n",((struct message *)tmpelement->data)->messageid,
- ((struct message *)tmpelement->data)->msize);
- found = 1;
- }
- tmpelement=tmpelement->nextnode;
- }
- if (!found)
- return pop3_error (session, stream,"-ERR no such message\r\n");
- else
- return 1;
- }
-
- /* just drop the list */
- fprintf ((FILE *)stream, "+OK %llu messages (%llu octets)\r\n",
- session->virtual_totalmessages,
- session->virtual_totalsize);
-
- if (session->virtual_totalmessages>0)
- {
- /* traversing list */
- while (tmpelement!=NULL)
- {
- if (((struct message *)tmpelement->data)->virtual_messagestatus<2)
- fprintf ((FILE *)stream,"%llu %llu\r\n",((struct message *)tmpelement->data)->messageid,
- ((struct message *)tmpelement->data)->msize);
- tmpelement=tmpelement->nextnode;
- }
- }
- fprintf ((FILE *)stream,".\r\n");
- return 1;
- }
-
- case POP3_STAT :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream, "-ERR wrong command mode, sir\r\n");
-
- fprintf ((FILE *)stream, "+OK %llu %llu\r\n",
- session->virtual_totalmessages,
- session->virtual_totalsize);
-
- return 1;
- }
-
- case POP3_RETR :
- {
- trace(TRACE_DEBUG,"pop3():RETR command, retrieving message");
-
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- tmpelement=list_getstart(&(session->messagelst));
-
- /* selecting a message */
- trace(TRACE_DEBUG,"pop3(): RETR command, selecting message");
- while (tmpelement!=NULL)
- {
- if (((struct message *)tmpelement->data)->messageid==strtoull(value, NULL, 10) &&
- ((struct message *)tmpelement->data)->virtual_messagestatus<2) /* message is not deleted */
- {
- ((struct message *)tmpelement->data)->virtual_messagestatus=1;
- fprintf ((FILE *)stream,"+OK %llu octets\r\n",((struct message *)tmpelement->data)->msize);
- return db_send_message_lines ((void *)stream, ((struct message *)tmpelement->data)->realmessageid,-2, 0);
- }
- tmpelement = tmpelement->nextnode;
- }
- return pop3_error (session, stream,"-ERR no such message\r\n");
- }
-
- case POP3_DELE :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- tmpelement=list_getstart(&(session->messagelst));
-
- /* selecting a message */
- while (tmpelement!=NULL)
- {
- if (((struct message *)tmpelement->data)->messageid==strtoull(value, NULL, 10) &&
- ((struct message *)tmpelement->data)->virtual_messagestatus<2) /* message is not deleted */
- {
- ((struct message *)tmpelement->data)->virtual_messagestatus=2;
- /* decrease our virtual list fields */
- session->virtual_totalsize-=((struct message *)tmpelement->data)->msize;
- session->virtual_totalmessages-=1;
-
- fprintf((FILE *)stream,"+OK message %llu deleted\r\n",
- ((struct message *)tmpelement->data)->messageid);
- return 1;
- }
- tmpelement = tmpelement->nextnode;
- }
- return pop3_error (session, stream,"-ERR [%s] no such message\r\n",value);
- }
-
- case POP3_RSET :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- tmpelement=list_getstart(&(session->messagelst));
-
- session->virtual_totalsize = session->totalsize;
- session->virtual_totalmessages = session->totalmessages;
-
- while (tmpelement!=NULL)
- {
- ((struct message *)tmpelement->data)->virtual_messagestatus=((struct message *)tmpelement->data)->messagestatus;
- tmpelement=tmpelement->nextnode;
- }
-
- fprintf ((FILE *)stream, "+OK %llu messages (%llu octets)\r\n",
- session->virtual_totalmessages,
- session->virtual_totalsize);
-
- return 1;
- }
-
- case POP3_LAST :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- tmpelement = list_getstart(&(session->messagelst));
-
- while (tmpelement!=NULL)
- {
- if (((struct message *)tmpelement->data)->virtual_messagestatus==0)
- {
- /* we need the last message that has been accessed */
- fprintf ((FILE *)stream, "+OK %llu\r\n",((struct message *)tmpelement->data)->messageid-1);
- return 1;
- }
- tmpelement = tmpelement->nextnode;
- }
-
- /* all old messages */
- fprintf ((FILE *)stream, "+OK %llu\r\n",
- session->virtual_totalmessages);
-
- return 1;
- }
-
- case POP3_NOOP :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- fprintf ((FILE *)stream, "+OK\r\n");
- return 1;
- }
-
- case POP3_UIDL :
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- tmpelement = list_getstart(&(session->messagelst));
-
- if (value!=NULL)
- {
- /* they're asking for a specific message */
- while (tmpelement!=NULL)
- {
- if (((struct message *)tmpelement->data)->messageid==strtoull(value, NULL, 10)&&
- ((struct message *)tmpelement->data)->virtual_messagestatus<2)
- {
- fprintf ((FILE *)stream,"+OK %llu %s\r\n",((struct message *)tmpelement->data)->messageid,
- ((struct message *)tmpelement->data)->uidl);
- found = 1;
- }
- tmpelement = tmpelement->nextnode;
- }
- if (!found)
- return pop3_error (session, stream,"-ERR no such message\r\n");
- else
- return 1;
- }
-
- /* just drop the list */
- fprintf ((FILE *)stream, "+OK Some very unique numbers for you\r\n");
-
- if (session->virtual_totalmessages > 0)
- {
- /* traversing list */
- while (tmpelement!=NULL)
- {
- if (((struct message *)tmpelement->data)->virtual_messagestatus<2)
- fprintf ((FILE *)stream,"%llu %s\r\n",((struct message *)tmpelement->data)->messageid,
- ((struct message *)tmpelement->data)->uidl);
-
- tmpelement = tmpelement->nextnode;
- }
- }
-
- fprintf ((FILE *)stream,".\r\n");
-
- return 1;
- }
-
- case POP3_APOP:
- {
- if (session->state != POP3_AUTHORIZATION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- /* find out where the md5 hash starts */
- searchptr=strstr(value," ");
-
- if (searchptr==NULL)
- return pop3_error (session, stream,"-ERR your command does not compute\r\n");
-
- /* skip the space */
- searchptr = searchptr+1;
-
- /* value should now be the username */
- value[searchptr-value-1]='\0';
-
- if (strlen(searchptr)!=32)
- return pop3_error(session, stream,"-ERR the thingy you issued is not a valid md5 hash\r\n");
-
- /* create memspace for md5 hash */
- memtst((md5_apop_he=(char *)my_malloc(strlen(searchptr)+1))==NULL);
- strncpy (md5_apop_he,searchptr,strlen(searchptr)+1);
-
- if (strlen(value)>MAX_USERID_SIZE)
- return pop3_error(session, stream,"-ERR userid is too long\r\n");
-
- /* create memspace for username */
- memtst((session->username = (char *)my_malloc(strlen(value)+1))==NULL);
- strncpy (session->username,value,strlen(value)+1);
-
- /*
- * check the encryption used for this user
- * note that if the user does not exist it is not noted
- * by db_getencryption()
- */
- if (auth_user_exists(session->username, &user_idnr) == -1) {
- trace(TRACE_ERROR, "%s,%s: error finding if user exists. "
- "username = [%s]", __FILE__, __FUNCTION__,
- session->username);
- return -1;
- }
- if (strcasecmp(auth_getencryption(user_idnr), "") != 0)
- {
- /* it should be clear text */
- my_free(md5_apop_he);
- my_free(session->username);
- session->username = NULL;
- md5_apop_he = 0;
- return pop3_error(session, stream,"-ERR APOP command is not supported for this user\r\n");
- }
-
- trace (TRACE_DEBUG,"pop3(): APOP auth, username [%s], md5_hash [%s]",
- session->username,
- md5_apop_he);
-
- result = auth_md5_validate (session->username, md5_apop_he, session->apop_stamp);
-
- my_free(md5_apop_he);
- md5_apop_he = 0;
-
- switch (result)
- {
- case -1: session->SessionResult = 3; return -1;
- case 0:
- trace (TRACE_ERROR,"pop3(): user [%s] tried to login with wrong password",
- session->username);
-
- my_free (session->username);
- session->username = NULL;
-
- my_free (session->password);
- session->password = NULL;
-
- return pop3_error(session, stream,"-ERR authentication attempt is invalid\r\n");
-
- default:
- {
- /* user logged in OK */
- session->state = POP3_TRANSACTION_STATE;
-
- /* user seems to be valid, let's build a session */
- trace(TRACE_DEBUG,"pop3(): validation OK, building a session for user [%s]",
- session->username);
-
- /* if pop_before_smtp is active, log this ip */
- if (pop_before_smtp)
- db_log_ip(client_ip);
-
- result=db_createsession(result, session);
- if (result == 1)
- {
- fprintf((FILE *)stream, "+OK %s has %llu messages (%llu octets)\r\n",
- session->username, session->virtual_totalmessages,
- session->virtual_totalsize);
-
- trace(TRACE_MESSAGE,"pop3(): user %s logged in [messages=%llu, octets=%llu]",
- session->username, session->virtual_totalmessages,
- session->virtual_totalsize);
+ } else
+ session->SessionResult = 4; /* something went wrong on DB layer */
+ return result;
+ }
+ }
+ return 1;
+ }
+
+ case POP3_LIST:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ tmpelement = list_getstart(&session->messagelst);
+ if (value != NULL) {
+ /* they're asking for a specific message */
+ while (tmpelement != NULL) {
+ if (((struct message *)
+ tmpelement->data)->
+ messageid == strtoull(value,
+ NULL, 10)
+ && ((struct message *)
+ tmpelement->data)->
+ virtual_messagestatus < 2) {
+ fprintf((FILE *) stream,
+ "+OK %llu %llu\r\n",
+ ((struct message *)
+ tmpelement->
+ data)->messageid,
+ ((struct message *)
+ tmpelement->
+ data)->msize);
+ found = 1;
+ }
+ tmpelement = tmpelement->nextnode;
+ }
+ if (!found)
+ return pop3_error(session, stream,
+ "-ERR no such message\r\n");
+ else
+ return 1;
+ }
+
+ /* just drop the list */
+ fprintf((FILE *) stream,
+ "+OK %llu messages (%llu octets)\r\n",
+ session->virtual_totalmessages,
+ session->virtual_totalsize);
+
+ if (session->virtual_totalmessages > 0) {
+ /* traversing list */
+ while (tmpelement != NULL) {
+ if (((struct message *)
+ tmpelement->data)->
+ virtual_messagestatus < 2)
+ fprintf((FILE *) stream,
+ "%llu %llu\r\n",
+ ((struct message *)
+ tmpelement->
+ data)->messageid,
+ ((struct message *)
+ tmpelement->
+ data)->msize);
+ tmpelement = tmpelement->nextnode;
+ }
+ }
+ fprintf((FILE *) stream, ".\r\n");
+ return 1;
+ }
+
+ case POP3_STAT:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ fprintf((FILE *) stream, "+OK %llu %llu\r\n",
+ session->virtual_totalmessages,
+ session->virtual_totalsize);
+
+ return 1;
+ }
+
+ case POP3_RETR:
+ {
+ trace(TRACE_DEBUG,
+ "pop3():RETR command, retrieving message");
+
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ tmpelement = list_getstart(&(session->messagelst));
+
+ /* selecting a message */
+ trace(TRACE_DEBUG,
+ "pop3(): RETR command, selecting message");
+ while (tmpelement != NULL) {
+ if (((struct message *) tmpelement->data)->messageid == strtoull(value, NULL, 10) && ((struct message *) tmpelement->data)->virtual_messagestatus < 2) { /* message is not deleted */
+ ((struct message *) tmpelement->
+ data)->virtual_messagestatus = 1;
+ fprintf((FILE *) stream,
+ "+OK %llu octets\r\n",
+ ((struct message *)
+ tmpelement->data)->msize);
+ return
+ db_send_message_lines((void *)
+ stream,
+ ((struct
+ message
+ *)
+ tmpelement->
+ data)->
+ realmessageid,
+ -2, 0);
+ }
+ tmpelement = tmpelement->nextnode;
+ }
+ return pop3_error(session, stream,
+ "-ERR no such message\r\n");
+ }
+
+ case POP3_DELE:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ tmpelement = list_getstart(&(session->messagelst));
+
+ /* selecting a message */
+ while (tmpelement != NULL) {
+ if (((struct message *) tmpelement->data)->messageid == strtoull(value, NULL, 10) && ((struct message *) tmpelement->data)->virtual_messagestatus < 2) { /* message is not deleted */
+ ((struct message *) tmpelement->
+ data)->virtual_messagestatus = 2;
+ /* decrease our virtual list fields */
+ session->virtual_totalsize -=
+ ((struct message *)
+ tmpelement->data)->msize;
+ session->virtual_totalmessages -=
+ 1;
+
+ fprintf((FILE *) stream,
+ "+OK message %llu deleted\r\n",
+ ((struct message *)
+ tmpelement->data)->
+ messageid);
+ return 1;
+ }
+ tmpelement = tmpelement->nextnode;
+ }
+ return pop3_error(session, stream,
+ "-ERR [%s] no such message\r\n",
+ value);
+ }
+
+ case POP3_RSET:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ tmpelement = list_getstart(&(session->messagelst));
+
+ session->virtual_totalsize = session->totalsize;
+ session->virtual_totalmessages =
+ session->totalmessages;
+
+ while (tmpelement != NULL) {
+ ((struct message *) tmpelement->data)->
+ virtual_messagestatus =
+ ((struct message *) tmpelement->data)->
+ messagestatus;
+ tmpelement = tmpelement->nextnode;
+ }
+
+ fprintf((FILE *) stream,
+ "+OK %llu messages (%llu octets)\r\n",
+ session->virtual_totalmessages,
+ session->virtual_totalsize);
+
+ return 1;
+ }
+
+ case POP3_LAST:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ tmpelement = list_getstart(&(session->messagelst));
+
+ while (tmpelement != NULL) {
+ if (((struct message *) tmpelement->data)->
+ virtual_messagestatus == 0) {
+ /* we need the last message that has been accessed */
+ fprintf((FILE *) stream,
+ "+OK %llu\r\n",
+ ((struct message *)
+ tmpelement->data)->
+ messageid - 1);
+ return 1;
+ }
+ tmpelement = tmpelement->nextnode;
+ }
+
+ /* all old messages */
+ fprintf((FILE *) stream, "+OK %llu\r\n",
+ session->virtual_totalmessages);
+
+ return 1;
+ }
+
+ case POP3_NOOP:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ fprintf((FILE *) stream, "+OK\r\n");
+ return 1;
+ }
+
+ case POP3_UIDL:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ tmpelement = list_getstart(&(session->messagelst));
+
+ if (value != NULL) {
+ /* they're asking for a specific message */
+ while (tmpelement != NULL) {
+ if (((struct message *)
+ tmpelement->data)->
+ messageid == strtoull(value,
+ NULL, 10)
+ && ((struct message *)
+ tmpelement->data)->
+ virtual_messagestatus < 2) {
+ fprintf((FILE *) stream,
+ "+OK %llu %s\r\n",
+ ((struct message *)
+ tmpelement->
+ data)->messageid,
+ ((struct message *)
+ tmpelement->
+ data)->uidl);
+ found = 1;
+ }
+ tmpelement = tmpelement->nextnode;
+ }
+ if (!found)
+ return pop3_error(session, stream,
+ "-ERR no such message\r\n");
+ else
+ return 1;
+ }
+
+ /* just drop the list */
+ fprintf((FILE *) stream,
+ "+OK Some very unique numbers for you\r\n");
+
+ if (session->virtual_totalmessages > 0) {
+ /* traversing list */
+ while (tmpelement != NULL) {
+ if (((struct message *)
+ tmpelement->data)->
+ virtual_messagestatus < 2)
+ fprintf((FILE *) stream,
+ "%llu %s\r\n",
+ ((struct message *)
+ tmpelement->
+ data)->messageid,
+ ((struct message *)
+ tmpelement->
+ data)->uidl);
+
+ tmpelement = tmpelement->nextnode;
+ }
+ }
+
+ fprintf((FILE *) stream, ".\r\n");
+
+ return 1;
+ }
+
+ case POP3_APOP:
+ {
+ if (session->state != POP3_AUTHORIZATION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ /* find out where the md5 hash starts */
+ searchptr = strstr(value, " ");
+
+ if (searchptr == NULL)
+ return pop3_error(session, stream,
+ "-ERR your command does not compute\r\n");
+
+ /* skip the space */
+ searchptr = searchptr + 1;
+
+ /* value should now be the username */
+ value[searchptr - value - 1] = '\0';
+
+ if (strlen(searchptr) != 32)
+ return pop3_error(session, stream,
+ "-ERR the thingy you issued is not a valid md5 hash\r\n");
+
+ /* create memspace for md5 hash */
+ memtst((md5_apop_he =
+ (char *) my_malloc(strlen(searchptr) +
+ 1)) == NULL);
+ strncpy(md5_apop_he, searchptr,
+ strlen(searchptr) + 1);
+
+ if (strlen(value) > MAX_USERID_SIZE)
+ return pop3_error(session, stream,
+ "-ERR userid is too long\r\n");
+
+ /* create memspace for username */
+ memtst((session->username =
+ (char *) my_malloc(strlen(value) + 1)) ==
+ NULL);
+ strncpy(session->username, value,
+ strlen(value) + 1);
+
+ /*
+ * check the encryption used for this user
+ * note that if the user does not exist it is not noted
+ * by db_getencryption()
+ */
+ if (auth_user_exists(session->username, &user_idnr)
+ == -1) {
+ trace(TRACE_ERROR,
+ "%s,%s: error finding if user exists. "
+ "username = [%s]", __FILE__,
+ __FUNCTION__, session->username);
+ return -1;
+ }
+ if (strcasecmp(auth_getencryption(user_idnr), "")
+ != 0) {
+ /* it should be clear text */
+ my_free(md5_apop_he);
+ my_free(session->username);
+ session->username = NULL;
+ md5_apop_he = 0;
+ return pop3_error(session, stream,
+ "-ERR APOP command is not supported for this user\r\n");
+ }
+
+ trace(TRACE_DEBUG,
+ "pop3(): APOP auth, username [%s], md5_hash [%s]",
+ session->username, md5_apop_he);
+
+ result =
+ auth_md5_validate(session->username,
+ md5_apop_he,
+ session->apop_stamp);
+
+ my_free(md5_apop_he);
+ md5_apop_he = 0;
+
+ switch (result) {
+ case -1:
+ session->SessionResult = 3;
+ return -1;
+ case 0:
+ trace(TRACE_ERROR,
+ "pop3(): user [%s] tried to login with wrong password",
+ session->username);
+
+ my_free(session->username);
+ session->username = NULL;
+
+ my_free(session->password);
+ session->password = NULL;
+
+ return pop3_error(session, stream,
+ "-ERR authentication attempt is invalid\r\n");
+
+ default:
+ {
+ /* user logged in OK */
+ session->state =
+ POP3_TRANSACTION_STATE;
+
+ /* user seems to be valid, let's build a session */
+ trace(TRACE_DEBUG,
+ "pop3(): validation OK, building a session for user [%s]",
+ session->username);
+
+ /* if pop_before_smtp is active, log this ip */
+ if (pop_before_smtp)
+ db_log_ip(client_ip);
+
+ result =
+ db_createsession(result,
+ session);
+ if (result == 1) {
+ fprintf((FILE *) stream,
+ "+OK %s has %llu messages (%llu octets)\r\n",
+ session->username,
+ session->
+ virtual_totalmessages,
+ session->
+ virtual_totalsize);
+
+ trace(TRACE_MESSAGE,
+ "pop3(): user %s logged in [messages=%llu, octets=%llu]",
+ session->username,
+ session->
+ virtual_totalmessages,
+ session->
+ virtual_totalsize);
#ifdef PROC_TITLES
- set_proc_title("USER %s [%s]", session->username, client_ip);
+ set_proc_title
+ ("USER %s [%s]",
+ session->username,
+ client_ip);
#endif
- }
- else
- session->SessionResult = 4; /* storage layer error */
-
- return result;
- }
- }
- return 1;
- }
-
- case POP3_AUTH:
- {
- if (session->state != POP3_AUTHORIZATION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- fprintf ((FILE *)stream, "+OK List of supported mechanisms\r\n.\r\n");
- return 1;
- }
-
- case POP3_TOP:
- {
- if (session->state != POP3_TRANSACTION_STATE)
- return pop3_error(session, stream,"-ERR wrong command mode, sir\r\n");
-
- /* find out how many lines they want */
- searchptr = strstr(value," ");
-
- /* insufficient parameters */
- if (searchptr == NULL)
- return pop3_error (session, stream,"-ERR your command does not compute\r\n");
-
- /* skip the space */
- searchptr = searchptr + 1;
-
- /* value should now be the the message that needs to be retrieved */
- value[searchptr-value-1] = '\0';
-
- /* check if searchptr or value are negative. If so return an
- error. This is done by only letting the strings contain
- digits (0-9) */
- if (strspn(searchptr, "0123456789") != strlen(searchptr))
- return pop3_error(session, stream, "-ERR wrong parameter\r\n");
- if (strspn(value, "0123456789") != strlen(value))
- return pop3_error(session, stream, "-ERR wrong parameter\r\n");
-
- top_lines = strtoull(searchptr, NULL, 10);
- top_messageid = strtoull(value, NULL, 10);
- if (top_messageid < 1)
- return pop3_error(session, stream,"-ERR wrong parameter\r\n");
-
- trace(TRACE_DEBUG,"pop3():TOP command (partially) retrieving message");
-
- tmpelement=list_getstart(&(session->messagelst));
-
- /* selecting a message */
- trace(TRACE_DEBUG,"pop3(): TOP command, selecting message");
-
- while (tmpelement != NULL)
- {
- if (((struct message *)tmpelement->data)->messageid==top_messageid &&
- ((struct message *)tmpelement->data)->virtual_messagestatus<2) /* message is not deleted */
- {
- fprintf ((FILE *)stream,"+OK %llu lines of message %llu\r\n",top_lines, top_messageid);
- return db_send_message_lines (stream, ((struct message *)tmpelement->data)->realmessageid, top_lines, 0);
- }
- tmpelement = tmpelement->nextnode;
- }
- return pop3_error (session, stream,"-ERR no such message\r\n");
-
- return 1;
- }
- case POP3_CAPA:
- {
- fprintf((FILE *)stream,
- "+OK, Capability list follows\r\n"
- "TOP\r\nUSER\r\nUIDL\r\n.\r\n");
- return 1;
- }
-
- default :
- {
- return pop3_error(session, stream,"-ERR command not understood, sir\r\n");
- }
- }
- return 1;
+ } else
+ session->SessionResult = 4; /* storage layer error */
+
+ return result;
+ }
+ }
+ return 1;
+ }
+
+ case POP3_AUTH:
+ {
+ if (session->state != POP3_AUTHORIZATION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ fprintf((FILE *) stream,
+ "+OK List of supported mechanisms\r\n.\r\n");
+ return 1;
+ }
+
+ case POP3_TOP:
+ {
+ if (session->state != POP3_TRANSACTION_STATE)
+ return pop3_error(session, stream,
+ "-ERR wrong command mode, sir\r\n");
+
+ /* find out how many lines they want */
+ searchptr = strstr(value, " ");
+
+ /* insufficient parameters */
+ if (searchptr == NULL)
+ return pop3_error(session, stream,
+ "-ERR your command does not compute\r\n");
+
+ /* skip the space */
+ searchptr = searchptr + 1;
+
+ /* value should now be the the message that needs to be retrieved */
+ value[searchptr - value - 1] = '\0';
+
+ /* check if searchptr or value are negative. If so return an
+ error. This is done by only letting the strings contain
+ digits (0-9) */
+ if (strspn(searchptr, "0123456789") !=
+ strlen(searchptr))
+ return pop3_error(session, stream,
+ "-ERR wrong parameter\r\n");
+ if (strspn(value, "0123456789") != strlen(value))
+ return pop3_error(session, stream,
+ "-ERR wrong parameter\r\n");
+
+ top_lines = strtoull(searchptr, NULL, 10);
+ top_messageid = strtoull(value, NULL, 10);
+ if (top_messageid < 1)
+ return pop3_error(session, stream,
+ "-ERR wrong parameter\r\n");
+
+ trace(TRACE_DEBUG,
+ "pop3():TOP command (partially) retrieving message");
+
+ tmpelement = list_getstart(&(session->messagelst));
+
+ /* selecting a message */
+ trace(TRACE_DEBUG,
+ "pop3(): TOP command, selecting message");
+
+ while (tmpelement != NULL) {
+ if (((struct message *) tmpelement->data)->messageid == top_messageid && ((struct message *) tmpelement->data)->virtual_messagestatus < 2) { /* message is not deleted */
+ fprintf((FILE *) stream,
+ "+OK %llu lines of message %llu\r\n",
+ top_lines, top_messageid);
+ return
+ db_send_message_lines(stream,
+ ((struct
+ message
+ *)
+ tmpelement->
+ data)->
+ realmessageid,
+ top_lines,
+ 0);
+ }
+ tmpelement = tmpelement->nextnode;
+ }
+ return pop3_error(session, stream,
+ "-ERR no such message\r\n");
+
+ return 1;
+ }
+ case POP3_CAPA:
+ {
+ fprintf((FILE *) stream,
+ "+OK, Capability list follows\r\n"
+ "TOP\r\nUSER\r\nUIDL\r\n.\r\n");
+ return 1;
+ }
+
+ default:
+ {
+ return pop3_error(session, stream,
+ "-ERR command not understood, sir\r\n");
+ }
+ }
+ return 1;
}
diff --git a/pop3.h b/pop3.h
index d7f28183..f6779574 100644
--- a/pop3.h
+++ b/pop3.h
@@ -54,7 +54,7 @@
/* processes */
#define MAXCHILDREN 5
-#define DEFAULT_CHILDREN 5
+#define DEFAULT_CHILDREN 5
#define POP3_DEF_MAXCONNECT 1500
/* connection */
@@ -62,21 +62,21 @@
/**
* all POP3 commands */
typedef enum {
- POP3_QUIT,
- POP3_USER,
- POP3_PASS,
- POP3_STAT,
- POP3_LIST,
- POP3_RETR,
- POP3_DELE,
- POP3_NOOP,
- POP3_LAST,
- POP3_RSET,
- POP3_UIDL,
- POP3_APOP,
- POP3_AUTH,
- POP3_TOP,
- POP3_CAPA,
+ POP3_QUIT,
+ POP3_USER,
+ POP3_PASS,
+ POP3_STAT,
+ POP3_LIST,
+ POP3_RETR,
+ POP3_DELE,
+ POP3_NOOP,
+ POP3_LAST,
+ POP3_RSET,
+ POP3_UIDL,
+ POP3_APOP,
+ POP3_AUTH,
+ POP3_TOP,
+ POP3_CAPA,
} Pop3Cmd_t;
/**
@@ -90,7 +90,8 @@ typedef enum {
* 0 on QUIT (client command)
* 1 on success
*/
-int pop3 (void *stream, char *buffer, char *client_ip, PopSession_t *session);
+int pop3(void *stream, char *buffer, char *client_ip,
+ PopSession_t * session);
/**
* \brief handles connection and calls pop command handler
@@ -98,6 +99,6 @@ int pop3 (void *stream, char *buffer, char *client_ip, PopSession_t *session);
* function
* \return 0
*/
-int pop3_handle_connection (clientinfo_t *ci);
+int pop3_handle_connection(clientinfo_t * ci);
#endif
diff --git a/pop3d.c b/pop3d.c
index 2b89dd35..ba6e6e71 100644
--- a/pop3d.c
+++ b/pop3d.c
@@ -37,7 +37,7 @@
#include <signal.h>
#include <unistd.h>
#include <errno.h>
-#include <unistd.h> /* for getopt() */
+#include <unistd.h> /* for getopt() */
#include "imap4.h"
#include "server.h"
#include "debug.h"
@@ -60,10 +60,10 @@ char *configFile = DEFAULT_CONFIG_FILE;
/* set up database login data */
extern db_param_t _db_params;
-static void SetConfigItems(serverConfig_t *config, struct list *items);
+static void SetConfigItems(serverConfig_t * config, struct list *items);
static void Daemonize(void);
static int SetMainSigHandler(void);
-static void MainSigHandler(int sig, siginfo_t *info, void *data);
+static void MainSigHandler(int sig, siginfo_t * info, void *data);
int pop_before_smtp = 0;
int mainRestart = 0;
@@ -76,268 +76,298 @@ char *timeout_setting;
#ifdef PROC_TITLES
int main(int argc, char *argv[], char **envp)
#else
- int main(int argc, char *argv[])
+int main(int argc, char *argv[])
#endif
{
- serverConfig_t config;
- struct list popItems, sysItems;
- int result, status;
- pid_t pid;
- int opt;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- /* get command-line options */
- opterr = 0; /* suppress error message from getopt() */
- while ((opt = getopt(argc, argv, "vhf:")) != -1) {
- switch (opt) {
- case 'v':
- printf ("\n*** DBMAIL: dbmail-pop3d version "
- "$Revision$ %s\n\n",COPYRIGHT);
- return 0;
- case 'h':
- printf ("\ndbmail-pop3d: DBMAIL pop3 daemon\n");
- printf ("Usage: dbmail-pop3d (-v|-h|[-f config_filename])\n");
- return 0;
- case 'f':
- if (optarg && strlen(optarg) > 0)
- configFile = optarg;
- else {
- fprintf(stderr,"dbmail-pop3d: -f requires a filename "
- "argument\n\n");
- return 1;
- }
- break;
-
- default:
- break;
- }
- }
-
- SetMainSigHandler();
- Daemonize();
- result = 0;
-
- do
- {
- mainStop = 0;
- mainRestart = 0;
-
- trace(TRACE_DEBUG, "main(): reading config");
-#ifdef PROC_TITLES
- init_set_proc_title(argc, argv, envp, PNAME);
- set_proc_title("%s", "Idle");
-#endif
-
- ReadConfig("POP", configFile, &popItems);
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetConfigItems(&config, &popItems);
- SetTraceLevel(&popItems);
- GetDBParams(&_db_params, &sysItems);
-
- config.ClientHandler = pop3_handle_connection;
- config.timeoutMsg = POP_TIMEOUT_MSG;
-
- CreateSocket(&config);
- trace(TRACE_DEBUG, "main(): socket created, starting server");
-
- switch ( (pid = fork()) )
- {
- case -1:
- close(config.listenSocket);
- trace(TRACE_FATAL, "main(): fork failed [%s]", strerror(errno));
-
- case 0:
- /* child process */
- drop_privileges(config.serverUser, config.serverGroup);
- result = StartServer(&config);
-
- trace(TRACE_INFO, "main(): server done, exit.");
- exit(result);
-
- default:
- /* parent process, wait for child to exit */
- while (waitpid(pid, &status, WNOHANG|WUNTRACED) == 0)
- {
- if (mainStop)
- kill(pid, SIGTERM);
-
- if (mainRestart)
- kill(pid, SIGHUP);
-
- sleep(2);
- }
-
- if (WIFEXITED(status))
- {
- /* child process terminated neatly */
- result = WEXITSTATUS(status);
- trace(TRACE_DEBUG, "main(): server has exited, exit status [%d]", result);
- }
- else
- {
- /* child stopped or signaled, don't like */
- /* make sure it is dead */
- trace(TRACE_DEBUG, "main(): server has not exited normally. Killing..");
-
- kill(pid, SIGKILL);
- result = 0;
- }
+ serverConfig_t config;
+ struct list popItems, sysItems;
+ int result, status;
+ pid_t pid;
+ int opt;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ /* get command-line options */
+ opterr = 0; /* suppress error message from getopt() */
+ while ((opt = getopt(argc, argv, "vhf:")) != -1) {
+ switch (opt) {
+ case 'v':
+ printf("\n*** DBMAIL: dbmail-pop3d version "
+ "$Revision$ %s\n\n", COPYRIGHT);
+ return 0;
+ case 'h':
+ printf("\ndbmail-pop3d: DBMAIL pop3 daemon\n");
+ printf
+ ("Usage: dbmail-pop3d (-v|-h|[-f config_filename])\n");
+ return 0;
+ case 'f':
+ if (optarg && strlen(optarg) > 0)
+ configFile = optarg;
+ else {
+ fprintf(stderr,
+ "dbmail-pop3d: -f requires a filename "
+ "argument\n\n");
+ return 1;
+ }
+ break;
+
+ default:
+ break;
+ }
}
- list_freelist(&popItems.start);
- list_freelist(&sysItems.start);
- close(config.listenSocket);
+ SetMainSigHandler();
+ Daemonize();
+ result = 0;
- } while (result == 1 && !mainStop) ; /* 1 means reread-config and restart */
+ do {
+ mainStop = 0;
+ mainRestart = 0;
+
+ trace(TRACE_DEBUG, "main(): reading config");
+#ifdef PROC_TITLES
+ init_set_proc_title(argc, argv, envp, PNAME);
+ set_proc_title("%s", "Idle");
+#endif
- trace(TRACE_INFO, "main(): exit");
- return 0;
+ ReadConfig("POP", configFile, &popItems);
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetConfigItems(&config, &popItems);
+ SetTraceLevel(&popItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ config.ClientHandler = pop3_handle_connection;
+ config.timeoutMsg = POP_TIMEOUT_MSG;
+
+ CreateSocket(&config);
+ trace(TRACE_DEBUG,
+ "main(): socket created, starting server");
+
+ switch ((pid = fork())) {
+ case -1:
+ close(config.listenSocket);
+ trace(TRACE_FATAL, "main(): fork failed [%s]",
+ strerror(errno));
+
+ case 0:
+ /* child process */
+ drop_privileges(config.serverUser,
+ config.serverGroup);
+ result = StartServer(&config);
+
+ trace(TRACE_INFO, "main(): server done, exit.");
+ exit(result);
+
+ default:
+ /* parent process, wait for child to exit */
+ while (waitpid(pid, &status, WNOHANG | WUNTRACED)
+ == 0) {
+ if (mainStop)
+ kill(pid, SIGTERM);
+
+ if (mainRestart)
+ kill(pid, SIGHUP);
+
+ sleep(2);
+ }
+
+ if (WIFEXITED(status)) {
+ /* child process terminated neatly */
+ result = WEXITSTATUS(status);
+ trace(TRACE_DEBUG,
+ "main(): server has exited, exit status [%d]",
+ result);
+ } else {
+ /* child stopped or signaled, don't like */
+ /* make sure it is dead */
+ trace(TRACE_DEBUG,
+ "main(): server has not exited normally. Killing..");
+
+ kill(pid, SIGKILL);
+ result = 0;
+ }
+ }
+
+ list_freelist(&popItems.start);
+ list_freelist(&sysItems.start);
+ close(config.listenSocket);
+
+ } while (result == 1 && !mainStop); /* 1 means reread-config and restart */
+
+ trace(TRACE_INFO, "main(): exit");
+ return 0;
}
-void MainSigHandler(int sig, siginfo_t *info UNUSED, void *data UNUSED)
+void MainSigHandler(int sig, siginfo_t * info UNUSED, void *data UNUSED)
{
- trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
+ trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
- if (sig == SIGHUP)
- mainRestart = 1;
- else
- mainStop = 1;
+ if (sig == SIGHUP)
+ mainRestart = 1;
+ else
+ mainStop = 1;
}
void Daemonize()
{
- if (fork())
- exit(0);
- setsid();
+ if (fork())
+ exit(0);
+ setsid();
- if (fork())
- exit(0);
+ if (fork())
+ exit(0);
}
int SetMainSigHandler()
{
- struct sigaction act;
+ struct sigaction act;
- /* init & install signal handlers */
- memset(&act, 0, sizeof(act));
+ /* init & install signal handlers */
+ memset(&act, 0, sizeof(act));
- act.sa_sigaction = MainSigHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = MainSigHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
- sigaction(SIGINT, &act, 0);
- sigaction(SIGQUIT, &act, 0);
- sigaction(SIGTERM, &act, 0);
- sigaction(SIGHUP, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
- return 0;
+ return 0;
}
-void SetConfigItems(serverConfig_t *config, struct list *items)
+void SetConfigItems(serverConfig_t * config, struct list *items)
{
- field_t val;
+ field_t val;
- /* read items: NCHILDREN */
- GetConfigValue("NCHILDREN", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for NCHILDREN in config file");
+ /* read items: NCHILDREN */
+ GetConfigValue("NCHILDREN", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for NCHILDREN in config file");
- if ( (config->nChildren = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for NCHILDREN is invalid: [%d]", config->nChildren);
+ if ((config->nChildren = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for NCHILDREN is invalid: [%d]",
+ config->nChildren);
- trace(TRACE_DEBUG, "SetConfigItems(): server will create [%d] children", config->nChildren);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): server will create [%d] children",
+ config->nChildren);
- /* read items: MAXCONNECTS */
- GetConfigValue("MAXCONNECTS", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for MAXCONNECTS in config file");
+ /* read items: MAXCONNECTS */
+ GetConfigValue("MAXCONNECTS", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for MAXCONNECTS in config file");
- if ( (config->childMaxConnect = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]", config->childMaxConnect);
+ if ((config->childMaxConnect = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]",
+ config->childMaxConnect);
- trace(TRACE_DEBUG, "SetConfigItems(): children will make max. [%d] connections", config->childMaxConnect);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): children will make max. [%d] connections",
+ config->childMaxConnect);
- /* read items: TIMEOUT */
- GetConfigValue("TIMEOUT", items, val);
- if (strlen(val) == 0)
- {
- trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMEOUT in config file");
- config->timeout = 0;
- }
- else if ( (config->timeout = atoi(val)) <= 30)
- trace(TRACE_FATAL, "SetConfigItems(): value for TIMEOUT is invalid: [%d]", config->timeout);
+ /* read items: TIMEOUT */
+ GetConfigValue("TIMEOUT", items, val);
+ if (strlen(val) == 0) {
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for TIMEOUT in config file");
+ config->timeout = 0;
+ } else if ((config->timeout = atoi(val)) <= 30)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for TIMEOUT is invalid: [%d]",
+ config->timeout);
- trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds", config->timeout);
+ trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds",
+ config->timeout);
- /* read items: PORT */
- GetConfigValue("PORT", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for PORT in config file");
+ /* read items: PORT */
+ GetConfigValue("PORT", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for PORT in config file");
- if ( (config->port = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for PORT is invalid: [%d]", config->port);
+ if ((config->port = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for PORT is invalid: [%d]",
+ config->port);
- trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]", config->port);
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]",
+ config->port);
- /* read items: BINDIP */
- GetConfigValue("BINDIP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for BINDIP in config file");
+ /* read items: BINDIP */
+ GetConfigValue("BINDIP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for BINDIP in config file");
- strncpy(config->ip, val, IPLEN);
- config->ip[IPLEN-1] = '\0';
+ strncpy(config->ip, val, IPLEN);
+ config->ip[IPLEN - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]", config->ip);
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]",
+ config->ip);
- /* read items: RESOLVE_IP */
- GetConfigValue("RESOLVE_IP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for RESOLVE_IP in config file");
+ /* read items: RESOLVE_IP */
+ GetConfigValue("RESOLVE_IP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for RESOLVE_IP in config file");
- config->resolveIP = (strcasecmp(val, "yes") == 0);
+ config->resolveIP = (strcasecmp(val, "yes") == 0);
- trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP", config->resolveIP ? "" : "not ");
+ trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP",
+ config->resolveIP ? "" : "not ");
- /* read items: IMAP-BEFORE-SMTP */
- GetConfigValue("POP_BEFORE_SMTP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for POP_BEFORE_SMTP in config file");
+ /* read items: IMAP-BEFORE-SMTP */
+ GetConfigValue("POP_BEFORE_SMTP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for POP_BEFORE_SMTP in config file");
- pop_before_smtp = (strcasecmp(val, "yes") == 0);
+ pop_before_smtp = (strcasecmp(val, "yes") == 0);
- trace(TRACE_DEBUG, "SetConfigItems(): %s POP-before-SMTP",
- pop_before_smtp ? "Enabling" : "Disabling");
+ trace(TRACE_DEBUG, "SetConfigItems(): %s POP-before-SMTP",
+ pop_before_smtp ? "Enabling" : "Disabling");
- /* read items: EFFECTIVE-USER */
- GetConfigValue("EFFECTIVE_USER", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_USER in config file");
+ /* read items: EFFECTIVE-USER */
+ GetConfigValue("EFFECTIVE_USER", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_USER in config file");
- strncpy(config->serverUser, val, FIELDSIZE);
- config->serverUser[FIELDSIZE-1] = '\0';
+ strncpy(config->serverUser, val, FIELDSIZE);
+ config->serverUser[FIELDSIZE - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): effective user shall be [%s]", config->serverUser);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective user shall be [%s]",
+ config->serverUser);
- /* read items: EFFECTIVE-GROUP */
- GetConfigValue("EFFECTIVE_GROUP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
+ /* read items: EFFECTIVE-GROUP */
+ GetConfigValue("EFFECTIVE_GROUP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
- strncpy(config->serverGroup, val, FIELDSIZE);
- config->serverGroup[FIELDSIZE-1] = '\0';
+ strncpy(config->serverGroup, val, FIELDSIZE);
+ config->serverGroup[FIELDSIZE - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): effective group shall be [%s]", config->serverGroup);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective group shall be [%s]",
+ config->serverGroup);
}
diff --git a/proctitleutils.c b/proctitleutils.c
index 07621c46..8110ce9b 100644
--- a/proctitleutils.c
+++ b/proctitleutils.c
@@ -29,68 +29,68 @@
#include "proctitleutils.h"
/* Globals */
-static char **Argv = ((void *)0);
-static char *LastArgv = ((void *)0);
+static char **Argv = ((void *) 0);
+static char *LastArgv = ((void *) 0);
static int start = 0;
-void init_set_proc_title(int argc, char *argv[], char *envp[], const char *name)
+void init_set_proc_title(int argc, char *argv[], char *envp[],
+ const char *name)
{
- int i, envpsize;
- extern char **environ;
- char **p;
- char *ptr;
-
- for(i = envpsize = 0; envp[i] != NULL; i++)
- envpsize += strlen(envp[i]) + 1;
-
- if((p = (char **) malloc((i + 1) * sizeof(char *))) != NULL ) {
- environ = p;
-
- for(i = 0; envp[i] != NULL; i++) {
- if((environ[i] = malloc(strlen(envp[i]) + 1)) != NULL)
- strcpy(environ[i], envp[i]);
- }
-
- environ[i] = NULL;
- }
-
- Argv = argv;
-
- for(i = 0; envp[i] != NULL; i++) {
- if((LastArgv + 1) == envp[i]) // Not sure if this conditional is needed
- LastArgv = envp[i] + strlen(envp[i]);
- }
-
- // Clear the title (from the start of argv to the start of envp)
- // All command line arguments should have been taken care of by now...
- for(ptr=Argv[0]; ptr<envp[0]; ptr++)
- *ptr='\0';
-
- set_proc_title("%s : ", name);
- start=strlen(name)+3;
+ int i, envpsize;
+ extern char **environ;
+ char **p;
+ char *ptr;
+
+ for (i = envpsize = 0; envp[i] != NULL; i++)
+ envpsize += strlen(envp[i]) + 1;
+
+ if ((p = (char **) malloc((i + 1) * sizeof(char *))) != NULL) {
+ environ = p;
+
+ for (i = 0; envp[i] != NULL; i++) {
+ if ((environ[i] =
+ malloc(strlen(envp[i]) + 1)) != NULL)
+ strcpy(environ[i], envp[i]);
+ }
+
+ environ[i] = NULL;
+ }
+
+ Argv = argv;
+
+ for (i = 0; envp[i] != NULL; i++) {
+ if ((LastArgv + 1) == envp[i]) // Not sure if this conditional is needed
+ LastArgv = envp[i] + strlen(envp[i]);
+ }
+
+ // Clear the title (from the start of argv to the start of envp)
+ // All command line arguments should have been taken care of by now...
+ for (ptr = Argv[0]; ptr < envp[0]; ptr++)
+ *ptr = '\0';
+
+ set_proc_title("%s : ", name);
+ start = strlen(name) + 3;
}
-void set_proc_title(char *fmt,...)
+void set_proc_title(char *fmt, ...)
{
- va_list msg;
- static char statbuf[8192];
- char *p = Argv[0];
- int maxlen = (LastArgv - Argv[0]) - 2;
+ va_list msg;
+ static char statbuf[8192];
+ char *p = Argv[0];
+ int maxlen = (LastArgv - Argv[0]) - 2;
- // Clear old Argv[0]
- for(p+=start;*p; p++)
- *p='\0';
-
- va_start(msg,fmt);
+ // Clear old Argv[0]
+ for (p += start; *p; p++)
+ *p = '\0';
- memset(statbuf, 0, sizeof(statbuf));
- vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
+ va_start(msg, fmt);
- va_end(msg);
+ memset(statbuf, 0, sizeof(statbuf));
+ vsnprintf(statbuf, sizeof(statbuf), fmt, msg);
- snprintf(Argv[0]+start, maxlen, "%s", statbuf);
-
- Argv[1] = ((void *)0) ;
-}
+ va_end(msg);
+ snprintf(Argv[0] + start, maxlen, "%s", statbuf);
+ Argv[1] = ((void *) 0);
+}
diff --git a/proctitleutils.h b/proctitleutils.h
index 7430c126..07a6aa19 100644
--- a/proctitleutils.h
+++ b/proctitleutils.h
@@ -32,7 +32,8 @@
#include "config.h"
#endif
-void set_proc_title(char *fmt,...);
-void init_set_proc_title(int argc, char *argv[], char *envp[], const char *name);
+void set_proc_title(char *fmt, ...);
+void init_set_proc_title(int argc, char *argv[], char *envp[],
+ const char *name);
#endif
diff --git a/quota.c b/quota.c
index ae061dd8..d8767175 100644
--- a/quota.c
+++ b/quota.c
@@ -30,16 +30,19 @@
/* Allocate a quota structure for `n_resources' resources.
* Returns NULL on failure.
*/
-quota_t *quota_alloc(int n_resources) {
- quota_t *quota;
+quota_t *quota_alloc(int n_resources)
+{
+ quota_t *quota;
- quota = malloc(sizeof(quota_t) + n_resources * sizeof(resource_limit_t));
- if (quota != NULL) {
- quota->root = NULL;
- quota->n_resources = n_resources;
- }
+ quota =
+ malloc(sizeof(quota_t) +
+ n_resources * sizeof(resource_limit_t));
+ if (quota != NULL) {
+ quota->root = NULL;
+ quota->n_resources = n_resources;
+ }
- return quota;
+ return quota;
}
/* Set a resource limit in a quota structure.
@@ -49,13 +52,14 @@ quota_t *quota_alloc(int n_resources) {
* usage: the current usage of the resource.
* limit: the usage limit for the resource.
*/
-void quota_set_resource_limit(quota_t *quota, int resource_idx,
+void quota_set_resource_limit(quota_t * quota, int resource_idx,
resource_type_t type,
- u64_t usage, u64_t limit) {
- resource_limit_t * rl = &(quota->resource[resource_idx]);
- rl->type = type;
- rl->usage = usage;
- rl->limit = limit;
+ u64_t usage, u64_t limit)
+{
+ resource_limit_t *rl = &(quota->resource[resource_idx]);
+ rl->type = type;
+ rl->usage = usage;
+ rl->limit = limit;
}
/* Set the name of the quota root.
@@ -63,16 +67,18 @@ void quota_set_resource_limit(quota_t *quota, int resource_idx,
* quota: the quota object to modify.
* root: the (new) name of the quota root.
*/
-int quota_set_root(quota_t *quota, char *root) {
- free(quota->root);
- quota->root = strdup(root);
- return (quota->root == NULL);
+int quota_set_root(quota_t * quota, char *root)
+{
+ free(quota->root);
+ quota->root = strdup(root);
+ return (quota->root == NULL);
}
/* Free a quota structure. */
-void quota_free(quota_t *quota) {
- free(quota->root);
- free(quota);
+void quota_free(quota_t * quota)
+{
+ free(quota->root);
+ free(quota);
}
@@ -86,15 +92,16 @@ void quota_free(quota_t *quota) {
* errormsg: will point to an error message if NULL is returned.
*/
char *quota_get_quotaroot(u64_t useridnr, const char *mailbox,
- char **errormsg) {
- u64_t mailbox_idnr;
-
- if (db_findmailbox(mailbox, useridnr, &mailbox_idnr) <= 0) {
- *errormsg = "mailbox not found";
- return NULL;
- }
-
- return "";
+ char **errormsg)
+{
+ u64_t mailbox_idnr;
+
+ if (db_findmailbox(mailbox, useridnr, &mailbox_idnr) <= 0) {
+ *errormsg = "mailbox not found";
+ return NULL;
+ }
+
+ return "";
}
/* Get the quota for a given quota root.
@@ -106,48 +113,53 @@ char *quota_get_quotaroot(u64_t useridnr, const char *mailbox,
* quotaroot: the quotaroot.
* errormsg: will point to an error message if NULL is returned.
*/
-quota_t *quota_get_quota(u64_t useridnr, char *quotaroot, char **errormsg) {
- quota_t *quota;
- u64_t maxmail_size, usage;
-
- /* Currently, there's only the quota root "". */
- if (strcmp(quotaroot, "") != 0) {
- trace(TRACE_ERROR, "quota_get_quota(): unknown quota root \"%s\"\n",
- quotaroot);
- *errormsg = "unknown quota root";
- return NULL;
- }
-
- if (auth_getmaxmailsize(useridnr, &maxmail_size) == -1) {
- trace(TRACE_ERROR, "quota_get_quota(): auth_getmaxmailsize() failed\n");
- *errormsg = "invalid user";
- return NULL;
- }
-
- if (db_get_quotum_used(useridnr, &usage) == -1) {
- trace(TRACE_ERROR,
- "quota_get_quota(): db_get_quotum_used() failed\n");
- *errormsg = "internal error";
- return NULL;
- }
-
- /* We support exactly one resource: RT_STORAGE */
- quota = quota_alloc(1);
- if (quota == NULL) {
- trace(TRACE_ERROR, "quota_get_quota(): out of memory\n");
- *errormsg = "out of memory";
- return NULL;
- }
-
- /* Set quota root */
- if (quota_set_root(quota, quotaroot)) {
- trace(TRACE_ERROR, "quota_get_quota(): quota_set_root() failed\n");
- *errormsg = "out of memory";
- return NULL;
- }
-
- /* Set usage and limit for RT_STORAGE */
- quota_set_resource_limit(quota, 0, RT_STORAGE, usage, maxmail_size);
-
- return quota;
+quota_t *quota_get_quota(u64_t useridnr, char *quotaroot, char **errormsg)
+{
+ quota_t *quota;
+ u64_t maxmail_size, usage;
+
+ /* Currently, there's only the quota root "". */
+ if (strcmp(quotaroot, "") != 0) {
+ trace(TRACE_ERROR,
+ "quota_get_quota(): unknown quota root \"%s\"\n",
+ quotaroot);
+ *errormsg = "unknown quota root";
+ return NULL;
+ }
+
+ if (auth_getmaxmailsize(useridnr, &maxmail_size) == -1) {
+ trace(TRACE_ERROR,
+ "quota_get_quota(): auth_getmaxmailsize() failed\n");
+ *errormsg = "invalid user";
+ return NULL;
+ }
+
+ if (db_get_quotum_used(useridnr, &usage) == -1) {
+ trace(TRACE_ERROR,
+ "quota_get_quota(): db_get_quotum_used() failed\n");
+ *errormsg = "internal error";
+ return NULL;
+ }
+
+ /* We support exactly one resource: RT_STORAGE */
+ quota = quota_alloc(1);
+ if (quota == NULL) {
+ trace(TRACE_ERROR, "quota_get_quota(): out of memory\n");
+ *errormsg = "out of memory";
+ return NULL;
+ }
+
+ /* Set quota root */
+ if (quota_set_root(quota, quotaroot)) {
+ trace(TRACE_ERROR,
+ "quota_get_quota(): quota_set_root() failed\n");
+ *errormsg = "out of memory";
+ return NULL;
+ }
+
+ /* Set usage and limit for RT_STORAGE */
+ quota_set_resource_limit(quota, 0, RT_STORAGE, usage,
+ maxmail_size);
+
+ return quota;
}
diff --git a/quota.h b/quota.h
index a595d34a..3a26f653 100644
--- a/quota.h
+++ b/quota.h
@@ -31,7 +31,7 @@
* RT_STORAGE: "STORAGE"
*/
typedef enum {
- RT_STORAGE
+ RT_STORAGE
} resource_type_t;
/* A resource limit.
@@ -40,9 +40,9 @@ typedef enum {
* limit: the maximum allowed usage of the resource
*/
typedef struct {
- resource_type_t type;
- u64_t usage;
- u64_t limit;
+ resource_type_t type;
+ u64_t usage;
+ u64_t limit;
} resource_limit_t;
/* A quota root and its resource limits.
@@ -52,19 +52,19 @@ typedef struct {
* describing a resource limit
*/
typedef struct {
- char *root;
- int n_resources;
- resource_limit_t resource[0];
+ char *root;
+ int n_resources;
+ resource_limit_t resource[0];
} quota_t;
/* Functions for manipulating quota_t objects */
quota_t *quota_alloc(int n_resources);
-void quota_free(quota_t *quota);
-void quota_set_resource_limit(quota_t *quota, int resource_idx,
+void quota_free(quota_t * quota);
+void quota_set_resource_limit(quota_t * quota, int resource_idx,
resource_type_t type,
u64_t usage, u64_t limit);
-int quota_set_root(quota_t *quota, char *root);
+int quota_set_root(quota_t * quota, char *root);
/* Functions for querying quota and quota root */
char *quota_get_quotaroot(u64_t useridnr, const char *mailbox,
diff --git a/rfcmsg.c b/rfcmsg.c
index 6342fc3f..d9ff9d2e 100644
--- a/rfcmsg.c
+++ b/rfcmsg.c
@@ -41,60 +41,58 @@
/*
* frees all the memory associated with a msg
*/
-void db_free_msg(mime_message_t *msg)
+void db_free_msg(mime_message_t * msg)
{
- struct element *tmp;
+ struct element *tmp;
- if (!msg)
- return;
+ if (!msg)
+ return;
- /* free the children msg's */
- tmp = list_getstart(&msg->children);
+ /* free the children msg's */
+ tmp = list_getstart(&msg->children);
- while (tmp)
- {
- db_free_msg((mime_message_t*)tmp->data);
- tmp = tmp->nextnode;
- }
+ while (tmp) {
+ db_free_msg((mime_message_t *) tmp->data);
+ tmp = tmp->nextnode;
+ }
+
+ tmp = list_getstart(&msg->children);
+ list_freelist(&tmp);
- tmp = list_getstart(&msg->children);
- list_freelist(&tmp);
-
- tmp = list_getstart(&msg->mimeheader);
- list_freelist(&tmp);
+ tmp = list_getstart(&msg->mimeheader);
+ list_freelist(&tmp);
- tmp = list_getstart(&msg->rfcheader);
- list_freelist(&tmp);
+ tmp = list_getstart(&msg->rfcheader);
+ list_freelist(&tmp);
- memset(msg, 0, sizeof(*msg));
+ memset(msg, 0, sizeof(*msg));
}
-
+
/*
* reverses the children lists of a msg
*/
-void db_reverse_msg(mime_message_t *msg)
+void db_reverse_msg(mime_message_t * msg)
{
- struct element *tmp;
+ struct element *tmp;
- if (!msg)
- return;
+ if (!msg)
+ return;
- /* reverse the children msg's */
- tmp = list_getstart(&msg->children);
+ /* reverse the children msg's */
+ tmp = list_getstart(&msg->children);
- while (tmp)
- {
- db_reverse_msg((mime_message_t*)tmp->data);
- tmp = tmp->nextnode;
- }
+ while (tmp) {
+ db_reverse_msg((mime_message_t *) tmp->data);
+ tmp = tmp->nextnode;
+ }
- /* reverse this list */
- msg->children.start = dbmail_list_reverse(msg->children.start);
+ /* reverse this list */
+ msg->children.start = dbmail_list_reverse(msg->children.start);
- /* reverse header items */
- msg->mimeheader.start = dbmail_list_reverse(msg->mimeheader.start);
- msg->rfcheader.start = dbmail_list_reverse(msg->rfcheader.start);
+ /* reverse header items */
+ msg->mimeheader.start = dbmail_list_reverse(msg->mimeheader.start);
+ msg->rfcheader.start = dbmail_list_reverse(msg->rfcheader.start);
}
/*
@@ -116,94 +114,98 @@ void db_reverse_msg(mime_message_t *msg)
* -1 parse error but msg is retrieved as plaintext
* 0 success
*/
-int db_fetch_headers(u64_t msguid, mime_message_t *msg)
+int db_fetch_headers(u64_t msguid, mime_message_t * msg)
{
- int result,level=0,maxlevel=-1;
+ int result, level = 0, maxlevel = -1;
- if (db_init_msgfetch(msguid) != 1)
- {
- trace(TRACE_ERROR,"db_fetch_headers(): could not init msgfetch\n");
- return -2;
- }
+ if (db_init_msgfetch(msguid) != 1) {
+ trace(TRACE_ERROR,
+ "db_fetch_headers(): could not init msgfetch\n");
+ return -2;
+ }
- result = db_start_msg(msg, NULL, &level, maxlevel); /* fetch message */
- if (result < 0)
- {
- trace(TRACE_INFO, "db_fetch_headers(): error fetching message, ID: %llu\n",msguid);
- trace(TRACE_INFO, "db_fetch_headers(): got error at level %d\n",level);
+ result = db_start_msg(msg, NULL, &level, maxlevel); /* fetch message */
+ if (result < 0) {
+ trace(TRACE_INFO,
+ "db_fetch_headers(): error fetching message, ID: %llu\n",
+ msguid);
+ trace(TRACE_INFO,
+ "db_fetch_headers(): got error at level %d\n",
+ level);
- db_close_msgfetch();
- db_free_msg(msg);
+ db_close_msgfetch();
+ db_free_msg(msg);
- if (result < -1)
- return result; /* memory/dbase error */
+ if (result < -1)
+ return result; /* memory/dbase error */
- /*
- * so an error occurred parsing the message.
- * try to lower the maxlevel of recursion
- */
+ /*
+ * so an error occurred parsing the message.
+ * try to lower the maxlevel of recursion
+ */
- for (maxlevel = level-1; maxlevel >= 0; maxlevel--)
- {
- trace(TRACE_DEBUG, "db_fetch_headers(): trying to fetch at maxlevel %d...\n",maxlevel);
+ for (maxlevel = level - 1; maxlevel >= 0; maxlevel--) {
+ trace(TRACE_DEBUG,
+ "db_fetch_headers(): trying to fetch at maxlevel %d...\n",
+ maxlevel);
- if (db_init_msgfetch(msguid) != 1)
- {
- trace(TRACE_ERROR,"db_fetch_headers(): could not init msgfetch\n");
- return -2;
- }
+ if (db_init_msgfetch(msguid) != 1) {
+ trace(TRACE_ERROR,
+ "db_fetch_headers(): could not init msgfetch\n");
+ return -2;
+ }
- level = 0;
- result = db_start_msg(msg, NULL, &level, maxlevel);
+ level = 0;
+ result = db_start_msg(msg, NULL, &level, maxlevel);
- db_close_msgfetch();
+ db_close_msgfetch();
- if (result != -1)
- break;
+ if (result != -1)
+ break;
- db_free_msg(msg);
- }
+ db_free_msg(msg);
+ }
- if (result < -1)
- {
- db_free_msg(msg);
- return result;
- }
+ if (result < -1) {
+ db_free_msg(msg);
+ return result;
+ }
- if (result >= 0)
- {
- trace(TRACE_WARNING,"db_fetch_headers(): succesfully recovered erroneous message %llu\n",
- msguid);
- db_reverse_msg(msg);
- return 0;
- }
+ if (result >= 0) {
+ trace(TRACE_WARNING,
+ "db_fetch_headers(): succesfully recovered erroneous message %llu\n",
+ msguid);
+ db_reverse_msg(msg);
+ return 0;
+ }
- /* ok still problems... try to make a message */
- if (db_init_msgfetch(msguid) != 1)
- {
- trace(TRACE_ERROR,"db_fetch_headers(): could not init msgfetch\n");
- return -2;
- }
+ /* ok still problems... try to make a message */
+ if (db_init_msgfetch(msguid) != 1) {
+ trace(TRACE_ERROR,
+ "db_fetch_headers(): could not init msgfetch\n");
+ return -2;
+ }
- result = db_parse_as_text(msg);
- if (result < 0)
- {
- /* probably some serious dbase error */
- trace(TRACE_ERROR,"db_fetch_headers(): could not recover message as plain text\n");
- db_free_msg(msg);
- return result;
+ result = db_parse_as_text(msg);
+ if (result < 0) {
+ /* probably some serious dbase error */
+ trace(TRACE_ERROR,
+ "db_fetch_headers(): could not recover message as plain text\n");
+ db_free_msg(msg);
+ return result;
+ }
+
+ trace(TRACE_WARNING,
+ "db_fetch_headers(): message recovered as plain text\n");
+ db_close_msgfetch();
+ return -1;
}
- trace(TRACE_WARNING, "db_fetch_headers(): message recovered as plain text\n");
- db_close_msgfetch();
- return -1;
- }
-
- db_reverse_msg(msg);
+ db_reverse_msg(msg);
- db_close_msgfetch();
- return 0;
+ db_close_msgfetch();
+ return 0;
}
@@ -219,223 +221,244 @@ int db_fetch_headers(u64_t msguid, mime_message_t *msg)
*
* returns the number of lines parsed or -1 on parse error, -2 on dbase error, -3 on memory error
*/
-int db_start_msg(mime_message_t *msg, char *stopbound, int *level, int maxlevel)
+int db_start_msg(mime_message_t * msg, char *stopbound, int *level,
+ int maxlevel)
{
- int len,sblen,result,totallines=0,nlines,hdrlines;
- struct mime_record *mr;
- char *newbound,*bptr;
- int continue_recursion = (maxlevel==0 && *level == 0) ? 0 : 1;
-
- trace(TRACE_DEBUG,"db_start_msg(): starting, stopbound: '%s'\n",stopbound ? stopbound : "<null>");
-
- list_init(&msg->children);
- msg->message_has_errors = (!continue_recursion);
-
-
- /* read header */
- if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1)
- return -2;
-
- if ((hdrlines = mime_readheader(&msgbuf_buf[msgbuf_idx], &msgbuf_idx,
- &msg->rfcheader, &msg->rfcheadersize)) < 0)
- return hdrlines; /* error reading header */
-
- db_give_msgpos(&msg->bodystart);
- msg->rfcheaderlines = hdrlines;
+ int len, sblen, result, totallines = 0, nlines, hdrlines;
+ struct mime_record *mr;
+ char *newbound, *bptr;
+ int continue_recursion = (maxlevel == 0 && *level == 0) ? 0 : 1;
- mime_findfield("content-type", &msg->rfcheader, &mr);
- if (continue_recursion &&
- mr && strncasecmp(mr->value,"multipart", strlen("multipart")) == 0)
- {
- trace(TRACE_DEBUG,"db_start_msg(): found multipart msg\n");
+ trace(TRACE_DEBUG, "db_start_msg(): starting, stopbound: '%s'\n",
+ stopbound ? stopbound : "<null>");
- /* multipart msg, find new boundary */
- for (bptr = mr->value; *bptr; bptr++)
- if (strncasecmp(bptr, "boundary=", sizeof("boundary=")-1) == 0)
- break;
+ list_init(&msg->children);
+ msg->message_has_errors = (!continue_recursion);
- if (!bptr)
- {
- trace(TRACE_WARNING, "db_start_msg(): could not find a new msg-boundary\n");
- return -1; /* no new boundary ??? */
- }
-
- bptr += sizeof("boundary=")-1;
- if (*bptr == '\"')
- {
- bptr++;
- newbound = bptr;
- while (*newbound && *newbound != '\"') newbound++;
- }
- else
- {
- newbound = bptr;
- while (*newbound && !isspace(*newbound) && *newbound!=';') newbound++;
- }
-
- len = newbound - bptr;
- if (!(newbound = (char*)my_malloc(len+1)))
- {
- trace(TRACE_ERROR, "db_start_msg(): out of memory\n");
- return -3;
- }
-
- strncpy(newbound, bptr, len);
- newbound[len] = '\0';
-
- trace(TRACE_DEBUG,"db_start_msg(): found new boundary: [%s], msgbuf_idx %llu\n",newbound,msgbuf_idx);
-
- /* advance to first boundary */
- if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1)
- {
- trace(TRACE_ERROR, "db_startmsg(): error updating msgbuf\n");
- my_free(newbound);
- return -2;
- }
-
- while (msgbuf_buf[msgbuf_idx])
- {
- if (strncmp(&msgbuf_buf[msgbuf_idx], newbound, strlen(newbound)) == 0)
- break;
- if (msgbuf_buf[msgbuf_idx] == '\n')
- totallines++;
+ /* read header */
+ if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1)
+ return -2;
- msgbuf_idx++;
- }
+ if ((hdrlines =
+ mime_readheader(&msgbuf_buf[msgbuf_idx], &msgbuf_idx,
+ &msg->rfcheader, &msg->rfcheadersize)) < 0)
+ return hdrlines; /* error reading header */
+
+ db_give_msgpos(&msg->bodystart);
+ msg->rfcheaderlines = hdrlines;
+
+ mime_findfield("content-type", &msg->rfcheader, &mr);
+ if (continue_recursion &&
+ mr
+ && strncasecmp(mr->value, "multipart",
+ strlen("multipart")) == 0) {
+ trace(TRACE_DEBUG,
+ "db_start_msg(): found multipart msg\n");
+
+ /* multipart msg, find new boundary */
+ for (bptr = mr->value; *bptr; bptr++)
+ if (strncasecmp
+ (bptr, "boundary=",
+ sizeof("boundary=") - 1) == 0)
+ break;
+
+ if (!bptr) {
+ trace(TRACE_WARNING,
+ "db_start_msg(): could not find a new msg-boundary\n");
+ return -1; /* no new boundary ??? */
+ }
- if (!msgbuf_buf[msgbuf_idx])
- {
- trace(TRACE_WARNING, "db_start_msg(): unexpected end-of-data\n");
- my_free(newbound);
- return -1;
- }
+ bptr += sizeof("boundary=") - 1;
+ if (*bptr == '\"') {
+ bptr++;
+ newbound = bptr;
+ while (*newbound && *newbound != '\"')
+ newbound++;
+ } else {
+ newbound = bptr;
+ while (*newbound && !isspace(*newbound)
+ && *newbound != ';')
+ newbound++;
+ }
- msgbuf_idx += strlen(newbound); /* skip the boundary */
- msgbuf_idx++; /* skip \n */
- totallines++; /* and count it */
-
- /* find MIME-parts */
- (*level)++;
- if ((nlines = db_add_mime_children(&msg->children, newbound, level, maxlevel)) < 0)
- {
- trace(TRACE_WARNING, "db_start_msg(): error adding MIME-children\n");
- my_free(newbound);
- return nlines;
- }
- (*level)--;
- totallines += nlines;
-
- /* skip stopbound if present */
- if (stopbound)
- {
- sblen = strlen(stopbound);
- msgbuf_idx += (2+sblen); /* double hyphen preceeds */
- }
+ len = newbound - bptr;
+ if (!(newbound = (char *) my_malloc(len + 1))) {
+ trace(TRACE_ERROR,
+ "db_start_msg(): out of memory\n");
+ return -3;
+ }
- my_free(newbound);
- newbound = NULL;
+ strncpy(newbound, bptr, len);
+ newbound[len] = '\0';
- if (msgbuf_idx > 0)
- {
- /* walk back because bodyend is inclusive */
- msgbuf_idx--;
- db_give_msgpos(&msg->bodyend);
- msgbuf_idx++;
- }
- else
- db_give_msgpos(&msg->bodyend); /* this case should never happen... */
+ trace(TRACE_DEBUG,
+ "db_start_msg(): found new boundary: [%s], msgbuf_idx %llu\n",
+ newbound, msgbuf_idx);
+ /* advance to first boundary */
+ if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1) {
+ trace(TRACE_ERROR,
+ "db_startmsg(): error updating msgbuf\n");
+ my_free(newbound);
+ return -2;
+ }
- msg->bodysize = db_give_range_size(&msg->bodystart, &msg->bodyend);
- msg->bodylines = totallines;
+ while (msgbuf_buf[msgbuf_idx]) {
+ if (strncmp
+ (&msgbuf_buf[msgbuf_idx], newbound,
+ strlen(newbound)) == 0)
+ break;
- return totallines+hdrlines; /* done */
- }
- else
- {
- /* single part msg, read untill stopbound OR end of buffer */
- trace(TRACE_DEBUG,"db_start_msg(): found singlepart msg\n");
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ totallines++;
- if (stopbound)
- {
- sblen = strlen(stopbound);
+ msgbuf_idx++;
+ }
- while (msgbuf_buf[msgbuf_idx])
- {
- if (db_update_msgbuf(sblen+3) == -1)
- return -2;
+ if (!msgbuf_buf[msgbuf_idx]) {
+ trace(TRACE_WARNING,
+ "db_start_msg(): unexpected end-of-data\n");
+ my_free(newbound);
+ return -1;
+ }
- if (msgbuf_buf[msgbuf_idx] == '\n')
- msg->bodylines++;
-
- if (msgbuf_buf[msgbuf_idx+1] == '-' && msgbuf_buf[msgbuf_idx+2] == '-' &&
- strncmp(&msgbuf_buf[msgbuf_idx+3], stopbound, sblen) == 0)
- {
- db_give_msgpos(&msg->bodyend);
- msg->bodysize = db_give_range_size(&msg->bodystart, &msg->bodyend);
-
- msgbuf_idx++; /* msgbuf_buf[msgbuf_idx] == '-' now */
-
- /* advance to after stopbound */
- msgbuf_idx += sblen+2; /* (add 2 cause double hyphen preceeds) */
- while (isspace(msgbuf_buf[msgbuf_idx]))
- {
- if (msgbuf_buf[msgbuf_idx] == '\n') totallines++;
- msgbuf_idx++;
- }
-
- trace(TRACE_DEBUG,"db_start_msg(): stopbound reached\n");
- return (totallines+msg->bodylines+hdrlines);
+ msgbuf_idx += strlen(newbound); /* skip the boundary */
+ msgbuf_idx++; /* skip \n */
+ totallines++; /* and count it */
+
+ /* find MIME-parts */
+ (*level)++;
+ if ((nlines =
+ db_add_mime_children(&msg->children, newbound, level,
+ maxlevel)) < 0) {
+ trace(TRACE_WARNING,
+ "db_start_msg(): error adding MIME-children\n");
+ my_free(newbound);
+ return nlines;
}
+ (*level)--;
+ totallines += nlines;
- msgbuf_idx++;
- }
+ /* skip stopbound if present */
+ if (stopbound) {
+ sblen = strlen(stopbound);
+ msgbuf_idx += (2 + sblen); /* double hyphen preceeds */
+ }
- /* end of buffer reached, invalid message encountered: there should be a stopbound! */
- /* but lets pretend there's nothing wrong... */
- db_give_msgpos(&msg->bodyend);
- msg->bodysize = db_give_range_size(&msg->bodystart, &msg->bodyend);
- totallines += msg->bodylines;
-
- trace(TRACE_WARNING, "db_start_msg(): no stopbound where expected...\n");
+ my_free(newbound);
+ newbound = NULL;
+
+ if (msgbuf_idx > 0) {
+ /* walk back because bodyend is inclusive */
+ msgbuf_idx--;
+ db_give_msgpos(&msg->bodyend);
+ msgbuf_idx++;
+ } else
+ db_give_msgpos(&msg->bodyend); /* this case should never happen... */
+
+
+ msg->bodysize =
+ db_give_range_size(&msg->bodystart, &msg->bodyend);
+ msg->bodylines = totallines;
+
+ return totallines + hdrlines; /* done */
+ } else {
+ /* single part msg, read untill stopbound OR end of buffer */
+ trace(TRACE_DEBUG,
+ "db_start_msg(): found singlepart msg\n");
+
+ if (stopbound) {
+ sblen = strlen(stopbound);
+
+ while (msgbuf_buf[msgbuf_idx]) {
+ if (db_update_msgbuf(sblen + 3) == -1)
+ return -2;
+
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ msg->bodylines++;
+
+ if (msgbuf_buf[msgbuf_idx + 1] == '-'
+ && msgbuf_buf[msgbuf_idx + 2] == '-'
+ && strncmp(&msgbuf_buf[msgbuf_idx + 3],
+ stopbound, sblen) == 0) {
+ db_give_msgpos(&msg->bodyend);
+ msg->bodysize =
+ db_give_range_size(&msg->
+ bodystart,
+ &msg->
+ bodyend);
+
+ msgbuf_idx++; /* msgbuf_buf[msgbuf_idx] == '-' now */
+
+ /* advance to after stopbound */
+ msgbuf_idx += sblen + 2; /* (add 2 cause double hyphen preceeds) */
+ while (isspace
+ (msgbuf_buf[msgbuf_idx])) {
+ if (msgbuf_buf[msgbuf_idx]
+ == '\n')
+ totallines++;
+ msgbuf_idx++;
+ }
+
+ trace(TRACE_DEBUG,
+ "db_start_msg(): stopbound reached\n");
+ return (totallines +
+ msg->bodylines + hdrlines);
+ }
+
+ msgbuf_idx++;
+ }
+
+ /* end of buffer reached, invalid message encountered: there should be a stopbound! */
+ /* but lets pretend there's nothing wrong... */
+ db_give_msgpos(&msg->bodyend);
+ msg->bodysize =
+ db_give_range_size(&msg->bodystart,
+ &msg->bodyend);
+ totallines += msg->bodylines;
+
+ trace(TRACE_WARNING,
+ "db_start_msg(): no stopbound where expected...\n");
/* return -1;
*/
- }
- else
- {
- /* walk on till end of buffer */
- result = 1;
- while (1)
- {
- for ( ; msgbuf_idx < msgbuf_buflen-1 && msgbuf_buf[msgbuf_idx]; msgbuf_idx++)
- if (msgbuf_buf[msgbuf_idx] == '\n')
- msg->bodylines++;
-
- if (result == 0)
- {
- /* end of msg reached, one char left in msgbuf */
- if (msgbuf_buf[msgbuf_idx] == '\n')
- msg->bodylines++;
-
- break;
+ } else {
+ /* walk on till end of buffer */
+ result = 1;
+ while (1) {
+ for (;
+ msgbuf_idx < msgbuf_buflen - 1
+ && msgbuf_buf[msgbuf_idx];
+ msgbuf_idx++)
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ msg->bodylines++;
+
+ if (result == 0) {
+ /* end of msg reached, one char left in msgbuf */
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ msg->bodylines++;
+
+ break;
+ }
+
+ result =
+ db_update_msgbuf(MSGBUF_FORCE_UPDATE);
+ if (result == -1)
+ return -2;
+ }
+
+ db_give_msgpos(&msg->bodyend);
+ msg->bodysize =
+ db_give_range_size(&msg->bodystart,
+ &msg->bodyend);
+ totallines += msg->bodylines;
}
-
- result = db_update_msgbuf(MSGBUF_FORCE_UPDATE);
- if (result == -1)
- return -2;
- }
-
- db_give_msgpos(&msg->bodyend);
- msg->bodysize = db_give_range_size(&msg->bodystart, &msg->bodyend);
- totallines += msg->bodylines;
}
- }
- trace(TRACE_DEBUG,"db_start_msg(): exit\n");
+ trace(TRACE_DEBUG, "db_start_msg(): exit\n");
- return totallines;
+ return totallines;
}
@@ -444,246 +467,266 @@ int db_start_msg(mime_message_t *msg, char *stopbound, int *level, int maxlevel)
* assume to enter just after a splitbound
* returns -1 on parse error, -2 on dbase error, -3 on memory error
*/
-int db_add_mime_children(struct list *brothers, char *splitbound, int *level, int maxlevel)
+int db_add_mime_children(struct list *brothers, char *splitbound,
+ int *level, int maxlevel)
{
- mime_message_t part;
- struct mime_record *mr;
- int sblen,nlines,totallines = 0,len;
- u64_t dummy;
- char *bptr,*newbound;
- int continue_recursion = (maxlevel < 0 || *level < maxlevel) ? 1 : 0;
-
- trace(TRACE_DEBUG,"db_add_mime_children(): starting, splitbound: '%s'\n",splitbound);
- sblen = strlen(splitbound);
-
- do
- {
- db_update_msgbuf(MSGBUF_FORCE_UPDATE);
- memset(&part, 0, sizeof(part));
- part.message_has_errors = (!continue_recursion);
-
- /* should have a MIME header right here */
- if ((nlines = mime_readheader(&msgbuf_buf[msgbuf_idx], &msgbuf_idx, &part.mimeheader, &dummy)) < 0)
- {
- trace(TRACE_WARNING,"db_add_mime_children(): error reading MIME-header\n");
- db_free_msg(&part);
- return nlines; /* error reading header */
- }
- totallines += nlines;
-
- mime_findfield("content-type", &part.mimeheader, &mr);
-
- if (continue_recursion &&
- mr && strncasecmp(mr->value, "message/rfc822", strlen("message/rfc822")) == 0)
- {
- trace(TRACE_DEBUG,"db_add_mime_children(): found an RFC822 message\n");
-
- /* a message will follow */
- if ((nlines = db_start_msg(&part, splitbound, level, maxlevel)) < 0)
- {
- trace(TRACE_WARNING,"db_add_mime_children(): error retrieving message\n");
- db_free_msg(&part);
- return nlines;
- }
- trace(TRACE_DEBUG,"db_add_mime_children(): got %d newlines from start_msg()\n",nlines);
- totallines += nlines;
- part.mimerfclines = nlines;
- }
- else if (continue_recursion &&
- mr && strncasecmp(mr->value, "multipart", strlen("multipart")) == 0)
- {
- trace(TRACE_DEBUG,"db_add_mime_children(): found a MIME multipart sub message\n");
-
- /* multipart msg, find new boundary */
- for (bptr = mr->value; *bptr; bptr++)
- if (strncasecmp(bptr, "boundary=", sizeof("boundary=")-1) == 0)
- break;
-
- if (!bptr)
- {
- trace(TRACE_WARNING, "db_add_mime_children(): could not find a new msg-boundary\n");
- db_free_msg(&part);
- return -1; /* no new boundary ??? */
- }
-
- bptr += sizeof("boundary=")-1;
- if (*bptr == '\"')
- {
- bptr++;
- newbound = bptr;
- while (*newbound && *newbound != '\"') newbound++;
- }
- else
- {
- newbound = bptr;
- while (*newbound && !isspace(*newbound) && *newbound!=';') newbound++;
- }
-
- len = newbound - bptr;
- if (!(newbound = (char*)my_malloc(len+1)))
- {
- trace(TRACE_ERROR, "db_add_mime_children(): out of memory\n");
- db_free_msg(&part);
- return -3;
- }
-
- strncpy(newbound, bptr, len);
- newbound[len] = '\0';
-
- trace(TRACE_DEBUG,"db_add_mime_children(): found new boundary: [%s], msgbuf_idx %llu\n",
- newbound,msgbuf_idx);
-
-
- /* advance to first boundary */
- if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1)
- {
- trace(TRACE_ERROR, "db_add_mime_children(): error updating msgbuf\n");
- db_free_msg(&part);
- my_free(newbound);
- return -2;
- }
-
- while (msgbuf_buf[msgbuf_idx])
- {
- if (strncmp(&msgbuf_buf[msgbuf_idx], newbound, strlen(newbound)) == 0)
- break;
-
- if (msgbuf_buf[msgbuf_idx] == '\n')
- {
- totallines++;
- part.bodylines++;
+ mime_message_t part;
+ struct mime_record *mr;
+ int sblen, nlines, totallines = 0, len;
+ u64_t dummy;
+ char *bptr, *newbound;
+ int continue_recursion = (maxlevel < 0
+ || *level < maxlevel) ? 1 : 0;
+
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): starting, splitbound: '%s'\n",
+ splitbound);
+ sblen = strlen(splitbound);
+
+ do {
+ db_update_msgbuf(MSGBUF_FORCE_UPDATE);
+ memset(&part, 0, sizeof(part));
+ part.message_has_errors = (!continue_recursion);
+
+ /* should have a MIME header right here */
+ if ((nlines =
+ mime_readheader(&msgbuf_buf[msgbuf_idx], &msgbuf_idx,
+ &part.mimeheader, &dummy)) < 0) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): error reading MIME-header\n");
+ db_free_msg(&part);
+ return nlines; /* error reading header */
}
-
- msgbuf_idx++;
- }
-
- if (!msgbuf_buf[msgbuf_idx])
- {
- trace(TRACE_WARNING, "db_add_mime_children(): unexpected end-of-data\n");
- my_free(newbound);
- db_free_msg(&part);
- return -1;
- }
-
- msgbuf_idx += strlen(newbound); /* skip the boundary */
- msgbuf_idx++; /* skip \n */
- totallines++; /* and count it */
- part.bodylines++;
- db_give_msgpos(&part.bodystart); /* remember position */
-
- (*level)++;
- if ((nlines = db_add_mime_children(&part.children, newbound, level, maxlevel)) < 0)
- {
- trace(TRACE_WARNING, "db_add_mime_children(): error adding mime children\n");
- my_free(newbound);
- db_free_msg(&part);
- return nlines;
- }
- (*level)--;
-
- my_free(newbound);
- newbound = NULL;
- msgbuf_idx += sblen+2; /* skip splitbound */
-
- if (msgbuf_idx > 0)
- {
- /* walk back because bodyend is inclusive */
- msgbuf_idx--;
- db_give_msgpos(&part.bodyend);
- msgbuf_idx++;
- }
- else
- db_give_msgpos(&part.bodyend); /* this case should never happen... */
-
-
- part.bodysize = db_give_range_size(&part.bodystart, &part.bodyend);
- part.bodylines += nlines;
- totallines += nlines;
- }
- else
- {
- trace(TRACE_DEBUG,"db_add_mime_children(): expecting body data...\n");
-
- /* just body data follows, advance to splitbound */
- db_give_msgpos(&part.bodystart);
-
- while (msgbuf_buf[msgbuf_idx])
- {
- if (db_update_msgbuf(sblen+3) == -1)
- {
- db_free_msg(&part);
- return -2;
+ totallines += nlines;
+
+ mime_findfield("content-type", &part.mimeheader, &mr);
+
+ if (continue_recursion &&
+ mr
+ && strncasecmp(mr->value, "message/rfc822",
+ strlen("message/rfc822")) == 0) {
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): found an RFC822 message\n");
+
+ /* a message will follow */
+ if ((nlines =
+ db_start_msg(&part, splitbound, level,
+ maxlevel)) < 0) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): error retrieving message\n");
+ db_free_msg(&part);
+ return nlines;
+ }
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): got %d newlines from start_msg()\n",
+ nlines);
+ totallines += nlines;
+ part.mimerfclines = nlines;
+ } else if (continue_recursion &&
+ mr
+ && strncasecmp(mr->value, "multipart",
+ strlen("multipart")) == 0) {
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): found a MIME multipart sub message\n");
+
+ /* multipart msg, find new boundary */
+ for (bptr = mr->value; *bptr; bptr++)
+ if (strncasecmp
+ (bptr, "boundary=",
+ sizeof("boundary=") - 1) == 0)
+ break;
+
+ if (!bptr) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): could not find a new msg-boundary\n");
+ db_free_msg(&part);
+ return -1; /* no new boundary ??? */
+ }
+
+ bptr += sizeof("boundary=") - 1;
+ if (*bptr == '\"') {
+ bptr++;
+ newbound = bptr;
+ while (*newbound && *newbound != '\"')
+ newbound++;
+ } else {
+ newbound = bptr;
+ while (*newbound && !isspace(*newbound)
+ && *newbound != ';')
+ newbound++;
+ }
+
+ len = newbound - bptr;
+ if (!(newbound = (char *) my_malloc(len + 1))) {
+ trace(TRACE_ERROR,
+ "db_add_mime_children(): out of memory\n");
+ db_free_msg(&part);
+ return -3;
+ }
+
+ strncpy(newbound, bptr, len);
+ newbound[len] = '\0';
+
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): found new boundary: [%s], msgbuf_idx %llu\n",
+ newbound, msgbuf_idx);
+
+
+ /* advance to first boundary */
+ if (db_update_msgbuf(MSGBUF_FORCE_UPDATE) == -1) {
+ trace(TRACE_ERROR,
+ "db_add_mime_children(): error updating msgbuf\n");
+ db_free_msg(&part);
+ my_free(newbound);
+ return -2;
+ }
+
+ while (msgbuf_buf[msgbuf_idx]) {
+ if (strncmp
+ (&msgbuf_buf[msgbuf_idx], newbound,
+ strlen(newbound)) == 0)
+ break;
+
+ if (msgbuf_buf[msgbuf_idx] == '\n') {
+ totallines++;
+ part.bodylines++;
+ }
+
+ msgbuf_idx++;
+ }
+
+ if (!msgbuf_buf[msgbuf_idx]) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): unexpected end-of-data\n");
+ my_free(newbound);
+ db_free_msg(&part);
+ return -1;
+ }
+
+ msgbuf_idx += strlen(newbound); /* skip the boundary */
+ msgbuf_idx++; /* skip \n */
+ totallines++; /* and count it */
+ part.bodylines++;
+ db_give_msgpos(&part.bodystart); /* remember position */
+
+ (*level)++;
+ if ((nlines =
+ db_add_mime_children(&part.children, newbound,
+ level, maxlevel)) < 0) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): error adding mime children\n");
+ my_free(newbound);
+ db_free_msg(&part);
+ return nlines;
+ }
+ (*level)--;
+
+ my_free(newbound);
+ newbound = NULL;
+ msgbuf_idx += sblen + 2; /* skip splitbound */
+
+ if (msgbuf_idx > 0) {
+ /* walk back because bodyend is inclusive */
+ msgbuf_idx--;
+ db_give_msgpos(&part.bodyend);
+ msgbuf_idx++;
+ } else
+ db_give_msgpos(&part.bodyend); /* this case should never happen... */
+
+
+ part.bodysize =
+ db_give_range_size(&part.bodystart,
+ &part.bodyend);
+ part.bodylines += nlines;
+ totallines += nlines;
+ } else {
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): expecting body data...\n");
+
+ /* just body data follows, advance to splitbound */
+ db_give_msgpos(&part.bodystart);
+
+ while (msgbuf_buf[msgbuf_idx]) {
+ if (db_update_msgbuf(sblen + 3) == -1) {
+ db_free_msg(&part);
+ return -2;
+ }
+
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ part.bodylines++;
+
+ if (msgbuf_buf[msgbuf_idx + 1] == '-'
+ && msgbuf_buf[msgbuf_idx + 2] == '-'
+ && strncmp(&msgbuf_buf[msgbuf_idx + 3],
+ splitbound, sblen) == 0)
+ break;
+
+ msgbuf_idx++;
+ }
+
+ /* at this point msgbuf_buf[msgbuf_idx] is either
+ * 0 (end of data) -- invalid message!
+ * or the character right before '--<splitbound>'
+ */
+
+ totallines += part.bodylines;
+
+ if (!msgbuf_buf[msgbuf_idx]) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): unexpected end of data\n");
+ db_free_msg(&part);
+ return -1; /* ?? splitbound should follow */
+ }
+
+ db_give_msgpos(&part.bodyend);
+ part.bodysize =
+ db_give_range_size(&part.bodystart,
+ &part.bodyend);
+
+ msgbuf_idx++; /* msgbuf_buf[msgbuf_idx] == '-' after this statement */
+
+ msgbuf_idx += sblen + 2; /* skip the boundary & double hypen */
}
- if (msgbuf_buf[msgbuf_idx] == '\n')
- part.bodylines++;
-
- if (msgbuf_buf[msgbuf_idx+1] == '-' && msgbuf_buf[msgbuf_idx+2] == '-' &&
- strncmp(&msgbuf_buf[msgbuf_idx+3], splitbound, sblen) == 0)
- break;
-
- msgbuf_idx++;
- }
-
- /* at this point msgbuf_buf[msgbuf_idx] is either
- * 0 (end of data) -- invalid message!
- * or the character right before '--<splitbound>'
- */
-
- totallines += part.bodylines;
-
- if (!msgbuf_buf[msgbuf_idx])
- {
- trace(TRACE_WARNING,"db_add_mime_children(): unexpected end of data\n");
- db_free_msg(&part);
- return -1; /* ?? splitbound should follow */
- }
-
- db_give_msgpos(&part.bodyend);
- part.bodysize = db_give_range_size(&part.bodystart, &part.bodyend);
-
- msgbuf_idx++; /* msgbuf_buf[msgbuf_idx] == '-' after this statement */
-
- msgbuf_idx += sblen+2; /* skip the boundary & double hypen */
- }
-
- /* add this part to brother list */
- if (list_nodeadd(brothers, &part, sizeof(part)) == NULL)
- {
- trace(TRACE_WARNING,"db_add_mime_children(): could not add node\n");
- db_free_msg(&part);
- return -3;
- }
-
- /* if double hyphen ('--') follows we're done */
- if (msgbuf_buf[msgbuf_idx] == '-' && msgbuf_buf[msgbuf_idx+1] == '-')
- {
- trace(TRACE_DEBUG,"db_add_mime_children(): found end after boundary [%s],\n",splitbound);
- trace(TRACE_DEBUG," followed by [%.*s],\n",
- 48,&msgbuf_buf[msgbuf_idx]);
-
- msgbuf_idx += 2; /* skip hyphens */
-
- /* probably some newlines will follow (not specified but often there) */
- while (msgbuf_buf[msgbuf_idx] == '\n')
- {
- totallines++;
- msgbuf_idx++;
- }
+ /* add this part to brother list */
+ if (list_nodeadd(brothers, &part, sizeof(part)) == NULL) {
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): could not add node\n");
+ db_free_msg(&part);
+ return -3;
+ }
- return totallines;
- }
+ /* if double hyphen ('--') follows we're done */
+ if (msgbuf_buf[msgbuf_idx] == '-'
+ && msgbuf_buf[msgbuf_idx + 1] == '-') {
+ trace(TRACE_DEBUG,
+ "db_add_mime_children(): found end after boundary [%s],\n",
+ splitbound);
+ trace(TRACE_DEBUG,
+ " followed by [%.*s],\n",
+ 48, &msgbuf_buf[msgbuf_idx]);
+
+ msgbuf_idx += 2; /* skip hyphens */
+
+ /* probably some newlines will follow (not specified but often there) */
+ while (msgbuf_buf[msgbuf_idx] == '\n') {
+ totallines++;
+ msgbuf_idx++;
+ }
+
+ return totallines;
+ }
- if (msgbuf_buf[msgbuf_idx] == '\n')
- {
- totallines++;
- msgbuf_idx++; /* skip the newline itself */
+ if (msgbuf_buf[msgbuf_idx] == '\n') {
+ totallines++;
+ msgbuf_idx++; /* skip the newline itself */
+ }
}
- }
- while (msgbuf_buf[msgbuf_idx]) ;
+ while (msgbuf_buf[msgbuf_idx]);
- trace(TRACE_WARNING,"db_add_mime_children(): sudden end of message\n");
- return totallines;
+ trace(TRACE_WARNING,
+ "db_add_mime_children(): sudden end of message\n");
+ return totallines;
/* trace(TRACE_ERROR,"db_add_mime_children(): invalid message (no ending boundary found)\n");
return -1;
@@ -700,60 +743,61 @@ int db_add_mime_children(struct list *brothers, char *splitbound, int *level, in
*
* returns -1 on dbase failure, -2 on memory error
*/
-int db_parse_as_text(mime_message_t *msg)
+int db_parse_as_text(mime_message_t * msg)
{
- int result;
- struct mime_record mr;
- struct element *el = NULL;
-
- memset(msg, 0, sizeof(*msg));
-
- strcpy(mr.field, "subject");
- strcpy(mr.value, "dbmail IMAP server info: this message could not be parsed");
- el = list_nodeadd(&msg->rfcheader, &mr, sizeof(mr));
- if (!el)
- return -3;
-
- strcpy(mr.field, "from");
- strcpy(mr.value, "imapserver@dbmail.org");
- el = list_nodeadd(&msg->rfcheader, &mr, sizeof(mr));
- if (!el)
- return -3;
-
- msg->rfcheadersize = strlen("subject: dbmail IMAP server info: this message could not be parsed\r\n")
- + strlen("from: imapserver@dbmail.org\r\n");
- msg->rfcheaderlines = 4;
-
- db_give_msgpos(&msg->bodystart);
-
- /* walk on till end of buffer */
- result = 1;
- while (1)
- {
- for ( ; msgbuf_idx < msgbuf_buflen - 1; msgbuf_idx++)
- if (msgbuf_buf[msgbuf_idx] == '\n')
- msg->bodylines++;
-
- if (result == 0)
- {
- /* end of msg reached, one char left in msgbuf_buf */
- if (msgbuf_buf[msgbuf_idx] == '\n')
- msg->bodylines++;
-
- break;
- }
+ int result;
+ struct mime_record mr;
+ struct element *el = NULL;
+
+ memset(msg, 0, sizeof(*msg));
+
+ strcpy(mr.field, "subject");
+ strcpy(mr.value,
+ "dbmail IMAP server info: this message could not be parsed");
+ el = list_nodeadd(&msg->rfcheader, &mr, sizeof(mr));
+ if (!el)
+ return -3;
+
+ strcpy(mr.field, "from");
+ strcpy(mr.value, "imapserver@dbmail.org");
+ el = list_nodeadd(&msg->rfcheader, &mr, sizeof(mr));
+ if (!el)
+ return -3;
+
+ msg->rfcheadersize =
+ strlen
+ ("subject: dbmail IMAP server info: this message could not be parsed\r\n")
+ + strlen("from: imapserver@dbmail.org\r\n");
+ msg->rfcheaderlines = 4;
+
+ db_give_msgpos(&msg->bodystart);
+
+ /* walk on till end of buffer */
+ result = 1;
+ while (1) {
+ for (; msgbuf_idx < msgbuf_buflen - 1; msgbuf_idx++)
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ msg->bodylines++;
+
+ if (result == 0) {
+ /* end of msg reached, one char left in msgbuf_buf */
+ if (msgbuf_buf[msgbuf_idx] == '\n')
+ msg->bodylines++;
+
+ break;
+ }
- result = db_update_msgbuf(MSGBUF_FORCE_UPDATE);
- if (result == -1)
- return -2;
- }
+ result = db_update_msgbuf(MSGBUF_FORCE_UPDATE);
+ if (result == -1)
+ return -2;
+ }
- db_give_msgpos(&msg->bodyend);
- msg->bodysize = db_give_range_size(&msg->bodystart, &msg->bodyend);
+ db_give_msgpos(&msg->bodyend);
+ msg->bodysize = db_give_range_size(&msg->bodystart, &msg->bodyend);
- return 0;
+ return 0;
}
-
+
/*
* db_msgdump()
@@ -761,85 +805,82 @@ int db_parse_as_text(mime_message_t *msg)
* dumps a message to stderr
* returns the size (in bytes) that the message occupies in memory
*/
-int db_msgdump(mime_message_t *msg, u64_t msguid, int level)
+int db_msgdump(mime_message_t * msg, u64_t msguid, int level)
{
- struct element *curr;
- struct mime_record *mr;
- char *spaces;
- int size = sizeof(mime_message_t);
-
- if (level < 0)
- return 0;
-
- if (!msg)
- {
- trace(TRACE_DEBUG,"db_msgdump: got null\n");
- return 0;
- }
-
- spaces = (char*)my_malloc(3*level + 1);
- if (!spaces)
- return 0;
-
- memset(spaces, ' ', 3*level);
- spaces[3*level] = 0;
-
-
- trace(TRACE_DEBUG,"%sMIME-header: \n",spaces);
- curr = list_getstart(&msg->mimeheader);
- if (!curr)
- trace(TRACE_DEBUG,"%s%snull\n",spaces,spaces);
- else
- {
- while (curr)
- {
- mr = (struct mime_record *)curr->data;
- trace(TRACE_DEBUG,"%s%s[%s] : [%s]\n",spaces,spaces,mr->field, mr->value);
- curr = curr->nextnode;
- size += sizeof(struct mime_record);
+ struct element *curr;
+ struct mime_record *mr;
+ char *spaces;
+ int size = sizeof(mime_message_t);
+
+ if (level < 0)
+ return 0;
+
+ if (!msg) {
+ trace(TRACE_DEBUG, "db_msgdump: got null\n");
+ return 0;
+ }
+
+ spaces = (char *) my_malloc(3 * level + 1);
+ if (!spaces)
+ return 0;
+
+ memset(spaces, ' ', 3 * level);
+ spaces[3 * level] = 0;
+
+
+ trace(TRACE_DEBUG, "%sMIME-header: \n", spaces);
+ curr = list_getstart(&msg->mimeheader);
+ if (!curr)
+ trace(TRACE_DEBUG, "%s%snull\n", spaces, spaces);
+ else {
+ while (curr) {
+ mr = (struct mime_record *) curr->data;
+ trace(TRACE_DEBUG, "%s%s[%s] : [%s]\n", spaces,
+ spaces, mr->field, mr->value);
+ curr = curr->nextnode;
+ size += sizeof(struct mime_record);
+ }
}
- }
- trace(TRACE_DEBUG,"%s*** MIME-header end\n",spaces);
-
- trace(TRACE_DEBUG,"%sRFC822-header: \n",spaces);
- curr = list_getstart(&msg->rfcheader);
- if (!curr)
- trace(TRACE_DEBUG,"%s%snull\n",spaces,spaces);
- else
- {
- while (curr)
- {
- mr = (struct mime_record *)curr->data;
- trace(TRACE_DEBUG,"%s%s[%s] : [%s]\n",spaces,spaces,mr->field, mr->value);
- curr = curr->nextnode;
- size += sizeof(struct mime_record);
+ trace(TRACE_DEBUG, "%s*** MIME-header end\n", spaces);
+
+ trace(TRACE_DEBUG, "%sRFC822-header: \n", spaces);
+ curr = list_getstart(&msg->rfcheader);
+ if (!curr)
+ trace(TRACE_DEBUG, "%s%snull\n", spaces, spaces);
+ else {
+ while (curr) {
+ mr = (struct mime_record *) curr->data;
+ trace(TRACE_DEBUG, "%s%s[%s] : [%s]\n", spaces,
+ spaces, mr->field, mr->value);
+ curr = curr->nextnode;
+ size += sizeof(struct mime_record);
+ }
}
- }
- trace(TRACE_DEBUG,"%s*** RFC822-header end\n",spaces);
+ trace(TRACE_DEBUG, "%s*** RFC822-header end\n", spaces);
+
+ trace(TRACE_DEBUG, "%s*** Body range:\n", spaces);
+ trace(TRACE_DEBUG,
+ "%s%s(%llu, %llu) - (%llu, %llu), size: %llu, newlines: %llu\n",
+ spaces, spaces, msg->bodystart.block, msg->bodystart.pos,
+ msg->bodyend.block, msg->bodyend.pos, msg->bodysize,
+ msg->bodylines);
- trace(TRACE_DEBUG,"%s*** Body range:\n",spaces);
- trace(TRACE_DEBUG,"%s%s(%llu, %llu) - (%llu, %llu), size: %llu, newlines: %llu\n",
- spaces,spaces,
- msg->bodystart.block, msg->bodystart.pos,
- msg->bodyend.block, msg->bodyend.pos,
- msg->bodysize, msg->bodylines);
-
/* trace(TRACE_DEBUG,"body: \n");
db_dump_range(msg->bodystart, msg->bodyend, msguid);
trace(TRACE_DEBUG,"*** body end\n");
*/
- trace(TRACE_DEBUG,"%sChildren of this msg:\n",spaces);
-
- curr = list_getstart(&msg->children);
- while (curr)
- {
- size += db_msgdump((mime_message_t*)curr->data,msguid,level+1);
- curr = curr->nextnode;
- }
- trace(TRACE_DEBUG,"%s*** child list end\n",spaces);
-
- my_free(spaces);
- return size;
-}
+ trace(TRACE_DEBUG, "%sChildren of this msg:\n", spaces);
+
+ curr = list_getstart(&msg->children);
+ while (curr) {
+ size +=
+ db_msgdump((mime_message_t *) curr->data, msguid,
+ level + 1);
+ curr = curr->nextnode;
+ }
+ trace(TRACE_DEBUG, "%s*** child list end\n", spaces);
+ my_free(spaces);
+ return size;
+}
diff --git a/rfcmsg.h b/rfcmsg.h
index 0cb58aa3..ba0cde59 100644
--- a/rfcmsg.h
+++ b/rfcmsg.h
@@ -32,13 +32,15 @@
#include "dbmailtypes.h"
-void db_free_msg(mime_message_t *msg);
-void db_reverse_msg(mime_message_t *msg);
-
-int db_fetch_headers(u64_t msguid, mime_message_t *msg);
-int db_add_mime_children(struct list *brothers, char *splitbound, int *level, int maxlevel);
-int db_start_msg(mime_message_t *msg, char *stopbound, int *level, int maxlevel);
-int db_parse_as_text(mime_message_t *msg);
-int db_msgdump(mime_message_t *msg, u64_t msguid, int level);
+void db_free_msg(mime_message_t * msg);
+void db_reverse_msg(mime_message_t * msg);
+
+int db_fetch_headers(u64_t msguid, mime_message_t * msg);
+int db_add_mime_children(struct list *brothers, char *splitbound,
+ int *level, int maxlevel);
+int db_start_msg(mime_message_t * msg, char *stopbound, int *level,
+ int maxlevel);
+int db_parse_as_text(mime_message_t * msg);
+int db_msgdump(mime_message_t * msg, u64_t msguid, int level);
#endif
diff --git a/server.c b/server.c
index 8a27edaa..791d59cb 100644
--- a/server.c
+++ b/server.c
@@ -53,246 +53,253 @@ int Restart = 0;
pid_t ParentPID = 0;
/* some extra prototypes (defintions are below) */
-static void ParentSigHandler(int sig, siginfo_t *info, void *data);
+static void ParentSigHandler(int sig, siginfo_t * info, void *data);
static int SetParentSigHandler(void);
int SetParentSigHandler()
{
- struct sigaction act;
-
- /* init & install signal handlers */
- memset(&act, 0, sizeof(act));
-
- act.sa_sigaction = ParentSigHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
-
- sigaction(SIGCHLD, &act, 0);
- sigaction(SIGINT, &act, 0);
- sigaction(SIGQUIT, &act, 0);
- sigaction(SIGILL, &act, 0);
- sigaction(SIGBUS, &act, 0);
- sigaction(SIGFPE, &act, 0);
- sigaction(SIGSEGV, &act, 0);
- sigaction(SIGTERM, &act, 0);
- sigaction(SIGALRM, &act, 0);
- sigaction(SIGHUP, &act, 0);
-
- return 0;
+ struct sigaction act;
+
+ /* init & install signal handlers */
+ memset(&act, 0, sizeof(act));
+
+ act.sa_sigaction = ParentSigHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+
+ sigaction(SIGCHLD, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGILL, &act, 0);
+ sigaction(SIGBUS, &act, 0);
+ sigaction(SIGFPE, &act, 0);
+ sigaction(SIGSEGV, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGALRM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
+
+ return 0;
}
-int StartServer(serverConfig_t *conf)
+int StartServer(serverConfig_t * conf)
{
- int i,stillSomeAlive,cnt;
- pid_t *pid = (pid_t*)malloc(sizeof(pid_t) * conf->nChildren);
- ChildInfo_t childinfo;
+ int i, stillSomeAlive, cnt;
+ pid_t *pid = (pid_t *) malloc(sizeof(pid_t) * conf->nChildren);
+ ChildInfo_t childinfo;
- if (!pid)
- trace(TRACE_FATAL, "StartServer(): no memory for PID list. Fatal.");
+ if (!pid)
+ trace(TRACE_FATAL,
+ "StartServer(): no memory for PID list. Fatal.");
- if (!conf)
- trace(TRACE_FATAL, "StartServer(): NULL configuration");
+ if (!conf)
+ trace(TRACE_FATAL, "StartServer(): NULL configuration");
- trace(TRACE_DEBUG, "StartServer(): init");
+ trace(TRACE_DEBUG, "StartServer(): init");
- ParentPID = getpid();
- Restart = 0;
- GeneralStopRequested = 0;
- SetParentSigHandler();
+ ParentPID = getpid();
+ Restart = 0;
+ GeneralStopRequested = 0;
+ SetParentSigHandler();
// AllocSharedMemory();
// AttachSharedMemory();
- trace(TRACE_DEBUG, "StartServer(): init ok. Creating children..");
+ trace(TRACE_DEBUG, "StartServer(): init ok. Creating children..");
- childinfo.maxConnect = conf->childMaxConnect;
- childinfo.listenSocket = conf->listenSocket;
- childinfo.timeout = conf->timeout;
- childinfo.ClientHandler = conf->ClientHandler;
- childinfo.timeoutMsg = conf->timeoutMsg;
- childinfo.resolveIP = conf->resolveIP;
+ childinfo.maxConnect = conf->childMaxConnect;
+ childinfo.listenSocket = conf->listenSocket;
+ childinfo.timeout = conf->timeout;
+ childinfo.ClientHandler = conf->ClientHandler;
+ childinfo.timeoutMsg = conf->timeoutMsg;
+ childinfo.resolveIP = conf->resolveIP;
- for (i=0; i<conf->nChildren; i++)
- {
- if ( (pid[i] = CreateChild(&childinfo)) == -1)
- {
- trace(TRACE_ERROR, "StartServer(): could not create child");
- trace(TRACE_ERROR, "StartServer(): killing children");
-
- while (--i >= 0)
- kill(pid[i], SIGKILL);
+ for (i = 0; i < conf->nChildren; i++) {
+ if ((pid[i] = CreateChild(&childinfo)) == -1) {
+ trace(TRACE_ERROR,
+ "StartServer(): could not create child");
+ trace(TRACE_ERROR,
+ "StartServer(): killing children");
- trace(TRACE_FATAL, "StartServer(): could not create children. Fatal.");
- }
- }
-
- trace(TRACE_DEBUG, "StartServer(): children created, starting main service loop");
-
- while (!GeneralStopRequested)
- {
- for (i=0; i<conf->nChildren; i++)
- {
- if (waitpid(pid[i], NULL, WNOHANG|WUNTRACED) == pid[i])
- {
- trace(TRACE_DEBUG, "StartServer(): child [%u] has exited", (unsigned)pid[i]);
- trace(TRACE_DEBUG, "StartServer(): creating new child");
- pid[i] = CreateChild(&childinfo);
- }
+ while (--i >= 0)
+ kill(pid[i], SIGKILL);
+
+ trace(TRACE_FATAL,
+ "StartServer(): could not create children. Fatal.");
+ }
}
- sleep(1);
- }
-
- trace(TRACE_INFO, "StartServer(): General stop requested. Killing children.. ");
-
- stillSomeAlive = 1;
- cnt = 0;
- while (stillSomeAlive && cnt < 10)
- {
- stillSomeAlive = 0;
- cnt++;
-
- for (i=0; i<conf->nChildren; i++)
- {
- if (pid[i] == 0)
- continue;
-
- if (CheckChildAlive(pid[i]))
- {
- trace(TRACE_DEBUG, "StartServer(): child [%d] is still alive, sending SIGTERM", pid[i]);
- kill(pid[i], SIGTERM);
- usleep(1000);
- }
- else
- trace(TRACE_DEBUG, "StartServer(): child [%d] is dead, zombie not yet cleaned", pid[i]);
-
-
- if (waitpid(pid[i], NULL, WNOHANG|WUNTRACED) == pid[i])
- {
- trace(TRACE_DEBUG, "StartServer(): child [%d] has exited, zombie cleaned up", pid[i]);
- pid[i] = 0;
- }
- else
- {
- stillSomeAlive = 1;
- trace(TRACE_DEBUG, "StartServer(): child [%d] hasn't provided exit status yet", pid[i]);
- }
+ trace(TRACE_DEBUG,
+ "StartServer(): children created, starting main service loop");
+
+ while (!GeneralStopRequested) {
+ for (i = 0; i < conf->nChildren; i++) {
+ if (waitpid(pid[i], NULL, WNOHANG | WUNTRACED) ==
+ pid[i]) {
+ trace(TRACE_DEBUG,
+ "StartServer(): child [%u] has exited",
+ (unsigned) pid[i]);
+ trace(TRACE_DEBUG,
+ "StartServer(): creating new child");
+ pid[i] = CreateChild(&childinfo);
+ }
+ }
+
+ sleep(1);
}
-
- if (stillSomeAlive)
- usleep(500);
- }
-
- if (stillSomeAlive)
- {
- trace(TRACE_INFO, "StartServer(): not all children terminated at SIGTERM, killing hard now");
-
- for (i=0; i<conf->nChildren; i++)
- {
- if (pid[i] != 0)
- kill(pid[i], SIGKILL);;
+
+ trace(TRACE_INFO,
+ "StartServer(): General stop requested. Killing children.. ");
+
+ stillSomeAlive = 1;
+ cnt = 0;
+ while (stillSomeAlive && cnt < 10) {
+ stillSomeAlive = 0;
+ cnt++;
+
+ for (i = 0; i < conf->nChildren; i++) {
+ if (pid[i] == 0)
+ continue;
+
+ if (CheckChildAlive(pid[i])) {
+ trace(TRACE_DEBUG,
+ "StartServer(): child [%d] is still alive, sending SIGTERM",
+ pid[i]);
+ kill(pid[i], SIGTERM);
+ usleep(1000);
+ } else
+ trace(TRACE_DEBUG,
+ "StartServer(): child [%d] is dead, zombie not yet cleaned",
+ pid[i]);
+
+
+ if (waitpid(pid[i], NULL, WNOHANG | WUNTRACED) ==
+ pid[i]) {
+ trace(TRACE_DEBUG,
+ "StartServer(): child [%d] has exited, zombie cleaned up",
+ pid[i]);
+ pid[i] = 0;
+ } else {
+ stillSomeAlive = 1;
+ trace(TRACE_DEBUG,
+ "StartServer(): child [%d] hasn't provided exit status yet",
+ pid[i]);
+ }
+ }
+
+ if (stillSomeAlive)
+ usleep(500);
}
- }
+ if (stillSomeAlive) {
+ trace(TRACE_INFO,
+ "StartServer(): not all children terminated at SIGTERM, killing hard now");
+
+ for (i = 0; i < conf->nChildren; i++) {
+ if (pid[i] != 0)
+ kill(pid[i], SIGKILL);;
+ }
+ }
// DeleteSharedMemory();
- free(pid);
- return Restart;
+ free(pid);
+ return Restart;
}
-
-void ParentSigHandler(int sig, siginfo_t *info, void *data)
-{
- if (ParentPID != getpid())
- {
- trace(TRACE_INFO, "ParentSigHandler(): i'm no longer father");
- ChildSigHandler(sig, info, data); /* this call is for a child but it's handler is not yet installed */
- }
+void ParentSigHandler(int sig, siginfo_t * info, void *data)
+{
+ if (ParentPID != getpid()) {
+ trace(TRACE_INFO,
+ "ParentSigHandler(): i'm no longer father");
+ ChildSigHandler(sig, info, data); /* this call is for a child but it's handler is not yet installed */
+ }
#ifdef _USE_STR_SIGNAL
- trace(TRACE_INFO, "ParentSigHandler(): got signal [%s]", strsignal(sig));
+ trace(TRACE_INFO, "ParentSigHandler(): got signal [%s]",
+ strsignal(sig));
#else
- trace(TRACE_INFO, "ParentSigHandler(): got signal [%d]", sig);
+ trace(TRACE_INFO, "ParentSigHandler(): got signal [%d]", sig);
#endif
- switch (sig)
- {
- case SIGCHLD:
- break; /* ignore, wait for child in main loop */
+ switch (sig) {
+ case SIGCHLD:
+ break; /* ignore, wait for child in main loop */
- case SIGHUP:
- trace(TRACE_DEBUG, "ParentSigHandler(): SIGHUP, setting Restart");
- Restart = 1;
+ case SIGHUP:
+ trace(TRACE_DEBUG,
+ "ParentSigHandler(): SIGHUP, setting Restart");
+ Restart = 1;
- default:
- GeneralStopRequested = 1;
- }
+ default:
+ GeneralStopRequested = 1;
+ }
}
-int CreateSocket(serverConfig_t *conf)
+int CreateSocket(serverConfig_t * conf)
{
- int sock, r, len;
- struct sockaddr_in saServer;
- int so_reuseaddress = 1; /**< reuseaddr to 1, so address will be reused */
-
- /* make a tcp/ip socket */
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock == -1)
- trace(TRACE_FATAL, "CreateSocket(): socket creation failed [%s]", strerror(errno));
-
- trace(TRACE_DEBUG, "CreateSocket(): socket created");
-
- /* make an (socket)address */
- memset(&saServer, 0, sizeof(saServer));
-
- saServer.sin_family = AF_INET;
- saServer.sin_port = htons(conf->port);
-
- if (conf->ip[0] == '*')
- saServer.sin_addr.s_addr = htonl(INADDR_ANY);
- else
- {
- r = inet_aton(conf->ip, &saServer.sin_addr);
- if (!r)
- {
- close(sock);
- trace(TRACE_FATAL, "CreateSocket(): invalid IP [%s]", conf->ip);
+ int sock, r, len;
+ struct sockaddr_in saServer;
+ int so_reuseaddress = 1;
+ /**< reuseaddr to 1, so address will be reused */
+
+ /* make a tcp/ip socket */
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock == -1)
+ trace(TRACE_FATAL,
+ "CreateSocket(): socket creation failed [%s]",
+ strerror(errno));
+
+ trace(TRACE_DEBUG, "CreateSocket(): socket created");
+
+ /* make an (socket)address */
+ memset(&saServer, 0, sizeof(saServer));
+
+ saServer.sin_family = AF_INET;
+ saServer.sin_port = htons(conf->port);
+
+ if (conf->ip[0] == '*')
+ saServer.sin_addr.s_addr = htonl(INADDR_ANY);
+ else {
+ r = inet_aton(conf->ip, &saServer.sin_addr);
+ if (!r) {
+ close(sock);
+ trace(TRACE_FATAL,
+ "CreateSocket(): invalid IP [%s]", conf->ip);
+ }
}
- }
- trace(TRACE_DEBUG, "CreateSocket(): socket IP requested [%s] OK", conf->ip);
+ trace(TRACE_DEBUG, "CreateSocket(): socket IP requested [%s] OK",
+ conf->ip);
- /* set socket option: reuse address */
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddress, sizeof(so_reuseaddress));
+ /* set socket option: reuse address */
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddress,
+ sizeof(so_reuseaddress));
- /* bind the address */
- len = sizeof(saServer);
- r = bind(sock, (struct sockaddr*)&saServer, len);
+ /* bind the address */
+ len = sizeof(saServer);
+ r = bind(sock, (struct sockaddr *) &saServer, len);
- if (r == -1)
- {
- close(sock);
- trace(TRACE_FATAL, "CreateSocket(): could not bind address to socket");
- }
-
- trace(TRACE_DEBUG, "CreateSocket(): IP bound to socket");
+ if (r == -1) {
+ close(sock);
+ trace(TRACE_FATAL,
+ "CreateSocket(): could not bind address to socket");
+ }
- r = listen(sock, BACKLOG);
- if (r == -1)
- {
- close(sock);
- trace(TRACE_FATAL, "CreateSocket(): error making socket listen [%s]", strerror(errno));
- }
-
- trace(TRACE_INFO, "CreateSocket(): socket creation complete");
- conf->listenSocket = sock;
+ trace(TRACE_DEBUG, "CreateSocket(): IP bound to socket");
- return 0;
-}
-
+ r = listen(sock, BACKLOG);
+ if (r == -1) {
+ close(sock);
+ trace(TRACE_FATAL,
+ "CreateSocket(): error making socket listen [%s]",
+ strerror(errno));
+ }
+ trace(TRACE_INFO, "CreateSocket(): socket creation complete");
+ conf->listenSocket = sock;
+ return 0;
+}
diff --git a/server.h b/server.h
index 2da91247..068bcf06 100644
--- a/server.h
+++ b/server.h
@@ -37,26 +37,20 @@
#include "dbmail.h"
#include "clientinfo.h"
-typedef struct
-{
- int listenSocket;
- int nChildren;
- int childMaxConnect;
- int timeout;
- char ip[IPLEN];
- int port;
- int resolveIP;
- char *timeoutMsg;
- field_t serverUser, serverGroup;
- int (*ClientHandler)(clientinfo_t *);
+typedef struct {
+ int listenSocket;
+ int nChildren;
+ int childMaxConnect;
+ int timeout;
+ char ip[IPLEN];
+ int port;
+ int resolveIP;
+ char *timeoutMsg;
+ field_t serverUser, serverGroup;
+ int (*ClientHandler) (clientinfo_t *);
} serverConfig_t;
-int CreateSocket(serverConfig_t *conf);
-int StartServer(serverConfig_t *conf);
+int CreateSocket(serverConfig_t * conf);
+int StartServer(serverConfig_t * conf);
#endif
-
-
-
-
-
diff --git a/serverchild.c b/serverchild.c
index a988ef9c..cc634041 100644
--- a/serverchild.c
+++ b/serverchild.c
@@ -56,128 +56,129 @@ int ChildStopRequested = 0;
int connected = 0;
clientinfo_t client;
-int PerformChildTask(ChildInfo_t *info);
+int PerformChildTask(ChildInfo_t * info);
-void ChildSigHandler(int sig, siginfo_t *info UNUSED, void *data UNUSED)
+void ChildSigHandler(int sig, siginfo_t * info UNUSED, void *data UNUSED)
{
- static int triedDisconnect = 0;
+ static int triedDisconnect = 0;
#ifdef _USE_STR_SIGNAL
- trace(TRACE_ERROR, "ChildSighandler(): got signal [%s]", strsignal(sig));
+ trace(TRACE_ERROR, "ChildSighandler(): got signal [%s]",
+ strsignal(sig));
#else
- trace(TRACE_ERROR, "ChildSighandler(): got signal [%d]", sig);
+ trace(TRACE_ERROR, "ChildSighandler(): got signal [%d]", sig);
#endif
- /* perform reinit at SIGHUP otherwise exit */
- switch (sig)
- {
- case SIGALRM:
- trace(TRACE_DEBUG, "ChildSighandler(): timeout received");
-
- if (client.tx)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): write stream open, closing");
- fprintf(client.tx, "%s", client.timeoutMsg);
- fflush(client.tx);
- fclose(client.tx); /* closes clientSocket as well */
- client.tx = NULL;
+ /* perform reinit at SIGHUP otherwise exit */
+ switch (sig) {
+ case SIGALRM:
+ trace(TRACE_DEBUG, "ChildSighandler(): timeout received");
+
+ if (client.tx) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): write stream open, closing");
+ fprintf(client.tx, "%s", client.timeoutMsg);
+ fflush(client.tx);
+ fclose(client.tx); /* closes clientSocket as well */
+ client.tx = NULL;
+ }
+
+ if (client.rx) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): read stream open, closing");
+ shutdown(fileno(client.rx), SHUT_RDWR);
+ fclose(client.rx);
+ client.rx = NULL;
+ }
+
+ break;
+
+ case SIGHUP:
+ case SIGTERM:
+ case SIGQUIT:
+ case SIGSTOP:
+ if (ChildStopRequested) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): already caught a stop request. Closing right now");
+
+ /* already caught this signal, exit the hard way now */
+ if (client.tx) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): write stream still open, closing");
+ fflush(client.tx);
+ fclose(client.tx); /* closes clientSocket as well */
+ client.tx = NULL;
+ }
+
+ if (client.rx) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): read stream still open, closing");
+ shutdown(fileno(client.rx), SHUT_RDWR);
+ fclose(client.rx);
+ client.rx = NULL;
+ }
+
+ if (connected) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): database connection still open, closing");
+ db_disconnect();
+ auth_disconnect();
+ connected = 0;
+ }
+
+ trace(TRACE_DEBUG, "ChildSighandler(): exit");
+ exit(1);
+ }
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): setting stop request");
+ ChildStopRequested = 1;
+ break;
+
+ default:
+ /* bad shtuff, exit */
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): cannot ignore this. Terminating");
+
+ /*
+ * For some reason i have not yet determined the process starts eating up
+ * all CPU time when trying to disconnect.
+ * For now: just bail out :-)
+ */
+ _exit(1);
+
+ if (!triedDisconnect) {
+ triedDisconnect = 1;
+
+ if (client.tx) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): write stream still open, closing");
+ fflush(client.tx);
+ fclose(client.tx); /* closes clientSocket as well */
+ client.tx = NULL;
+ }
+
+ if (client.rx) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): read stream still open, closing");
+ shutdown(fileno(client.rx), SHUT_RDWR);
+ fclose(client.rx);
+ client.rx = NULL;
+ }
+
+ if (connected) {
+ trace(TRACE_DEBUG,
+ "ChildSighandler(): database connection still open, closing");
+ db_disconnect();
+ auth_disconnect();
+ }
+
+ connected = 0;
+ }
+
+ trace(TRACE_DEBUG, "ChildSighandler(): exit");
+ exit(1);
}
-
- if (client.rx)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): read stream open, closing");
- shutdown(fileno(client.rx), SHUT_RDWR);
- fclose(client.rx);
- client.rx = NULL;
- }
-
- break;
-
- case SIGHUP:
- case SIGTERM:
- case SIGQUIT:
- case SIGSTOP:
- if (ChildStopRequested)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): already caught a stop request. Closing right now");
-
- /* already caught this signal, exit the hard way now */
- if (client.tx)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): write stream still open, closing");
- fflush(client.tx);
- fclose(client.tx); /* closes clientSocket as well */
- client.tx = NULL;
- }
-
- if (client.rx)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): read stream still open, closing");
- shutdown(fileno(client.rx), SHUT_RDWR);
- fclose(client.rx);
- client.rx = NULL;
- }
-
- if (connected)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): database connection still open, closing");
- db_disconnect();
- auth_disconnect();
- connected = 0;
- }
-
- trace(TRACE_DEBUG, "ChildSighandler(): exit");
- exit(1);
- }
- trace(TRACE_DEBUG, "ChildSighandler(): setting stop request");
- ChildStopRequested = 1;
- break;
-
- default:
- /* bad shtuff, exit */
- trace(TRACE_DEBUG, "ChildSighandler(): cannot ignore this. Terminating");
-
- /*
- * For some reason i have not yet determined the process starts eating up
- * all CPU time when trying to disconnect.
- * For now: just bail out :-)
- */
- _exit(1);
-
- if (!triedDisconnect)
- {
- triedDisconnect = 1;
-
- if (client.tx)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): write stream still open, closing");
- fflush(client.tx);
- fclose(client.tx); /* closes clientSocket as well */
- client.tx = NULL;
- }
-
- if (client.rx)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): read stream still open, closing");
- shutdown(fileno(client.rx), SHUT_RDWR);
- fclose(client.rx);
- client.rx = NULL;
- }
-
- if (connected)
- {
- trace(TRACE_DEBUG, "ChildSighandler(): database connection still open, closing");
- db_disconnect();
- auth_disconnect();
- }
-
- connected = 0;
- }
-
- trace(TRACE_DEBUG, "ChildSighandler(): exit");
- exit(1);
- }
}
@@ -189,27 +190,27 @@ void ChildSigHandler(int sig, siginfo_t *info UNUSED, void *data UNUSED)
*/
int SetChildSigHandler()
{
- struct sigaction act;
-
- /* init & install signal handlers */
- memset(&act, 0, sizeof(act));
-
- act.sa_sigaction = ChildSigHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
-
- sigaction(SIGINT, &act, 0);
- sigaction(SIGQUIT, &act, 0);
- sigaction(SIGILL, &act, 0);
- sigaction(SIGBUS, &act, 0);
- sigaction(SIGPIPE, &act, 0);
- sigaction(SIGFPE, &act, 0);
- sigaction(SIGSEGV, &act, 0);
- sigaction(SIGTERM, &act, 0);
- sigaction(SIGHUP, &act, 0);
- sigaction(SIGALRM, &act, 0);
-
- return 0;
+ struct sigaction act;
+
+ /* init & install signal handlers */
+ memset(&act, 0, sizeof(act));
+
+ act.sa_sigaction = ChildSigHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGILL, &act, 0);
+ sigaction(SIGBUS, &act, 0);
+ sigaction(SIGPIPE, &act, 0);
+ sigaction(SIGFPE, &act, 0);
+ sigaction(SIGSEGV, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
+ sigaction(SIGALRM, &act, 0);
+
+ return 0;
}
@@ -218,21 +219,22 @@ int SetChildSigHandler()
*
* creates a new child, returning only to the parent process
*/
-pid_t CreateChild(ChildInfo_t *info)
+pid_t CreateChild(ChildInfo_t * info)
{
- pid_t pid = fork();
-
- if (pid != 0)
- return pid;
+ pid_t pid = fork();
- ChildStopRequested = 0;
- SetChildSigHandler();
- trace(TRACE_INFO, "CreateChild(): signal handler placed, going to perform task now");
+ if (pid != 0)
+ return pid;
- PerformChildTask(info);
+ ChildStopRequested = 0;
+ SetChildSigHandler();
+ trace(TRACE_INFO,
+ "CreateChild(): signal handler placed, going to perform task now");
- usleep(10000);
- exit(0);
+ PerformChildTask(info);
+
+ usleep(10000);
+ exit(0);
}
@@ -242,138 +244,144 @@ pid_t CreateChild(ChildInfo_t *info)
*/
int CheckChildAlive(pid_t pid)
{
- return (kill(pid, 0) == -1) ? 0 : 1;
+ return (kill(pid, 0) == -1) ? 0 : 1;
}
-int PerformChildTask(ChildInfo_t *info)
+int PerformChildTask(ChildInfo_t * info)
{
- int i,len,clientSocket;
- struct sockaddr_in saClient;
- struct hostent *clientHost;
-
- if (!info)
- {
- trace(TRACE_ERROR, "PerformChildTask(): NULL info supplied");
- return -1;
- }
-
- if (db_connect() != 0)
- {
- trace(TRACE_ERROR, "PerformChildTask(): could not connect to database");
- return -1;
- }
-
- if (auth_connect() != 0)
- {
- trace(TRACE_ERROR, "PerformChildTask(): could not connect to authentication");
- return -1;
- }
-
- srand((int) ((int) time(NULL) + (int) getpid()) );
- connected = 1;
-
- for (i=0; i<info->maxConnect && !ChildStopRequested; i++)
- {
- trace(TRACE_INFO, "PerformChildTask(): waiting for connection");
-
- /* wait for connect */
- len = sizeof(saClient);
- clientSocket = accept(info->listenSocket, (struct sockaddr*)&saClient, &len);
-
- if (clientSocket == -1)
- {
- i--; /* don't count this as a connect */
- trace(TRACE_INFO, "PerformChildTask(): accept failed");
- continue; /* accept failed, refuse connection & continue */
+ int i, len, clientSocket;
+ struct sockaddr_in saClient;
+ struct hostent *clientHost;
+
+ if (!info) {
+ trace(TRACE_ERROR,
+ "PerformChildTask(): NULL info supplied");
+ return -1;
}
- memset(&client, 0, sizeof(client)); /* zero-init */
-
- client.timeoutMsg = info->timeoutMsg;
- client.timeout = info->timeout;
- strncpy(client.ip, inet_ntoa(saClient.sin_addr), IPNUM_LEN);
- client.clientname[0] = '\0';
-
- if (info->resolveIP)
- {
- clientHost = gethostbyaddr((char *)&saClient.sin_addr,
- sizeof(saClient.sin_addr),
- saClient.sin_family);
-
- if (clientHost && clientHost->h_name)
- strncpy(client.clientname, clientHost->h_name, FIELDSIZE);
-
- trace (TRACE_MESSAGE,"PerformChildTask(): incoming connection from [%s (%s)]",
- client.ip, client.clientname[0] ? client.clientname : "Lookup failed");
- }
- else
- {
- trace (TRACE_MESSAGE,"PerformChildTask(): incoming connection from [%s]",
- client.ip);
+ if (db_connect() != 0) {
+ trace(TRACE_ERROR,
+ "PerformChildTask(): could not connect to database");
+ return -1;
}
- /* make streams */
- if (! (client.rx = fdopen(dup(clientSocket), "r")) )
- {
- /* read-FILE opening failure */
- trace(TRACE_ERROR, "PerformChildTask(): error opening read file stream");
- close(clientSocket);
- continue;
- }
-
- if (! (client.tx = fdopen(clientSocket, "w")) )
- {
- /* write-FILE opening failure */
- trace(TRACE_ERROR, "PerformChildTask(): error opening write file stream");
- fclose(client.rx);
- close(clientSocket);
- memset(&client, 0, sizeof(client));
- continue;
+ if (auth_connect() != 0) {
+ trace(TRACE_ERROR,
+ "PerformChildTask(): could not connect to authentication");
+ return -1;
}
-
- setlinebuf(client.tx);
- setlinebuf(client.rx);
-
- trace(TRACE_DEBUG, "PerformChildTask(): client info init complete, calling client handler");
-
- /* streams are ready, perform handling */
- info->ClientHandler(&client);
+
+ srand((int) ((int) time(NULL) + (int) getpid()));
+ connected = 1;
+
+ for (i = 0; i < info->maxConnect && !ChildStopRequested; i++) {
+ trace(TRACE_INFO,
+ "PerformChildTask(): waiting for connection");
+
+ /* wait for connect */
+ len = sizeof(saClient);
+ clientSocket =
+ accept(info->listenSocket,
+ (struct sockaddr *) &saClient, &len);
+
+ if (clientSocket == -1) {
+ i--; /* don't count this as a connect */
+ trace(TRACE_INFO,
+ "PerformChildTask(): accept failed");
+ continue; /* accept failed, refuse connection & continue */
+ }
+
+ memset(&client, 0, sizeof(client)); /* zero-init */
+
+ client.timeoutMsg = info->timeoutMsg;
+ client.timeout = info->timeout;
+ strncpy(client.ip, inet_ntoa(saClient.sin_addr),
+ IPNUM_LEN);
+ client.clientname[0] = '\0';
+
+ if (info->resolveIP) {
+ clientHost =
+ gethostbyaddr((char *) &saClient.sin_addr,
+ sizeof(saClient.sin_addr),
+ saClient.sin_family);
+
+ if (clientHost && clientHost->h_name)
+ strncpy(client.clientname,
+ clientHost->h_name, FIELDSIZE);
+
+ trace(TRACE_MESSAGE,
+ "PerformChildTask(): incoming connection from [%s (%s)]",
+ client.ip,
+ client.clientname[0] ? client.
+ clientname : "Lookup failed");
+ } else {
+ trace(TRACE_MESSAGE,
+ "PerformChildTask(): incoming connection from [%s]",
+ client.ip);
+ }
+
+ /* make streams */
+ if (!(client.rx = fdopen(dup(clientSocket), "r"))) {
+ /* read-FILE opening failure */
+ trace(TRACE_ERROR,
+ "PerformChildTask(): error opening read file stream");
+ close(clientSocket);
+ continue;
+ }
+
+ if (!(client.tx = fdopen(clientSocket, "w"))) {
+ /* write-FILE opening failure */
+ trace(TRACE_ERROR,
+ "PerformChildTask(): error opening write file stream");
+ fclose(client.rx);
+ close(clientSocket);
+ memset(&client, 0, sizeof(client));
+ continue;
+ }
+
+ setlinebuf(client.tx);
+ setlinebuf(client.rx);
+
+ trace(TRACE_DEBUG,
+ "PerformChildTask(): client info init complete, calling client handler");
+
+ /* streams are ready, perform handling */
+ info->ClientHandler(&client);
#ifdef PROC_TITLES
- set_proc_title("%s", "Idle");
+ set_proc_title("%s", "Idle");
#endif
- trace(TRACE_DEBUG, "PerformChildTask(): client handling complete, closing streams");
+ trace(TRACE_DEBUG,
+ "PerformChildTask(): client handling complete, closing streams");
- if (client.tx)
- {
- fflush(client.tx);
- fclose(client.tx); /* closes clientSocket as well */
- client.tx = NULL;
- }
+ if (client.tx) {
+ fflush(client.tx);
+ fclose(client.tx); /* closes clientSocket as well */
+ client.tx = NULL;
+ }
+
+ if (client.rx) {
+ shutdown(fileno(client.rx), SHUT_RDWR);
+ fclose(client.rx);
+ client.rx = NULL;
+ }
- if (client.rx)
- {
- shutdown(fileno(client.rx), SHUT_RDWR);
- fclose(client.rx);
- client.rx = NULL;
+ trace(TRACE_INFO, "PerformChildTask(): connection closed");
}
-
- trace(TRACE_INFO, "PerformChildTask(): connection closed");
- }
-
- db_disconnect();
- auth_disconnect();
- connected = 0; /* FIXME a signal between this line and the previous one
- * would screw things up. Would like to have all this in
- * db_disconnect() making 'connected' obsolete
- */
-
- if (!ChildStopRequested)
- trace(TRACE_ERROR, "PerformChildTask(): maximum number of connections reached, stopping now");
- else
- trace(TRACE_ERROR, "PerformChildTask(): stop requested");
-
- return 0;
-}
+ db_disconnect();
+ auth_disconnect();
+ connected = 0; /* FIXME a signal between this line and the previous one
+ * would screw things up. Would like to have all this in
+ * db_disconnect() making 'connected' obsolete
+ */
+
+ if (!ChildStopRequested)
+ trace(TRACE_ERROR,
+ "PerformChildTask(): maximum number of connections reached, stopping now");
+ else
+ trace(TRACE_ERROR, "PerformChildTask(): stop requested");
+
+ return 0;
+}
diff --git a/serverchild.h b/serverchild.h
index 4fe7188d..4dd25751 100644
--- a/serverchild.h
+++ b/serverchild.h
@@ -35,20 +35,19 @@
#include <signal.h>
#include "clientinfo.h"
-typedef struct
-{
- int maxConnect;
- int listenSocket;
- int resolveIP;
- int timeout;
- char *timeoutMsg;
- int (*ClientHandler)(clientinfo_t *);
+typedef struct {
+ int maxConnect;
+ int listenSocket;
+ int resolveIP;
+ int timeout;
+ char *timeoutMsg;
+ int (*ClientHandler) (clientinfo_t *);
} ChildInfo_t;
-void ChildSigHandler(int sig, siginfo_t *info, void *data);
+void ChildSigHandler(int sig, siginfo_t * info, void *data);
int CheckChildAlive(pid_t pid);
int SetChildSigHandler(void);
-pid_t CreateChild(ChildInfo_t *info);
+pid_t CreateChild(ChildInfo_t * info);
#endif
diff --git a/settings.c b/settings.c
index 1025e26d..ab72b88e 100644
--- a/settings.c
+++ b/settings.c
@@ -14,80 +14,75 @@
#define LINE_BUFFER_SIZE 516
-int main (int argc, char *argv[])
+int main(int argc, char *argv[])
{
- FILE *configfile;
- char *readbuf, *field, *val,*fname;
- int i;
-
- readbuf = (char *)malloc(LINE_BUFFER_SIZE);
-
- printf("*** dbmail-config ***\n\n");
- if (argc<2)
- {
- printf("No configuration file specified, using %s\n",DEFAULT_CONFIG_FILE);
- fname = DEFAULT_CONFIG_FILE;
- }
- else
- {
- fname = argv[1];
- }
+ FILE *configfile;
+ char *readbuf, *field, *val, *fname;
+ int i;
- if (db_connect() != 0)
- {
- printf ("Could not connect to database.\n");
- return -1;
- }
-
- if (auth_connect() != 0)
- {
- printf ("Could not connect to authentication.\n");
- return -1;
- }
-
- printf("reading configuration for %s...\n", fname);
- configfile = fopen(fname,"r"); /* open the configuration file */
- if (configfile == NULL) /* error test */
- {
- fprintf (stderr,"Error: can not open input file %s\n",fname);
- return 8;
- }
-
- i = 0;
-
- /* clear existing configuration */
- db_clear_config();
+ readbuf = (char *) malloc(LINE_BUFFER_SIZE);
- while (!feof(configfile))
- {
- fgets (readbuf, LINE_BUFFER_SIZE,configfile);
- if (readbuf != NULL)
- {
- i++;
- readbuf[strlen(readbuf)-1]='\0';
- if ((readbuf[0] != '#') && (strlen(readbuf)>3)) /* ignore comments */
- {
- val = strchr(readbuf, '=');
- field = readbuf;
- if (!val)
- {
- fprintf (stderr,"Configread error in line: %d\n",i);
- }
- else
- {
- *val='\0';
- val++;
- if (db_insert_config_item (field, val) != 0)
- fprintf (stderr,"error in line:%d, could not insert item\n",i);
- else
- printf ("%s is now set to %s\n",field,val);
- }
- }
+ printf("*** dbmail-config ***\n\n");
+ if (argc < 2) {
+ printf("No configuration file specified, using %s\n",
+ DEFAULT_CONFIG_FILE);
+ fname = DEFAULT_CONFIG_FILE;
+ } else {
+ fname = argv[1];
}
- else
- fprintf (stderr,"end of buffer\n");
-
- }
- return 0;
-}
+ if (db_connect() != 0) {
+ printf("Could not connect to database.\n");
+ return -1;
+ }
+
+ if (auth_connect() != 0) {
+ printf("Could not connect to authentication.\n");
+ return -1;
+ }
+
+ printf("reading configuration for %s...\n", fname);
+ configfile = fopen(fname, "r"); /* open the configuration file */
+ if (configfile == NULL) { /* error test */
+ fprintf(stderr, "Error: can not open input file %s\n",
+ fname);
+ return 8;
+ }
+
+ i = 0;
+
+ /* clear existing configuration */
+ db_clear_config();
+
+ while (!feof(configfile)) {
+ fgets(readbuf, LINE_BUFFER_SIZE, configfile);
+ if (readbuf != NULL) {
+ i++;
+ readbuf[strlen(readbuf) - 1] = '\0';
+ if ((readbuf[0] != '#') && (strlen(readbuf) > 3)) { /* ignore comments */
+ val = strchr(readbuf, '=');
+ field = readbuf;
+ if (!val) {
+ fprintf(stderr,
+ "Configread error in line: %d\n",
+ i);
+ } else {
+ *val = '\0';
+ val++;
+ if (db_insert_config_item
+ (field, val) != 0)
+ fprintf(stderr,
+ "error in line:%d, could not insert item\n",
+ i);
+ else
+ printf
+ ("%s is now set to %s\n",
+ field, val);
+ }
+ }
+ } else
+ fprintf(stderr, "end of buffer\n");
+
+ }
+ return 0;
+}
diff --git a/sievecmd.c b/sievecmd.c
index a46aa758..4d5b9927 100644
--- a/sievecmd.c
+++ b/sievecmd.c
@@ -51,321 +51,311 @@ extern db_param_t _db_params;
int main(int argc, char *argv[])
{
- struct list sysItems;
- int res = 0, opt = 0, act = 0;
- u64_t user_idnr = 0;
- char *user_name = NULL;
- char *name = NULL;
- FILE *source = NULL;
- extern char *optarg;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- setvbuf(stdout, 0, _IONBF, 0);
-
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetTraceLevel(&sysItems);
- GetDBParams(&_db_params, &sysItems);
-
- configure_debug(TRACE_ERROR, 1, 0);
-
- while (opt != -1 && act != 'h')
- {
- opt = getopt(argc, argv, "a:d:i:r:u:l");
-
- switch (opt)
- {
- case -1:
- /* Break right away if this is the end of the args */
- break;
- case 'a':
- case 'd':
- case 'i':
- case 'r':
- if (act != 0)
- act = 'h';
- else
- act = opt;
- name = optarg;
- source = stdin; // FIXME to take files as input, too
- break;
- case 'u':
- user_name = strdup(optarg);
- break;
- case 'l':
- if (act != 0)
- act = 'h';
- else
- act = opt;
- break;
- default:
- act = 'h';
- break;
- }
- }
-
- if (act != 'h' && act != 0)
- {
- printf ("*** dbmail-sievecmd ***\n");
-
- /* Open database connection */
- printf ("Opening connection to database...\n");
- if (db_connect() != 0)
- {
- printf ("Failed. Could not connect to database (check log)\n");
- return -1;
- }
-
- /* Open authentication connection */
- printf ("Opening connection to authentication...\n");
- if (auth_connect() != 0)
- {
- printf ("Failed. Could not connect to authentication (check log)\n");
- return -1;
- }
-
- printf ("Ok. Connected!\n");
-
- /* Retrieve the user ID number */
- switch(auth_user_exists(user_name, &user_idnr))
- {
- case 0:
- printf( "User [%s] does not exist!\n", user_name);
- break;
- case -1:
- printf( "Error retrieving User ID Number\n" );
- res = -1;
- goto mainend;
- }
- }
-
- switch (act)
- {
- case 'a':
- res = do_activate(user_idnr, name);
- break;
- case 'd':
- res = do_deactivate(user_idnr, name);
- break;
- case 'i':
- res = do_insert(user_idnr, name, source);
- break;
- case 'r':
- res = do_remove(user_idnr, name);
- break;
- case 'l':
- res = do_list(user_idnr);
- break;
- case 'h':
- default:
- res = do_showhelp();
- break;
- }
-
- mainend:
- free(user_name);
- db_disconnect();
- auth_disconnect();
- return res;
+ struct list sysItems;
+ int res = 0, opt = 0, act = 0;
+ u64_t user_idnr = 0;
+ char *user_name = NULL;
+ char *name = NULL;
+ FILE *source = NULL;
+ extern char *optarg;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ setvbuf(stdout, 0, _IONBF, 0);
+
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetTraceLevel(&sysItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ configure_debug(TRACE_ERROR, 1, 0);
+
+ while (opt != -1 && act != 'h') {
+ opt = getopt(argc, argv, "a:d:i:r:u:l");
+
+ switch (opt) {
+ case -1:
+ /* Break right away if this is the end of the args */
+ break;
+ case 'a':
+ case 'd':
+ case 'i':
+ case 'r':
+ if (act != 0)
+ act = 'h';
+ else
+ act = opt;
+ name = optarg;
+ source = stdin; // FIXME to take files as input, too
+ break;
+ case 'u':
+ user_name = strdup(optarg);
+ break;
+ case 'l':
+ if (act != 0)
+ act = 'h';
+ else
+ act = opt;
+ break;
+ default:
+ act = 'h';
+ break;
+ }
+ }
+
+ if (act != 'h' && act != 0) {
+ printf("*** dbmail-sievecmd ***\n");
+
+ /* Open database connection */
+ printf("Opening connection to database...\n");
+ if (db_connect() != 0) {
+ printf
+ ("Failed. Could not connect to database (check log)\n");
+ return -1;
+ }
+
+ /* Open authentication connection */
+ printf("Opening connection to authentication...\n");
+ if (auth_connect() != 0) {
+ printf
+ ("Failed. Could not connect to authentication (check log)\n");
+ return -1;
+ }
+
+ printf("Ok. Connected!\n");
+
+ /* Retrieve the user ID number */
+ switch (auth_user_exists(user_name, &user_idnr)) {
+ case 0:
+ printf("User [%s] does not exist!\n", user_name);
+ break;
+ case -1:
+ printf("Error retrieving User ID Number\n");
+ res = -1;
+ goto mainend;
+ }
+ }
+
+ switch (act) {
+ case 'a':
+ res = do_activate(user_idnr, name);
+ break;
+ case 'd':
+ res = do_deactivate(user_idnr, name);
+ break;
+ case 'i':
+ res = do_insert(user_idnr, name, source);
+ break;
+ case 'r':
+ res = do_remove(user_idnr, name);
+ break;
+ case 'l':
+ res = do_list(user_idnr);
+ break;
+ case 'h':
+ default:
+ res = do_showhelp();
+ break;
+ }
+
+ mainend:
+ free(user_name);
+ db_disconnect();
+ auth_disconnect();
+ return res;
}
int do_activate(u64_t user_idnr, char *name)
{
- int res = 0;
-
- res = db_activate_sievescript(user_idnr, name);
- if (res == -3)
- {
- printf( "Script [%s] does not exist.\n", name );
- return -1;
- }
- else if (res != 0)
- {
- printf( "Error activating script [%s].\n"
- "It is possible that no script is currently active!\n", name );
- return -1;
- }
- printf( "Script [%s] is now active. All others are inactive.\n", name );
-
- return 0;
+ int res = 0;
+
+ res = db_activate_sievescript(user_idnr, name);
+ if (res == -3) {
+ printf("Script [%s] does not exist.\n", name);
+ return -1;
+ } else if (res != 0) {
+ printf("Error activating script [%s].\n"
+ "It is possible that no script is currently active!\n",
+ name);
+ return -1;
+ }
+ printf("Script [%s] is now active. All others are inactive.\n",
+ name);
+
+ return 0;
}
int do_deactivate(u64_t user_idnr, char *name)
{
- int res = 0;
-
- res = db_deactivate_sievescript(user_idnr, name);
- if (res == -3)
- {
- printf( "Script [%s] does not exist.\n", name );
- return -1;
- }
- else if (res != 0)
- {
- printf( "Error deactivating script [%s].\n", name );
- return -1;
- }
- printf( "Script [%s] is now deactivated. No scripts are currently active.\n", name );
-
- return 0;
+ int res = 0;
+
+ res = db_deactivate_sievescript(user_idnr, name);
+ if (res == -3) {
+ printf("Script [%s] does not exist.\n", name);
+ return -1;
+ } else if (res != 0) {
+ printf("Error deactivating script [%s].\n", name);
+ return -1;
+ }
+ printf
+ ("Script [%s] is now deactivated. No scripts are currently active.\n",
+ name);
+
+ return 0;
}
-int do_insert(u64_t user_idnr, char *name, FILE *source)
+int do_insert(u64_t user_idnr, char *name, FILE * source)
{
- int res = 0;
- char *buf = NULL;
- char *errmsg = NULL;
-
- /* Read the file into a char array */
- res = read_script_file(source, &buf);
- if (res != 0)
- {
- printf( "Error reading in your script!\n" );
- return -1;
- }
-
- /* Check if the script is valid */
- res = my_sieve_script_validate(buf, &errmsg);
- if (res != 0)
- {
- printf( "Script has errors: [%s].\n", name, errmsg );
- return -1;
- }
-
- /* Make the DB call to store the script */
- res = db_add_sievescript(user_idnr, name, buf);
- if (res == -3)
- {
- printf( "Script [%s] already exists.\n", name );
- return -1;
- }
- else if (res != 0)
- {
- printf( "Error inserting script [%s] into the database!\n", name );
- return -1;
- }
-
- printf( "Script [%s] successfully inserted and marked inactive!\n", name );
- return 0;
+ int res = 0;
+ char *buf = NULL;
+ char *errmsg = NULL;
+
+ /* Read the file into a char array */
+ res = read_script_file(source, &buf);
+ if (res != 0) {
+ printf("Error reading in your script!\n");
+ return -1;
+ }
+
+ /* Check if the script is valid */
+ res = my_sieve_script_validate(buf, &errmsg);
+ if (res != 0) {
+ printf("Script has errors: [%s].\n", name, errmsg);
+ return -1;
+ }
+
+ /* Make the DB call to store the script */
+ res = db_add_sievescript(user_idnr, name, buf);
+ if (res == -3) {
+ printf("Script [%s] already exists.\n", name);
+ return -1;
+ } else if (res != 0) {
+ printf("Error inserting script [%s] into the database!\n",
+ name);
+ return -1;
+ }
+
+ printf("Script [%s] successfully inserted and marked inactive!\n",
+ name);
+ return 0;
}
int do_remove(u64_t user_idnr, char *name)
{
- int res;
-
- res = db_delete_sievescript(user_idnr, name);
- if (res == -3)
- {
- printf( "Script [%s] does not exist.\n", name );
- return -1;
- }
- else if (res != 0)
- {
- printf( "Error deleting script [%s].\n", name );
- return -1;
- }
-
- printf( "Script [%s] deleted.\n", name );
-
- return 0;
+ int res;
+
+ res = db_delete_sievescript(user_idnr, name);
+ if (res == -3) {
+ printf("Script [%s] does not exist.\n", name);
+ return -1;
+ } else if (res != 0) {
+ printf("Error deleting script [%s].\n", name);
+ return -1;
+ }
+
+ printf("Script [%s] deleted.\n", name);
+
+ return 0;
}
int do_list(u64_t user_idnr)
{
- struct list scriptlist;
- struct element *tmp;
-
- if(db_get_sievescript_listall(user_idnr, &scriptlist) < 0)
- {
- printf("Error retrieving Sieve script list.\n");
- return -1;
- }
-
- if (list_totalnodes(&scriptlist) > 0)
- printf( "Found %ld scripts:\n", list_totalnodes(&scriptlist) );
- else
- printf( "No scripts found!\n" );
-
- tmp = list_getstart(&scriptlist);
- while (tmp)
- {
- struct ssinfo *info = (struct ssinfo *)tmp->data;
- if(info->active == 1)
- printf(" + ");
- else
- printf(" - ");
- printf("%s\n", info->name);
- tmp = tmp->nextnode;
- }
-
- if (scriptlist.start)
- list_freelist(&scriptlist.start);
-
- return 0;
+ struct list scriptlist;
+ struct element *tmp;
+
+ if (db_get_sievescript_listall(user_idnr, &scriptlist) < 0) {
+ printf("Error retrieving Sieve script list.\n");
+ return -1;
+ }
+
+ if (list_totalnodes(&scriptlist) > 0)
+ printf("Found %ld scripts:\n",
+ list_totalnodes(&scriptlist));
+ else
+ printf("No scripts found!\n");
+
+ tmp = list_getstart(&scriptlist);
+ while (tmp) {
+ struct ssinfo *info = (struct ssinfo *) tmp->data;
+ if (info->active == 1)
+ printf(" + ");
+ else
+ printf(" - ");
+ printf("%s\n", info->name);
+ tmp = tmp->nextnode;
+ }
+
+ if (scriptlist.start)
+ list_freelist(&scriptlist.start);
+
+ return 0;
}
int do_showhelp()
{
- printf ("*** dbmail-sievecmd ***\n");
-
- printf("Use this program to manage your users' Sieve scripts.\n");
- printf("See the man page for more info. Summary:\n\n");
- printf(" -u username Username of script user \n");
- printf(" -l List scripts belonging to user \n");
- printf(" -a scriptname Activate the named script \n");
- printf(" (only one script can be active; \n"
- " deactivates any others) \n");
- printf(" -d scriptname Deactivate the named script \n");
- printf(" (no scripts will be active after this) \n");
- printf(" -i scriptname file Insert the named script from file \n");
- printf(" (a single dash, -, indicates input \n"
- " from STDIN) \n");
- printf(" -r scriptname Remove the named script \n");
- printf(" (if script was active, no script is \n"
- " active after deletion) \n");
-
- return 0;
+ printf("*** dbmail-sievecmd ***\n");
+
+ printf("Use this program to manage your users' Sieve scripts.\n");
+ printf("See the man page for more info. Summary:\n\n");
+ printf(" -u username Username of script user \n");
+ printf
+ (" -l List scripts belonging to user \n");
+ printf(" -a scriptname Activate the named script \n");
+ printf
+ (" (only one script can be active; \n"
+ " deactivates any others) \n");
+ printf
+ (" -d scriptname Deactivate the named script \n");
+ printf
+ (" (no scripts will be active after this) \n");
+ printf
+ (" -i scriptname file Insert the named script from file \n");
+ printf
+ (" (a single dash, -, indicates input \n"
+ " from STDIN) \n");
+ printf(" -r scriptname Remove the named script \n");
+ printf
+ (" (if script was active, no script is \n"
+ " active after deletion) \n");
+
+ return 0;
}
-int read_script_file(FILE *f, char **m_buf)
+int read_script_file(FILE * f, char **m_buf)
{
- size_t f_len=0;
- size_t f_pos=0;
- char *tmp_buf = NULL;
- char *f_buf = NULL;
-
- if (!f)
- {
- printf( "Received NULL as script input\n" );
- return -1;
- }
-
- while(!feof(f))
- {
- if( f_pos + 1 >= f_len )
- {
- tmp_buf = realloc(f_buf, sizeof(char) * (f_len+=200));
- if( tmp_buf != NULL )
- f_buf = tmp_buf;
- else
- return -2;
- }
- f_buf[f_pos] = fgetc(f);
- f_pos++;
- }
-
- if(f_pos)
- f_buf[f_pos] = '\0';
-
- /* Since f_buf is either NULL or valid, we're golden */
- *m_buf = f_buf;
- return 0;
+ size_t f_len = 0;
+ size_t f_pos = 0;
+ char *tmp_buf = NULL;
+ char *f_buf = NULL;
+
+ if (!f) {
+ printf("Received NULL as script input\n");
+ return -1;
+ }
+
+ while (!feof(f)) {
+ if (f_pos + 1 >= f_len) {
+ tmp_buf =
+ realloc(f_buf, sizeof(char) * (f_len += 200));
+ if (tmp_buf != NULL)
+ f_buf = tmp_buf;
+ else
+ return -2;
+ }
+ f_buf[f_pos] = fgetc(f);
+ f_pos++;
+ }
+
+ if (f_pos)
+ f_buf[f_pos] = '\0';
+
+ /* Since f_buf is either NULL or valid, we're golden */
+ *m_buf = f_buf;
+ return 0;
}
-
diff --git a/sievecmd.h b/sievecmd.h
index 7fa4e5de..72dcebed 100644
--- a/sievecmd.h
+++ b/sievecmd.h
@@ -33,7 +33,6 @@ int do_list(u64_t user_idnr);
int do_activate(u64_t user_idnr, char *name);
int do_deactivate(u64_t user_idnr, char *name);
int do_remove(u64_t user_idnr, char *name);
-int do_insert(u64_t user_idnr, char *name, FILE *source);
-
-int read_script_file(FILE *f, char **m_buf);
+int do_insert(u64_t user_idnr, char *name, FILE * source);
+int read_script_file(FILE * f, char **m_buf);
diff --git a/smtp-convert.c b/smtp-convert.c
index a098c34e..585b5a26 100644
--- a/smtp-convert.c
+++ b/smtp-convert.c
@@ -48,229 +48,220 @@ char blk[READ_BLOCK_SIZE + MAX_LINESIZE + 1];
/* syslog */
#define PNAME "dbmail/uni-one-convertor"
-char *getusername (char *path);
-int traverse (char *path);
+char *getusername(char *path);
+int traverse(char *path);
int process_mboxfile(char *file, u64_t userid);
-int main (int argc, char* argv[])
+int main(int argc, char *argv[])
{
- time_t start;
- time_t stop;
- int result;
-
- if (argc < 2)
- {
- printf ("Error, traverse need a directory as argument\n");
- return -1;
- }
-
- openlog(PNAME, LOG_PID, LOG_MAIL); /* open connection to syslog */
- configure_debug(TRACE_ERROR, 1, 0);
-
- /* open database connection */
- if (db_connect() != 0)
- {
- printf("Error opening database connection\n");
- return -1;
- }
-
- /* open authentication connection */
- if (auth_connect() != 0)
- {
- printf("Error opening authentication connection\n");
- return -1;
- }
-
- srand((int) ((int) time(NULL) + (int) getpid()) );
-
- time (&start); /* mark the starting time */
- result = traverse (argv[1]);
- time (&stop); /* mark the ending time */
-
- printf ("Conversion started @ %s", ctime(&start));
- printf ("Conversion finished @ %s", ctime(&stop));
-
- return result;
+ time_t start;
+ time_t stop;
+ int result;
+
+ if (argc < 2) {
+ printf("Error, traverse need a directory as argument\n");
+ return -1;
+ }
+
+ openlog(PNAME, LOG_PID, LOG_MAIL); /* open connection to syslog */
+ configure_debug(TRACE_ERROR, 1, 0);
+
+ /* open database connection */
+ if (db_connect() != 0) {
+ printf("Error opening database connection\n");
+ return -1;
+ }
+
+ /* open authentication connection */
+ if (auth_connect() != 0) {
+ printf("Error opening authentication connection\n");
+ return -1;
+ }
+
+ srand((int) ((int) time(NULL) + (int) getpid()));
+
+ time(&start); /* mark the starting time */
+ result = traverse(argv[1]);
+ time(&stop); /* mark the ending time */
+
+ printf("Conversion started @ %s", ctime(&start));
+ printf("Conversion finished @ %s", ctime(&stop));
+
+ return result;
}
-char *getusername (char *path)
+char *getusername(char *path)
{
- int i;
- char *tmp;
-
- i = strlen (path);
- tmp = path+i;
-
- while ( (tmp!=path) && (*tmp!='/'))
- tmp--;
-
- return tmp+1;
+ int i;
+ char *tmp;
+
+ i = strlen(path);
+ tmp = path + i;
+
+ while ((tmp != path) && (*tmp != '/'))
+ tmp--;
+
+ return tmp + 1;
}
-int traverse (char *path)
+int traverse(char *path)
{
- char newpath [1024];
- char *username;
- struct dirent **namelist;
- int n;
- u64_t userid;
-
- n = scandir (path, &namelist, 0, alphasort);
-
- if (n < 0)
- {
- printf ("file %s\n",path);
- username = getusername(path);
- printf ("username %s\n", username);
-
- printf("creating user...");
- userid = auth_adduser(username, "default", "", "0", "10M");
- if (userid != -1 && userid != 0)
- {
- printf("Ok id [%llu]\n", userid);
- printf("converting mailbox...");
- fflush(stdout);
- n = process_mboxfile(path, userid);
- if (n != 0)
- printf("Warning: error converting mailbox\n");
- else
- printf ("done :)\n");
- }
- else
- {
- printf("user already exists. Skipping\n");
+ char newpath[1024];
+ char *username;
+ struct dirent **namelist;
+ int n;
+ u64_t userid;
+
+ n = scandir(path, &namelist, 0, alphasort);
+
+ if (n < 0) {
+ printf("file %s\n", path);
+ username = getusername(path);
+ printf("username %s\n", username);
+
+ printf("creating user...");
+ userid = auth_adduser(username, "default", "", "0", "10M");
+ if (userid != -1 && userid != 0) {
+ printf("Ok id [%llu]\n", userid);
+ printf("converting mailbox...");
+ fflush(stdout);
+ n = process_mboxfile(path, userid);
+ if (n != 0)
+ printf
+ ("Warning: error converting mailbox\n");
+ else
+ printf("done :)\n");
+ } else {
+ printf("user already exists. Skipping\n");
+ }
+
+ } else {
+ while (n--) {
+ if ((strcmp(namelist[n]->d_name, "..") != 0) &&
+ (strcmp(namelist[n]->d_name, ".") != 0)) {
+ sprintf(newpath, "%s/%s", path,
+ namelist[n]->d_name);
+ traverse(newpath);
+ }
+ free(namelist[n]);
+ }
+ free(namelist);
}
-
- }
- else
- {
- while (n--)
- {
- if ((strcmp(namelist[n]->d_name,"..")!=0) &&
- (strcmp(namelist[n]->d_name,".")!=0))
- {
- sprintf (newpath,"%s/%s",path, namelist[n]->d_name);
- traverse (newpath);
- }
- free (namelist[n]);
- }
- free(namelist);
- }
- return 0;
+ return 0;
}
int process_mboxfile(char *file, u64_t userid)
{
- regex_t preg;
- int result;
- FILE *infile;
- int in_msg, header_passed;
- char newunique[UID_SIZE];
- unsigned cnt,len,newlines;
- u64_t msgid=0, size;
- char saved;
-
- if ((result = regcomp(&preg, mbox_delimiter_pattern, REG_NOSUB)) != 0)
- {
- trace(TRACE_ERROR,"Regex compilation failed.");
- return -1;
- }
-
- if ( (infile = fopen(file, "r")) == 0)
- {
-
- trace(TRACE_ERROR,"Could not open file [%s]", infile);
- return -1;
- }
-
- in_msg = 0;
- cnt = 0;
- size = 0;
- newlines = 0;
-
- while (!feof(infile) && !ferror(infile))
- {
- if (fgets(&blk[cnt], MAX_LINESIZE, infile) == 0)
- break;
-
- /* check if this is an mbox delimiter */
- if (regexec(&preg, &blk[cnt], 0, NULL, 0) == 0)
- {
- if (!in_msg)
- in_msg = 1; /* ok start of a new msg */
- else
- {
- /* update & end message */
- db_insert_message_block(blk, cnt, msgid);
-
- create_unique_id(newunique, msgid);
- db_update_message(msgid, newunique, size+cnt, size+cnt+newlines);
- trace(TRACE_ERROR, "message [%llu] inserted, [%u] bytes", msgid, size+cnt);
- }
-
- /* start new message */
- msgid = db_insert_message(userid, 0, ERROR_IF_MBOX_NOT_FOUND, 0);
- header_passed = 0;
- cnt = 0;
- size = 0;
- newlines = 0;
+ regex_t preg;
+ int result;
+ FILE *infile;
+ int in_msg, header_passed;
+ char newunique[UID_SIZE];
+ unsigned cnt, len, newlines;
+ u64_t msgid = 0, size;
+ char saved;
+
+ if ((result =
+ regcomp(&preg, mbox_delimiter_pattern, REG_NOSUB)) != 0) {
+ trace(TRACE_ERROR, "Regex compilation failed.");
+ return -1;
}
- else
- {
- newlines++;
- if (header_passed == 0)
- {
- /* we're still reading the header */
- len = strlen(&blk[cnt]);
- if (strcmp(&blk[cnt], "\n") == 0)
- {
- db_insert_message_block(blk, cnt+len, msgid);
- header_passed = 1;
- size += (cnt+len);
- cnt = 0;
- }
- else
- cnt += len;
- }
- else
- {
- /* this is body data */
- len = strlen(&blk[cnt]);
- cnt += len;
-
- if (cnt >= READ_BLOCK_SIZE)
- {
- /* write block */
- saved = blk[READ_BLOCK_SIZE];
-
- blk[READ_BLOCK_SIZE] = '\0';
- db_insert_message_block(blk, READ_BLOCK_SIZE, msgid);
- blk[READ_BLOCK_SIZE] = saved;
-
- memmove(blk, &blk[READ_BLOCK_SIZE], cnt - (READ_BLOCK_SIZE));
- size += READ_BLOCK_SIZE;
- cnt -= READ_BLOCK_SIZE;
+
+ if ((infile = fopen(file, "r")) == 0) {
+
+ trace(TRACE_ERROR, "Could not open file [%s]", infile);
+ return -1;
+ }
+
+ in_msg = 0;
+ cnt = 0;
+ size = 0;
+ newlines = 0;
+
+ while (!feof(infile) && !ferror(infile)) {
+ if (fgets(&blk[cnt], MAX_LINESIZE, infile) == 0)
+ break;
+
+ /* check if this is an mbox delimiter */
+ if (regexec(&preg, &blk[cnt], 0, NULL, 0) == 0) {
+ if (!in_msg)
+ in_msg = 1; /* ok start of a new msg */
+ else {
+ /* update & end message */
+ db_insert_message_block(blk, cnt, msgid);
+
+ create_unique_id(newunique, msgid);
+ db_update_message(msgid, newunique,
+ size + cnt,
+ size + cnt + newlines);
+ trace(TRACE_ERROR,
+ "message [%llu] inserted, [%u] bytes",
+ msgid, size + cnt);
+ }
+
+ /* start new message */
+ msgid =
+ db_insert_message(userid, 0,
+ ERROR_IF_MBOX_NOT_FOUND, 0);
+ header_passed = 0;
+ cnt = 0;
+ size = 0;
+ newlines = 0;
+ } else {
+ newlines++;
+ if (header_passed == 0) {
+ /* we're still reading the header */
+ len = strlen(&blk[cnt]);
+ if (strcmp(&blk[cnt], "\n") == 0) {
+ db_insert_message_block(blk,
+ cnt + len,
+ msgid);
+ header_passed = 1;
+ size += (cnt + len);
+ cnt = 0;
+ } else
+ cnt += len;
+ } else {
+ /* this is body data */
+ len = strlen(&blk[cnt]);
+ cnt += len;
+
+ if (cnt >= READ_BLOCK_SIZE) {
+ /* write block */
+ saved = blk[READ_BLOCK_SIZE];
+
+ blk[READ_BLOCK_SIZE] = '\0';
+ db_insert_message_block(blk,
+ READ_BLOCK_SIZE,
+ msgid);
+ blk[READ_BLOCK_SIZE] = saved;
+
+ memmove(blk, &blk[READ_BLOCK_SIZE],
+ cnt - (READ_BLOCK_SIZE));
+ size += READ_BLOCK_SIZE;
+ cnt -= READ_BLOCK_SIZE;
+ }
+ }
}
- }
}
- }
- /* update & end message */
- if (msgid > 0)
- {
- db_insert_message_block(blk, cnt, msgid);
+ /* update & end message */
+ if (msgid > 0) {
+ db_insert_message_block(blk, cnt, msgid);
- create_unique_id(newunique, msgid);
- db_update_message(msgid, newunique, size+cnt, size+cnt+newlines);
- trace(TRACE_ERROR, "message [%llu] inserted, [%u] bytes", msgid, size+cnt);
- }
+ create_unique_id(newunique, msgid);
+ db_update_message(msgid, newunique, size + cnt,
+ size + cnt + newlines);
+ trace(TRACE_ERROR, "message [%llu] inserted, [%u] bytes",
+ msgid, size + cnt);
+ }
- fclose(infile);
- return 0;
+ fclose(infile);
+ return 0;
}
diff --git a/sort.h b/sort.h
index ac091a36..39e6b279 100644
--- a/sort.h
+++ b/sort.h
@@ -24,14 +24,14 @@
#define SA_SIEVE 6
typedef struct sort_action {
- int method;
- char *destination;
- char *message;
+ int method;
+ char *destination;
+ char *message;
} sort_action_t;
dsn_class_t sort_and_deliver(u64_t msgidnr,
- const char *header, u64_t headersize,
- u64_t msgsize, u64_t rfcsize,
- u64_t useridnr, const char *mailbox);
+ const char *header, u64_t headersize,
+ u64_t msgsize, u64_t rfcsize,
+ u64_t useridnr, const char *mailbox);
-#endif /* #ifndef _SORTING_H */
+#endif /* #ifndef _SORTING_H */
diff --git a/sort/sort.c b/sort/sort.c
index 2ab0eea7..00acf28e 100644
--- a/sort/sort.c
+++ b/sort/sort.c
@@ -46,285 +46,333 @@ extern struct list smtpItems, sysItems;
* Then do it!
* */
dsn_class_t sort_and_deliver(u64_t msgidnr,
- const char *header, u64_t headersize,
- u64_t totalmsgsize, u64_t totalrfcsize,
- u64_t useridnr, const char *mailbox)
+ const char *header, u64_t headersize,
+ u64_t totalmsgsize, u64_t totalrfcsize,
+ u64_t useridnr, const char *mailbox)
{
- field_t val;
- int do_regex = 0, do_sieve = 0;
- struct list actions;
- struct element *tmp;
- int actiontaken = 0, ret = 0;
- u64_t mboxidnr, newmsgidnr;
- char unique_id[UID_SIZE];
- char *bounce_id = NULL;
- char *inbox = "INBOX";
+ field_t val;
+ int do_regex = 0, do_sieve = 0;
+ struct list actions;
+ struct element *tmp;
+ int actiontaken = 0, ret = 0;
+ u64_t mboxidnr, newmsgidnr;
+ char unique_id[UID_SIZE];
+ char *bounce_id = NULL;
+ char *inbox = "INBOX";
- GetConfigValue("SQLREGEX", &smtpItems, val);
- if (strcasecmp(val, "yes") == 0)
- do_regex = 1;
+ GetConfigValue("SQLREGEX", &smtpItems, val);
+ if (strcasecmp(val, "yes") == 0)
+ do_regex = 1;
- GetConfigValue("LIBSIEVE", &smtpItems, val);
- if (strcasecmp(val, "yes") == 0)
- do_sieve = 1;
+ GetConfigValue("LIBSIEVE", &smtpItems, val);
+ if (strcasecmp(val, "yes") == 0)
+ do_sieve = 1;
- list_init(&actions);
+ list_init(&actions);
- if (do_regex)
- {
- /* Call out to Jonas' regex sorting function!
- * */
- // ret = db_regexsort(useridnr, header, actions);
- trace(TRACE_ERROR, "%s, %s: Regex sort is enabled in dbmail.conf, but has not been compiled", __FILE__, __FUNCTION__);
- }
+ if (do_regex) {
+ /* Call out to Jonas' regex sorting function!
+ * */
+ // ret = db_regexsort(useridnr, header, actions);
+ trace(TRACE_ERROR,
+ "%s, %s: Regex sort is enabled in dbmail.conf, but has not been compiled",
+ __FILE__, __FUNCTION__);
+ }
- if (do_sieve)
- {
- /* Don't code the Sieve guts right here,
- * call out to a function that encapsulates it!
- * */
+ if (do_sieve) {
+ /* Don't code the Sieve guts right here,
+ * call out to a function that encapsulates it!
+ * */
#ifdef SIEVE
- ret = sortsieve_msgsort(useridnr, header, headersize, totalmsgsize, &actions);
+ ret =
+ sortsieve_msgsort(useridnr, header, headersize,
+ totalmsgsize, &actions);
#else
- /* Give the postmaster a clue as to why Sieve isn't working... */
- trace(TRACE_ERROR, "%s, %s: Sieve enabled in dbmail.conf, but Sieve support has not been compiled", __FILE__, __FUNCTION__);
-#endif /* SIEVE */
- }
+ /* Give the postmaster a clue as to why Sieve isn't working... */
+ trace(TRACE_ERROR,
+ "%s, %s: Sieve enabled in dbmail.conf, but Sieve support has not been compiled",
+ __FILE__, __FUNCTION__);
+#endif /* SIEVE */
+ }
- if (mailbox == NULL)
- mailbox = inbox;
+ if (mailbox == NULL)
+ mailbox = inbox;
- /* actions is a list of things to do with this message
- * each data pointer in the actions list references
- * a structure like this:
- *
- * typedef sort_action {
- * int method,
- * char *destination,
- * char *message
- * } sort_action_t;
- *
- * Where message is some descriptive text, used
- * primarily for rejection noticed, and where
- * destination is either a mailbox name or a
- * forwarding address, and method is one of these:
- *
- * SA_KEEP,
- * SA_DISCARD,
- * SA_REDIRECT,
- * SA_REJECT,
- * SA_FILEINTO
- * (see RFC 3028 [SIEVE] for details)
- *
- * SA_SIEVE:
- * In addition, this implementation allows for
- * the internel Regex matching to call a Sieve
- * script into action. In this case, the method
- * is SA_SIEVE and the destination is the script's name.
- * Note that Sieve must be enabled in the configuration
- * file or else an error will be generated.
- *
- * In the absence of any valid actions (ie. actions
- * is an empty list, or all attempts at performing the
- * actions fail...) an implicit SA_KEEP is performed,
- * using INBOX as the destination (hardcoded).
- * */
+ /* actions is a list of things to do with this message
+ * each data pointer in the actions list references
+ * a structure like this:
+ *
+ * typedef sort_action {
+ * int method,
+ * char *destination,
+ * char *message
+ * } sort_action_t;
+ *
+ * Where message is some descriptive text, used
+ * primarily for rejection noticed, and where
+ * destination is either a mailbox name or a
+ * forwarding address, and method is one of these:
+ *
+ * SA_KEEP,
+ * SA_DISCARD,
+ * SA_REDIRECT,
+ * SA_REJECT,
+ * SA_FILEINTO
+ * (see RFC 3028 [SIEVE] for details)
+ *
+ * SA_SIEVE:
+ * In addition, this implementation allows for
+ * the internel Regex matching to call a Sieve
+ * script into action. In this case, the method
+ * is SA_SIEVE and the destination is the script's name.
+ * Note that Sieve must be enabled in the configuration
+ * file or else an error will be generated.
+ *
+ * In the absence of any valid actions (ie. actions
+ * is an empty list, or all attempts at performing the
+ * actions fail...) an implicit SA_KEEP is performed,
+ * using INBOX as the destination (hardcoded).
+ * */
- if (list_totalnodes(&actions) > 0)
- {
- tmp = list_getstart(&actions);
- while (tmp != NULL)
- {
- /* Try not to think about the structures too hard ;-) */
- switch ( (int)((sort_action_t *)tmp->data)->method )
- {
- case SA_SIEVE:
- {
- /* Run the script specified by destination and
- * add the resulting list onto the *end* of the
- * actions list. Note that this is a deep hack...
- * */
- if ((char *)((sort_action_t *)tmp->data)->destination != NULL)
- {
- struct list localtmplist;
- struct element *localtmpelem;
+ if (list_totalnodes(&actions) > 0) {
+ tmp = list_getstart(&actions);
+ while (tmp != NULL) {
+ /* Try not to think about the structures too hard ;-) */
+ switch ((int) ((sort_action_t *) tmp->data)->
+ method) {
+ case SA_SIEVE:
+ {
+ /* Run the script specified by destination and
+ * add the resulting list onto the *end* of the
+ * actions list. Note that this is a deep hack...
+ * */
+ if ((char *) ((sort_action_t *)
+ tmp->data)->
+ destination != NULL) {
+ struct list localtmplist;
+ struct element
+ *localtmpelem;
// if (sortsieve_msgsort(useridnr, header, headersize, (char *)((sort_action_t *)tmp->data)->destination, localtmplist))
- {
- /* FIXME: This can all be replaced with some
- * function called list_append(), if written! */
- /* Fast forward to the end of the actions list */
- localtmpelem = list_getstart(&actions);
- while (localtmpelem != NULL)
- {
- localtmpelem = localtmpelem->nextnode;
- }
- /* And tack on the start of the Sieve list */
- localtmpelem->nextnode = list_getstart(&localtmplist);
- /* Remeber to increment the node count, too */
- actions.total_nodes += list_totalnodes(&localtmplist);
- }
- }
- break;
- }
- case SA_FILEINTO:
- {
- char *fileinto_mailbox = (char *)((sort_action_t *)tmp->data)->destination;
+ {
+ /* FIXME: This can all be replaced with some
+ * function called list_append(), if written! */
+ /* Fast forward to the end of the actions list */
+ localtmpelem =
+ list_getstart
+ (&actions);
+ while (localtmpelem
+ != NULL) {
+ localtmpelem
+ =
+ localtmpelem->
+ nextnode;
+ }
+ /* And tack on the start of the Sieve list */
+ localtmpelem->
+ nextnode =
+ list_getstart
+ (&localtmplist);
+ /* Remeber to increment the node count, too */
+ actions.
+ total_nodes +=
+ list_totalnodes
+ (&localtmplist);
+ }
+ }
+ break;
+ }
+ case SA_FILEINTO:
+ {
+ char *fileinto_mailbox =
+ (char *) ((sort_action_t *)
+ tmp->data)->
+ destination;
- /* If the action doesn't come with a mailbox, use the default. */
+ /* If the action doesn't come with a mailbox, use the default. */
- if (fileinto_mailbox == NULL)
- {
- /* Cast the const away because fileinto_mailbox may need to be freed. */
- fileinto_mailbox = (char *)mailbox;
- trace(TRACE_MESSAGE, "sort_and_deliver(): mailbox not specified, using [%s]",
- fileinto_mailbox);
- }
+ if (fileinto_mailbox == NULL) {
+ /* Cast the const away because fileinto_mailbox may need to be freed. */
+ fileinto_mailbox =
+ (char *) mailbox;
+ trace(TRACE_MESSAGE,
+ "sort_and_deliver(): mailbox not specified, using [%s]",
+ fileinto_mailbox);
+ }
- /* Did we fail to create the mailbox? */
- if (db_find_create_mailbox(fileinto_mailbox, useridnr, &mboxidnr) != 0)
- {
- /* FIXME: Serious failure situation! This needs to be
- * passed up the chain to notify the user, sender, etc.
- * Perhaps we should *force* the implicit-keep to occur,
- * or give another try at using INBOX. */
- trace(TRACE_ERROR, "sort_and_deliver(): mailbox [%s] not found nor created, message may not have been delivered",
- fileinto_mailbox);
- }
- else
- {
- switch(db_copymsg(msgidnr, mboxidnr, useridnr, &newmsgidnr))
- {
- case -2:
- /* Couldn't deliver because the quota has been reached */
- bounce_id = auth_get_userid(useridnr);
- bounce(header, bounce_id, BOUNCE_STORAGE_LIMIT_REACHED);
- my_free (bounce_id);
- break;
- case -1:
- /* Couldn't deliver because something something went wrong */
- trace(TRACE_ERROR, "sort_and_deliver(): error copying message to user [%llu]", useridnr);
- /* Don't worry about error conditions.
- * It's annoying if the message isn't delivered,
- * but as long as *something* happens it's OK.
- * Otherwise, actiontaken will be 0 and another
- * delivery attempt will be made before passing
- * up the error at the end of the function.
- * */
- break;
- default:
- trace(TRACE_MESSAGE, "sort_and_deliver(): message id=%llu, size=%llu is inserted",
- newmsgidnr, totalmsgsize);
-
- /* Create a unique ID for this message;
- * Each message for each user must have a unique ID!
- * */
- create_unique_id(unique_id, newmsgidnr);
- db_message_set_unique_id(newmsgidnr, unique_id);
-
- actiontaken = 1;
- break;
- }
- }
+ /* Did we fail to create the mailbox? */
+ if (db_find_create_mailbox
+ (fileinto_mailbox, useridnr,
+ &mboxidnr) != 0) {
+ /* FIXME: Serious failure situation! This needs to be
+ * passed up the chain to notify the user, sender, etc.
+ * Perhaps we should *force* the implicit-keep to occur,
+ * or give another try at using INBOX. */
+ trace(TRACE_ERROR,
+ "sort_and_deliver(): mailbox [%s] not found nor created, message may not have been delivered",
+ fileinto_mailbox);
+ } else {
+ switch (db_copymsg
+ (msgidnr, mboxidnr,
+ useridnr,
+ &newmsgidnr)) {
+ case -2:
+ /* Couldn't deliver because the quota has been reached */
+ bounce_id =
+ auth_get_userid
+ (useridnr);
+ bounce(header,
+ bounce_id,
+ BOUNCE_STORAGE_LIMIT_REACHED);
+ my_free(bounce_id);
+ break;
+ case -1:
+ /* Couldn't deliver because something something went wrong */
+ trace(TRACE_ERROR,
+ "sort_and_deliver(): error copying message to user [%llu]",
+ useridnr);
+ /* Don't worry about error conditions.
+ * It's annoying if the message isn't delivered,
+ * but as long as *something* happens it's OK.
+ * Otherwise, actiontaken will be 0 and another
+ * delivery attempt will be made before passing
+ * up the error at the end of the function.
+ * */
+ break;
+ default:
+ trace
+ (TRACE_MESSAGE,
+ "sort_and_deliver(): message id=%llu, size=%llu is inserted",
+ newmsgidnr,
+ totalmsgsize);
- /* If these are not same pointers, then we need to free. */
- if (fileinto_mailbox != mailbox)
- my_free(fileinto_mailbox);
+ /* Create a unique ID for this message;
+ * Each message for each user must have a unique ID!
+ * */
+ create_unique_id
+ (unique_id,
+ newmsgidnr);
+ db_message_set_unique_id
+ (newmsgidnr,
+ unique_id);
- break;
- }
- case SA_DISCARD:
- {
- /* Basically do nothing! */
- actiontaken = 1;
- break;
- }
- case SA_REJECT:
- {
- // FIXME: I'm happy with this code, but it's not quite right...
- // Plus we want to specify a message to go along with it!
- bounce_id = auth_get_userid(useridnr);
- bounce(header, bounce_id, BOUNCE_NO_SUCH_USER);
+ actiontaken = 1;
+ break;
+ }
+ }
- my_free(bounce_id);
- actiontaken = 1;
- break;
- }
- case SA_REDIRECT:
- {
- char *forward_id;
- struct list targets;
+ /* If these are not same pointers, then we need to free. */
+ if (fileinto_mailbox != mailbox)
+ my_free(fileinto_mailbox);
- list_init(&targets);
- list_nodeadd(&targets, (char *)((sort_action_t *)tmp->data)->destination, strlen((char *)((sort_action_t *)tmp->data)->destination)+1);
- my_free((char *)((sort_action_t *)tmp->data)->destination);
+ break;
+ }
+ case SA_DISCARD:
+ {
+ /* Basically do nothing! */
+ actiontaken = 1;
+ break;
+ }
+ case SA_REJECT:
+ {
+ // FIXME: I'm happy with this code, but it's not quite right...
+ // Plus we want to specify a message to go along with it!
+ bounce_id =
+ auth_get_userid(useridnr);
+ bounce(header, bounce_id,
+ BOUNCE_NO_SUCH_USER);
- /* Put the destination into the targets list */
- /* The From header will contain... */
- forward_id = auth_get_userid(useridnr);
- forward(msgidnr, &targets, forward_id, header, headersize);
+ my_free(bounce_id);
+ actiontaken = 1;
+ break;
+ }
+ case SA_REDIRECT:
+ {
+ char *forward_id;
+ struct list targets;
- list_freelist(&targets.start);
- my_free (forward_id);
- actiontaken = 1;
- break;
- }
- /*
- case SA_KEEP:
- default:
- {
- // Don't worry! This is handled by implicit keep :-)
- break;
- }
- */
- } /* case */
- tmp = tmp->nextnode;
- } /* while */
- list_freelist(&actions.start);
- } /* if */
- else
- {
- /* Might as well be explicit about this... */
- actiontaken = 0;
- }
+ list_init(&targets);
+ list_nodeadd(&targets,
+ (char
+ *) ((sort_action_t *)
+ tmp->data)->
+ destination,
+ strlen((char
+ *) ((sort_action_t *) tmp->data)->destination) + 1);
+ my_free((char *) ((sort_action_t *)
+ tmp->data)->
+ destination);
- /* This is that implicit keep I mentioned earlier...
- * If possible, put the message in the specified
- * mailbox, otherwise use INBOX. */
- if (actiontaken == 0)
- {
- /* Did we fail to create the mailbox? */
- if (db_find_create_mailbox(mailbox, useridnr, &mboxidnr) != 0)
- {
- /* Serious failure situation! */
- trace(TRACE_ERROR, "sort_and_deliver(): INBOX not found");
- }
- else
- {
- switch(db_copymsg(msgidnr, mboxidnr, useridnr, &newmsgidnr))
- {
- case -2:
- /* Couldn't deliver because the quotum is exceeded. */
- trace(TRACE_DEBUG, "%s, %s: error copying message to user [%llu], maxmail exceeded",
- __FILE__, __FUNCTION__, useridnr);
- break;
- case -1:
- /* Couldn't deliver because something something went wrong. */
- trace(TRACE_ERROR, "%s, %s: error copying message to user [%llu]",
- __FILE__, __FUNCTION__, useridnr);
- break;
- default:
- trace(TRACE_MESSAGE,"%s, %s: message id=%llu, size=%llu is inserted",
- __FILE__, __FUNCTION__, newmsgidnr, totalmsgsize);
- actiontaken = 1;
- break;
- }
- }
- }
+ /* Put the destination into the targets list */
+ /* The From header will contain... */
+ forward_id =
+ auth_get_userid(useridnr);
+ forward(msgidnr, &targets,
+ forward_id, header,
+ headersize);
- if (actiontaken)
- return DSN_CLASS_OK;
- return DSN_CLASS_TEMP;
-}
+ list_freelist(&targets.start);
+ my_free(forward_id);
+ actiontaken = 1;
+ break;
+ }
+ /*
+ case SA_KEEP:
+ default:
+ {
+ // Don't worry! This is handled by implicit keep :-)
+ break;
+ }
+ */
+ } /* case */
+ tmp = tmp->nextnode;
+ } /* while */
+ list_freelist(&actions.start);
+ } /* if */
+ else {
+ /* Might as well be explicit about this... */
+ actiontaken = 0;
+ }
+
+ /* This is that implicit keep I mentioned earlier...
+ * If possible, put the message in the specified
+ * mailbox, otherwise use INBOX. */
+ if (actiontaken == 0) {
+ /* Did we fail to create the mailbox? */
+ if (db_find_create_mailbox(mailbox, useridnr, &mboxidnr) !=
+ 0) {
+ /* Serious failure situation! */
+ trace(TRACE_ERROR,
+ "sort_and_deliver(): INBOX not found");
+ } else {
+ switch (db_copymsg
+ (msgidnr, mboxidnr, useridnr,
+ &newmsgidnr)) {
+ case -2:
+ /* Couldn't deliver because the quotum is exceeded. */
+ trace(TRACE_DEBUG,
+ "%s, %s: error copying message to user [%llu], maxmail exceeded",
+ __FILE__, __FUNCTION__, useridnr);
+ break;
+ case -1:
+ /* Couldn't deliver because something something went wrong. */
+ trace(TRACE_ERROR,
+ "%s, %s: error copying message to user [%llu]",
+ __FILE__, __FUNCTION__, useridnr);
+ break;
+ default:
+ trace(TRACE_MESSAGE,
+ "%s, %s: message id=%llu, size=%llu is inserted",
+ __FILE__, __FUNCTION__, newmsgidnr,
+ totalmsgsize);
+ actiontaken = 1;
+ break;
+ }
+ }
+ }
+ if (actiontaken)
+ return DSN_CLASS_OK;
+ return DSN_CLASS_TEMP;
+}
diff --git a/sort/sortsieve.c b/sort/sortsieve.c
index aa2fe424..a5cc9ab2 100644
--- a/sort/sortsieve.c
+++ b/sort/sortsieve.c
@@ -51,272 +51,285 @@ extern struct list smtpItems, sysItems;
* such as dbmail-lmtpd, the daemon should
* finish storing the message and restart.
* */
-int sortsieve_msgsort(u64_t useridnr, char *header, u64_t headersize, u64_t messagesize, struct list *actions)
+int sortsieve_msgsort(u64_t useridnr, char *header, u64_t headersize,
+ u64_t messagesize, struct list *actions)
{
- sieve2_message_t *m;
- sieve2_support_t *p;
- sieve2_script_t *s;
- sieve2_action_t *a;
- sieve2_loader_t scriptloader, msgloader;
- char *scriptname = NULL, *script = NULL, *freestr = NULL;
- int res = 0, ret = 0;
-
- /* Pass the address of the char *script, and it will come
- * back magically allocated. Don't forget to free it later! */
- res = db_get_sievescript_active(useridnr, &scriptname);
- if( res < 0 ) {
- printf("db_get_sievescript_active() returns %d\n", res);
- ret = -1;
- goto no_free;
- }
-
- printf( "Looking up script [%s]\n", scriptname );
- res = db_get_sievescript_byname(useridnr, scriptname, &script);
- if( res < 0 ) {
- printf("db_get_sievescript_byname() returns %d\n", res);
- ret = -1;
- goto char_scriptname_free;
- }
-
- res = sieve2_action_alloc(&a);
- if (res != SIEVE2_OK) {
- printf("sieve2_action_alloc() returns %d\n", res);
- ret = -1;
- goto char_script_free;
- }
-
- res = sieve2_support_alloc(&p);
- if (res != SIEVE2_OK) {
- printf("sieve2_support_alloc() returns %d\n", res);
- ret = -1;
- goto action_free;
- }
-
- res = sieve2_support_register(p, SIEVE2_ACTION_FILEINTO);
- res = sieve2_support_register(p, SIEVE2_ACTION_REDIRECT);
- res = sieve2_support_register(p, SIEVE2_ACTION_REJECT);
+ sieve2_message_t *m;
+ sieve2_support_t *p;
+ sieve2_script_t *s;
+ sieve2_action_t *a;
+ sieve2_loader_t scriptloader, msgloader;
+ char *scriptname = NULL, *script = NULL, *freestr = NULL;
+ int res = 0, ret = 0;
+
+ /* Pass the address of the char *script, and it will come
+ * back magically allocated. Don't forget to free it later! */
+ res = db_get_sievescript_active(useridnr, &scriptname);
+ if (res < 0) {
+ printf("db_get_sievescript_active() returns %d\n", res);
+ ret = -1;
+ goto no_free;
+ }
+
+ printf("Looking up script [%s]\n", scriptname);
+ res = db_get_sievescript_byname(useridnr, scriptname, &script);
+ if (res < 0) {
+ printf("db_get_sievescript_byname() returns %d\n", res);
+ ret = -1;
+ goto char_scriptname_free;
+ }
+
+ res = sieve2_action_alloc(&a);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_action_alloc() returns %d\n", res);
+ ret = -1;
+ goto char_script_free;
+ }
+
+ res = sieve2_support_alloc(&p);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_support_alloc() returns %d\n", res);
+ ret = -1;
+ goto action_free;
+ }
+
+ res = sieve2_support_register(p, SIEVE2_ACTION_FILEINTO);
+ res = sieve2_support_register(p, SIEVE2_ACTION_REDIRECT);
+ res = sieve2_support_register(p, SIEVE2_ACTION_REJECT);
// res = sieve2_support_register(p, SIEVE2_ACTION_NOTIFY);
- res = sieve2_script_alloc(&s);
- if (res != SIEVE2_OK) {
- printf("sieve2_script_alloc() returns %d\n", res);
- ret = -1;
- goto support_free;
- }
-
- res = sieve2_support_bind(p, s);
- if (res != SIEVE2_OK) {
- printf("sieve2_support_bind() returns %d\n", res);
- ret = -1;
- goto script_free;
- }
-
- res = sieve2_script_parse(s, script);
- if (res != SIEVE2_OK) {
- printf("sieve2_script_parse() returns %d: %s\n", res, sieve2_errstr(res, &freestr));
- my_free(freestr);
- ret = -1;
- goto script_free;
- }
-
- res = sieve2_message_alloc(&m);
- if (res != SIEVE2_OK) {
- printf("sieve2_message_alloc() returns %d\n", res);
- ret = -1;
- goto script_free;
- }
-
- res = sieve2_message_register(m, &messagesize, SIEVE2_MESSAGE_SIZE);
- if (res != SIEVE2_OK) {
- printf("sieve2_message_register() returns %d\n", res);
- ret = -1;
- goto message_free;
- }
- res = sieve2_message_register(m, header, SIEVE2_MESSAGE_HEADER);
- if (res != SIEVE2_OK) {
- printf("sieve2_message_register() returns %d\n", res);
- ret = -1;
- goto message_free;
- }
-
- res = sieve2_script_exec(s, m, a);
- if (res != SIEVE2_OK) {
- printf("sieve2_execute_script() returns %d\n", res);
- ret = -1;
- goto message_free;
- }
-
- res = sortsieve_unroll_action(a, actions);
- if (res != SIEVE2_OK && res != SIEVE2_DONE ) {
- printf("unroll_action() returns %d\n", res);
- ret = -1;
- goto action_free;
- }
-
-message_free:
- res = sieve2_message_free(m);
- if (res != SIEVE2_OK) {
- printf("sieve2_message_free() returns %d\n", res);
- ret = 1;
- }
-
-script_free:
- res = sieve2_script_free(s);
- if (res != SIEVE2_OK) {
- printf("sieve2_script_free() returns %d\n", res);
- ret = 1;
- }
-
-support_free:
- res = sieve2_support_free(p);
- if (res != SIEVE2_OK) {
- printf("sieve2_support_free() returns %d\n", res);
- ret = 1;
- }
-
-action_free:
- res = sieve2_action_free(a);
- if (res != SIEVE2_OK) {
- printf("sieve2_action_free() returns %d\n", res);
- ret = 1;
- }
-
- /* Good thing we're not forgetting ;-) */
-char_script_free:
- if (script != NULL)
- my_free(script);
-char_scriptname_free:
- if (scriptname != NULL)
- my_free(scriptname);
-
-no_free:
- return ret;
+ res = sieve2_script_alloc(&s);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_script_alloc() returns %d\n", res);
+ ret = -1;
+ goto support_free;
+ }
+
+ res = sieve2_support_bind(p, s);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_support_bind() returns %d\n", res);
+ ret = -1;
+ goto script_free;
+ }
+
+ res = sieve2_script_parse(s, script);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_script_parse() returns %d: %s\n", res,
+ sieve2_errstr(res, &freestr));
+ my_free(freestr);
+ ret = -1;
+ goto script_free;
+ }
+
+ res = sieve2_message_alloc(&m);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_message_alloc() returns %d\n", res);
+ ret = -1;
+ goto script_free;
+ }
+
+ res =
+ sieve2_message_register(m, &messagesize, SIEVE2_MESSAGE_SIZE);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_message_register() returns %d\n", res);
+ ret = -1;
+ goto message_free;
+ }
+ res = sieve2_message_register(m, header, SIEVE2_MESSAGE_HEADER);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_message_register() returns %d\n", res);
+ ret = -1;
+ goto message_free;
+ }
+
+ res = sieve2_script_exec(s, m, a);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_execute_script() returns %d\n", res);
+ ret = -1;
+ goto message_free;
+ }
+
+ res = sortsieve_unroll_action(a, actions);
+ if (res != SIEVE2_OK && res != SIEVE2_DONE) {
+ printf("unroll_action() returns %d\n", res);
+ ret = -1;
+ goto action_free;
+ }
+
+ message_free:
+ res = sieve2_message_free(m);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_message_free() returns %d\n", res);
+ ret = 1;
+ }
+
+ script_free:
+ res = sieve2_script_free(s);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_script_free() returns %d\n", res);
+ ret = 1;
+ }
+
+ support_free:
+ res = sieve2_support_free(p);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_support_free() returns %d\n", res);
+ ret = 1;
+ }
+
+ action_free:
+ res = sieve2_action_free(a);
+ if (res != SIEVE2_OK) {
+ printf("sieve2_action_free() returns %d\n", res);
+ ret = 1;
+ }
+
+ /* Good thing we're not forgetting ;-) */
+ char_script_free:
+ if (script != NULL)
+ my_free(script);
+ char_scriptname_free:
+ if (scriptname != NULL)
+ my_free(scriptname);
+
+ no_free:
+ return ret;
}
-int sortsieve_unroll_action(sieve2_action_t *a, struct list *actions)
+int sortsieve_unroll_action(sieve2_action_t * a, struct list *actions)
{
- int res = SIEVE2_OK;
- int code;
- void *action_context;
-
- /* Working variables to set up
- * the struct then nodeadd it */
- sort_action_t *tmpsa = NULL;
- char *tmpdest = NULL;
- char *tmpmsg = NULL;
- int tmpmeth = 0;
-
- while(res == SIEVE2_OK)
- {
- if((tmpsa = malloc(sizeof(sort_action_t))) == NULL)
- break;
- res = sieve2_action_next(&a, &code, &action_context);
- if(res == SIEVE2_DONE)
- {
- printf("We've reached the end.\n");
- break;
- }
- else if (res != SIEVE2_OK)
- {
- printf("Error in action list.\n");
- break;
- }
- printf("Action code is: %d\n", code);
-
- switch (code)
- {
- case SIEVE2_ACTION_REDIRECT:
- {
- sieve2_redirect_context_t *context = (sieve2_redirect_context_t *)action_context;
- printf( "Action is REDIRECT: " );
- printf( "Destination is %s\n", context->addr);
- tmpmeth = SA_REDIRECT;
- tmpdest = strdup(context->addr);
- break;
- }
- case SIEVE2_ACTION_REJECT:
- {
- sieve2_reject_context_t *context = (sieve2_reject_context_t *)action_context;
- printf( "Action is REJECT: " );
- printf( "Message is %s\n", context->msg);
- tmpmeth = SA_REJECT;
- tmpmsg = strdup(context->msg);
- break;
- }
- case SIEVE2_ACTION_DISCARD:
- printf( "Action is DISCARD\n" );
- tmpmeth = SA_DISCARD;
- break;
- case SIEVE2_ACTION_FILEINTO:
- {
- sieve2_fileinto_context_t *context = (sieve2_fileinto_context_t *)action_context;
- printf( "Action is FILEINTO: " );
- printf( "Destination is %s\n", context->mailbox);
- tmpmeth = SA_FILEINTO;
- tmpdest = strdup(context->mailbox);
- break;
- }
- case SIEVE2_ACTION_NOTIFY:
- {
- sieve2_notify_context_t *context = (sieve2_notify_context_t *)action_context;
- printf( "Action is NOTIFY: \n" );
- // FIXME: Prefer to have a function for this?
- while(context != NULL)
- {
- printf( " ID \"%s\" is %s\n", context->id, ( context->isactive ? "ACTIVE" : "INACTIVE" ) );
- printf( " Method is %s\n", context->method );
- printf( " Priority is %s\n", context->priority );
- printf( " Message is %s\n", context->message );
- if(context->options != NULL)
- {
- size_t opt = 0;
- while(context->options[opt] != NULL)
- {
- printf( " Options are %s\n", context->options[opt] );
- opt++;
- }
- }
- context = context->next;
- }
- break;
- }
- case SIEVE2_ACTION_KEEP:
- printf( "Action is KEEP\n" );
- break;
- default:
- printf( "Unrecognized action code: %d\n", code );
- break;
- } /* case */
-
- tmpsa->method = tmpmeth;
- tmpsa->destination = tmpdest;
- tmpsa->message = tmpmsg;
-
- list_nodeadd(actions, tmpsa, sizeof(sort_action_t));
-
- my_free(tmpsa);
- tmpsa = NULL;
-
- } /* while */
-
- if (tmpsa != NULL)
- my_free(tmpsa);
-
- return res;
+ int res = SIEVE2_OK;
+ int code;
+ void *action_context;
+
+ /* Working variables to set up
+ * the struct then nodeadd it */
+ sort_action_t *tmpsa = NULL;
+ char *tmpdest = NULL;
+ char *tmpmsg = NULL;
+ int tmpmeth = 0;
+
+ while (res == SIEVE2_OK) {
+ if ((tmpsa = malloc(sizeof(sort_action_t))) == NULL)
+ break;
+ res = sieve2_action_next(&a, &code, &action_context);
+ if (res == SIEVE2_DONE) {
+ printf("We've reached the end.\n");
+ break;
+ } else if (res != SIEVE2_OK) {
+ printf("Error in action list.\n");
+ break;
+ }
+ printf("Action code is: %d\n", code);
+
+ switch (code) {
+ case SIEVE2_ACTION_REDIRECT:
+ {
+ sieve2_redirect_context_t *context =
+ (sieve2_redirect_context_t *)
+ action_context;
+ printf("Action is REDIRECT: ");
+ printf("Destination is %s\n",
+ context->addr);
+ tmpmeth = SA_REDIRECT;
+ tmpdest = strdup(context->addr);
+ break;
+ }
+ case SIEVE2_ACTION_REJECT:
+ {
+ sieve2_reject_context_t *context =
+ (sieve2_reject_context_t *)
+ action_context;
+ printf("Action is REJECT: ");
+ printf("Message is %s\n", context->msg);
+ tmpmeth = SA_REJECT;
+ tmpmsg = strdup(context->msg);
+ break;
+ }
+ case SIEVE2_ACTION_DISCARD:
+ printf("Action is DISCARD\n");
+ tmpmeth = SA_DISCARD;
+ break;
+ case SIEVE2_ACTION_FILEINTO:
+ {
+ sieve2_fileinto_context_t *context =
+ (sieve2_fileinto_context_t *)
+ action_context;
+ printf("Action is FILEINTO: ");
+ printf("Destination is %s\n",
+ context->mailbox);
+ tmpmeth = SA_FILEINTO;
+ tmpdest = strdup(context->mailbox);
+ break;
+ }
+ case SIEVE2_ACTION_NOTIFY:
+ {
+ sieve2_notify_context_t *context =
+ (sieve2_notify_context_t *)
+ action_context;
+ printf("Action is NOTIFY: \n");
+ // FIXME: Prefer to have a function for this?
+ while (context != NULL) {
+ printf(" ID \"%s\" is %s\n",
+ context->id,
+ (context->
+ isactive ? "ACTIVE" :
+ "INACTIVE"));
+ printf(" Method is %s\n",
+ context->method);
+ printf(" Priority is %s\n",
+ context->priority);
+ printf(" Message is %s\n",
+ context->message);
+ if (context->options != NULL) {
+ size_t opt = 0;
+ while (context->
+ options[opt] !=
+ NULL) {
+ printf
+ (" Options are %s\n",
+ context->
+ options[opt]);
+ opt++;
+ }
+ }
+ context = context->next;
+ }
+ break;
+ }
+ case SIEVE2_ACTION_KEEP:
+ printf("Action is KEEP\n");
+ break;
+ default:
+ printf("Unrecognized action code: %d\n", code);
+ break;
+ } /* case */
+
+ tmpsa->method = tmpmeth;
+ tmpsa->destination = tmpdest;
+ tmpsa->message = tmpmsg;
+
+ list_nodeadd(actions, tmpsa, sizeof(sort_action_t));
+
+ my_free(tmpsa);
+ tmpsa = NULL;
+
+ } /* while */
+
+ if (tmpsa != NULL)
+ my_free(tmpsa);
+
+ return res;
}
/* Return 0 on script OK, 1 on script error. */
int sortsieve_script_validate(char *script, char **errmsg)
{
- if(sieve2_validate(t, s, p, e) == SIEVE2_OK)
- {
- *errmsg = NULL;
- return 0;
- }
- else
- {
- *errmsg = "Script error...";
- return 1;
- }
+ if (sieve2_validate(t, s, p, e) == SIEVE2_OK) {
+ *errmsg = NULL;
+ return 0;
+ } else {
+ *errmsg = "Script error...";
+ return 1;
+ }
}
-
diff --git a/sort/sortsieve.h b/sort/sortsieve.h
index 9fb4048e..c1cf3bbe 100644
--- a/sort/sortsieve.h
+++ b/sort/sortsieve.h
@@ -16,8 +16,9 @@
#define MAX_SIEVE_SCRIPTNAME 100
-int sortsieve_msgsort(u64_t useridnr, char *header, u64_t headersize, u64_t messagesize, struct list *actions);
-int sortsieve_unroll_action(sieve2_action_t *a, struct list *actions);
+int sortsieve_msgsort(u64_t useridnr, char *header, u64_t headersize,
+ u64_t messagesize, struct list *actions);
+int sortsieve_unroll_action(sieve2_action_t * a, struct list *actions);
int sortsieve_script_validate(char *script, char **errmsg);
#endif
diff --git a/timsieve.c b/timsieve.c
index 127be50d..9f23ff8f 100644
--- a/timsieve.c
+++ b/timsieve.c
@@ -44,8 +44,7 @@
* and so that part of the Implementation line is absolutely required. */
/* allowed timsieve commands */
-const char *commands [] =
-{
+const char *commands[] = {
"LOGOUT", "STARTTLS", "CAPABILITY", "LISTSCRIPTS",
"AUTHENTICATE", "DELETESCRIPT", "GETSCRIPT", "SETACTIVE",
"HAVESPACE", "PUTSCRIPT"
@@ -53,684 +52,789 @@ const char *commands [] =
/* \" is added to the standard set of stuff... */
const char validchars[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-"_.!@#$%^&*()-+=~[]{}<>:;\\\"/ ";
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "_.!@#$%^&*()-+=~[]{}<>:;\\\"/ ";
char myhostname[64];
-int tims_handle_connection(clientinfo_t *ci)
+int tims_handle_connection(clientinfo_t * ci)
{
- /*
- Handles connection and calls
- tims command handler
- */
-
- int done = 1; /* loop state */
- char *buffer = NULL; /* connection buffer */
- int cnt; /* counter */
- time_t timestamp;
-
- PopSession_t session; /* current connection session */
-
- /* setting Session variables */
- session.error_count = 0;
-
- session.username = NULL;
- session.password = NULL;
-
- session.SessionResult = 0;
-
- /* reset counters */
- session.totalsize = 0;
- session.virtual_totalsize = 0;
- session.totalmessages = 0;
- session.virtual_totalmessages = 0;
-
-
- /* getting hostname */
- gethostname(myhostname, 64);
- myhostname[63] = 0; /* make sure string is terminated */
-
- buffer = (char *)my_malloc(INCOMING_BUFFER_SIZE * sizeof(char));
-
- if (!buffer)
- {
- trace(TRACE_MESSAGE, "tims_handle_connection(): Could not allocate buffer");
- return 0;
- }
-
- if (ci->tx)
- {
- /* This is a macro shared with TIMS_CAPA, per the draft RFC. */
- GREETING(ci->tx);
- fflush(ci->tx);
- }
- else
- {
- trace(TRACE_MESSAGE, "tims_handle_connection(): TX stream is null!");
- return 0;
- }
-
- while (done > 0)
- {
- /* set the timeout counter */
- alarm(ci->timeout);
-
- /* clear the buffer */
- memset(buffer, 0, INCOMING_BUFFER_SIZE);
-
- for (cnt = 0; cnt < INCOMING_BUFFER_SIZE - 1; cnt++)
- {
- do
- {
- clearerr(ci->rx);
- fread(&buffer[cnt], 1, 1, ci->rx);
-
- /* leave, an alarm has occured during fread */
- if (!ci->rx) return 0;
- }
- while (ferror(ci->rx) && errno == EINTR);
-
- if (buffer[cnt] == '\n' || feof(ci->rx) || ferror(ci->rx))
- {
- if (cnt > 0)
- {
- /* Ignore single newlines and \r\n pairs */
- if (cnt != 1 || buffer[cnt-1] != '\r')
- {
- buffer[cnt+1] = '\0';
- break;
- }
- /* Overwrite those silly extra \r\n's */
- else
- {
- /* Incremented to 0 at top of loop */
- cnt = -1;
- }
- }
- }
- }
-
- if (feof(ci->rx) || ferror(ci->rx))
- {
- /* check client eof */
- done = -1;
- }
- else
- {
- /* reset function handle timeout */
- alarm(0);
- /* handle tims commands */
- done = tims(ci->tx, ci->rx, buffer, ci->ip, &session);
- }
- fflush(ci->tx);
- }
-
- /* memory cleanup */
- my_free(buffer);
- buffer = NULL;
-
- /* reset timers */
- alarm (0);
- __debug_dumpallocs();
-
- return 0;
+ /*
+ Handles connection and calls
+ tims command handler
+ */
+
+ int done = 1; /* loop state */
+ char *buffer = NULL; /* connection buffer */
+ int cnt; /* counter */
+ time_t timestamp;
+
+ PopSession_t session; /* current connection session */
+
+ /* setting Session variables */
+ session.error_count = 0;
+
+ session.username = NULL;
+ session.password = NULL;
+
+ session.SessionResult = 0;
+
+ /* reset counters */
+ session.totalsize = 0;
+ session.virtual_totalsize = 0;
+ session.totalmessages = 0;
+ session.virtual_totalmessages = 0;
+
+
+ /* getting hostname */
+ gethostname(myhostname, 64);
+ myhostname[63] = 0; /* make sure string is terminated */
+
+ buffer = (char *) my_malloc(INCOMING_BUFFER_SIZE * sizeof(char));
+
+ if (!buffer) {
+ trace(TRACE_MESSAGE,
+ "tims_handle_connection(): Could not allocate buffer");
+ return 0;
+ }
+
+ if (ci->tx) {
+ /* This is a macro shared with TIMS_CAPA, per the draft RFC. */
+ GREETING(ci->tx);
+ fflush(ci->tx);
+ } else {
+ trace(TRACE_MESSAGE,
+ "tims_handle_connection(): TX stream is null!");
+ return 0;
+ }
+
+ while (done > 0) {
+ /* set the timeout counter */
+ alarm(ci->timeout);
+
+ /* clear the buffer */
+ memset(buffer, 0, INCOMING_BUFFER_SIZE);
+
+ for (cnt = 0; cnt < INCOMING_BUFFER_SIZE - 1; cnt++) {
+ do {
+ clearerr(ci->rx);
+ fread(&buffer[cnt], 1, 1, ci->rx);
+
+ /* leave, an alarm has occured during fread */
+ if (!ci->rx)
+ return 0;
+ }
+ while (ferror(ci->rx) && errno == EINTR);
+
+ if (buffer[cnt] == '\n' || feof(ci->rx)
+ || ferror(ci->rx)) {
+ if (cnt > 0) {
+ /* Ignore single newlines and \r\n pairs */
+ if (cnt != 1
+ || buffer[cnt - 1] != '\r') {
+ buffer[cnt + 1] = '\0';
+ break;
+ }
+ /* Overwrite those silly extra \r\n's */
+ else {
+ /* Incremented to 0 at top of loop */
+ cnt = -1;
+ }
+ }
+ }
+ }
+
+ if (feof(ci->rx) || ferror(ci->rx)) {
+ /* check client eof */
+ done = -1;
+ } else {
+ /* reset function handle timeout */
+ alarm(0);
+ /* handle tims commands */
+ done =
+ tims(ci->tx, ci->rx, buffer, ci->ip, &session);
+ }
+ fflush(ci->tx);
+ }
+
+ /* memory cleanup */
+ my_free(buffer);
+ buffer = NULL;
+
+ /* reset timers */
+ alarm(0);
+ __debug_dumpallocs();
+
+ return 0;
}
-int tims_reset(PopSession_t *session)
- {
- session->state = STRT;
+int tims_reset(PopSession_t * session)
+{
+ session->state = STRT;
- return 1;
- }
+ return 1;
+}
-int tims_error(PopSession_t *session, void *stream, const char *formatstring, ...)
+int tims_error(PopSession_t * session, void *stream,
+ const char *formatstring, ...)
{
- va_list argp;
-
- if (session->error_count >= MAX_ERRORS)
- {
- trace(TRACE_MESSAGE, "tims_error(): too many errors (MAX_ERRORS is %d)", MAX_ERRORS);
- fprintf((FILE *)stream, "BYE \"Too many errors, closing connection.\"\r\n");
- session->SessionResult = 2; /* possible flood */
- tims_reset(session);
- return -3;
- }
- else
- {
- va_start(argp, formatstring);
- vfprintf((FILE *)stream, formatstring, argp);
- va_end(argp);
- }
-
- trace(TRACE_DEBUG, "tims_error(): an invalid command was issued");
- session->error_count++;
- return 1;
+ va_list argp;
+
+ if (session->error_count >= MAX_ERRORS) {
+ trace(TRACE_MESSAGE,
+ "tims_error(): too many errors (MAX_ERRORS is %d)",
+ MAX_ERRORS);
+ fprintf((FILE *) stream,
+ "BYE \"Too many errors, closing connection.\"\r\n");
+ session->SessionResult = 2; /* possible flood */
+ tims_reset(session);
+ return -3;
+ } else {
+ va_start(argp, formatstring);
+ vfprintf((FILE *) stream, formatstring, argp);
+ va_end(argp);
+ }
+
+ trace(TRACE_DEBUG, "tims_error(): an invalid command was issued");
+ session->error_count++;
+ return 1;
}
-int tims(void *stream, void *instream, char *buffer, char *client_ip, PopSession_t *session)
+int tims(void *stream, void *instream, char *buffer, char *client_ip,
+ PopSession_t * session)
{
- /* returns values:
- * 0 to quit
- * -1 on failure
- * 1 on success */
- char *command, *value;
- int cmdtype;
- int indx=0;
-
- /* buffer overflow attempt */
- if (strlen(buffer) > MAX_IN_BUFFER)
- {
- trace(TRACE_DEBUG, "tims(): buffer overflow attempt");
- return -3;
- }
-
- /* check for command issued */
- while (strchr(validchars, buffer[indx]))
- indx++;
-
- /* end buffer */
- buffer[indx] = '\0';
-
- trace(TRACE_DEBUG, "tims(): incoming buffer: [%s]", buffer);
-
- command = buffer;
-
- value = strstr(command, " "); /* look for the separator */
-
- if (value != NULL)
- {
- *value = '\0'; /* set a \0 on the command end */
- value++; /* skip space */
-
- if (strlen(value) == 0)
- {
- value = NULL; /* no value specified */
- }
- else
- {
- trace(TRACE_DEBUG, "tims(): command issued: cmd [%s], val [%s]", command, value);
- }
- }
-
- for (cmdtype = TIMS_STRT; cmdtype < TIMS_END; cmdtype ++)
- if (strcasecmp(command, commands[cmdtype]) == 0) break;
-
- trace(TRACE_DEBUG, "tims(): command looked up as commandtype %d", cmdtype);
-
- /* commands that are allowed to have no arguments */
- if ((value == NULL) && !(cmdtype < TIMS_NOARGS) && (cmdtype < TIMS_END))
- {
- return tims_error(session, stream, "NO \"This command requires an argument.\"\r\n");
- }
-
- switch (cmdtype)
- {
- case TIMS_LOUT :
- {
- fprintf((FILE *)stream, "OK\r\n");
- tims_reset(session);
- return 0; /* return 0 to cause the connection to close */
- }
- case TIMS_STLS :
- {
- /* We don't support TLS, sorry! */
- fprintf((FILE *)stream, "NO\r\n");
- return 1;
- }
- case TIMS_CAPA :
- {
- /* This is macro-ized because it is also used in the greeting. */
- GREETING((FILE *)stream);
- return 1;
- }
- case TIMS_AUTH :
- {
- /* We currently only support plain authentication,
- * which means that the command we accept will look
- * like this: Authenticate "PLAIN" "base64-password"
- * */
- if (strlen(value) > strlen("\"PLAIN\""))
- {
- /* Only compare the first part of value */
- if (strncasecmp(value, "\"PLAIN\"", strlen("\"PLAIN\"")) == 0)
- {
- size_t tmplen=0;
- size_t tmppos=0;
- char *tmpleft=NULL, **tmp64=NULL;
-
- /* First see if the base64 SASL is simply quoted */
- if (0 != find_bounded(value+strlen("\"PLAIN\""), '"', '"', &tmpleft, &tmplen, &tmppos))
- {
- u64_t authlen; /* Actually, script length must be 32-bit unsigned int. */
- char tmpcharlen[11]; /* A 32-bit unsigned int is ten decimal digits in length. */
-
- /* Second, failing that, see if it's an {n+} literal */
- find_bounded(value+strlen("\"PLAIN\""), '{', '+', &tmpleft, &tmplen, &tmppos);
-
- strncpy(tmpcharlen, tmpleft, (10 < tmplen ? 10 : tmplen));
- tmpcharlen[(10 < tmplen ? 10 : tmplen)] = '\0';
- my_free(tmpleft);
-
- authlen = strtoull(tmpcharlen, NULL, 10);
- if (authlen >= UINT_MAX)
- {
- fprintf((FILE *)stream, "NO \"Invalid SASL length.\"\r\n");
- tmplen = 0; /* HACK: This prevents the next block from running. */
- }
- else
- {
- if (0 != read_from_stream((FILE *)instream, &tmpleft, authlen))
- {
- fprintf((FILE *)stream, "NO \"Error reading SASL.\"\r\n");
- }
- else
- {
- tmplen = authlen; /* HACK: This allows the next block to run. */
- }
- }
- }
-
- if (tmplen < 1)
- {
- /* Definitely an empty password string */
- fprintf((FILE *)stream, "NO \"Password required.\"\r\n");
- }
- else
- {
- size_t i;
- u64_t useridnr;
-
- tmp64 = base64_decode(tmpleft, tmplen);
- if (tmp64 == NULL)
- {
- fprintf((FILE *)stream, "NO \"SASL decode error.\"\r\n");
- }
- else
- {
- for (i = 0; tmp64[i] != NULL; i++) { /* Just count 'em up */ }
- if (i < 3)
- {
- fprintf((FILE *)stream, "NO \"Too few encoded SASL arguments.\"\r\n");
- }
- /* The protocol specifies that the base64 encoding
- * be made up of three parts: proxy, username, password
- * Between them are NULLs, which are conveniently encoded
- * by the base64 process... */
- if (auth_validate(tmp64[1], tmp64[2], &useridnr) == 1)
- {
- fprintf((FILE *)stream, "OK\r\n");
- session->state = AUTH;
- session->useridnr = useridnr;
- session->username = strdup(tmp64[1]);
- session->password = strdup(tmp64[2]);
- }
- else
- {
- fprintf((FILE *)stream, "NO \"Username or password incorrect.\"\r\n");
- }
- for (i = 0; tmp64[i] != NULL; i++)
- {
- my_free(tmp64[i]);
- }
- my_free(tmp64);
- }
- } /* if... tmplen < 1 */
- } /* if... strncasecmp() == "PLAIN" */
- else
- {
- trace(TRACE_INFO, "tims(): Input simply was not PLAIN auth");
- fprintf((FILE *)stream, "NO \"Authentication scheme not supported.\"\r\n");
- }
- } /* if... strlen() < "PLAIN" */
- else
- {
- trace(TRACE_INFO, "tims(): Input too short to possibly be PLAIN auth");
- fprintf((FILE *)stream, "NO \"Authentication scheme not supported.\"\r\n");
- }
-
- return 1;
- }
- case TIMS_PUTS :
- {
- if (session->state != AUTH)
- {
- fprintf((FILE *)stream, "NO \"Please authenticate first.\"\r\n");
- }
- else
- {
- size_t tmplen=0;
- size_t tmppos=0;
- char *tmpleft=NULL;
-
- find_bounded(value, '"', '"', &tmpleft, &tmplen, &tmppos);
-
- if (tmplen < 1)
- {
- /* Possibly an empty password... */
- fprintf((FILE *)stream, "NO \"Script name required.\"\r\n");
- }
- else
- {
- char scriptname[MAX_SIEVE_SCRIPTNAME+1];
-
- strncpy(scriptname, tmpleft,
- (MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen));
- /* Of course, be sure to NULL terminate, because strncpy() likely won't */
- scriptname[(MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen)] = '\0';
- my_free(tmpleft);
-
- /* Offset from the previous match to make sure not to pull
- * the "length" from a script with a malicious name */
- find_bounded(value+tmppos, '{', '+', &tmpleft, &tmplen, &tmppos);
-
- if (tmplen < 1)
- {
- /* Possibly an empty password... */
- fprintf((FILE *)stream, "NO \"Length required.\"\r\n");
- }
- else
- {
- u64_t scriptlen; /* Actually, script length must be 32-bit unsigned int. */
- char tmpcharlen[11]; /* A 32-bit unsigned int is ten decimal digits in length. */
-
- strncpy(tmpcharlen, tmpleft, (10 < tmplen ? 10 : tmplen));
- tmpcharlen[(10 < tmplen ? 10 : tmplen)] = '\0';
- my_free(tmpleft);
-
- scriptlen = strtoull(tmpcharlen, NULL, 10);
- trace(TRACE_INFO, "%s, %s: Client sending script of length [%llu]",
- __FILE__, __FUNCTION__, scriptlen);
- if (scriptlen >= UINT_MAX)
- {
- trace(TRACE_INFO, "%s, %s: Length [%llu] is larger than UINT_MAX [%u]",
- __FILE__, __FUNCTION__, scriptlen, UINT_MAX);
- fprintf((FILE *)stream, "NO \"Invalid script length.\"\r\n");
- }
- else
- {
- char *f_buf = NULL;
-
- if (0 != read_from_stream((FILE *)instream, &f_buf, scriptlen))
- {
- trace(TRACE_INFO, "%s, %s: Error reading script with read_from_stream()",
- __FILE__, __FUNCTION__);
- fprintf((FILE *)stream, "NO \"Error reading script.\"\r\n");
- }
- else
- {
- if (0 != db_check_sievescript_quota(session->useridnr, scriptlen))
- {
- trace(TRACE_INFO, "%s, %s: Script exceeds user's quota, dumping it",
- __FILE__, __FUNCTION__);
- fprintf((FILE *)stream, "NO \"Script exceeds available space.\"\r\n");
- }
- else
- {
- char *errmsg = NULL;
-
- if (0 != sortsieve_script_validate(f_buf, &errmsg))
- {
- trace(TRACE_INFO, "%s, %s: Script has syntax errrors: [%s]",
- __FILE__, __FUNCTION__, errmsg);
- fprintf((FILE *)stream, "NO \"Script error: %s.\"\r\n", errmsg);
- }
- else
- {
- /* According to the draft RFC, a script with the same
- * name as an existing script should [atomically] replace it. */
- if (0 != db_replace_sievescript(session->useridnr, scriptname, f_buf))
- {
- trace(TRACE_INFO, "%s, %s: Error inserting script",
- __FILE__, __FUNCTION__);
- fprintf((FILE *)stream, "NO \"Error inserting script.\"\r\n");
- }
- else
- {
- trace(TRACE_INFO, "%s, %s: Script successfully received",
- __FILE__, __FUNCTION__);
- fprintf((FILE *)stream, "OK \"Script successfully received.\"\r\n");
- }
- }
- my_free(f_buf);
- }
- }
- }
- }
- }
- }
- return 1;
- }
- case TIMS_SETS:
- {
- if (session->state != AUTH)
- {
- fprintf((FILE *)stream, "NO \"Please authenticate first.\"\r\n");
- }
- else
- {
- int ret;
- size_t tmplen=0;
- size_t tmppos=0;
- char *tmpleft=NULL;
-
- find_bounded(value, '"', '"', &tmpleft, &tmplen, &tmppos);
-
- /* Only activate a new script if one was specified */
- if (tmplen > 0)
- {
- char scriptname[MAX_SIEVE_SCRIPTNAME+1];
-
- strncpy(scriptname, tmpleft,
- (MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen));
- /* Of course, be sure to NULL terminate, because strncpy() likely won't */
- scriptname[(MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen)] = '\0';
- my_free(tmpleft);
-
- ret = db_activate_sievescript(session->useridnr, scriptname);
- if (ret == -3)
- {
- fprintf((FILE *)stream, "NO \"Script does not exist.\"\r\n");
- return -1;
- }
- else if (ret != 0)
- {
- fprintf((FILE *)stream, "NO \"Internal error.\"\r\n");
- return -1;
- }
- else
- {
- fprintf((FILE *)stream, "OK \"Script activated.\"\r\n");
- }
- }
- else
- {
- char *scriptname=NULL;
- ret = db_get_sievescript_active(session->useridnr, &scriptname);
- if (scriptname == NULL)
- {
- fprintf((FILE *)stream, "OK \"No scripts are active at this time.\"\r\n");
- }
- else
- {
- ret = db_deactivate_sievescript(session->useridnr, scriptname);
- my_free(scriptname);
- if (ret == -3)
- {
- fprintf((FILE *)stream, "NO \"Active script does not exist.\"\r\n");
- return -1;
- }
- else if (ret != 0)
- {
- fprintf((FILE *)stream, "NO \"Internal error.\"\r\n");
- return -1;
- }
- else
- {
- fprintf((FILE *)stream, "OK \"All scripts deactivated.\"\r\n");
- }
- }
- }
- }
- return 1;
- }
- case TIMS_GETS:
- {
- if (session->state != AUTH)
- {
- fprintf((FILE *)stream, "NO \"Please authenticate first.\"\r\n");
- }
- else
- {
- size_t tmplen=0;
- size_t tmppos=0;
- char *tmpleft=NULL;
-
- find_bounded(value, '"', '"', &tmpleft, &tmplen, &tmppos);
-
- if (tmplen < 1)
- {
- /* Possibly an empty password... */
- fprintf((FILE *)stream, "NO \"Script name required.\"\r\n");
- }
- else
- {
- int ret = 0;
- char *script = NULL;
- char scriptname[MAX_SIEVE_SCRIPTNAME+1];
-
- strncpy(scriptname, tmpleft,
- (MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen));
- /* Of course, be sure to NULL terminate, because strncpy() likely won't */
- scriptname[(MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen)] = '\0';
- my_free(tmpleft);
-
- ret = db_get_sievescript_byname(session->useridnr, scriptname, &script);
- if (ret == -3)
- {
- fprintf((FILE *)stream, "NO \"Script not found.\"\r\n");
- }
- else if (ret != 0 || script == NULL)
- {
- fprintf((FILE *)stream, "NO \"Internal error.\"\r\n");
- }
- else
- {
- fprintf((FILE *)stream, "{%u+}\r\n", strlen(script));
- fprintf((FILE *)stream, "%s\r\n", script);
- fprintf((FILE *)stream, "OK\r\n");
- }
+ /* returns values:
+ * 0 to quit
+ * -1 on failure
+ * 1 on success */
+ char *command, *value;
+ int cmdtype;
+ int indx = 0;
+
+ /* buffer overflow attempt */
+ if (strlen(buffer) > MAX_IN_BUFFER) {
+ trace(TRACE_DEBUG, "tims(): buffer overflow attempt");
+ return -3;
+ }
+
+ /* check for command issued */
+ while (strchr(validchars, buffer[indx]))
+ indx++;
+
+ /* end buffer */
+ buffer[indx] = '\0';
+
+ trace(TRACE_DEBUG, "tims(): incoming buffer: [%s]", buffer);
+
+ command = buffer;
+
+ value = strstr(command, " "); /* look for the separator */
+
+ if (value != NULL) {
+ *value = '\0'; /* set a \0 on the command end */
+ value++; /* skip space */
+
+ if (strlen(value) == 0) {
+ value = NULL; /* no value specified */
+ } else {
+ trace(TRACE_DEBUG,
+ "tims(): command issued: cmd [%s], val [%s]",
+ command, value);
+ }
+ }
+
+ for (cmdtype = TIMS_STRT; cmdtype < TIMS_END; cmdtype++)
+ if (strcasecmp(command, commands[cmdtype]) == 0)
+ break;
+
+ trace(TRACE_DEBUG, "tims(): command looked up as commandtype %d",
+ cmdtype);
+
+ /* commands that are allowed to have no arguments */
+ if ((value == NULL) && !(cmdtype < TIMS_NOARGS)
+ && (cmdtype < TIMS_END)) {
+ return tims_error(session, stream,
+ "NO \"This command requires an argument.\"\r\n");
+ }
+
+ switch (cmdtype) {
+ case TIMS_LOUT:
+ {
+ fprintf((FILE *) stream, "OK\r\n");
+ tims_reset(session);
+ return 0; /* return 0 to cause the connection to close */
}
- }
- return 1;
- }
- case TIMS_DELS:
- {
- if (session->state != AUTH)
- {
- fprintf((FILE *)stream, "NO \"Please authenticate first.\"\r\n");
- }
- else
- {
- size_t tmplen=0;
- size_t tmppos=0;
- char *tmpleft=NULL;
-
- find_bounded(value, '"', '"', &tmpleft, &tmplen, &tmppos);
-
- if (tmplen < 1)
- {
- /* Possibly an empty password... */
- fprintf((FILE *)stream, "NO \"Script name required.\"\r\n");
- }
- else
- {
- int ret = 0;
- char scriptname[MAX_SIEVE_SCRIPTNAME+1];
-
- strncpy(scriptname, tmpleft,
- (MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen));
- /* Of course, be sure to NULL terminate, because strncpy() likely won't */
- scriptname[(MAX_SIEVE_SCRIPTNAME < tmplen ? MAX_SIEVE_SCRIPTNAME : tmplen)] = '\0';
- my_free(tmpleft);
-
- ret = db_delete_sievescript(session->useridnr, scriptname);
- if (ret == -3)
- {
- fprintf((FILE *)stream, "NO \"Script not found.\"\r\n");
- }
- else if (ret != 0)
- {
- fprintf((FILE *)stream, "NO \"Internal error.\"\r\n");
- }
- else
- {
- fprintf((FILE *)stream, "OK\r\n");
- }
+ case TIMS_STLS:
+ {
+ /* We don't support TLS, sorry! */
+ fprintf((FILE *) stream, "NO\r\n");
+ return 1;
}
- }
- return 1;
- }
- case TIMS_SPAC:
- {
- if (session->state != AUTH)
- {
- fprintf((FILE *)stream, "NO \"Please authenticate first.\"\r\n");
- }
- else
- {
- fprintf((FILE *)stream, "NO \"Command not implemented.\"\r\n");
- }
- return 1;
- }
- case TIMS_LIST:
- {
- if (session->state != AUTH)
- {
- fprintf((FILE *)stream, "NO \"Please authenticate first.\"\r\n");
- }
- else
- {
- struct list scriptlist;
- struct element *tmp;
-
- if(db_get_sievescript_listall(session->useridnr, &scriptlist) < 0)
- {
- fprintf((FILE *)stream, "NO \"Internal error.\"\r\n");
- }
- else
- {
- if (list_totalnodes(&scriptlist) == 0)
- {
- /* The command hasn't failed, but there aren't any scripts */
- fprintf((FILE *)stream, "OK \"No scripts found.\"\r\n");
- }
- else
- {
- tmp = list_getstart(&scriptlist);
- while (tmp != NULL)
- {
- struct ssinfo *info = (struct ssinfo *)tmp->data;
- fprintf((FILE *)stream, "\"%s\"%s\r\n",
- info->name, (info->active == 1 ? " ACTIVE" : ""));
- tmp = tmp->nextnode;
- }
- fprintf((FILE *)stream, "OK\r\n");
- }
- if (scriptlist.start)
- list_freelist(&scriptlist.start);
- }
- }
- return 1;
- }
- default :
- {
- return tims_error(session, stream,"NO \"What are you trying to say here?\"\r\n");
- }
- }
- return 1;
+ case TIMS_CAPA:
+ {
+ /* This is macro-ized because it is also used in the greeting. */
+ GREETING((FILE *) stream);
+ return 1;
+ }
+ case TIMS_AUTH:
+ {
+ /* We currently only support plain authentication,
+ * which means that the command we accept will look
+ * like this: Authenticate "PLAIN" "base64-password"
+ * */
+ if (strlen(value) > strlen("\"PLAIN\"")) {
+ /* Only compare the first part of value */
+ if (strncasecmp
+ (value, "\"PLAIN\"",
+ strlen("\"PLAIN\"")) == 0) {
+ size_t tmplen = 0;
+ size_t tmppos = 0;
+ char *tmpleft = NULL, **tmp64 =
+ NULL;
+
+ /* First see if the base64 SASL is simply quoted */
+ if (0 !=
+ find_bounded(value +
+ strlen
+ ("\"PLAIN\""),
+ '"', '"',
+ &tmpleft, &tmplen,
+ &tmppos)) {
+ u64_t authlen; /* Actually, script length must be 32-bit unsigned int. */
+ char tmpcharlen[11]; /* A 32-bit unsigned int is ten decimal digits in length. */
+
+ /* Second, failing that, see if it's an {n+} literal */
+ find_bounded(value +
+ strlen
+ ("\"PLAIN\""),
+ '{', '+',
+ &tmpleft,
+ &tmplen,
+ &tmppos);
+
+ strncpy(tmpcharlen,
+ tmpleft,
+ (10 <
+ tmplen ? 10 :
+ tmplen));
+ tmpcharlen[(10 <
+ tmplen ? 10 :
+ tmplen)] =
+ '\0';
+ my_free(tmpleft);
+
+ authlen =
+ strtoull(tmpcharlen,
+ NULL, 10);
+ if (authlen >= UINT_MAX) {
+ fprintf((FILE *)
+ stream,
+ "NO \"Invalid SASL length.\"\r\n");
+ tmplen = 0; /* HACK: This prevents the next block from running. */
+ } else {
+ if (0 !=
+ read_from_stream
+ ((FILE *)
+ instream,
+ &tmpleft,
+ authlen)) {
+ fprintf((FILE *) stream, "NO \"Error reading SASL.\"\r\n");
+ } else {
+ tmplen = authlen; /* HACK: This allows the next block to run. */
+ }
+ }
+ }
+
+ if (tmplen < 1) {
+ /* Definitely an empty password string */
+ fprintf((FILE *) stream,
+ "NO \"Password required.\"\r\n");
+ } else {
+ size_t i;
+ u64_t useridnr;
+
+ tmp64 =
+ base64_decode(tmpleft,
+ tmplen);
+ if (tmp64 == NULL) {
+ fprintf((FILE *)
+ stream,
+ "NO \"SASL decode error.\"\r\n");
+ } else {
+ for (i = 0; tmp64[i] != NULL; i++) { /* Just count 'em up */
+ }
+ if (i < 3) {
+ fprintf((FILE *) stream, "NO \"Too few encoded SASL arguments.\"\r\n");
+ }
+ /* The protocol specifies that the base64 encoding
+ * be made up of three parts: proxy, username, password
+ * Between them are NULLs, which are conveniently encoded
+ * by the base64 process... */
+ if (auth_validate
+ (tmp64[1],
+ tmp64[2],
+ &useridnr) ==
+ 1) {
+ fprintf((FILE *) stream, "OK\r\n");
+ session->
+ state =
+ AUTH;
+ session->
+ useridnr
+ =
+ useridnr;
+ session->
+ username
+ =
+ strdup
+ (tmp64
+ [1]);
+ session->
+ password
+ =
+ strdup
+ (tmp64
+ [2]);
+ } else {
+ fprintf((FILE *) stream, "NO \"Username or password incorrect.\"\r\n");
+ }
+ for (i = 0;
+ tmp64[i] !=
+ NULL; i++) {
+ my_free
+ (tmp64
+ [i]);
+ }
+ my_free(tmp64);
+ }
+ } /* if... tmplen < 1 */
+ } /* if... strncasecmp() == "PLAIN" */
+ else {
+ trace(TRACE_INFO,
+ "tims(): Input simply was not PLAIN auth");
+ fprintf((FILE *) stream,
+ "NO \"Authentication scheme not supported.\"\r\n");
+ }
+ } /* if... strlen() < "PLAIN" */
+ else {
+ trace(TRACE_INFO,
+ "tims(): Input too short to possibly be PLAIN auth");
+ fprintf((FILE *) stream,
+ "NO \"Authentication scheme not supported.\"\r\n");
+ }
+
+ return 1;
+ }
+ case TIMS_PUTS:
+ {
+ if (session->state != AUTH) {
+ fprintf((FILE *) stream,
+ "NO \"Please authenticate first.\"\r\n");
+ } else {
+ size_t tmplen = 0;
+ size_t tmppos = 0;
+ char *tmpleft = NULL;
+
+ find_bounded(value, '"', '"', &tmpleft,
+ &tmplen, &tmppos);
+
+ if (tmplen < 1) {
+ /* Possibly an empty password... */
+ fprintf((FILE *) stream,
+ "NO \"Script name required.\"\r\n");
+ } else {
+ char scriptname
+ [MAX_SIEVE_SCRIPTNAME + 1];
+
+ strncpy(scriptname, tmpleft,
+ (MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen));
+ /* Of course, be sure to NULL terminate, because strncpy() likely won't */
+ scriptname[(MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen)] = '\0';
+ my_free(tmpleft);
+
+ /* Offset from the previous match to make sure not to pull
+ * the "length" from a script with a malicious name */
+ find_bounded(value + tmppos, '{',
+ '+', &tmpleft,
+ &tmplen, &tmppos);
+
+ if (tmplen < 1) {
+ /* Possibly an empty password... */
+ fprintf((FILE *) stream,
+ "NO \"Length required.\"\r\n");
+ } else {
+ u64_t scriptlen; /* Actually, script length must be 32-bit unsigned int. */
+ char tmpcharlen[11]; /* A 32-bit unsigned int is ten decimal digits in length. */
+
+ strncpy(tmpcharlen,
+ tmpleft,
+ (10 <
+ tmplen ? 10 :
+ tmplen));
+ tmpcharlen[(10 <
+ tmplen ? 10 :
+ tmplen)] =
+ '\0';
+ my_free(tmpleft);
+
+ scriptlen =
+ strtoull(tmpcharlen,
+ NULL, 10);
+ trace(TRACE_INFO,
+ "%s, %s: Client sending script of length [%llu]",
+ __FILE__,
+ __FUNCTION__,
+ scriptlen);
+ if (scriptlen >= UINT_MAX) {
+ trace(TRACE_INFO,
+ "%s, %s: Length [%llu] is larger than UINT_MAX [%u]",
+ __FILE__,
+ __FUNCTION__,
+ scriptlen,
+ UINT_MAX);
+ fprintf((FILE *)
+ stream,
+ "NO \"Invalid script length.\"\r\n");
+ } else {
+ char *f_buf = NULL;
+
+ if (0 !=
+ read_from_stream
+ ((FILE *)
+ instream,
+ &f_buf,
+ scriptlen)) {
+ trace
+ (TRACE_INFO,
+ "%s, %s: Error reading script with read_from_stream()",
+ __FILE__,
+ __FUNCTION__);
+ fprintf((FILE *) stream, "NO \"Error reading script.\"\r\n");
+ } else {
+ if (0 !=
+ db_check_sievescript_quota
+ (session->
+ useridnr,
+ scriptlen))
+ {
+ trace
+ (TRACE_INFO,
+ "%s, %s: Script exceeds user's quota, dumping it",
+ __FILE__,
+ __FUNCTION__);
+ fprintf
+ ((FILE *) stream, "NO \"Script exceeds available space.\"\r\n");
+ } else {
+ char *errmsg = NULL;
+
+ if (0 != sortsieve_script_validate(f_buf, &errmsg)) {
+ trace
+ (TRACE_INFO,
+ "%s, %s: Script has syntax errrors: [%s]",
+ __FILE__,
+ __FUNCTION__,
+ errmsg);
+ fprintf
+ ((FILE *) stream, "NO \"Script error: %s.\"\r\n", errmsg);
+ } else {
+ /* According to the draft RFC, a script with the same
+ * name as an existing script should [atomically] replace it. */
+ if (0 != db_replace_sievescript(session->useridnr, scriptname, f_buf)) {
+ trace
+ (TRACE_INFO,
+ "%s, %s: Error inserting script",
+ __FILE__,
+ __FUNCTION__);
+ fprintf
+ ((FILE *) stream, "NO \"Error inserting script.\"\r\n");
+ } else {
+ trace
+ (TRACE_INFO,
+ "%s, %s: Script successfully received",
+ __FILE__,
+ __FUNCTION__);
+ fprintf
+ ((FILE *) stream, "OK \"Script successfully received.\"\r\n");
+ }
+ }
+ my_free
+ (f_buf);
+ }
+ }
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ case TIMS_SETS:
+ {
+ if (session->state != AUTH) {
+ fprintf((FILE *) stream,
+ "NO \"Please authenticate first.\"\r\n");
+ } else {
+ int ret;
+ size_t tmplen = 0;
+ size_t tmppos = 0;
+ char *tmpleft = NULL;
+
+ find_bounded(value, '"', '"', &tmpleft,
+ &tmplen, &tmppos);
+
+ /* Only activate a new script if one was specified */
+ if (tmplen > 0) {
+ char scriptname
+ [MAX_SIEVE_SCRIPTNAME + 1];
+
+ strncpy(scriptname, tmpleft,
+ (MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen));
+ /* Of course, be sure to NULL terminate, because strncpy() likely won't */
+ scriptname[(MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen)] = '\0';
+ my_free(tmpleft);
+
+ ret =
+ db_activate_sievescript
+ (session->useridnr,
+ scriptname);
+ if (ret == -3) {
+ fprintf((FILE *) stream,
+ "NO \"Script does not exist.\"\r\n");
+ return -1;
+ } else if (ret != 0) {
+ fprintf((FILE *) stream,
+ "NO \"Internal error.\"\r\n");
+ return -1;
+ } else {
+ fprintf((FILE *) stream,
+ "OK \"Script activated.\"\r\n");
+ }
+ } else {
+ char *scriptname = NULL;
+ ret =
+ db_get_sievescript_active
+ (session->useridnr,
+ &scriptname);
+ if (scriptname == NULL) {
+ fprintf((FILE *) stream,
+ "OK \"No scripts are active at this time.\"\r\n");
+ } else {
+ ret =
+ db_deactivate_sievescript
+ (session->useridnr,
+ scriptname);
+ my_free(scriptname);
+ if (ret == -3) {
+ fprintf((FILE *)
+ stream,
+ "NO \"Active script does not exist.\"\r\n");
+ return -1;
+ } else if (ret != 0) {
+ fprintf((FILE *)
+ stream,
+ "NO \"Internal error.\"\r\n");
+ return -1;
+ } else {
+ fprintf((FILE *)
+ stream,
+ "OK \"All scripts deactivated.\"\r\n");
+ }
+ }
+ }
+ }
+ return 1;
+ }
+ case TIMS_GETS:
+ {
+ if (session->state != AUTH) {
+ fprintf((FILE *) stream,
+ "NO \"Please authenticate first.\"\r\n");
+ } else {
+ size_t tmplen = 0;
+ size_t tmppos = 0;
+ char *tmpleft = NULL;
+
+ find_bounded(value, '"', '"', &tmpleft,
+ &tmplen, &tmppos);
+
+ if (tmplen < 1) {
+ /* Possibly an empty password... */
+ fprintf((FILE *) stream,
+ "NO \"Script name required.\"\r\n");
+ } else {
+ int ret = 0;
+ char *script = NULL;
+ char scriptname
+ [MAX_SIEVE_SCRIPTNAME + 1];
+
+ strncpy(scriptname, tmpleft,
+ (MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen));
+ /* Of course, be sure to NULL terminate, because strncpy() likely won't */
+ scriptname[(MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen)] = '\0';
+ my_free(tmpleft);
+
+ ret =
+ db_get_sievescript_byname
+ (session->useridnr, scriptname,
+ &script);
+ if (ret == -3) {
+ fprintf((FILE *) stream,
+ "NO \"Script not found.\"\r\n");
+ } else if (ret != 0
+ || script == NULL) {
+ fprintf((FILE *) stream,
+ "NO \"Internal error.\"\r\n");
+ } else {
+ fprintf((FILE *) stream,
+ "{%u+}\r\n",
+ strlen(script));
+ fprintf((FILE *) stream,
+ "%s\r\n", script);
+ fprintf((FILE *) stream,
+ "OK\r\n");
+ }
+ }
+ }
+ return 1;
+ }
+ case TIMS_DELS:
+ {
+ if (session->state != AUTH) {
+ fprintf((FILE *) stream,
+ "NO \"Please authenticate first.\"\r\n");
+ } else {
+ size_t tmplen = 0;
+ size_t tmppos = 0;
+ char *tmpleft = NULL;
+
+ find_bounded(value, '"', '"', &tmpleft,
+ &tmplen, &tmppos);
+
+ if (tmplen < 1) {
+ /* Possibly an empty password... */
+ fprintf((FILE *) stream,
+ "NO \"Script name required.\"\r\n");
+ } else {
+ int ret = 0;
+ char scriptname
+ [MAX_SIEVE_SCRIPTNAME + 1];
+
+ strncpy(scriptname, tmpleft,
+ (MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen));
+ /* Of course, be sure to NULL terminate, because strncpy() likely won't */
+ scriptname[(MAX_SIEVE_SCRIPTNAME <
+ tmplen ?
+ MAX_SIEVE_SCRIPTNAME :
+ tmplen)] = '\0';
+ my_free(tmpleft);
+
+ ret =
+ db_delete_sievescript(session->
+ useridnr,
+ scriptname);
+ if (ret == -3) {
+ fprintf((FILE *) stream,
+ "NO \"Script not found.\"\r\n");
+ } else if (ret != 0) {
+ fprintf((FILE *) stream,
+ "NO \"Internal error.\"\r\n");
+ } else {
+ fprintf((FILE *) stream,
+ "OK\r\n");
+ }
+ }
+ }
+ return 1;
+ }
+ case TIMS_SPAC:
+ {
+ if (session->state != AUTH) {
+ fprintf((FILE *) stream,
+ "NO \"Please authenticate first.\"\r\n");
+ } else {
+ fprintf((FILE *) stream,
+ "NO \"Command not implemented.\"\r\n");
+ }
+ return 1;
+ }
+ case TIMS_LIST:
+ {
+ if (session->state != AUTH) {
+ fprintf((FILE *) stream,
+ "NO \"Please authenticate first.\"\r\n");
+ } else {
+ struct list scriptlist;
+ struct element *tmp;
+
+ if (db_get_sievescript_listall
+ (session->useridnr, &scriptlist) < 0) {
+ fprintf((FILE *) stream,
+ "NO \"Internal error.\"\r\n");
+ } else {
+ if (list_totalnodes(&scriptlist) ==
+ 0) {
+ /* The command hasn't failed, but there aren't any scripts */
+ fprintf((FILE *) stream,
+ "OK \"No scripts found.\"\r\n");
+ } else {
+ tmp =
+ list_getstart
+ (&scriptlist);
+ while (tmp != NULL) {
+ struct ssinfo *info
+ =
+ (struct ssinfo
+ *) tmp->data;
+ fprintf((FILE *)
+ stream,
+ "\"%s\"%s\r\n",
+ info->name,
+ (info->
+ active ==
+ 1 ?
+ " ACTIVE"
+ : ""));
+ tmp =
+ tmp->nextnode;
+ }
+ fprintf((FILE *) stream,
+ "OK\r\n");
+ }
+ if (scriptlist.start)
+ list_freelist(&scriptlist.
+ start);
+ }
+ }
+ return 1;
+ }
+ default:
+ {
+ return tims_error(session, stream,
+ "NO \"What are you trying to say here?\"\r\n");
+ }
+ }
+ return 1;
}
-
diff --git a/timsieve.h b/timsieve.h
index 5bfd4df4..8791db5c 100644
--- a/timsieve.h
+++ b/timsieve.h
@@ -38,7 +38,7 @@
/* processes */
#define MAXCHILDREN 5
-#define DEFAULT_CHILDREN 5
+#define DEFAULT_CHILDREN 5
#define TIMS_DEF_MAXCONNECT 1500
@@ -58,22 +58,23 @@ const char *commands [] =
"HAVESPACE", "PUTSCRIPT"
}; */
-#define TIMS_STRT 0 /* lower bound of array - 0 */
+#define TIMS_STRT 0 /* lower bound of array - 0 */
#define TIMS_LOUT 0
#define TIMS_STLS 1
#define TIMS_CAPA 2
-#define TIMS_LIST 3
-#define TIMS_NOARGS 4 /* use with if( cmd < TIMS_NOARGS )... */
+#define TIMS_LIST 3
+#define TIMS_NOARGS 4 /* use with if( cmd < TIMS_NOARGS )... */
#define TIMS_AUTH 4
#define TIMS_DELS 5
#define TIMS_GETS 6
#define TIMS_SETS 7
-#define TIMS_ONEARG 8 /* use with if( cmd < TIMS_ONEARG )... */
+#define TIMS_ONEARG 8 /* use with if( cmd < TIMS_ONEARG )... */
#define TIMS_SPAC 8
#define TIMS_PUTS 9
-#define TIMS_END 10 /* upper bound of array + 1 */
+#define TIMS_END 10 /* upper bound of array + 1 */
-int tims (void *stream, void *instream, char *buffer, char *client_ip, PopSession_t *session);
-int tims_handle_connection (clientinfo_t *ci);
+int tims(void *stream, void *instream, char *buffer, char *client_ip,
+ PopSession_t * session);
+int tims_handle_connection(clientinfo_t * ci);
#endif
diff --git a/timsieved.c b/timsieved.c
index 48313439..a6a6422b 100644
--- a/timsieved.c
+++ b/timsieved.c
@@ -43,10 +43,10 @@ char *configFile = DEFAULT_CONFIG_FILE;
/* set up database login data */
extern db_param_t _db_params;
-void SetConfigItems(serverConfig_t *config, struct list *items);
+void SetConfigItems(serverConfig_t * config, struct list *items);
static int SetMainSigHandler(void);
static void Daemonize(void);
-void MainSigHandler(int sig, siginfo_t *info, void *data);
+void MainSigHandler(int sig, siginfo_t * info, void *data);
int tims_before_smtp = 0;
int mainRestart = 0;
@@ -59,256 +59,282 @@ char *timeout_setting;
#ifdef PROC_TITLES
int main(int argc, char *argv[], char **envp)
#else
- int main(int argc, char *argv[])
+int main(int argc, char *argv[])
#endif
{
- serverConfig_t config;
- int result, status;
- pid_t pid;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- if (argc >= 2 && (argv[1]))
- {
- if (strcmp (argv[1],"-v") == 0)
- {
- printf ("\n*** DBMAIL: dbmail-timsieved version $Revision$ %s\n\n",COPYRIGHT);
- return 0;
- }
- else
- if (strcmp(argv[1],"-f")==0 && (argv[2]))
- configFile = argv[2];
- }
-
- SetMainSigHandler();
- Daemonize();
- result = 0;
-
- do
- {
- mainStop = 0;
- mainRestart = 0;
-
- trace(TRACE_DEBUG, "main(): reading config");
-#ifdef PROC_TITLES
- init_set_proc_title(argc, argv, envp, PNAME);
- set_proc_title("%s", "Idle");
-#endif
-
- /* We need smtp config for bounce.c and forward.c */
- ReadConfig("SMTP", configFile, &smtpItems);
- ReadConfig("TIMSIEVED", configFile, &timsItems);
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetConfigItems(&config, &timsItems);
- SetTraceLevel(&timsItems);
- GetDBParams(&_db_params, &sysItems);
-
- config.ClientHandler = tims_handle_connection;
- config.timeoutMsg = TIMS_TIMEOUT_MSG;
-
- CreateSocket(&config);
- trace(TRACE_DEBUG, "main(): socket created, starting server");
-
- switch ( (pid = fork()) )
- {
- case -1:
- close(config.listenSocket);
- trace(TRACE_FATAL, "main(): fork failed [%s]", strerror(errno));
-
- case 0:
- /* child process */
- drop_privileges(config.serverUser, config.serverGroup);
- result = StartServer(&config);
-
- trace(TRACE_INFO, "main(): server done, exit.");
- exit(result);
-
- default:
- /* parent process, wait for child to exit */
- while (waitpid(pid, &status, WNOHANG|WUNTRACED) == 0)
- {
- if (mainStop)
- kill(pid, SIGTERM);
-
- if (mainRestart)
- kill(pid, SIGHUP);
-
- sleep(2);
- }
-
- if (WIFEXITED(status))
- {
- /* child process terminated neatly */
- result = WEXITSTATUS(status);
- trace(TRACE_DEBUG, "main(): server has exited, exit status [%d]", result);
- }
- else
- {
- /* child stopped or signaled, don't like */
- /* make sure it is dead */
- trace(TRACE_DEBUG, "main(): server has not exited normally. Killing..");
-
- kill(pid, SIGKILL);
- result = 0;
- }
+ serverConfig_t config;
+ int result, status;
+ pid_t pid;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ if (argc >= 2 && (argv[1])) {
+ if (strcmp(argv[1], "-v") == 0) {
+ printf
+ ("\n*** DBMAIL: dbmail-timsieved version $Revision$ %s\n\n",
+ COPYRIGHT);
+ return 0;
+ } else if (strcmp(argv[1], "-f") == 0 && (argv[2]))
+ configFile = argv[2];
}
- list_freelist(&smtpItems.start);
- list_freelist(&timsItems.start);
- list_freelist(&sysItems.start);
- close(config.listenSocket);
+ SetMainSigHandler();
+ Daemonize();
+ result = 0;
- } while (result == 1 && !mainStop) ; /* 1 means reread-config and restart */
+ do {
+ mainStop = 0;
+ mainRestart = 0;
+
+ trace(TRACE_DEBUG, "main(): reading config");
+#ifdef PROC_TITLES
+ init_set_proc_title(argc, argv, envp, PNAME);
+ set_proc_title("%s", "Idle");
+#endif
- trace(TRACE_INFO, "main(): exit");
- return 0;
+ /* We need smtp config for bounce.c and forward.c */
+ ReadConfig("SMTP", configFile, &smtpItems);
+ ReadConfig("TIMSIEVED", configFile, &timsItems);
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetConfigItems(&config, &timsItems);
+ SetTraceLevel(&timsItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ config.ClientHandler = tims_handle_connection;
+ config.timeoutMsg = TIMS_TIMEOUT_MSG;
+
+ CreateSocket(&config);
+ trace(TRACE_DEBUG,
+ "main(): socket created, starting server");
+
+ switch ((pid = fork())) {
+ case -1:
+ close(config.listenSocket);
+ trace(TRACE_FATAL, "main(): fork failed [%s]",
+ strerror(errno));
+
+ case 0:
+ /* child process */
+ drop_privileges(config.serverUser,
+ config.serverGroup);
+ result = StartServer(&config);
+
+ trace(TRACE_INFO, "main(): server done, exit.");
+ exit(result);
+
+ default:
+ /* parent process, wait for child to exit */
+ while (waitpid(pid, &status, WNOHANG | WUNTRACED)
+ == 0) {
+ if (mainStop)
+ kill(pid, SIGTERM);
+
+ if (mainRestart)
+ kill(pid, SIGHUP);
+
+ sleep(2);
+ }
+
+ if (WIFEXITED(status)) {
+ /* child process terminated neatly */
+ result = WEXITSTATUS(status);
+ trace(TRACE_DEBUG,
+ "main(): server has exited, exit status [%d]",
+ result);
+ } else {
+ /* child stopped or signaled, don't like */
+ /* make sure it is dead */
+ trace(TRACE_DEBUG,
+ "main(): server has not exited normally. Killing..");
+
+ kill(pid, SIGKILL);
+ result = 0;
+ }
+ }
+
+ list_freelist(&smtpItems.start);
+ list_freelist(&timsItems.start);
+ list_freelist(&sysItems.start);
+ close(config.listenSocket);
+
+ } while (result == 1 && !mainStop); /* 1 means reread-config and restart */
+
+ trace(TRACE_INFO, "main(): exit");
+ return 0;
}
-void MainSigHandler(int sig, siginfo_t *info, void *data)
+void MainSigHandler(int sig, siginfo_t * info, void *data)
{
- trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
+ trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig);
- if (sig == SIGHUP)
- mainRestart = 1;
- else
- mainStop = 1;
+ if (sig == SIGHUP)
+ mainRestart = 1;
+ else
+ mainStop = 1;
}
void Daemonize()
{
- if (fork())
- exit(0);
- setsid();
+ if (fork())
+ exit(0);
+ setsid();
- if (fork())
- exit(0);
+ if (fork())
+ exit(0);
}
int SetMainSigHandler()
{
- struct sigaction act;
+ struct sigaction act;
- /* init & install signal handlers */
- memset(&act, 0, sizeof(act));
+ /* init & install signal handlers */
+ memset(&act, 0, sizeof(act));
- act.sa_sigaction = MainSigHandler;
- sigemptyset(&act.sa_mask);
- act.sa_flags = SA_SIGINFO;
+ act.sa_sigaction = MainSigHandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
- sigaction(SIGINT, &act, 0);
- sigaction(SIGQUIT, &act, 0);
- sigaction(SIGTERM, &act, 0);
- sigaction(SIGHUP, &act, 0);
+ sigaction(SIGINT, &act, 0);
+ sigaction(SIGQUIT, &act, 0);
+ sigaction(SIGTERM, &act, 0);
+ sigaction(SIGHUP, &act, 0);
- return 0;
+ return 0;
}
-void SetConfigItems(serverConfig_t *config, struct list *items)
+void SetConfigItems(serverConfig_t * config, struct list *items)
{
- field_t val;
+ field_t val;
- /* read items: NCHILDREN */
- GetConfigValue("NCHILDREN", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for NCHILDREN in config file");
+ /* read items: NCHILDREN */
+ GetConfigValue("NCHILDREN", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for NCHILDREN in config file");
- if ( (config->nChildren = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for NCHILDREN is invalid: [%d]", config->nChildren);
+ if ((config->nChildren = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for NCHILDREN is invalid: [%d]",
+ config->nChildren);
- trace(TRACE_DEBUG, "SetConfigItems(): server will create [%d] children", config->nChildren);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): server will create [%d] children",
+ config->nChildren);
- /* read items: MAXCONNECTS */
- GetConfigValue("MAXCONNECTS", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for MAXCONNECTS in config file");
+ /* read items: MAXCONNECTS */
+ GetConfigValue("MAXCONNECTS", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for MAXCONNECTS in config file");
- if ( (config->childMaxConnect = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]", config->childMaxConnect);
+ if ((config->childMaxConnect = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]",
+ config->childMaxConnect);
- trace(TRACE_DEBUG, "SetConfigItems(): children will make max. [%d] connections", config->childMaxConnect);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): children will make max. [%d] connections",
+ config->childMaxConnect);
- /* read items: TIMEOUT */
- GetConfigValue("TIMEOUT", items, val);
- if (strlen(val) == 0)
- {
- trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMEOUT in config file");
- config->timeout = 0;
- }
- else if ( (config->timeout = atoi(val)) <= 30)
- trace(TRACE_FATAL, "SetConfigItems(): value for TIMEOUT is invalid: [%d]", config->timeout);
+ /* read items: TIMEOUT */
+ GetConfigValue("TIMEOUT", items, val);
+ if (strlen(val) == 0) {
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for TIMEOUT in config file");
+ config->timeout = 0;
+ } else if ((config->timeout = atoi(val)) <= 30)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for TIMEOUT is invalid: [%d]",
+ config->timeout);
- trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds", config->timeout);
+ trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds",
+ config->timeout);
- /* read items: PORT */
- GetConfigValue("PORT", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for PORT in config file");
+ /* read items: PORT */
+ GetConfigValue("PORT", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for PORT in config file");
- if ( (config->port = atoi(val)) <= 0)
- trace(TRACE_FATAL, "SetConfigItems(): value for PORT is invalid: [%d]", config->port);
+ if ((config->port = atoi(val)) <= 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): value for PORT is invalid: [%d]",
+ config->port);
- trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]", config->port);
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]",
+ config->port);
- /* read items: BINDIP */
- GetConfigValue("BINDIP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for BINDIP in config file");
+ /* read items: BINDIP */
+ GetConfigValue("BINDIP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for BINDIP in config file");
- strncpy(config->ip, val, IPLEN);
- config->ip[IPLEN-1] = '\0';
+ strncpy(config->ip, val, IPLEN);
+ config->ip[IPLEN - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]", config->ip);
+ trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]",
+ config->ip);
- /* read items: RESOLVE_IP */
- GetConfigValue("RESOLVE_IP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for RESOLVE_IP in config file");
+ /* read items: RESOLVE_IP */
+ GetConfigValue("RESOLVE_IP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for RESOLVE_IP in config file");
- config->resolveIP = (strcasecmp(val, "yes") == 0);
+ config->resolveIP = (strcasecmp(val, "yes") == 0);
- trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP", config->resolveIP ? "" : "not ");
+ trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP",
+ config->resolveIP ? "" : "not ");
- /* read items: IMAP-BEFORE-SMTP */
- GetConfigValue("TIMS_BEFORE_SMTP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMS_BEFORE_SMTP in config file");
+ /* read items: IMAP-BEFORE-SMTP */
+ GetConfigValue("TIMS_BEFORE_SMTP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): no value for TIMS_BEFORE_SMTP in config file");
- tims_before_smtp = (strcasecmp(val, "yes") == 0);
+ tims_before_smtp = (strcasecmp(val, "yes") == 0);
- trace(TRACE_DEBUG, "SetConfigItems(): %s TIMS-before-SMTP",
- tims_before_smtp ? "Enabling" : "Disabling");
+ trace(TRACE_DEBUG, "SetConfigItems(): %s TIMS-before-SMTP",
+ tims_before_smtp ? "Enabling" : "Disabling");
- /* read items: EFFECTIVE-USER */
- GetConfigValue("EFFECTIVE_USER", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_USER in config file");
+ /* read items: EFFECTIVE-USER */
+ GetConfigValue("EFFECTIVE_USER", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_USER in config file");
- strncpy(config->serverUser, val, FIELDSIZE);
- config->serverUser[FIELDSIZE-1] = '\0';
+ strncpy(config->serverUser, val, FIELDSIZE);
+ config->serverUser[FIELDSIZE - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): effective user shall be [%s]", config->serverUser);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective user shall be [%s]",
+ config->serverUser);
- /* read items: EFFECTIVE-GROUP */
- GetConfigValue("EFFECTIVE_GROUP", items, val);
- if (strlen(val) == 0)
- trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
+ /* read items: EFFECTIVE-GROUP */
+ GetConfigValue("EFFECTIVE_GROUP", items, val);
+ if (strlen(val) == 0)
+ trace(TRACE_FATAL,
+ "SetConfigItems(): no value for EFFECTIVE_GROUP in config file");
- strncpy(config->serverGroup, val, FIELDSIZE);
- config->serverGroup[FIELDSIZE-1] = '\0';
+ strncpy(config->serverGroup, val, FIELDSIZE);
+ config->serverGroup[FIELDSIZE - 1] = '\0';
- trace(TRACE_DEBUG, "SetConfigItems(): effective group shall be [%s]", config->serverGroup);
+ trace(TRACE_DEBUG,
+ "SetConfigItems(): effective group shall be [%s]",
+ config->serverGroup);
diff --git a/user.c b/user.c
index f272e30c..397b73ba 100644
--- a/user.c
+++ b/user.c
@@ -48,18 +48,18 @@ char *configFile = DEFAULT_CONFIG_FILE;
#define SHADOWFILE "/etc/shadow"
-char *getToken(char** str,const char* delims);
+char *getToken(char **str, const char *delims);
char csalt[] = "........";
-char *bgetpwent (char *filename, char *name);
+char *bgetpwent(char *filename, char *name);
char *cget_salt(void);
/* database login data */
extern db_param_t _db_params;
/* valid characters for passwd/username */
-const char ValidChars[] =
-"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
-"_.!@#$%^&*()-+=~[]{}<>:;\\/";
+const char ValidChars[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
+ "_.!@#$%^&*()-+=~[]{}<>:;\\/";
void show_help(void);
int quiet = 0;
@@ -78,77 +78,87 @@ int is_valid(const char *name);
int main(int argc, char *argv[])
{
- struct list sysItems;
- int result;
- int argidx = 0;
-
- openlog(PNAME, LOG_PID, LOG_MAIL);
-
- setvbuf(stdout,0,_IONBF,0);
-
- if (argc<2)
- {
- show_help();
- return 0;
- }
-
- if (strcasecmp(argv[1], "quiet") == 0)
- {
- if (argc < 3)
- {
- show_help();
- return 0;
+ struct list sysItems;
+ int result;
+ int argidx = 0;
+
+ openlog(PNAME, LOG_PID, LOG_MAIL);
+
+ setvbuf(stdout, 0, _IONBF, 0);
+
+ if (argc < 2) {
+ show_help();
+ return 0;
+ }
+
+ if (strcasecmp(argv[1], "quiet") == 0) {
+ if (argc < 3) {
+ show_help();
+ return 0;
+ }
+
+ quiet = 1;
+ argidx = 1;
+ }
+
+ ReadConfig("DBMAIL", configFile, &sysItems);
+ SetTraceLevel(&sysItems);
+ GetDBParams(&_db_params, &sysItems);
+
+ quiet_printf("\n*** dbmail-adduser ***\n");
+
+ /* open database connection */
+ quiet_printf("Opening connection to database...\n");
+ if (db_connect() != 0) {
+ quiet_printf
+ ("Failed. Could not connect to database (check log)\n");
+ return -1;
}
- quiet = 1;
- argidx = 1;
- }
-
- ReadConfig("DBMAIL", configFile, &sysItems);
- SetTraceLevel(&sysItems);
- GetDBParams(&_db_params, &sysItems);
-
- quiet_printf ("\n*** dbmail-adduser ***\n");
-
- /* open database connection */
- quiet_printf ("Opening connection to database...\n");
- if (db_connect() != 0)
- {
- quiet_printf ("Failed. Could not connect to database (check log)\n");
- return -1;
- }
-
- /* open authentication connection */
- quiet_printf ("Opening connection to authentication...\n");
- if (auth_connect() != 0)
- {
- quiet_printf ("Failed. Could not connect to authentication (check log)\n");
- return -1;
- }
-
- quiet_printf ("Ok. Connected\n");
- configure_debug(TRACE_ERROR, 1, 0);
-
- switch (argv[argidx+1][0])
- {
- case 'a': result = do_add(argc- (2+argidx),&argv[2+argidx]); break;
- case 'c': result = do_change(&argv[2+argidx]); break;
- case 'd': result = do_delete(argv[2+argidx]); break;
- case 's': result = do_show(argv[2+argidx]); break;
- case 'f': result = do_make_alias(&argv[2+argidx]); break;
- case 'x': result = do_remove_alias(&argv[2+argidx]); break;
- case 'e': result = do_empty(argv[2+argidx]); break;
- default:
- show_help();
- db_disconnect();
- auth_disconnect();
- return 0;
- }
-
-
- db_disconnect();
- auth_disconnect();
- return result;
+ /* open authentication connection */
+ quiet_printf("Opening connection to authentication...\n");
+ if (auth_connect() != 0) {
+ quiet_printf
+ ("Failed. Could not connect to authentication (check log)\n");
+ return -1;
+ }
+
+ quiet_printf("Ok. Connected\n");
+ configure_debug(TRACE_ERROR, 1, 0);
+
+ switch (argv[argidx + 1][0]) {
+ case 'a':
+ result = do_add(argc - (2 + argidx), &argv[2 + argidx]);
+ break;
+ case 'c':
+ result = do_change(&argv[2 + argidx]);
+ break;
+ case 'd':
+ result = do_delete(argv[2 + argidx]);
+ break;
+ case 's':
+ result = do_show(argv[2 + argidx]);
+ break;
+ case 'f':
+ result = do_make_alias(&argv[2 + argidx]);
+ break;
+ case 'x':
+ result = do_remove_alias(&argv[2 + argidx]);
+ break;
+ case 'e':
+ result = do_empty(argv[2 + argidx]);
+ break;
+ default:
+ show_help();
+ db_disconnect();
+ auth_disconnect();
+ return 0;
+ }
+
+
+ db_disconnect();
+ auth_disconnect();
+ return result;
}
@@ -158,560 +168,579 @@ int main(int argc, char *argv[])
*/
int do_make_alias(char *argv[])
{
- int result;
+ int result;
- if (!argv[0] || !argv[1])
- {
- quiet_printf ("invalid arguments specified. Check the man page\n");
- return -1;
- }
+ if (!argv[0] || !argv[1]) {
+ quiet_printf
+ ("invalid arguments specified. Check the man page\n");
+ return -1;
+ }
- quiet_printf("Adding alias [%s] --> [%s]...", argv[0], argv[1]);
- switch ( (result = db_addalias_ext(argv[0], argv[1], 0)) )
- {
- case -1:
- quiet_printf("Failed\n\nCheck logs for details\n\n");
- break;
+ quiet_printf("Adding alias [%s] --> [%s]...", argv[0], argv[1]);
+ switch ((result = db_addalias_ext(argv[0], argv[1], 0))) {
+ case -1:
+ quiet_printf("Failed\n\nCheck logs for details\n\n");
+ break;
- case 0:
- quiet_printf("Ok alias added\n");
- break;
+ case 0:
+ quiet_printf("Ok alias added\n");
+ break;
- case 1:
- quiet_printf("Already exists. no extra alias added\n");
- result = -1; /* return error */
- break;
+ case 1:
+ quiet_printf("Already exists. no extra alias added\n");
+ result = -1; /* return error */
+ break;
- }
+ }
- return result;
+ return result;
}
int do_remove_alias(char *argv[])
{
- if (!argv[0] || !argv[1])
- {
- quiet_printf ("invalid arguments specified. Check the man page\n");
- return -1;
- }
-
- quiet_printf("Removing alias [%s] --> [%s]...", argv[0], argv[1]);
- if (db_removealias_ext(argv[0], argv[1]) != 0)
- {
- quiet_printf("Failed\n\nCheck logs for details\n\n");
- return -1;
- }
-
- quiet_printf("Ok alias removed\n");
- return 0;
+ if (!argv[0] || !argv[1]) {
+ quiet_printf
+ ("invalid arguments specified. Check the man page\n");
+ return -1;
+ }
+
+ quiet_printf("Removing alias [%s] --> [%s]...", argv[0], argv[1]);
+ if (db_removealias_ext(argv[0], argv[1]) != 0) {
+ quiet_printf("Failed\n\nCheck logs for details\n\n");
+ return -1;
+ }
+
+ quiet_printf("Ok alias removed\n");
+ return 0;
}
int do_add(int argc, char *argv[])
{
- u64_t useridnr;
- int add_user_result;
- int i, result;
- char pw[50]="";
-
- if (argc < 4)
- {
- quiet_printf ("invalid number of options specified. Check the man page\n");
- return -1;
- }
-
- if (!is_valid(argv[0]))
- {
- quiet_printf("Error: invalid characters in username [%s] encountered\n",argv[0]);
- return -1;
- }
-
- quiet_printf ("Adding user %s with password %s, %s bytes mailbox limit and clientid %s...",
- argv[0], argv[1], argv[3], argv[2]);
-
- /* check if we need to encrypt this pwd */
- if (strncasecmp(argv[1], "{crypt:}", strlen("{crypt:}")) == 0)
- {
- /* encrypt using crypt() */
- strcat(pw,crypt(&argv[1][strlen("{crypt:}")], cget_salt()));
- add_user_result = auth_adduser(argv[0], pw, "crypt",
- argv[2],argv[3], &useridnr);
- }
- else if (strncasecmp(argv[1], "{crypt}", strlen("{crypt}")) == 0)
- {
- /* assume passwd is encrypted on command line */
- add_user_result = auth_adduser(argv[0], &argv[1][strlen("{crypt}")],
- "crypt",argv[2],argv[3], &useridnr);
- }
- else if (strncasecmp(argv[1], "{md5:}", strlen("{md5:}")) == 0)
- {
- /* encrypt using md5 crypt() */
- sprintf(pw,"%s%s%s","$1$",cget_salt(),"$");
- strncpy(pw,crypt(&argv[1][strlen("{md5:}")], pw),49);
- add_user_result = auth_adduser(argv[0], pw, "md5",
- argv[2],argv[3], &useridnr);
- }
- else if (strncasecmp(argv[1], "{md5}", strlen("{md5}")) == 0)
- {
- /* assume passwd is encrypted on command line */
- add_user_result = auth_adduser(argv[0], &argv[1][strlen("{md5}")],
- "md5",argv[2],argv[3], &useridnr);
- }
- else if (strncasecmp(argv[1], "{md5sum:}", strlen("{md5sum:}")) == 0)
- {
- /* encrypt using md5 digest */
- strcat(pw,makemd5(&argv[1][strlen("{md5sum:}")]));
- add_user_result = auth_adduser(argv[0], pw, "md5sum",argv[2],
- argv[3], &useridnr);
- }
- else if (strncasecmp(argv[1], "{md5sum}", strlen("{md5sum}")) == 0)
- {
- /* assume passwd is encrypted on command line */
- add_user_result = auth_adduser(argv[0], &argv[1][strlen("{md5sum}")],
- "md5sum",argv[2],argv[3], &useridnr);
- }
- else
- {
- add_user_result = auth_adduser(argv[0],argv[1],"",
- argv[2],argv[3], &useridnr);
- }
-
- if (add_user_result == -1) {
- /* check if existance of another user with the same name caused
- the failure */
- if (auth_user_exists(argv[0], &useridnr) == -1) {
- quiet_printf("Failed\n\nCheck logs for details\n\n");
- return -1; /* database failure */
- }
- if (useridnr != 0)
- quiet_printf("Failed: user exists [%llu]\n", useridnr);
- else { /* useridnr is 0 ! */
- quiet_printf("Failed\n\nCheck logs for details\n\n");
- useridnr = -1;
- }
- return -1;
- }
-
- quiet_printf ("Ok, user added id [%llu]\n",useridnr);
-
- for (i = 4, result = 0; i<argc; i++)
- {
- quiet_printf ("Adding alias %s...",argv[i]);
- switch ( db_addalias(useridnr,argv[i],atoi(argv[2])) )
- {
- case -1:
- quiet_printf ("Failed\n");
- result = -1;
- break;
-
- case 0:
- quiet_printf ("Ok, added\n");
- break;
+ u64_t useridnr;
+ int add_user_result;
+ int i, result;
+ char pw[50] = "";
+
+ if (argc < 4) {
+ quiet_printf
+ ("invalid number of options specified. Check the man page\n");
+ return -1;
+ }
- case 1:
- quiet_printf("Already exists. No extra alias added\n");
- result = -1;
- break;
+ if (!is_valid(argv[0])) {
+ quiet_printf
+ ("Error: invalid characters in username [%s] encountered\n",
+ argv[0]);
+ return -1;
}
- }
-
- quiet_printf ("adduser done\n");
- if (result != 0)
- quiet_printf("Warning: user added but not all the specified aliases\n");
- return result;
+ quiet_printf
+ ("Adding user %s with password %s, %s bytes mailbox limit and clientid %s...",
+ argv[0], argv[1], argv[3], argv[2]);
+
+ /* check if we need to encrypt this pwd */
+ if (strncasecmp(argv[1], "{crypt:}", strlen("{crypt:}")) == 0) {
+ /* encrypt using crypt() */
+ strcat(pw,
+ crypt(&argv[1][strlen("{crypt:}")], cget_salt()));
+ add_user_result =
+ auth_adduser(argv[0], pw, "crypt", argv[2], argv[3],
+ &useridnr);
+ } else if (strncasecmp(argv[1], "{crypt}", strlen("{crypt}")) == 0) {
+ /* assume passwd is encrypted on command line */
+ add_user_result =
+ auth_adduser(argv[0], &argv[1][strlen("{crypt}")],
+ "crypt", argv[2], argv[3], &useridnr);
+ } else if (strncasecmp(argv[1], "{md5:}", strlen("{md5:}")) == 0) {
+ /* encrypt using md5 crypt() */
+ sprintf(pw, "%s%s%s", "$1$", cget_salt(), "$");
+ strncpy(pw, crypt(&argv[1][strlen("{md5:}")], pw), 49);
+ add_user_result = auth_adduser(argv[0], pw, "md5",
+ argv[2], argv[3],
+ &useridnr);
+ } else if (strncasecmp(argv[1], "{md5}", strlen("{md5}")) == 0) {
+ /* assume passwd is encrypted on command line */
+ add_user_result =
+ auth_adduser(argv[0], &argv[1][strlen("{md5}")], "md5",
+ argv[2], argv[3], &useridnr);
+ } else if (strncasecmp(argv[1], "{md5sum:}", strlen("{md5sum:}"))
+ == 0) {
+ /* encrypt using md5 digest */
+ strcat(pw, makemd5(&argv[1][strlen("{md5sum:}")]));
+ add_user_result =
+ auth_adduser(argv[0], pw, "md5sum", argv[2], argv[3],
+ &useridnr);
+ } else if (strncasecmp(argv[1], "{md5sum}", strlen("{md5sum}")) ==
+ 0) {
+ /* assume passwd is encrypted on command line */
+ add_user_result =
+ auth_adduser(argv[0], &argv[1][strlen("{md5sum}")],
+ "md5sum", argv[2], argv[3], &useridnr);
+ } else {
+ add_user_result = auth_adduser(argv[0], argv[1], "",
+ argv[2], argv[3],
+ &useridnr);
+ }
+
+ if (add_user_result == -1) {
+ /* check if existance of another user with the same name caused
+ the failure */
+ if (auth_user_exists(argv[0], &useridnr) == -1) {
+ quiet_printf
+ ("Failed\n\nCheck logs for details\n\n");
+ return -1; /* database failure */
+ }
+ if (useridnr != 0)
+ quiet_printf("Failed: user exists [%llu]\n",
+ useridnr);
+ else { /* useridnr is 0 ! */
+ quiet_printf
+ ("Failed\n\nCheck logs for details\n\n");
+ useridnr = -1;
+ }
+ return -1;
+ }
+
+ quiet_printf("Ok, user added id [%llu]\n", useridnr);
+
+ for (i = 4, result = 0; i < argc; i++) {
+ quiet_printf("Adding alias %s...", argv[i]);
+ switch (db_addalias(useridnr, argv[i], atoi(argv[2]))) {
+ case -1:
+ quiet_printf("Failed\n");
+ result = -1;
+ break;
+
+ case 0:
+ quiet_printf("Ok, added\n");
+ break;
+
+ case 1:
+ quiet_printf
+ ("Already exists. No extra alias added\n");
+ result = -1;
+ break;
+ }
+ }
+
+ quiet_printf("adduser done\n");
+ if (result != 0)
+ quiet_printf
+ ("Warning: user added but not all the specified aliases\n");
+
+ return result;
}
int do_change(char *argv[])
{
- int i,result = 0, retval=0;
- u64_t newsize,userid,newcid;
- u64_t client_id;
- char *endptr = NULL,*entry = NULL,*passwdfile = NULL;
- char pw[50]="";
-
- /* verify the existence of this user */
- if (auth_user_exists(argv[0], &userid) == -1) {
- quiet_printf("Error verifying existence of user [%s]. Please check the log.\n",argv[0]);
- return -1;
- }
-
- if (userid == 0)
- {
- quiet_printf("Error: user [%s] does not exist.\n",argv[0]);
- return -1;
- }
-
- quiet_printf("Performing changes for user [%s]...",argv[0]);
-
- for (i=1; argv[i]; i++)
- {
- if (argv[i][0] != '-' && argv[i][0] != '+' && argv[i][0] != 'x'
- && argv[i][0] != 'd' && argv[i][0] != 'D')
- {
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
+ int i, result = 0, retval = 0;
+ u64_t newsize, userid, newcid;
+ u64_t client_id;
+ char *endptr = NULL, *entry = NULL, *passwdfile = NULL;
+ char pw[50] = "";
+
+ /* verify the existence of this user */
+ if (auth_user_exists(argv[0], &userid) == -1) {
+ quiet_printf
+ ("Error verifying existence of user [%s]. Please check the log.\n",
+ argv[0]);
+ return -1;
}
-
- switch (argv[i][1])
- {
- case 'u':
- /* change the name */
- if (argv[i][0] != '-')
- {
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
- if (!is_valid(argv[i+1]))
- {
- quiet_printf("\nWarning: username contains invalid characters. Username not updated. ");
- retval = -1;
- }
-
- if (auth_change_username(userid,argv[i+1]) != 0)
- {
- quiet_printf("\nWarning: could not change username ");
- retval = -1;
- }
-
- i++;
- break;
-
- case 'p':
- /* change the password */
- if (!is_valid(argv[i+1]))
- {
- quiet_printf("\nWarning: password contains invalid characters. Password not updated. ");
- retval = -1;
- }
-
- switch (argv[i][0])
- {
- case '+':
- /* +p will convert clear text into crypt hash value */
- strcat(pw,crypt(argv[i+1], cget_salt()));
- result = auth_change_password(userid,pw,"crypt");
- break;
- case '-':
- strncpy(pw,argv[i+1],49);
- result = auth_change_password(userid,pw,"");
- break;
- case 'x':
- /* 'xp' will copy passwd from command line
- assuming that the supplied passwd is crypt encrypted
- */
- strncpy(pw,argv[i+1],49);
- result = auth_change_password(userid,pw,"crypt");
- break;
- default:
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
-
- if (result != 0)
- {
- quiet_printf("\nWarning: could not change password ");
- retval = -1;
- }
-
- i++;
- break;
-
- case '5':
- /* md5 passwords */
- if (!is_valid(argv[i+1]))
- {
- quiet_printf("\nWarning: password contains invalid characters. Password not updated. ");
- retval = -1;
- }
- switch (argv[i][0])
- {
- case '-':
- /* -5 takes a md5 hash and saves it */
- strncpy(pw,argv[i+1],49);
- result = auth_change_password(userid,pw,"md5");
- break;
- case '+':
- /* +5 takes a plaintext password and saves as a md5 hash */
- sprintf(pw,"%s%s%s","$1$",cget_salt(),"$");
- strncpy(pw,crypt(argv[i+1], pw),49);
- result = auth_change_password(userid,pw,"md5");
- break;
- case 'd':
- /* d5 takes a md5 digest and saves it */
- strncpy(pw,argv[i+1],49);
- result = auth_change_password(userid,pw,"md5sum");
- break;
- case 'D':
- /* D5 takes a plaintext password and saves as a md5 digest */
- strncat(pw,makemd5(argv[i+1]),49);
- result = auth_change_password(userid,pw,"md5sum");
- break;
-
- default:
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
-
- if (result != 0)
- {
- quiet_printf("\nWarning: could not change password ");
- retval = -1;
- }
-
- i++;
- break;
-
- case 'P':
- /* -P will copy password from SHADOWFILE */
- /* -P:filename will copy password from filename */
- if (argv[i][0] != '-')
- {
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
- if (argv[i][2] == ':')
- passwdfile = &argv[i][3];
- else
- passwdfile = SHADOWFILE;
-
-
- entry = bgetpwent(passwdfile, argv[0]);
- if (!entry)
- {
- quiet_printf("\nWarning: error finding password from [%s] - are you superuser?\n",
- passwdfile);
- retval = -1;
- break;
- }
-
- strncat(pw,entry,50);
- if ( strcmp(pw, "") == 0 )
- {
- quiet_printf("\n%s's password not found at \"%s\" !\n", argv[0],passwdfile);
- retval = -1;
- }
- else
- {
- if ( strncmp(pw, "$1$", 3) )
- {
- if (auth_change_password(userid,pw,"crypt") != 0)
- {
- quiet_printf("\nWarning: could not change password");
- retval = -1;
- }
- }
- else
- {
- if (auth_change_password(userid,pw,"md5") != 0)
- {
- quiet_printf("\nWarning: could not change password");
- retval = -1;
- }
- }
- }
- break;
- case 'c':
- if (argv[i][0] != '-')
- {
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
-
- newcid = strtoull(argv[i+1], 0, 10);
-
- if (auth_change_clientid(userid, newcid) != 0)
- {
- quiet_printf("\nWarning: could not change client id ");
- retval = -1;
- }
-
- i++;
- break;
-
- case 'q':
- if (argv[i][0] != '-')
- {
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
-
- newsize = strtoull(argv[i+1], &endptr, 10);
- switch (*endptr)
- {
- case 'm':
- case 'M':
- newsize *= (1024 * 1024);
- break;
-
- case 'k':
- case 'K':
- newsize *= 1024;
- break;
- }
-
- if (auth_change_mailboxsize(userid, newsize) != 0)
- {
- quiet_printf("\nWarning: could not change max mailboxsize ");
- retval = -1;
- }
-
- i++;
- break;
-
- case 'a':
- switch (argv[i][0])
- {
- case '-':
- /* remove alias */
- if (db_removealias(userid, argv[i+1]) < 0)
- {
- quiet_printf("\nWarning: could not remove alias [%s] ",argv[i+1]);
- retval = -1;
+ if (userid == 0) {
+ quiet_printf("Error: user [%s] does not exist.\n",
+ argv[0]);
+ return -1;
+ }
+
+ quiet_printf("Performing changes for user [%s]...", argv[0]);
+
+ for (i = 1; argv[i]; i++) {
+ if (argv[i][0] != '-' && argv[i][0] != '+'
+ && argv[i][0] != 'x' && argv[i][0] != 'd'
+ && argv[i][0] != 'D') {
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
}
- break;
- case '+':
- /* add alias */
- auth_getclientid(userid, &client_id);
- if (db_addalias(userid, argv[i+1], client_id) < 0)
- {
- quiet_printf("\nWarning: could not add alias [%s]",argv[i+1]);
- retval = -1;
+
+ switch (argv[i][1]) {
+ case 'u':
+ /* change the name */
+ if (argv[i][0] != '-') {
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+ if (!is_valid(argv[i + 1])) {
+ quiet_printf
+ ("\nWarning: username contains invalid characters. Username not updated. ");
+ retval = -1;
+ }
+
+ if (auth_change_username(userid, argv[i + 1]) != 0) {
+ quiet_printf
+ ("\nWarning: could not change username ");
+ retval = -1;
+ }
+
+ i++;
+ break;
+
+ case 'p':
+ /* change the password */
+ if (!is_valid(argv[i + 1])) {
+ quiet_printf
+ ("\nWarning: password contains invalid characters. Password not updated. ");
+ retval = -1;
+ }
+
+ switch (argv[i][0]) {
+ case '+':
+ /* +p will convert clear text into crypt hash value */
+ strcat(pw,
+ crypt(argv[i + 1], cget_salt()));
+ result =
+ auth_change_password(userid, pw,
+ "crypt");
+ break;
+ case '-':
+ strncpy(pw, argv[i + 1], 49);
+ result =
+ auth_change_password(userid, pw, "");
+ break;
+ case 'x':
+ /* 'xp' will copy passwd from command line
+ assuming that the supplied passwd is crypt encrypted
+ */
+ strncpy(pw, argv[i + 1], 49);
+ result =
+ auth_change_password(userid, pw,
+ "crypt");
+ break;
+ default:
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+
+ if (result != 0) {
+ quiet_printf
+ ("\nWarning: could not change password ");
+ retval = -1;
+ }
+
+ i++;
+ break;
+
+ case '5':
+ /* md5 passwords */
+ if (!is_valid(argv[i + 1])) {
+ quiet_printf
+ ("\nWarning: password contains invalid characters. Password not updated. ");
+ retval = -1;
+ }
+ switch (argv[i][0]) {
+ case '-':
+ /* -5 takes a md5 hash and saves it */
+ strncpy(pw, argv[i + 1], 49);
+ result =
+ auth_change_password(userid, pw,
+ "md5");
+ break;
+ case '+':
+ /* +5 takes a plaintext password and saves as a md5 hash */
+ sprintf(pw, "%s%s%s", "$1$", cget_salt(),
+ "$");
+ strncpy(pw, crypt(argv[i + 1], pw), 49);
+ result =
+ auth_change_password(userid, pw,
+ "md5");
+ break;
+ case 'd':
+ /* d5 takes a md5 digest and saves it */
+ strncpy(pw, argv[i + 1], 49);
+ result =
+ auth_change_password(userid, pw,
+ "md5sum");
+ break;
+ case 'D':
+ /* D5 takes a plaintext password and saves as a md5 digest */
+ strncat(pw, makemd5(argv[i + 1]), 49);
+ result =
+ auth_change_password(userid, pw,
+ "md5sum");
+ break;
+
+ default:
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+
+ if (result != 0) {
+ quiet_printf
+ ("\nWarning: could not change password ");
+ retval = -1;
+ }
+
+ i++;
+ break;
+
+ case 'P':
+ /* -P will copy password from SHADOWFILE */
+ /* -P:filename will copy password from filename */
+ if (argv[i][0] != '-') {
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+ if (argv[i][2] == ':')
+ passwdfile = &argv[i][3];
+ else
+ passwdfile = SHADOWFILE;
+
+
+ entry = bgetpwent(passwdfile, argv[0]);
+ if (!entry) {
+ quiet_printf
+ ("\nWarning: error finding password from [%s] - are you superuser?\n",
+ passwdfile);
+ retval = -1;
+ break;
+ }
+
+ strncat(pw, entry, 50);
+ if (strcmp(pw, "") == 0) {
+ quiet_printf
+ ("\n%s's password not found at \"%s\" !\n",
+ argv[0], passwdfile);
+ retval = -1;
+ } else {
+ if (strncmp(pw, "$1$", 3)) {
+ if (auth_change_password
+ (userid, pw, "crypt") != 0) {
+ quiet_printf
+ ("\nWarning: could not change password");
+ retval = -1;
+ }
+ } else {
+ if (auth_change_password
+ (userid, pw, "md5") != 0) {
+ quiet_printf
+ ("\nWarning: could not change password");
+ retval = -1;
+ }
+ }
+ }
+ break;
+
+ case 'c':
+ if (argv[i][0] != '-') {
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+
+ newcid = strtoull(argv[i + 1], 0, 10);
+
+ if (auth_change_clientid(userid, newcid) != 0) {
+ quiet_printf
+ ("\nWarning: could not change client id ");
+ retval = -1;
+ }
+
+ i++;
+ break;
+
+ case 'q':
+ if (argv[i][0] != '-') {
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+
+ newsize = strtoull(argv[i + 1], &endptr, 10);
+ switch (*endptr) {
+ case 'm':
+ case 'M':
+ newsize *= (1024 * 1024);
+ break;
+
+ case 'k':
+ case 'K':
+ newsize *= 1024;
+ break;
+ }
+
+ if (auth_change_mailboxsize(userid, newsize) != 0) {
+ quiet_printf
+ ("\nWarning: could not change max mailboxsize ");
+ retval = -1;
+ }
+
+ i++;
+ break;
+
+ case 'a':
+ switch (argv[i][0]) {
+ case '-':
+ /* remove alias */
+ if (db_removealias(userid, argv[i + 1]) <
+ 0) {
+ quiet_printf
+ ("\nWarning: could not remove alias [%s] ",
+ argv[i + 1]);
+ retval = -1;
+ }
+ break;
+ case '+':
+ /* add alias */
+ auth_getclientid(userid, &client_id);
+ if (db_addalias
+ (userid, argv[i + 1], client_id) < 0) {
+ quiet_printf
+ ("\nWarning: could not add alias [%s]",
+ argv[i + 1]);
+ retval = -1;
+ }
+ break;
+ default:
+ quiet_printf
+ ("Failed: invalid option specified. Check the man page\n");
+ return -1;
+ }
+ i++;
+ break;
+
+ default:
+ quiet_printf
+ ("invalid option specified. Check the man page\n");
+ return -1;
}
- break;
- default:
- quiet_printf ("Failed: invalid option specified. Check the man page\n");
- return -1;
- }
- i++;
- break;
- default:
- quiet_printf ("invalid option specified. Check the man page\n");
- return -1;
}
-
- }
- quiet_printf("Done\n");
+ quiet_printf("Done\n");
- return retval;
+ return retval;
}
int do_delete(char *name)
{
- int result;
+ int result;
- quiet_printf("Deleting user [%s]...",name);
+ quiet_printf("Deleting user [%s]...", name);
- result = auth_delete_user(name);
+ result = auth_delete_user(name);
- if (result < 0)
- {
- quiet_printf("Failed. Please check the log\n");
- return -1;
- }
+ if (result < 0) {
+ quiet_printf("Failed. Please check the log\n");
+ return -1;
+ }
- quiet_printf("Done\n");
- return 0;
+ quiet_printf("Done\n");
+ return 0;
}
int do_show(char *name)
{
- u64_t userid,cid,quotum,quotumused;
- struct list userlist;
- struct element *tmp;
- char *deliver_to;
-
- if (!name)
- {
- /* show all users */
- quiet_printf("Existing users:\n");
-
- auth_get_known_users(&userlist);
-
- tmp = list_getstart(&userlist);
- while (tmp)
- {
- quiet_printf("[%s]\n", (char*)tmp->data);
- tmp = tmp->nextnode;
- }
+ u64_t userid, cid, quotum, quotumused;
+ struct list userlist;
+ struct element *tmp;
+ char *deliver_to;
- if (userlist.start)
- list_freelist(&userlist.start);
- }
- else
- {
- quiet_printf("Info for user [%s]",name);
-
- if (auth_user_exists(name, &userid) == -1) {
- quiet_printf("\nError verifying existence of user [%s]. Please check the log.\n",name);
- return -1;
- }
-
- if (userid == 0)
- {
- /* 'name' is not a user, try it as an alias */
- quiet_printf("..is not a user, trying as an alias");
-
- deliver_to = db_get_deliver_from_alias(name);
-
- if (!deliver_to)
- {
- quiet_printf("\nError verifying existence of alias [%s]. Please check the log.\n",name);
- return -1;
- }
-
- if (deliver_to[0] == '\0')
- {
- quiet_printf("..is not an alias.\n");
- return 0;
- }
-
- userid = strtoul(deliver_to, NULL, 10);
- if (userid == 0)
- {
- quiet_printf("\n[%s] is an alias for [%s]\n", name, deliver_to);
- my_free(deliver_to);
- return 0;
- }
-
- my_free(deliver_to);
- quiet_printf("\nFound user for alias [%s]:\n\n", name);
- }
+ if (!name) {
+ /* show all users */
+ quiet_printf("Existing users:\n");
- auth_getclientid(userid, &cid);
- auth_getmaxmailsize(userid, &quotum);
- db_get_quotum_used(userid, &quotumused);
-
- quiet_printf("\n");
- quiet_printf("User ID : %llu\n", userid);
- quiet_printf("Username : %s\n", auth_get_userid(userid));
- quiet_printf("Client ID : %llu\n",cid);
- quiet_printf("Max. mailboxsize: %.02f MB\n",(double)quotum/(1024.0*1024.0));
- quiet_printf("Quotum used : %.02f MB (%.01f%%)\n", (double)quotumused/(1024.0*1024.0),
- (100.0 * quotumused)/(double)quotum);
- quiet_printf("\n");
-
- quiet_printf("Aliases:\n");
- db_get_user_aliases(userid, &userlist);
-
- tmp = list_getstart(&userlist);
- while (tmp)
- {
- quiet_printf("%s\n",(char*)tmp->data);
- tmp = tmp->nextnode;
- }
+ auth_get_known_users(&userlist);
+
+ tmp = list_getstart(&userlist);
+ while (tmp) {
+ quiet_printf("[%s]\n", (char *) tmp->data);
+ tmp = tmp->nextnode;
+ }
+
+ if (userlist.start)
+ list_freelist(&userlist.start);
+ } else {
+ quiet_printf("Info for user [%s]", name);
+
+ if (auth_user_exists(name, &userid) == -1) {
+ quiet_printf
+ ("\nError verifying existence of user [%s]. Please check the log.\n",
+ name);
+ return -1;
+ }
- quiet_printf("\n");
- if (userlist.start)
- list_freelist(&userlist.start);
- }
+ if (userid == 0) {
+ /* 'name' is not a user, try it as an alias */
+ quiet_printf
+ ("..is not a user, trying as an alias");
+
+ deliver_to = db_get_deliver_from_alias(name);
+
+ if (!deliver_to) {
+ quiet_printf
+ ("\nError verifying existence of alias [%s]. Please check the log.\n",
+ name);
+ return -1;
+ }
+
+ if (deliver_to[0] == '\0') {
+ quiet_printf("..is not an alias.\n");
+ return 0;
+ }
+
+ userid = strtoul(deliver_to, NULL, 10);
+ if (userid == 0) {
+ quiet_printf
+ ("\n[%s] is an alias for [%s]\n", name,
+ deliver_to);
+ my_free(deliver_to);
+ return 0;
+ }
+
+ my_free(deliver_to);
+ quiet_printf("\nFound user for alias [%s]:\n\n",
+ name);
+ }
+
+ auth_getclientid(userid, &cid);
+ auth_getmaxmailsize(userid, &quotum);
+ db_get_quotum_used(userid, &quotumused);
+
+ quiet_printf("\n");
+ quiet_printf("User ID : %llu\n", userid);
+ quiet_printf("Username : %s\n",
+ auth_get_userid(userid));
+ quiet_printf("Client ID : %llu\n", cid);
+ quiet_printf("Max. mailboxsize: %.02f MB\n",
+ (double) quotum / (1024.0 * 1024.0));
+ quiet_printf("Quotum used : %.02f MB (%.01f%%)\n",
+ (double) quotumused / (1024.0 * 1024.0),
+ (100.0 * quotumused) / (double) quotum);
+ quiet_printf("\n");
+
+ quiet_printf("Aliases:\n");
+ db_get_user_aliases(userid, &userlist);
+
+ tmp = list_getstart(&userlist);
+ while (tmp) {
+ quiet_printf("%s\n", (char *) tmp->data);
+ tmp = tmp->nextnode;
+ }
+
+ quiet_printf("\n");
+ if (userlist.start)
+ list_freelist(&userlist.start);
+ }
- return 0;
+ return 0;
}
@@ -720,125 +749,127 @@ int do_show(char *name)
*/
int do_empty(char *name)
{
- u64_t userid;
- int result;
-
- if (auth_user_exists(name, &userid) == -1) {
- quiet_printf("Error verifying existence of user [%s]. "
- "Please check the log.\n",name);
- return -1;
- }
-
- if (userid == 0)
- {
- quiet_printf("User [%s] does not exist.\n", name);
- return -1;
- }
-
- quiet_printf("Emptying mailbox..."); fflush(stdout);
-
- result = db_empty_mailbox(userid);
- if (result != 0)
- quiet_printf("Error. Please check the log.\n",name);
- else
- quiet_printf("Ok.\n");
-
- return result;
+ u64_t userid;
+ int result;
+
+ if (auth_user_exists(name, &userid) == -1) {
+ quiet_printf("Error verifying existence of user [%s]. "
+ "Please check the log.\n", name);
+ return -1;
+ }
+
+ if (userid == 0) {
+ quiet_printf("User [%s] does not exist.\n", name);
+ return -1;
+ }
+
+ quiet_printf("Emptying mailbox...");
+ fflush(stdout);
+
+ result = db_empty_mailbox(userid);
+ if (result != 0)
+ quiet_printf("Error. Please check the log.\n", name);
+ else
+ quiet_printf("Ok.\n");
+
+ return result;
}
int is_valid(const char *name)
{
- int i;
-
- for (i=0; name[i]; i++)
- if (strchr(ValidChars, name[i]) == NULL)
- return 0;
+ int i;
+
+ for (i = 0; name[i]; i++)
+ if (strchr(ValidChars, name[i]) == NULL)
+ return 0;
- return 1;
+ return 1;
}
void show_help()
{
- printf ("\n*** dbmail-adduser ***\n");
-
- printf("Use this program to manage the users for your dbmail system.\n");
- printf("See the man page for more info. Summary:\n\n");
- printf("dbmail-adduser [quiet] <a|d|c|s|f|x|e> [username] [options...]\n\n");
+ printf("\n*** dbmail-adduser ***\n");
+
+ printf
+ ("Use this program to manage the users for your dbmail system.\n");
+ printf("See the man page for more info. Summary:\n\n");
+ printf
+ ("dbmail-adduser [quiet] <a|d|c|s|f|x|e> [username] [options...]\n\n");
}
int quiet_printf(const char *fmt, ...)
{
- va_list argp;
- int r;
+ va_list argp;
+ int r;
- if (quiet)
- return 0;
-
- va_start(argp, fmt);
- r = vprintf(fmt, argp);
- va_end(argp);
+ if (quiet)
+ return 0;
- return r;
+ va_start(argp, fmt);
+ r = vprintf(fmt, argp);
+ va_end(argp);
+
+ return r;
}
-
+
/*eddy
This two function was base from "cpu" by Blake Matheny <matheny@dbaseiv.net>
bgetpwent : get hash password from /etc/shadow
cget_salt : generate salt value for crypt
*/
-char *bgetpwent(char *filename, char *name)
+char *bgetpwent(char *filename, char *name)
{
- FILE *passfile = NULL;
- char pass_char[512];
- int pass_size = 511;
- char *pw = NULL;
- char *user = NULL;
-
- if ((passfile = fopen(filename, "r")) == NULL)
- return NULL;
-
- while (fgets(pass_char, pass_size, passfile) != NULL) {
- char *m = pass_char;
- int num_tok = 0;
- char *toks;
-
- while (m != NULL && *m != 0) {
- toks = getToken(&m, ":");
- if (num_tok == 0)
- user = toks;
- else if (num_tok == 1)
- /*result->pw_passwd = toks;*/
- pw = toks;
- else
- break;
- num_tok++;
- }
- if (strcmp(user, name) == 0)
- return pw;
-
- }
- return "";
+ FILE *passfile = NULL;
+ char pass_char[512];
+ int pass_size = 511;
+ char *pw = NULL;
+ char *user = NULL;
+
+ if ((passfile = fopen(filename, "r")) == NULL)
+ return NULL;
+
+ while (fgets(pass_char, pass_size, passfile) != NULL) {
+ char *m = pass_char;
+ int num_tok = 0;
+ char *toks;
+
+ while (m != NULL && *m != 0) {
+ toks = getToken(&m, ":");
+ if (num_tok == 0)
+ user = toks;
+ else if (num_tok == 1)
+ /*result->pw_passwd = toks; */
+ pw = toks;
+ else
+ break;
+ num_tok++;
+ }
+ if (strcmp(user, name) == 0)
+ return pw;
+
+ }
+ return "";
}
char *cget_salt()
{
- unsigned long seed[2];
- const char *const seedchars =
- "./0123456789ABCDEFGHIJKLMNOPQRST"
- "UVWXYZabcdefghijklmnopqrstuvwxyz";
- int i;
-
- seed[0] = time(NULL);
- seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
- for (i = 0; i < 8; i++)
- csalt[i] = seedchars[(seed[i / 5] >> (i % 5) * 6) & 0x3f];
-
- return csalt;
+ unsigned long seed[2];
+ const char *const seedchars =
+ "./0123456789ABCDEFGHIJKLMNOPQRST"
+ "UVWXYZabcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ seed[0] = time(NULL);
+ seed[1] = getpid() ^ (seed[0] >> 14 & 0x30000);
+ for (i = 0; i < 8; i++)
+ csalt[i] = seedchars[(seed[i / 5] >> (i % 5) * 6) & 0x3f];
+
+ return csalt;
}
@@ -847,28 +878,26 @@ char *cget_salt()
by Blake Matheny <matheny@dbaseiv.net>
getToken : break down username and password from a file
*/
-char *getToken(char** str,const char* delims)
+char *getToken(char **str, const char *delims)
{
- char* token;
-
- if (*str==NULL)
- {
- /* No more tokens */
- return NULL;
- }
-
- token=*str;
- while (**str!='\0')
- {
- if (strchr(delims,**str)!=NULL) {
- **str='\0';
- (*str)++;
- return token;
- }
- (*str)++;
- }
+ char *token;
+
+ if (*str == NULL) {
+ /* No more tokens */
+ return NULL;
+ }
- /* There is no other token */
- *str=NULL;
- return token;
+ token = *str;
+ while (**str != '\0') {
+ if (strchr(delims, **str) != NULL) {
+ **str = '\0';
+ (*str)++;
+ return token;
+ }
+ (*str)++;
+ }
+
+ /* There is no other token */
+ *str = NULL;
+ return token;
}
diff --git a/user.h b/user.h
index 7aeb87a5..639bdadc 100644
--- a/user.h
+++ b/user.h
@@ -25,4 +25,3 @@
#endif
#define PNAME "dbmail/adduser"
-
diff --git a/vut2dbmail.c b/vut2dbmail.c
index 8cea3d80..0615853a 100644
--- a/vut2dbmail.c
+++ b/vut2dbmail.c
@@ -46,145 +46,139 @@ int process_piece(char *left, char *right);
int main(void)
{
- int i,result;
- char *left, *right, *tmp;
-
- if (db_connect() != 0)
- {
- fprintf(stderr, "Could not connect to database\n");
- return 1;
- }
-
- if (auth_connect() != 0)
- {
- fprintf(stderr, "Could not connect to authentication\n");
- db_disconnect();
- return 1;
- }
-
- do
- {
- fgets(line, MAXLINESIZE, stdin);
-
- if (ferror(stdin) || feof(stdin))
- break;
-
- if (line[0] != '#' && line[0] != '\n' && line[0])
- {
- line[strlen(line)-1] = 0; /* remove trailing space */
-
- /* get left part of entry */
- for (i=0; line[i] && !isspace(line[i]); i++) ;
-
- if (!line[i] || line[i] == '\n')
- {
- if (i > 0)
- {
- fprintf(stderr, "Found [%*s], don't know what to do with it\n",
- i-1, line);
- }
- continue;
- }
+ int i, result;
+ char *left, *right, *tmp;
- line[i] = 0;
- left = line;
+ if (db_connect() != 0) {
+ fprintf(stderr, "Could not connect to database\n");
+ return 1;
+ }
- while (isspace(line[++i])) ;
+ if (auth_connect() != 0) {
+ fprintf(stderr, "Could not connect to authentication\n");
+ db_disconnect();
+ return 1;
+ }
- right = &line[i];
+ do {
+ fgets(line, MAXLINESIZE, stdin);
- do
- {
- tmp = strchr(right, ','); /* find delimiter */
+ if (ferror(stdin) || feof(stdin))
+ break;
- if (tmp)
- *tmp = 0; /* end string on delimiter position */
+ if (line[0] != '#' && line[0] != '\n' && line[0]) {
+ line[strlen(line) - 1] = 0; /* remove trailing space */
- if ((result = process_piece(left, right)) < 0)
- {
- if (result == -1)
- {
- fprintf(stderr, "Error processing [%s] [%s]\n",left,right);
- }
- }
+ /* get left part of entry */
+ for (i = 0; line[i] && !isspace(line[i]); i++);
- if (tmp)
- {
- right = tmp+1;
- while (isspace(*right)) right++;
- }
- } while (tmp && *right);
+ if (!line[i] || line[i] == '\n') {
+ if (i > 0) {
+ fprintf(stderr,
+ "Found [%*s], don't know what to do with it\n",
+ i - 1, line);
+ }
+ continue;
+ }
- }
- } while (!feof(stdin) && !ferror(stdin));
+ line[i] = 0;
+ left = line;
+
+ while (isspace(line[++i]));
+
+ right = &line[i];
+
+ do {
+ tmp = strchr(right, ','); /* find delimiter */
+
+ if (tmp)
+ *tmp = 0; /* end string on delimiter position */
+
+ if ((result =
+ process_piece(left, right)) < 0) {
+ if (result == -1) {
+ fprintf(stderr,
+ "Error processing [%s] [%s]\n",
+ left, right);
+ }
+ }
- /* ok everything inserted.
- *
- * the alias table should be cleaned up now..
- */
+ if (tmp) {
+ right = tmp + 1;
+ while (isspace(*right))
+ right++;
+ }
+ } while (tmp && *right);
- db_disconnect();
- auth_disconnect();
- return 0;
+ }
+ } while (!feof(stdin) && !ferror(stdin));
+
+ /* ok everything inserted.
+ *
+ * the alias table should be cleaned up now..
+ */
+
+ db_disconnect();
+ auth_disconnect();
+ return 0;
}
-
+
int process_piece(char *left, char *right)
{
- u64_t useridnr,clientidnr;
-
- /* check what right contains:
- * username or email address
- */
-
- if (strchr(right, '@') || strchr(right,'|'))
- {
- /* email
- * add this alias if it doesn't already exist
- */
-
- if (db_addalias_ext(left, right, 0) == -1)
- return -1;
-
- printf("alias [%s] --> [%s] created\n",left,right);
- return 0;
- }
- else
- {
- /* username
- * check if this user exists
- */
-
- if (auth_user_exists(right, &useridnr) < -1)
- return -1;
-
- if (useridnr == 0)
- {
- /* new user */
- if (auth_adduser(right, "geheim", "", "0", "0", &useridnr) == -1)
- {
- fprintf(stderr,"Could not add user [%s]\n",right);
- return -1;
- }
- }
+ u64_t useridnr, clientidnr;
+
+ /* check what right contains:
+ * username or email address
+ */
+
+ if (strchr(right, '@') || strchr(right, '|')) {
+ /* email
+ * add this alias if it doesn't already exist
+ */
+
+ if (db_addalias_ext(left, right, 0) == -1)
+ return -1;
+
+ printf("alias [%s] --> [%s] created\n", left, right);
+ return 0;
+ } else {
+ /* username
+ * check if this user exists
+ */
+
+ if (auth_user_exists(right, &useridnr) < -1)
+ return -1;
+
+ if (useridnr == 0) {
+ /* new user */
+ if (auth_adduser
+ (right, "geheim", "", "0", "0",
+ &useridnr) == -1) {
+ fprintf(stderr,
+ "Could not add user [%s]\n",
+ right);
+ return -1;
+ }
+ }
- /* this user now exists, add alias */
- if ( auth_getclientid(useridnr, &clientidnr) == -1)
- {
- fprintf(stderr,"Could not retrieve client id nr for user [%s] [id %llu]\n",
- right, useridnr);
- return -1;
- }
+ /* this user now exists, add alias */
+ if (auth_getclientid(useridnr, &clientidnr) == -1) {
+ fprintf(stderr,
+ "Could not retrieve client id nr for user [%s] [id %llu]\n",
+ right, useridnr);
+ return -1;
+ }
- if (db_addalias(useridnr, left, clientidnr) == -1)
- {
- fprintf(stderr,"Could not add alias [%s] for user [%s] [id %llu]\n",
- left, right, useridnr);
- return -1;
- }
+ if (db_addalias(useridnr, left, clientidnr) == -1) {
+ fprintf(stderr,
+ "Could not add alias [%s] for user [%s] [id %llu]\n",
+ left, right, useridnr);
+ return -1;
+ }
- printf("alias [%s] --> [%s] created\n",left,right);
- return 0;
- }
+ printf("alias [%s] --> [%s] created\n", left, right);
+ return 0;
+ }
}