/* **++ ** FACILITY: WWW CGI Scripts ** ** MODULE DESCRIPTION: ** ** This mails the contents of a FORM POSTed to the URL invoking ths ** program. The url embeds the mail address as follows: ** ** http://www.acornsw.com/htbin/cgi-mailto.exe/mailaddress ** ** For for mail to local user's, the user's web directory must ** contain the file .www_mailable before the script will deliver ** mail to that account. ** ** AUTHORS: ** ** Dick Munroe ** Acorn Software, Inc. ** 179 Great Rd. ** Acton, Ma. 01720 ** ** (508) 266-9800 ** fax: 266-9707 ** ** munroe@acornsw.com ** ** David Jones ** Ohio State University ** ** CREATION DATE: 04-Dec-94 ** ** DESIGN ISSUES: ** ** {@tbs@} ** ** [@optional module tags@]... ** ** MODIFICATION HISTORY: ** ** 0.000 Dick Munroe 04-Dec-94 ** Initial Version Created. ** ** 0.001 David Jones 10-Dec-1994 ** Added check for .www_mailable to web directory. ** ** 0.002 David Jones 6-Feb-1995 ** Convert extra path info to subject line for mail message. ** Include REMOTE_ADDRESS info in mail message. ** ** 0.003 David Jones 28-Feb-1995 ** Remove FROM_LINE from send_attribute call. ** ** 0.004 David Jones 16-May-1995 ** Use new cgi_translate_path routine to verify .www_mailable. ** ** 0.005 D. Jones 21-Jun-1995 ** Delete extra '\r's in cgi_printf() calls ('\n's are automatically ** converted to "\r\n" already. ** [@tbs@]... **-- */ #if defined(__ALPHA) #pragma nomember_alignment #endif /** MGD **/ #if defined(__ia64) #pragma nomember_alignment #endif /* ** ** INCLUDE FILES ** */ #include #include #include #include "cgi-mailto.h" #include "cgilib.h" /* #include "utl-itemlist.h" */ struct ItemList { short int length, code; char *buffer; long returnLength; }; #include #include #include #include #include #include #include #include #include static char* getField(char*) ; static void getFieldNameAndValue(char*,char**,char**) ; static char* getRepeatedFieldValue(char*) ; static void htmlStrcpy(char*, char*) ; extern unsigned long mail$send_begin() ; extern unsigned long mail$send_add_attribute() ; extern unsigned long mail$send_add_address() ; extern unsigned long mail$send_add_bodypart() ; extern unsigned long mail$send_message() ; extern unsigned long mail$send_end() ; int main ( int argc, char **argv ) { char buffer[1024] ; char *content_data; int content_length; char *cp ; int i, sys$setprv() ; struct ItemList itemList[10] ; struct ItemList nullItemList = {0, 0, 0, 0} ; unsigned long sendContext = 0 ; long privs[2], priv_mask[2]; int status; char *to ; char *subject, *raddr; struct dsc$descriptor_d xxxDesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0}; priv_mask[0] = PRV$M_SYSPRV; priv_mask[1] = 0; status = sys$setprv ( 0, priv_mask, 0, privs ); if ( (status&1) == 0 ){ fprintf(stderr,"setprv error: %d\n", status ); } fprintf(stderr,"Priv mask: %x, previous privs: %x\n", priv_mask[0], privs[0] ); #define ENABLE_SYSPRV if (priv_mask[0]&privs[0]) sys$setprv(1,priv_mask,0,0); #define DISABLE_SYSPRV if (priv_mask[0]&privs[0]) sys$setprv(0,priv_mask,0,0); status = cgi_init_env ( argc, argv ); to = cgi_info( ("PATH_INFO") ) ; /* PATH_INFO is of the form /mailaddress */ to++ ; /* Advance past the / */ if (strchr (to, '@') != NULL) { sprintf (buffer, TO_ADDRESS, to) ; subject = ""; to = buffer ; /* The address is one on a distant machine, so set up the mail */ /* transport. */ } else { /* Verify that user has enabled recieving mail */ int xlate_len; stat_t s_buf; char control_doc[400], translation[800]; subject = strchr ( to, '/' ); if ( subject ) { int k; *subject++ = '\0'; for ( k = 0; subject[k]; k++ ) if (subject[k] == '/') subject[k] = ' '; } else subject = ""; sprintf ( control_doc, "(GET)/~%s/.www_mailable", to ); status = cgi_translate_path ( control_doc, 1, translation, sizeof(translation)-1, &xlate_len ); translation[xlate_len] = '\0'; if ( (status&1) && (xlate_len > 0) ) { /* If we can't stat file, treat as translation failure */ if ( stat ( translation, &s_buf ) < 0 ) xlate_len = 0; } if ( xlate_len == 0 ) { cgi_begin_output ( 1 ); cgi_printf("content-type: text/plain\n\n"); /* CGI header */ cgi_printf ( "Cannot send MAIL to %s, no .www_mailable file present\n", to ); cgi_printf ( "in user's web directory\n" ); cgi_printf ( "(%s)", translation[0] ? translation : control_doc ); return 1; } } cgi_begin_output ( 1 ); cgi_printf("content-type: text/plain\n\n"); /* CGI header */ cgi_printf("Sending form data as MAIL to: %s\n",to); content_length = atoi(cgi_info ("CONTENT_LENGTH")); if (content_length == 0) { cgi_printf("Send failed: No data in CONTENT_LENGTH\n") ; return 1; } content_data = (char *) malloc(sizeof(char)*(content_length+1)); status = cgi_read(content_data, content_length); if (status == 0) { cgi_printf("Send failed: No data from cgi_read\n") ; return 1; } content_data[content_length] = '\0'; ENABLE_SYSPRV status = mail$send_begin ( &sendContext, &nullItemList, &nullItemList) ; /* Set up to construct the mail context. */ DISABLE_SYSPRV if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_BEGIN returned %%X%0X\n",status) ; return 1 ; } ; /* ** Now build up the attributes of the message. */ status = JPI$_USERNAME ; lib$getjpi (&status, 0, 0, 0, &xxxDesc,0) ; str$trim (&xxxDesc, &xxxDesc) ; i = -1 ; itemList[++i].length = strlen(to) ; itemList[i].code = MAIL$_SEND_TO_LINE ; itemList[i].buffer = to ; itemList[i].returnLength = 0 ; #ifdef DONT_NEED_SYSPRV itemList[++i].length = xxxDesc.dsc$w_length ; itemList[i].code = MAIL$_SEND_FROM_LINE ; itemList[i].buffer = xxxDesc.dsc$a_pointer ; itemList[i].returnLength = 0 ; #endif itemList[++i].length = strlen(subject); itemList[i].code = MAIL$_SEND_SUBJECT ; itemList[i].buffer = subject; itemList[i].returnLength = 0 ; itemList[++i].length = 0 ; itemList[i].code = 0 ; ENABLE_SYSPRV status = mail$send_add_attribute ( &sendContext, &itemList, &nullItemList) ; /* Add the the message header. */ if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_ADD_ATTRIBUTE returned %%X%0X\n",status) ; return 1 ; } ; i = -1 ; itemList[++i].length = strlen(to) ; itemList[i].code = MAIL$_SEND_USERNAME ; itemList[i].buffer = to ; itemList[i].returnLength = 0 ; itemList[++i] = nullItemList ; /* The itemlist describes an address of a receipient. */ status = mail$send_add_address ( &sendContext, &itemList, &nullItemList) ; /* Add the sender of the message to the list of receipients. */ if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_ADD_ADDRESS returned %%X%0X\n",status) ; return 1 ; } ; /* ** Include address of sender. */ raddr = cgi_info ( "REMOTE_ADDR" ); if ( raddr ) { sprintf ( buffer, "REMOTE_ADDRESS: %s", raddr ); i = -1 ; itemList[++i].length = strlen(buffer) ; itemList[i].code = MAIL$_SEND_RECORD ; itemList[i].buffer = buffer ; itemList[i].returnLength = 0 ; itemList[++i] = nullItemList ; /* The itemlist describes the body of the message. */ status = mail$send_add_bodypart (&sendContext, &itemList, &nullItemList) ; /* Add the body to the message. */ if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_ADD_BODYPART returned %%X%0X\n",status) ; return 1 ; } ; } /* ** The content data is of the form: ** ** fieldName=fielddata[&fieldName=fielddata...] */ for (cp = getField(content_data); cp; cp = getField(NULL)) { char *field ; int j = 0 ; int multiline = 0 ; char *name ; char *value ; #ifdef DEBUG printf ("%s\n", cp) ; printf ("%d\n", strlen(cp)) ; #endif getFieldNameAndValue(cp, &name, &value) ; #ifdef DEBUG printf ("%p\n", name) ; printf ("%s\n", name) ; printf ("%d\n", strlen(name)) ; printf ("%p\n", value) ; printf ("%s\n", value) ; printf ("%d\n", strlen(value)) ; #endif htmlStrcpy(name, name) ; #ifdef DEBUG printf ("%s\n", name) ; printf ("%d\n", strlen(name)) ; #endif htmlStrcpy(value, value) ; #ifdef DEBUG printf ("%s\n", value) ; printf ("%d\n", strlen(value)) ; #endif multiline = ((strchr(value,'\n')) && (strlen(name) > 8)) ; #ifdef DEBUG printf ("multiline = %d\n", multiline) ; #endif if (!multiline) { multiline = ((strlen(name) > 8) && ((strlen(name) + strlen(value) + 2) > 80)) ; #ifdef DEBUG printf ("multiline = %d\n", multiline) ; #endif } for (field = getRepeatedFieldValue(value); field; field = getRepeatedFieldValue(NULL)) { if (j == 0) { if (multiline) { j = 8 ; sprintf (buffer, "%s:", name) ; #ifdef DEBUG printf("%s\n", buffer) ; #endif i = -1 ; itemList[++i].length = strlen(buffer) ; itemList[i].code = MAIL$_SEND_RECORD ; itemList[i].buffer = buffer ; itemList[i].returnLength = 0 ; itemList[++i] = nullItemList ; status = mail$send_add_bodypart (&sendContext, &itemList, &nullItemList) ; if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_ADD_BODYPART returned %%X%0X\n",status) ; return 1 ; } ; sprintf (buffer, "%*c%s", j, ' ', field) ; } else { j = strlen(name) + 2 ; sprintf (buffer, "%s: %s", name, field) ; } } else { sprintf (buffer, "%*c%s", j, ' ', field) ; } #ifdef DEBUG printf("%s\n", buffer) ; #endif i = -1 ; itemList[++i].length = strlen(buffer) ; itemList[i].code = MAIL$_SEND_RECORD ; itemList[i].buffer = buffer ; itemList[i].returnLength = 0 ; itemList[++i] = nullItemList ; /* The itemlist describes the body of the message. */ status = mail$send_add_bodypart (&sendContext, &itemList, &nullItemList) ; /* Add the body to the message. */ if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_ADD_BODYPART returned %%X%0X\n",status) ; return 1 ; } ; } } status = mail$send_message ( &sendContext, &nullItemList, &nullItemList) ; /* Send the message. */ if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_MESSAGE returned %%X%0X\n",status) ; return 1 ; } ; status = mail$send_end ( &sendContext, &nullItemList, &nullItemList) ; /* Set up to construct the mail context. */ DISABLE_SYSPRV if (!$VMS_STATUS_SUCCESS(status)) { cgi_printf("Send failed: MAIL$SEND_END returned %%X%0X\n",status) ; return 1 ; } ; str$free1_dx (&xxxDesc) ; cgi_printf("Send Succeeded: submitted form data mailed\n") ; return 1; } char* getField ( char* field) { static char *cp = NULL ; char *next ; char *xxx ; if (field) { cp = field ; } if (!cp) { return cp ; } next = strchr(cp, '&') ; if (next) { *next++ = 0 ; } ; xxx = cp ; cp = next ; return xxx ; } void getFieldNameAndValue ( char* field, char** name, char** value) { char *cp ; if (!field) { *name = NULL ; *value = NULL ; return ; } *name = field ; cp = strchr(field, '=') ; if (!cp) { *name = NULL ; *value = NULL ; return ; } *cp++ = 0 ; *value = cp ; return ; } char* getRepeatedFieldValue ( char* field) { static char *cp = NULL ; char *next ; char *xxx ; if (field) { cp = field ; } if (!cp) { return cp ; } next = strchr(cp, '\n') ; if (next) { *next++ = 0 ; } ; xxx = cp ; cp = next ; return xxx ; } void htmlStrcpy ( char *out, char *in) { int i ; for (i = strlen(in); i >= 0; i--) { if (*in == '%') { int xxx ; sscanf (&in[1], "%02x", &xxx) ; *out++ = (char) xxx ; i -= 2 ; in += 3 ; } else if ( *in == '+' ) { *out++ = ' '; in++; } else { *out++ = *in++ ; } } }