OSSP CVS Repository

ossp - Check-in [201]
Not logged in
[Honeypot]  [Browse]  [Home]  [Login]  [Reports
[Search]  [Ticket]  [Timeline
  [Patchset]  [Tagging/Branching

Check-in Number: 201
Date: 2000-Dec-12 14:19:24 (local)
2000-Dec-12 13:19:24 (UTC)
User:simons
Branch:
Comment: Initial revision
Tickets:
Inspections:
Files:
ossp-pkg/petidomo/mailer.c      added-> 1.1
ossp-pkg/petidomo/main.c      added-> 1.1
ossp-pkg/petidomo/members.c      added-> 1.1
ossp-pkg/petidomo/parsearray.c      added-> 1.1
ossp-pkg/petidomo/password.c      added-> 1.1
ossp-pkg/petidomo/rfcparse.c      added-> 1.1

ossp-pkg/petidomo/mailer.c -> 1.1

*** /dev/null    Sat Nov 23 01:25:13 2024
--- -    Sat Nov 23 01:25:25 2024
***************
*** 0 ****
--- 1,261 ----
+ /*
+  *      $Source: /v/ossp/cvs/ossp-pkg/petidomo/mailer.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 <stdarg.h>
+ #include <limits.h>
+ #include <sys/wait.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ 
+ #include <text.h>
+ #include <petidomo.h>
+ 
+ #ifndef ARG_NUM_MAX
+ #  define ARG_NUM_MAX 4096
+ #endif
+ #ifndef ARG_MAX
+ #  define ARG_MAX 4096
+ #endif
+ 
+ static char *
+ my_strcpy(char * dst, const char * src)
+ {
+     while((*dst++ = *src++) != '\0')
+       ;
+     return dst-1;
+ }
+ 
+ FILE *
+ OpenMailer(const char * envelope, const char * recipients[])
+ {
+     assert(1==0);
+     return NULL;
+ }
+ 
+ FILE *
+ vOpenMailer(const char * envelope, ...)
+ {
+     const struct PD_Config *   MasterConfig;
+     va_list                    ap;
+     FILE *                     fh;
+     char *                     cmdline;
+     char *                     p;
+     const char *               q;
+     const char *               options;
+     unsigned int               cmdline_len;
+ 
+     MasterConfig = getMasterConfig();
+ 
+     debug((DEBUG_MAILER, 2, "MTA is \"%s\".", MasterConfig->mta));
+     debug((DEBUG_MAILER, 2, "MTA options are \"%s\".", MasterConfig->mta_options));
+     debug((DEBUG_MAILER, 2, "Envelope is \"%s\".", envelope));
+ 
+     /* Determine the length of the required buffer. */
+ 
+     cmdline_len = strlen(MasterConfig->mta);
+     cmdline_len += strlen(MasterConfig->mta_options);
+     cmdline_len += strlen(envelope);
+     va_start(ap, envelope);
+     while ((q = va_arg(ap, const char *)) != NULL) {
+        debug((DEBUG_MAILER, 2, "Recipient: \"%s\".", q));
+        cmdline_len += strlen(q) + 1;
+     }
+     va_end(ap);
+     cmdline = xmalloc(cmdline_len+8); /* we don't take any risks :) */
+     debug((DEBUG_MAILER, 3, "Command line will be %u byte long.", cmdline_len));
+ 
+     /* Copy the mta's path and name into the buffer. */
+ 
+     p = my_strcpy(cmdline, MasterConfig->mta);
+     *p++ = ' ';
+ 
+     /* Copy the mta's options into the array, while replacing '%s'
+        with the envelope. */
+ 
+     for (options = MasterConfig->mta_options; *options != '\0'; ) {
+        debug((DEBUG_MAILER, 4, "Parsing '%c' character.", *options));
+        if (options[0] == '%' && options[1] == 's') {
+            p = my_strcpy(p, envelope);
+            *p++ = ' ';
+            options += 2;
+            break;
+        }
+        else {
+            debug((DEBUG_MAILER, 4, "Wrote '%c' to aray.", *options));
+            *p++ = *options++;
+        }
+     }
+     *p++ = ' ';
+ 
+     /* Append the list of recipients. */
+ 
+     va_start(ap, envelope);
+     while ((q = va_arg(ap, const char *)) != NULL) {
+        p = my_strcpy(p, q);
+        *p++ = ' ';
+     }
+     p[-1] = '\0';
+     va_end(ap);
+ 
+     debug((DEBUG_MAILER, 1, "Starting up \"%s\".", cmdline));
+ 
+     fh = popen(cmdline, "w");
+     if (fh == NULL)
+       syslog(LOG_ERR, "Failed opening pipe to \"%s\": %m", cmdline);
+ 
+     free(cmdline);
+     return fh;
+ }
+ 
+ 
+ int
+ CloseMailer(FILE * fh)
+ {
+     return pclose(fh);
+ }
+ 
+ 
+ static int
+ my_strlen(const char * p)
+ {
+     u_int  i;
+     for (i = 0; *p && !isspace((int)*p); p++)
+       i++;
+     return i;
+ }
+ 
+ #define MYPIPE_READ fildes[0]
+ #define MYPIPE_WRITE fildes[1]
+ 
+ int
+ ListMail(const char * envelope, const char * listname, const struct Mail * MailStruct)
+ {
+     const struct PD_Config * MasterConfig = getMasterConfig();
+     char **   arguments;
+     u_int     arguments_num = 256;
+     char      buffer[256];
+     char *    listfile;
+     char *    nextAddress;
+     char *    currAddress;
+     char *    p;
+     u_int     counter;
+     u_int     len;
+     u_int     address_byte;
+     u_int     max_address_byte;
+     int       fildes[2];
+     pid_t     child_pid;
+     int       child_status;
+ 
+     /* Initialize internal stuff. */
+ 
+     arguments = xmalloc((arguments_num+1) * sizeof(char *));
+     max_address_byte = ARG_MAX - strlen(envelope) - strlen(MasterConfig->mta) -
+        strlen(MasterConfig->mta_options) - 8;
+ 
+     /* Load the list of recipients. */
+ 
+     sprintf(buffer, "lists/%s/list", listname);
+     listfile = loadfile(buffer);
+     if (listfile == NULL)
+       return 1;
+ 
+     /* Now go into delivery loop until we're finished. */
+ 
+     for(counter = 0, currAddress = listfile; *currAddress != '\0'; counter = 0) {
+ 
+        /* Set up the call to the MTA, including options. */
+ 
+        arguments[counter++] = MasterConfig->mta;
+        debug((DEBUG_MAILER, 5, "MTA is \"%s\".", arguments[0]));
+        sprintf(buffer, MasterConfig->mta_options, envelope);
+        debug((DEBUG_MAILER, 5, "MTA options are \"%s\".", buffer));
+        for (p = buffer, arguments[counter++] = buffer; *p != '\0'; p++) {
+            debug((DEBUG_MAILER, 9, "Left to parse: \"%s\".", p));
+            if (isspace((int)*p)) {
+                *p++ = '\0';
+                debug((DEBUG_MAILER, 9, "Left to parse: \"%s\".", p));
+                while(*p != '\0' && isspace((int)*p))
+                  p++;
+                debug((DEBUG_MAILER, 9, "Left to parse: \"%s\".", p));
+                arguments[counter++] = p;
+            }
+        }
+        if (strlen(arguments[counter-1]) == 0)
+          counter--;
+ 
+        /* Append as many recipients as fit. */
+ 
+        for (address_byte = 0; *currAddress != '\0' ; currAddress = nextAddress) {
+            nextAddress = text_find_next_line(currAddress);
+            len = my_strlen(currAddress);
+            if (address_byte + len > max_address_byte) {
+                debug((DEBUG_MAILER, 1, "Sending early, command line exceeds %d characters.", ARG_MAX));
+                break;
+            }
+            if (counter > ARG_NUM_MAX) {
+                debug((DEBUG_MAILER, 1, "Sending early, command line exceeds %d arguments.", ARG_NUM_MAX));
+                break;
+            }
+            currAddress[len] = '\0';
+            debug((DEBUG_MAILER, 8, "Address \"%s\" is %u byte long.", currAddress, len));
+            address_byte += len;
+            arguments[counter++] = currAddress;
+            if (counter+8 >= arguments_num) {
+                debug((DEBUG_MAILER, 1, "Enlarging internal array."));
+                arguments_num += 256;
+                arguments = realloc(arguments, (arguments_num+1) * sizeof(char *));
+                if (arguments == NULL)
+                  return -1;
+            }
+        }
+ 
+        /* Deliver the mail. */
+ 
+        arguments[counter++] = NULL;
+        if (pipe(fildes) == -1) {
+            syslog(LOG_ERR, "Couldn't open a pipe to my child process: %m");
+            return -1;
+        }
+        child_pid = fork();
+        switch(child_pid) {
+          case 0:
+              /* Child */
+              close(MYPIPE_WRITE);
+              if (dup2(MYPIPE_READ, STDIN_FILENO) == -1) {
+                  syslog(LOG_ERR, "Child process couldn't read from pipe: %m");
+                  return -1;
+              }
+              close(MYPIPE_READ);
+              execv(MasterConfig->mta, arguments);
+              syslog(LOG_ERR, "Couldn't exec(\"%s\"): %m", MasterConfig->mta);
+              return -1;
+          case -1:
+              /* Error */
+              syslog(LOG_ERR, "Couldn't fork: %m");
+              return -1;
+          default:
+              /* everything is fine */
+              close(MYPIPE_READ);
+        }
+        write(MYPIPE_WRITE, MailStruct->Header, strlen(MailStruct->Header));
+        write(MYPIPE_WRITE, "\n", 1);
+        write(MYPIPE_WRITE, MailStruct->Body, strlen(MailStruct->Body));
+        if (MailStruct->ListSignature != NULL)
+          write(MYPIPE_WRITE, MailStruct->ListSignature, strlen(MailStruct->ListSignature));
+        close(MYPIPE_WRITE);
+        waitpid(child_pid, &child_status, 0);
+        if (!(WIFEXITED(child_status) && WEXITSTATUS(child_status) == 0)) {
+            syslog(LOG_ERR, "The executed mail agent return error %d, aborting.",
+                WEXITSTATUS(child_status));
+            return -1;
+        }
+     }
+     return 0;
+ }


ossp-pkg/petidomo/main.c -> 1.1

*** /dev/null    Sat Nov 23 01:25:13 2024
--- -    Sat Nov 23 01:25:25 2024
***************
*** 0 ****
--- 1,146 ----
+ /*
+  *      $Source: /v/ossp/cvs/ossp-pkg/petidomo/main.c,v $
+  *      $Revision: 1.1 $
+  *      $Date: 2000/12/13 13:19:24 $
+  *
+  *      Copyright (C) 1996 by CyberSolutions GmbH.
+  *      All rights reserved.
+  */
+ 
+ #include <stdio.h>
+ #include <sys/stat.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <string.h>
+ 
+ #include <argv.h>
+ #include <petidomo.h>
+ #include "version.h"
+ 
+ #ifndef LOG_PERROR
+ #  define LOG_PERROR 0
+ #endif
+ 
+ MODULE_TABLE                   /* defined in debug.h */
+ static char *        listname = NULL;
+ static argv_array_t  debug;
+ 
+ int
+ main(int argc, char * argv[])
+ {
+     const struct PD_Config * MasterConfig;
+     char *        incoming_mail;
+     char *        programname;
+     argv_t        args[] = {
+ #ifdef DEBUG
+         {'d', "debug", ARGV_CHARP | ARGV_ARRAY , &debug, "debug",
+          "Set debug level per module."},
+ #endif
+         {ARGV_MAYBE, 0L, ARGV_CHARP, &listname, "listname", "Default mailing list."},
+         {ARGV_LAST}
+     };
+     int           fd;
+ 
+     /* Determine the name we have been called under. */
+ 
+     programname = strrchr(argv[0], (int) '/');
+     if (programname == NULL)
+       programname = argv[0];
+     else
+       programname++;
+ 
+     /* Init logging routines first of all, so that we can report
+        errors. */
+ 
+     openlog(programname, LOG_CONS | LOG_PID | LOG_PERROR, LOG_MAIL);
+ 
+     /* Set our umask. */
+ 
+     umask(S_IRWXO);            /* We don't care for "others". */
+ 
+     /* Switch real and effective uid/gid to 'petidomo'. */
+ 
+ #ifdef HAVE_SETREUID
+     setreuid(geteuid(), geteuid());
+ #endif
+ #ifdef HAVE_SETREGID
+     setregid(getegid(), getegid());
+ #endif
+ 
+     /* Parse the command line. */
+ 
+     argv_help_string = "Petidomo Mailing List Server";
+     argv_version_string = VERS;
+     argv_process(args, argc, argv);
+ 
+     /* Set debug level according to the wishes of the user. */
+ 
+ #ifdef DEBUG
+     if (argvSetDebugLevel(debug) != 0)
+       exit(1);
+ #endif
+ 
+     /* Init Petidomo's internal stuff. */
+ 
+     if (InitPetidomo() != 0) {
+        syslog(LOG_CRIT, "Failed to initialize my internals.");
+        exit(1);
+     }
+     MasterConfig = getMasterConfig();
+ 
+     /* Load the file from standard input and save it, so that it isn't
+        lost in case of an error. */
+ 
+     incoming_mail = LoadFromDescriptor(STDIN_FILENO);
+     if (incoming_mail == NULL) {
+        syslog(LOG_ERR, "Failed to read incoming mail from standard input.");
+        exit(1);
+     }
+     RescueMail(incoming_mail);
+ 
+     /* Detach ourselves, if the configurator wished it so. */
+ 
+     if (MasterConfig->detach == TRUE) {
+        debug((DEBUG_MAIN, 3, "Detaching from control terminal and running asyncronously."));
+         switch (fork()) {
+          case -1:
+              syslog(LOG_CRIT, "Can't fork(): %m");
+              exit(1);
+          case 0:
+              setsid();
+              fd = open("/dev/null", O_RDWR, 0);
+              if (fd != -1) {
+                  dup2(fd, STDIN_FILENO);
+                  dup2(fd, STDOUT_FILENO);
+                  dup2(fd, STDERR_FILENO);
+                  if (fd > 2)
+                    close (fd);
+              }
+              break;
+          default:
+              _exit(0);
+         }
+     }
+ 
+     /* Now decide what we actually do with the mail. */
+ 
+     if (strcasecmp("listserv", programname) == 0)
+       listserv_main(incoming_mail, listname);
+     else if (strcasecmp("hermes", programname) == 0) {
+        if (listname != NULL)
+          hermes_main(incoming_mail, listname);
+        else {
+            syslog(LOG_ERR, "Wrong command line syntax. \"hermes\" requires a parameter.");
+            exit(1);
+        }
+     }
+     else {
+        syslog(LOG_ERR, "I have been called under an unknown name \"%s\".", programname);
+        exit(1);
+     }
+ 
+     /* Exit gracefully. */
+ 
+     RemoveRescueMail();
+     return 0;
+ }


ossp-pkg/petidomo/members.c -> 1.1

*** /dev/null    Sat Nov 23 01:25:13 2024
--- -    Sat Nov 23 01:25:25 2024
***************
*** 0 ****
--- 1,145 ----
+ /*
+  *      $Source: /v/ossp/cvs/ossp-pkg/petidomo/members.c,v $
+  *      $Revision: 1.1 $
+  *      $Date: 2000/12/13 13:19:24 $
+  *
+  *      Copyright (C) 1997 by CyberSolutions GmbH.
+  *      All rights reserved.
+  */
+ 
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <dirent.h>
+ #include <ctype.h>
+ 
+ #include <text.h>
+ #include <petidomo.h>
+ 
+ int
+ SendSubscriberList(struct Mail * MailStruct,
+                   const char * param1,
+                   const char * param2,
+                   const char * defaultlist)
+ {
+     const struct List_Config * ListConfig;
+     FILE *         fh;
+     const char *   address = NULL;
+     const char *   listname = NULL;
+     char           owner[4096];
+     char           envelope[4096];
+     char *         buffer;
+     char *         p;
+     int            i;
+ 
+     debug((DEBUG_COMMAND, 3, "SendSubscriberList(\"%s\") with default list \"%s\".",
+           param1, defaultlist));
+ 
+     /* Try to find out, which parameter is what. */
+ 
+     if (param1 != NULL) {
+        if (isValidListName(param1) == TRUE)
+          listname = param1;
+     }
+ 
+     address = (MailStruct->Reply_To) ? MailStruct->Reply_To : MailStruct->From;
+     if (listname == NULL && defaultlist != NULL)
+       listname = defaultlist;
+ 
+     if (address == NULL || listname == NULL) {
+        syslog(LOG_NOTICE, "%s: members-command invalid: No list specified.",
+            MailStruct->From);
+        return 0;
+     }
+ 
+     /* Initialize internal stuff. */
+ 
+     ListConfig = getListConfig(listname);
+     sprintf(owner, "%s-owner@%s", listname, ListConfig->fqdn);
+     sprintf(envelope, "%s-owner@%s", listname, ListConfig->fqdn);
+ 
+     /* Check whether 'members' is allowed for this list. */
+ 
+     if (isValidAdminPassword(getPassword(), listname) == FALSE &&
+        ListConfig->allowmembers == FALSE) {
+ 
+        syslog(LOG_NOTICE, "MEMBERS command from \"%s\" has been denied.", address);
+        fh = vOpenMailer(envelope, address, owner, NULL);
+        if (fh != NULL) {
+            fprintf(fh, "From: %s-request@%s (Petidomo Mailing List Server)\n",
+                    listname, ListConfig->fqdn);
+            fprintf(fh, "To: %s\n", address);
+            fprintf(fh, "Cc: %s\n", owner);
+            fprintf(fh, "Subject: Request \"members %s\"\n", listname);
+            if (MailStruct->Message_Id != NULL)
+              fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id);
+            fprintf(fh, "Precedence: junk\n");
+            fprintf(fh, "Sender: %s\n", envelope);
+            fprintf(fh, "\n");
+            buffer = text_easy_sprintf(
+ "The MEMBERS command has been disabled for this mailing list, I am " \
+ "afraid. If there's a certain reason, why you need to know the list " \
+ "of subscribed addresses, please contact the mailing list administrator " \
+ "under the address \"%s\" instead.", owner);
+            text_wordwrap(buffer, 75);
+            fprintf(fh, "%s\n", buffer);
+            AppendSignature(fh);
+            CloseMailer(fh);
+        }
+        else
+ 
+     syslog(LOG_ERR, "Failed to send mail to \"%s\"", address);
+        return 0;
+     }
+ 
+     /* Okay, send the address list back. */
+ 
+     debug((DEBUG_COMMAND, 1, "Sending list of subscribed addresses for list "
+           "\"%s\" to \"%s\".", listname, address));
+ 
+     buffer = text_easy_sprintf("lists/%s/list", listname);
+     buffer = loadfile(buffer);
+     if (buffer == NULL) {
+        syslog(LOG_ERR, "Failed to open file \"~petidomo/lists/%s/list\"", listname);
+        return -1;
+     }
+ 
+     fh = vOpenMailer(envelope, address, NULL);
+     if (fh != NULL) {
+        fprintf(fh, "From: %s-request@%s (Petidomo Mailing List Server)\n",
+                listname, ListConfig->fqdn);
+        fprintf(fh, "To: %s\n", address);
+        fprintf(fh, "Subject: Request \"members %s\"\n", listname);
+        if (MailStruct->Message_Id != NULL)
+          fprintf(fh, "In-Reply-To: %s\n", MailStruct->Message_Id);
+        fprintf(fh, "Precedence: junk\n");
+        fprintf(fh, "Sender: %s\n", envelope);
+        fprintf(fh, "\n");
+        fprintf(fh, "Subscribers of list \"%s\":\n", listname);
+        fprintf(fh, "=======================");
+        fflush(fh);
+        for (i = 0; i < strlen(listname); i++) {
+            fputc('=', fh);
+        }
+        fputc('\n', fh);
+        for (p = buffer; *p; p++) {
+            if (isspace((int)*p)) {
+                fputc('\n', fh);
+                while (*p != '\0' && *p != '\n')
+                  p++;
+            }
+            else {
+              fputc(*p, fh);
+            }
+        }
+        AppendSignature(fh);
+        CloseMailer(fh);
+     }
+     else {
+        free(buffer);
+        syslog(LOG_ERR, "Failed to send email to \"%s\"!", address);
+        return -1;
+     }
+ 
+     free(buffer);
+     return 0;
+ }


ossp-pkg/petidomo/parsearray.c -> 1.1

*** /dev/null    Sat Nov 23 01:25:13 2024
--- -    Sat Nov 23 01:25:25 2024
***************
*** 0 ****
--- 1,28 ----
+ /*
+  *      $Source: /v/ossp/cvs/ossp-pkg/petidomo/parsearray.c,v $
+  *      $Revision: 1.1 $
+  *      $Date: 2000/12/13 13:19:24 $
+  *
+  *      Copyright (C) 1996 by CyberSolutions GmbH.
+  *      All rights reserved.
+  */
+ 
+ #include "petidomo.h"
+ 
+ struct Parse ParseArray[] = {
+     { "add", AddAddress },
+     { "subscribe", AddAddress },
+     { "delete", DeleteAddress },
+     { "unsubscribe", DeleteAddress },
+     { "remove", DeleteAddress },
+     { "approve", setPassword },
+     { "passwd", setPassword },
+     { "password", setPassword },
+     { "index", GenIndex },
+     { "lists", GenIndex },
+     { "longindex", GenIndex },
+     { "help", SendHelp },
+     { "who", SendSubscriberList },
+     { "members", SendSubscriberList },
+     { NULL, NULL }
+ };


ossp-pkg/petidomo/password.c -> 1.1

*** /dev/null    Sat Nov 23 01:25:13 2024
--- -    Sat Nov 23 01:25:25 2024
***************
*** 0 ****
--- 1,67 ----
+ /*
+  *      $Source: /v/ossp/cvs/ossp-pkg/petidomo/password.c,v $
+  *      $Revision: 1.1 $
+  *      $Date: 2000/12/13 13:19:24 $
+  *
+  *      Copyright (C) 1996 by CyberSolutions GmbH.
+  *      All rights reserved.
+  */
+ 
+ #include <ctype.h>
+ 
+ #include <petidomo.h>
+ 
+ static const char * s_password = NULL;
+ extern char *       g_currLine;
+ 
+ int
+ setPassword(struct Mail * MailStruct,
+                const char * param1,
+                const char * param2,
+                const char * defaultlist)
+ {
+     char *         p;
+     char *         q;
+ 
+     debug((DEBUG_COMMAND, 3, "setPassword(\"%s\").", param1));
+ 
+     /* Find the beginning of the parameter. */
+ 
+     p = g_currLine;
+     while(*p && !isspace((int)*p))
+       p++;
+     while(*p && isspace((int)*p))
+       p++;
+ 
+     /* If the rest is empty, there ain't no fucking password. */
+ 
+     if (*p == '\0' || strlen(p) == 0)
+       return 0;
+ 
+     /* Cut trailing blanks. */
+ 
+     q = p + strlen(p);
+     while(isspace((int)q[-1]))
+       q--;
+     *q = '\0';
+ 
+     /* Okay, check for quotes and that's it then. */
+ 
+     if (*p == '\"' && q[-1] == '\"') {
+        p++;
+        q[-1] = '\0';
+     }
+ 
+     /* Store the result. */
+ 
+     debug((DEBUG_COMMAND, 2, "Setting current password to \"%s\".", p));
+     s_password = p;
+ 
+     return 0;
+ }
+ 
+ const char *
+ getPassword(void)
+ {
+     return s_password;
+ }


ossp-pkg/petidomo/rfcparse.c -> 1.1

*** /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;
+ }

CVSTrac 2.0.1