diff options
Diffstat (limited to 'imaputil.c')
-rw-r--r-- | imaputil.c | 5044 |
1 files changed, 2446 insertions, 2598 deletions
@@ -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; } |