/* emailer 1.0, copyright 1998-2002, zap technologies */ #include #include #include #include #define POINTERWIDTH 4 #define COMMANDSIZE 256 #define FORMCACHESIZE 2048 /* threshold for: message body too long */ #define TEST "ZAPTECH_CGITEST" #define FORMERR_MEMORYLOW 1 /* data tytpes */ struct cgiarg { struct cgiarg *next; char *name; char *value; }; /* prototypes */ struct cgiarg *cacheformargs(); char *findformarg(char *arg, struct cgiarg *head); /* global variables */ short formargerror = 0; char formargscache[FORMCACHESIZE]; /* warning, this must start on longword boundary */ char cgitest = 0; main(int argc, char *argv[]) { char command[COMMANDSIZE]; FILE *fp; struct cgiarg *harg, *temparg; char *flagstr, *email, *subject, *body, *suffix; int c; time_t tm; time(&tm); srand(tm); printf("Content-type: text/html\n\n"); harg = cacheformargs(); if (harg == 0) goto x; flagstr = findformarg("flags", harg); email= findformarg("prefix", harg); suffix = findformarg("suffix", harg); if (!harg || !email || !suffix) { /* warning strcmp will crash if given a null ptr */ if (flagstr && !(strcmp(flagstr, "DEBUG"))) { debugout: temparg = harg; while (temparg) { if (temparg != harg) printf("
\n...
\n"); printf("%s ...
\n%s", temparg->name, temparg->value); temparg = temparg->next; } } else { x: printf("\n\n\n"); if (formargerror == FORMERR_MEMORYLOW) printf("

\nmessage body too long\n\n"); else printf("

\ninsuffient arguments\n\n"); printf("

Please go back to the previous page before continuing to browse.\n"); printf("

real time: %X
\n", tm); printf("

\n"); printf("\n\n"); printf("\n"); } } else { printf("\n"); printf("\n"); if (flagstr && !(strcmp(flagstr, "DEBUG"))) goto debugout; printf(email); if (email = findformarg("email_to", harg)) { if (!(subject = findformarg("subject", harg))) subject = "no subject"; /* need to check that command string won't overflow */ if ((strlen(email) + strlen(subject)) > (COMMANDSIZE - 16)) goto noto; sprintf(command, "mail -s \"%s\" %s", subject, email); /* OS X likes -s before email */ if (!(body = findformarg("body", harg))) body = "no body"; if (!(email = findformarg("email_return", harg))) email = "no email_return"; if (cgitest) { printf("CGITEST mode: no mail sent\n\n"); printf("%s\n", command); printf("from: %s
\n\n%s\n", email, body); } else { /* submit to command line */ if (fp = popen(command, "w")) fprintf(fp, "from: %s\n\n%s\n", email, body); else printf("No pipe opened
\n"); pclose(fp); } if (!(subject = findformarg("acknowledge", harg))) subject = "thank you"; } else { noto: if (!(subject = findformarg("errormsg", harg))) subject = "unknown error"; } printf(subject); printf(suffix); } } char *findformarg(char *arg, struct cgiarg *head) { struct cgiarg *carg; char *success = 0; carg = head; while (carg) { if (strcmp(arg, carg->name) == 0) { success = carg->value; break; } carg = carg->next; } return (success); } /* Note: Now checks for cacheformargs overrun. Any arg */ /* overrun cancels all args that precede it ... */ /* may change this in future version? */ /* Return: */ /* ->hout = -1 insufficient buffer space */ /* = 0 error condition */ /* > 0 success */ struct cgiarg *cacheformargs() { struct cgiarg *harg = 0; /* head */ struct cgiarg *parg = 0; /* prev */ struct cgiarg *carg; char *env; int c, i; int cachefree = sizeof(formargscache); char c2, parse_state = 0; carg = (struct cgiarg *) &formargscache; env = getenv(TEST); if (env) { cgitest = 1; printf("found environment variable: " TEST "
\n"); goto test; } env = getenv("REQUEST_METHOD"); if (env && !(strcmp("POST",env))) { env = getenv("CONTENT_LENGTH"); if (env) { i = atoi(env); /* get POST length, ignored */ test: while ((c = getchar()) != EOF) { switch (parse_state) { case 0: i = 0; carg->next = 0; carg->name = (char *) carg + sizeof(struct cgiarg); carg->name[i++] = c; if ((cachefree -= 13) < 1) goto co; parse_state++; break; case 1: if ((cachefree -= 1) < 1) goto co; if (c == '=') { carg->name[i++] = 0; carg->value = &carg->name[i]; i = 0; parse_state++; } else carg->name[i++] = c; break; case 2: if (c == '&') { carg->value[i++] = 0; if (harg) parg->next = carg; else harg = carg; parg = carg; carg = (struct cgiarg *) &carg->value[i]; c = (POINTERWIDTH - (unsigned long) carg % POINTERWIDTH) & (POINTERWIDTH - 1); carg = (struct cgiarg *) ((unsigned long) carg + c); if ((cachefree -= (c + 1)) < 0) goto co; parse_state = 0; } else { if ((cachefree -= 1) < 1) { co: formargerror = FORMERR_MEMORYLOW; harg = 0; goto exit; } if (c == '%') parse_state = 3; else { if (c == '+') c = ' '; carg->value[i++] = c; } } break; case 3: if (c > '9') c = c - 'A' + 10; else c -= '0'; c2 = c; parse_state++; break; case 4: if (c > '9') c = c - 'A' + 10; else c -= '0'; carg->value[i++] = (c2 << 4) + c; parse_state = 2; } } /* while */ if (parse_state == 2) { /* note trailing carriage return before EOF */ carg->value[i - 1] = 0; if (harg) parg->next = carg; else harg = carg; } } /* if env */ } /* if env */ exit: return (harg); }