*** /dev/null Sat Nov 23 01:25:13 2024
--- - Sat Nov 23 01:25:25 2024
***************
*** 0 ****
--- 1,350 ----
+ /*
+ * $Source: /v/ossp/cvs/ossp-pkg/petidomo/rfcparse.c,v $
+ * $Revision: 1.1 $
+ * $Date: 2000/12/13 13:19:24 $
+ *
+ * Copyright (C) 1996 by CyberSolutions GmbH.
+ * All rights reserved.
+ */
+
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+
+ #include <rfc822.h>
+ #include <text.h>
+ #include <petidomo.h>
+
+ void
+ RemoveCarrigeReturns(char * buffer)
+ {
+ char * src = buffer;
+ char * dst = buffer;
+
+ while(*src != '\0') {
+ switch(*src) {
+ case '\n':
+ *dst++ = ' ';
+ while(isspace((int)*src))
+ src++;
+ break;
+ default:
+ *dst++ = *src++;
+ }
+ }
+ *dst++ = '\0';
+ }
+
+ bool
+ isRFC822Address(const char * buffer)
+ {
+ char * address;
+ int rc;
+
+ rc = rfc822_parse_address(buffer, &address, NULL, NULL);
+ if (rc == RFC822_OK) {
+ debug((DEBUG_RFCPARSE, 3, "'%s' is a valid rfc address.", address));
+ if (address) {
+ free(address);
+ }
+ return TRUE;
+ }
+ else {
+ debug((DEBUG_RFCPARSE, 4, "'%s' is not a valid rfc address", buffer));
+ return FALSE;
+ }
+ }
+
+ int
+ ParseAddressLine(char * buffer)
+ {
+ struct rfc822_address_sep_state sep_state;
+ char * p,
+ * address;
+ int rc;
+
+ /* Handle continuation lines. */
+
+ RemoveCarrigeReturns(buffer);
+
+ /* Initialize the structure needed for address_sep(). */
+
+ sep_state.address_line = buffer;
+ sep_state.group_nest = 0;
+
+ debug((DEBUG_RFCPARSE, 2, "Original address is \"%s\".", buffer));
+
+ /* We want only the first address, if multiple are there. */
+
+ while ((p = rfc822_address_sep(&sep_state)) != NULL) {
+ if (*p == '\0')
+ continue;
+ else
+ break;
+ }
+
+ if (p == NULL) {
+ /* line is empty */
+ return -1;
+ }
+
+ debug((DEBUG_RFCPARSE, 2, "First part is \"%s\".", p));
+
+ rc = rfc822_parse_address(p, &address, NULL, NULL);
+ if (rc == RFC822_OK && address != NULL) {
+ debug((DEBUG_RFCPARSE, 2, "Parsed address is: '%s'", address));
+ strcpy(buffer, address);
+ free(address);
+ return 0;
+ }
+ else
+ return -1;
+ }
+
+ int
+ ParseReplyToLine(char * buffer)
+ {
+ return ParseAddressLine(buffer);
+ }
+
+ int
+ ParseFromLine(char * buffer)
+ {
+ return ParseAddressLine(buffer);
+ }
+
+ int
+ ParseMessageIdLine(char * buffer)
+ {
+ int rc;
+
+ debug((DEBUG_RFCPARSE, 2, "Unparsed Message-Id: '%s'", buffer));
+
+ rc = ParseAddressLine(buffer);
+ if (rc != 0)
+ return rc; /* Error! */
+
+ memmove(buffer+1, buffer, strlen(buffer)+1);
+ buffer[0] = '<';
+ strcat(buffer, ">");
+
+ debug((DEBUG_RFCPARSE, 2, "Parsed Message-Id: '%s'", buffer));
+
+ return rc;
+ }
+
+ int
+ ParseApproveLine(char * buffer)
+ {
+ char * src;
+ char * dst;
+
+ RemoveCarrigeReturns(buffer);
+
+ src = buffer;
+ dst = buffer;
+
+ /* Skip leading whitespace. */
+
+ while(isspace((int)*src))
+ src++;
+
+ /* Skip a quote if there is one. */
+
+ if (*src == '\"')
+ src++;
+
+ /* Copy String. */
+
+ while((*dst++ = *src++) != '\0')
+ ;
+ dst--;
+
+ /* Kill trailing whitespace. */
+
+ while(isspace((int)dst[-1]))
+ *(--dst) = '\0';
+
+ /* Kill a quote if there is one. */
+
+ if (dst[-1] == '\"')
+ *(--dst) = '\0';
+
+ return 0;
+ }
+
+ void
+ CanonizeAddress(char ** buffer, const char * fqdn)
+ {
+ const struct PD_Config * MasterConfig;
+ char * newbuf;
+ char * local,
+ * host;
+ int rc;
+
+ assert(buffer != NULL);
+ assert(*buffer != NULL);
+
+ if (buffer == NULL || *buffer == NULL)
+ return;
+
+ debug((DEBUG_RFCPARSE, 3, "Check whether \"%s\" is a canon address.", *buffer));
+
+ rc = rfc822_parse_address(*buffer, NULL, &local, &host);
+ if (rc == RFC822_OK) {
+ if (local != NULL && host == NULL) {
+ debug((DEBUG_RFCPARSE, 3, "'%s' is a local address, appending my hostname.",
+ *buffer));
+ if (fqdn == NULL) {
+ MasterConfig = getMasterConfig();
+ fqdn = MasterConfig->fqdn;
+ }
+ newbuf = xmalloc(strlen(*buffer) + strlen(fqdn) + 3);
+ sprintf(newbuf, "%s@%s", local, fqdn);
+ free(local);
+ *buffer = newbuf;
+ debug((DEBUG_RFCPARSE, 3, "Canonized address: '%s'.", *buffer));
+ }
+ else
+ debug((DEBUG_RFCPARSE, 3, "\"%s\" is a full address.", *buffer));
+ }
+ }
+
+ int
+ ParseMail(struct Mail **result, char * incoming_mail, const char * fqdn)
+ {
+ struct Mail * MailStruct;
+ char * currLine;
+ char * nextLine;
+ int rc;
+
+ /* Allocate structure. */
+
+ MailStruct = calloc(sizeof(struct Mail), 1);
+ if (MailStruct == NULL) {
+ syslog(LOG_ERR, "Failed to allocate %d byte of memory.", sizeof(struct Mail));
+ return -1;
+ }
+
+ /* Rescue the mail in its original state, before the parsing
+ routines have havoc in the buffer. */
+
+ MailStruct->Header = strdup(incoming_mail);
+ if (MailStruct->Header == NULL) {
+ syslog(LOG_ERR, "Failed to allocate %d byte of memory.", strlen(incoming_mail));
+ return -1;
+ }
+ for (MailStruct->Body = MailStruct->Header;
+ *MailStruct->Body != '\n' && *MailStruct->Body != '\0';
+ MailStruct->Body = text_find_next_line(MailStruct->Body))
+ ;
+ if (*MailStruct->Body == '\n') {
+ *MailStruct->Body = '\0';
+ MailStruct->Body++;
+ }
+
+ /* Get the envelope. */
+
+ currLine = incoming_mail;
+ nextLine = text_find_next_line(incoming_mail);
+ if (strncasecmp("From ", currLine, strlen("From ")) == 0) {
+ if (nextLine[-1] == '\n')
+ nextLine[-1] = '\0';
+ currLine += strlen("From ");
+ while (isspace((int)*currLine))
+ currLine++;
+ MailStruct->Envelope = currLine;
+ while (!isspace((int)*currLine))
+ currLine++;
+ *currLine = '\0';
+ CanonizeAddress(&(MailStruct->Envelope), fqdn);
+ debug((DEBUG_RFCPARSE, 5, "Envelope is \"%s\".", MailStruct->Envelope));
+ currLine = nextLine;
+ }
+
+ /* Parse the incoming mail's header. */
+
+ for (nextLine = text_find_next_line(currLine);
+ *currLine != '\n' && *currLine != '\0';
+ currLine = nextLine, nextLine = text_find_next_line(currLine)) {
+
+ /* Find continuation lines. */
+
+ while (*nextLine == ' ' || *nextLine == '\t')
+ nextLine = text_find_next_line(nextLine);
+
+ /* remove trailing \n */
+
+ if (nextLine[-1] == '\n')
+ nextLine[-1] = '\0';
+
+ /* Log contents of current line. */
+
+ debug((DEBUG_RFCPARSE, 6, "Parsing line \"%s\".", currLine));
+
+ /* Check whether it is a header we're interested in. */
+
+ if (strncasecmp("From:", currLine, strlen("From:")) == 0) {
+ if (MailStruct->From != NULL) {
+ syslog(LOG_NOTICE, "Received mail with multiple From: lines.");
+ continue;
+ }
+ MailStruct->From = &currLine[strlen("From:")];
+ rc = ParseFromLine(MailStruct->From);
+ if (rc != 0)
+ return rc;
+ CanonizeAddress(&(MailStruct->From), fqdn);
+ debug((DEBUG_RFCPARSE, 5, "From: is \"%s\".", MailStruct->From));
+ } else if (strncasecmp("Reply-To:", currLine, strlen("Reply-To:")) == 0) {
+ if (MailStruct->Reply_To != NULL) {
+ syslog(LOG_NOTICE, "Received mail with multiple Reply-To: lines.");
+ continue;
+ }
+ MailStruct->Reply_To = &currLine[strlen("Reply-To:")];
+ rc = ParseReplyToLine(MailStruct->Reply_To);
+ if (rc != 0)
+ return rc;
+ CanonizeAddress(&(MailStruct->Reply_To), fqdn);
+ debug((DEBUG_RFCPARSE, 5, "Reply-To: is \"%s\".", MailStruct->Reply_To));
+ } else if (strncasecmp("Message-Id:", currLine, strlen("Message-Id:")) == 0) {
+ if (MailStruct->Message_Id != NULL) {
+ syslog(LOG_NOTICE, "Received mail with multiple Message-Id: lines.");
+ continue;
+ }
+ MailStruct->Message_Id = &currLine[strlen("Message-Id:")];
+ rc = ParseMessageIdLine(MailStruct->Message_Id);
+ if (rc != 0)
+ return rc;
+ debug((DEBUG_RFCPARSE, 5, "Message-Id: is \"%s\".", MailStruct->Message_Id));
+ }
+ else if (strncasecmp("Approve:", currLine, strlen("Approve:")) == 0) {
+ if (MailStruct->Approve != NULL)
+ syslog(LOG_NOTICE, "Received mail with multiple Approve: lines.");
+ MailStruct->Approve = &currLine[strlen("Approve:")];
+ rc = ParseApproveLine(MailStruct->Approve);
+ if (rc != 0)
+ return rc;
+ debug((DEBUG_RFCPARSE, 5, "Approve: is \"%s\".", MailStruct->Approve));
+ }
+ else if (strncasecmp("Approved:", currLine, strlen("Approved:")) == 0) {
+ if (MailStruct->Approve != NULL)
+ syslog(LOG_NOTICE, "Received mail with multiple Approve: lines.");
+ MailStruct->Approve = &currLine[strlen("Approved:")];
+ rc = ParseApproveLine(MailStruct->Approve);
+ if (rc != 0)
+ return rc;
+ debug((DEBUG_RFCPARSE, 5, "Approve: is \"%s\".", MailStruct->Approve));
+ }
+ else if (strncasecmp("Subject:", currLine, strlen("Subject:")) == 0) {
+ if (MailStruct->Subject != NULL)
+ syslog(LOG_NOTICE, "Received mail with multiple Subject: lines.");
+ MailStruct->Subject = &currLine[strlen("Subject:")];
+ if (*MailStruct->Subject == ' ')
+ MailStruct->Subject += 1;
+ debug((DEBUG_RFCPARSE, 5, "Subject: is \"%s\".", MailStruct->Subject));
+ }
+ }
+
+ *result = MailStruct;
+ return 0;
+ }
|