\n");
}
/*****************************************************************************/
/*
Provide each attachment (part with a name or file-name) as a checkbox and
associated name and content-type below the message body text area. This is
used to selectively [forward] any attachments with a message.
*/
void ComposeForwardAttachList (REQUEST_DATA *rdptr)
{
BOOL OriginalForward;
int cnt, FwdCount;
char *cptr, *nptr, *tptr;
char buf [64];
MIME_DATA *mdptr;
VMS_MAIL_MSG *vmptr;
VMS_MAIL_USER *muptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeForwardAttachList()\n");
muptr = &VmsMailUser;
vmptr = &muptr->VmsMailMsg;
CGIVARNULL (cptr, "FORM_COMPOSE_FWD_COUNT");
if (cptr)
{
/* this is the compose page at a subsequent request */
FwdCount = atoi(cptr);
if (FwdCount < 0 || FwdCount > 100) ErrorExit (SS$_BUGCHECK, FI_LI);
/* if no attachments to forward */
if (!FwdCount) return;
OriginalForward = FALSE;
}
else
{
/* this is the compose page at the original [forward] request */
FwdCount = 0;
for (mdptr = vmptr->MimeDataPtr; mdptr; mdptr = mdptr->NextMimePtr)
if (mdptr->NamePtr || mdptr->FileNamePtr) FwdCount++;
/* if no attachments to forward */
if (!FwdCount) return;
mdptr = vmptr->MimeDataPtr;
OriginalForward = TRUE;
}
fprintf (stdout,
"\n\n\
\n\
\n",
FwdCount);
for (cnt = 1; cnt <= FwdCount; cnt++)
{
if (OriginalForward)
{
/* this is the compose page at the original [forward] request */
while (mdptr && !(mdptr->NamePtr || mdptr->FileNamePtr))
{
mdptr = mdptr->NextMimePtr;
continue;
}
if (!mdptr) break;
cptr = " checked";
if (mdptr->NamePtr)
nptr = HTML_ESCAPE(mdptr->NamePtr);
else
nptr = HTML_ESCAPE(mdptr->FileNamePtr);
tptr = HTML_ESCAPE(mdptr->ContentTypePtr);
mdptr = mdptr->NextMimePtr;
}
else
{
/* this is the compose page at a subsequent request */
sprintf (buf, "FORM_COMPOSE_FWD_%d", cnt);
CGIVARNULL (cptr, buf);
if (cptr) cptr = " checked"; else cptr = "";
sprintf (buf, "FORM_COMPOSE_FWD_NAME_%d", cnt);
CGIVARNULL (nptr, buf);
if (!nptr) ErrorExit (SS$_BUGCHECK, FI_LI);
sprintf (buf, "FORM_COMPOSE_FWD_TYPE_%d", cnt);
CGIVARNULL (tptr, buf);
if (!tptr) ErrorExit (SS$_BUGCHECK, FI_LI);
nptr = HTML_ESCAPE(nptr);
tptr = HTML_ESCAPE(tptr);
}
fprintf (stdout,
"%s\
%s (%s)\n\
\n\
\n",
cnt == 1 ? "" : " ",
cnt, cptr,
nptr, tptr,
cnt, nptr,
cnt, tptr);
}
fprintf (stdout, "
\n\
\n\n");
}
/*****************************************************************************/
/*
Ensure the text of a message is reasonably formatted.
This includes wrapping lines at 78..132 characters if not quoted.
The 'escape sequence' of a backslash ('\') plus the (user-option) quote
character suppresses wrapping of that line (the 'escape sequence' is removed).
*/
char* ComposeBodyTextMassage
(
char *TextPtr,
int MaxLineLen,
char *QuoteString
)
{
int cnt, lcnt;
char *cptr, *c2ptr, *sptr, *s2ptr, *wsptr, *zptr,
*RevisedTextPtr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeBodyTextMassage() |%s|\n", QuoteString);
if (MaxLineLen <= 0) MaxLineLen = atoi(DEFAULT_WRAP_AT);
/* first, a quick scan to see if any changes are necessary */
lcnt = 0;
cptr = TextPtr;
while (*cptr)
{
zptr = cptr + MaxLineLen;
if (*QuoteString == *cptr)
while (*cptr && *cptr != '\r' && *cptr != '\n') cptr++;
else
{
for (; *cptr && *cptr != '\r' && *cptr != '\n'; cptr++)
{
if (cptr < zptr) continue;
zptr = cptr + MaxLineLen;
lcnt++;
}
}
while (*cptr == '\r' || *cptr == '\n') cptr++;
}
/* original length plus two CRLF for each additional line */
cnt = cptr - TextPtr + lcnt + lcnt + 1;
sptr = RevisedTextPtr = CgiLibVeeMemCalloc (cnt * 10);
if (!sptr) ErrorExit (vaxc$errno, FI_LI);
cptr = TextPtr;
while (*cptr)
{
zptr = sptr + MaxLineLen;
if (*cptr == '\\' && *(cptr+1) == *QuoteString)
{
/* remove the 'escape sequence' and do not wrap the line */
cptr += 2;
/* replace consecutive quote characters by spaces */
while (*cptr && *cptr == *QuoteString)
{
*sptr++ = ' ';
cptr++;
}
while (*cptr && *cptr != '\r' && *cptr != '\n') *sptr++ = *cptr++;
}
else
if (*cptr == *QuoteString)
{
/* 'quoted' - do not wrap the line */
while (*cptr && *cptr != '\r' && *cptr != '\n') *sptr++ = *cptr++;
}
else
{
/* to the end of the current line */
while (*cptr && *cptr != '\r' && *cptr != '\n')
{
/* note the current buffered char */
s2ptr = sptr;
if (*cptr == ' ' || *cptr == '\t')
{
/* white space - look ahead */
c2ptr = cptr;
while ((*c2ptr == ' ' || *c2ptr == '\t') && s2ptr < zptr)
{
c2ptr++;
s2ptr++;
}
/* then further ahead at not white space */
while (*c2ptr && *c2ptr != ' ' && *c2ptr != '\t' &&
*c2ptr != '\r' && *c2ptr != '\n' && s2ptr < zptr)
{
c2ptr++;
s2ptr++;
}
if (s2ptr >= zptr)
{
/* over line length, add a CRLF */
*sptr++ = '\r';
*sptr++ = '\n';
zptr = sptr + MaxLineLen;
/* and absorb remaining white-space */
while (*cptr == ' ' || *cptr == '\t') cptr++;
continue;
}
}
*sptr++ = *cptr++;
}
}
while (*cptr == '\r' || *cptr == '\n') *sptr++ = *cptr++;
}
*sptr = '\0';
return (RevisedTextPtr);
}
/*****************************************************************************/
/*
Create a 'self' address for use as the [SELF] contact and as the SMTP/RFC
"From:" header field.
*/
char* ComposeSelfAddress (REQUEST_DATA *rdptr)
{
int len;
char *cptr, *fhptr, *pnptr, *sptr, *zptr;
char LocalPart [128];
COMPOSE_DATA *cdptr;
USER_OPTIONS *uoptr;
VMS_MAIL_USER *muptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeSelfAddress()\n");
muptr = &VmsMailUser;
cdptr = &rdptr->ComposeData;
uoptr = &rdptr->UserOptions;
len = 16; /* elbow room */
pnptr = NULL;
if (uoptr->PersonalName[0])
len += strlen(pnptr = uoptr->PersonalName);
else
if (muptr->VmsMailPersonalName[0])
len += strlen(pnptr = muptr->VmsMailPersonalName);
fhptr = NULL;
/* user option can just be a host/domain name for user@host/domain */
if (uoptr->SmtpFrom) fhptr = uoptr->SmtpFrom;
if (!fhptr || !*fhptr) fhptr = SoyMailConfig.SmtpFromHost;
/* if not then try for MX logical names */
if (!fhptr) fhptr = TrnLnm ("MX_FROM_HOST", NULL, 0);
if (!fhptr) fhptr = TrnLnm ("MX_ENVELOPE_FROM_HOST", NULL, 0);
if (!fhptr) fhptr = TrnLnm ("MX_NODE_NAME", NULL, 0);
/* fall back to the IP host name */
if (!fhptr) fhptr = LocalHostName;
if (fhptr) len += strlen(fhptr);
if (AddressIsRfc(fhptr))
{
/* full 'whomever@wherever' specified (usually in the user option) */
sptr = CgiLibVeeMemCalloc (len);
if (!sptr) ErrorExit (vaxc$errno, FI_LI);
if (pnptr)
sprintf (sptr, "%s <%s>", pnptr, fhptr);
else
strcpy (sptr, fhptr);
}
else
{
zptr = (sptr = LocalPart) + sizeof(LocalPart)-1;
if (SoyMailConfig.LoginAliasSmtpFrom && rdptr->LoginAliasLength)
{
/* use the login alias as the local part */
for (cptr = rdptr->LoginAlias;
*cptr && sptr < zptr;
*sptr++ = *cptr++);
}
else
{
/* just the host/domain name */
for (cptr = rdptr->UserName;
*cptr && sptr < zptr;
*sptr++ = tolower(*cptr++));
}
*sptr = '\0';
len += sptr - LocalPart;
sptr = CgiLibVeeMemCalloc (len);
if (!sptr) ErrorExit (vaxc$errno, FI_LI);
if (pnptr)
sprintf (sptr, "%s <%s@%s>",
pnptr, LocalPart, fhptr);
else
sprintf (sptr, "%s@%s", LocalPart, fhptr);
}
cdptr->SelfPtr = sptr;
if (WatchEnabled) WatchThis ("SELF !AZ", cdptr->SelfPtr);
return (sptr);
}
/*****************************************************************************/
/*
This monolithic and over-long function creates a MIME compliant RFC822 message.
If there are forwarded attachments and/or soyMAIL attachment files that have
been checked for inclusion a "multipart/mixed" MIME message is generated.
Each attachment with a "text/.." content-type is quoted-printable encoded in a
separate part. Attachments with non-text content are provided as base-64
encoded parts. If there is a message body this is appropriately encoded and
supplied as the first part with a content-type of "text/plain".
If there are no forwarded attachments or files present or checked the message
body is appropriately encoded and made into an in-line MIME message.
*/
BOOL ComposeMime (REQUEST_DATA *rdptr)
{
#define STRINIT(ptr,size) zptr = (sptr = (char*)ptr) + size;
#define STRCAT(str) for (cptr=str; *cptr && sptr= zptr
static char ThisMessageIsInMimeFormat [] =
"This message is in MIME format. If your mail reader does not understand\r\n\
this format, some or all of the message may not be legible.\r\n";
int cnt, len, status,
AttachFileCount,
FwdCount,
DataLength,
FileSizeBytes;
char *cptr, *fnptr, *sptr, *zptr,
*CgiHttpXForwardedForPtr,
*CgiRemoteAddrPtr,
*CgiRemoteHostPtr,
*CgiRemotePortPtr,
*CgiServerNamePtr,
*CharSetPtr,
*ContentTypePtr,
*DataPtr,
*HtmlTextPtr,
*MessageTextPtr,
*MimeEncodedPtr,
*NamePtr,
*PlainTextPtr,
*QuotedPrintableTextPtr,
*TransferEncodingPtr;
char AttId [64],
HeaderBuffer [16384],
MimeBoundary [64],
ScratchBuffer [512];
unsigned long BinTime [2];
stat_t FstatBuffer;
FILE *fp;
COMPOSE_DATA *cdptr;
MIME_DATA *mdptr;
REQUEST_DATA *sdptr;
USER_OPTIONS *uoptr;
TEXT_DATA *tl1ptr, *tl2ptr, *tl3ptr;
VMS_MAIL_MSG *vmptr;
VMS_MAIL_USER *muptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeMime()\n");
muptr = &VmsMailUser;
vmptr = &muptr->VmsMailMsg;
cdptr = &rdptr->ComposeData;
uoptr = &rdptr->UserOptions;
sdptr = (REQUEST_DATA*)rdptr->StateDataPtr;
if (!muptr->VmsMailFullDirectoryLength) ErrorExit (SS$_BUGCHECK, FI_LI);
if (rdptr->MessageId)
{
vmptr->MessageId = rdptr->MessageId;
vmptr->ConfirmHash = rdptr->MessageHash;
}
else
{
vmptr->MessageId = rdptr->MessageId = sdptr->MessageId;
vmptr->ConfirmHash = rdptr->MessageHash = sdptr->MessageHash;
}
sys$gettim (&BinTime);
MimeBoundary[0] = '\0';
CharSetPtr = ComposeSetCharSet (rdptr);
/* the right-to-left flag of a compose-page character set */
if (CharSetPtr[0] == '<') CharSetPtr++;
if (Debug) fprintf (stdout, "charset: %s\n", CharSetPtr);
/****************/
/* message text */
/****************/
if (cdptr->EditorType == COMPOSE_EDITOR_HTML)
MessageTextPtr = cdptr->TextPtr;
else
if (cdptr->WrapAt)
MessageTextPtr = ComposeBodyTextMassage (cdptr->TextPtr,
cdptr->WrapAt,
uoptr->QuoteReply);
else
MessageTextPtr = cdptr->TextPtr;
HtmlTextPtr = MimeEncodedPtr =
PlainTextPtr = QuotedPrintableTextPtr = NULL;
if (cdptr->EditorType == COMPOSE_EDITOR_HTML)
{
/* the HTML text body requires 'quoted-printable'ing */
MimeEncodedPtr = MimeEncQuotedPrintable (MessageTextPtr, -1);
QuotedPrintableTextPtr = MimeEncodedPtr;
HtmlTextPtr = MessageTextPtr;
}
else
if (MimeEncNeedsQuotedPrintable (MessageTextPtr))
{
/* the plain text body requires 'quoted-printable'ing */
MimeEncodedPtr = MimeEncQuotedPrintable (MessageTextPtr, -1);
QuotedPrintableTextPtr = MimeEncodedPtr;
}
else
PlainTextPtr = MimeEncodedPtr = MessageTextPtr;
tl1ptr = tl2ptr = NULL;
AttachFileCount = 0;
/*************************/
/* check for attachments */
/*************************/
/* for forwarded attachments */
CGIVARNULL (cptr, "FORM_COMPOSE_FWD_COUNT");
if (cptr)
FwdCount = atoi(cptr);
else
FwdCount = 0;
if (FwdCount < 0 || FwdCount > 100)
{
StatusMessage (FI_LI, 1, "%s", SysGetMsg(SS$_BUGCHECK));
return (FALSE);
}
if (FwdCount)
{
/* check if any of the attachments are checked */
for (cnt = 1; cnt <= FwdCount; cnt++)
{
sprintf (ScratchBuffer, "FORM_COMPOSE_FWD_%d", cnt);
CGIVARNULL (cptr, ScratchBuffer);
if (cptr) break;
}
if (!cptr) FwdCount = 0;
}
/* for file-system attachments */
fnptr = FileSpecSearch (FALSE, muptr->VmsMailFullDirectory, "SOYMAIL_*.ATT");
/* if either */
if (FwdCount || fnptr)
{
/*******************************/
/* prepare for multipart/mixed */
/*******************************/
/*
Quite possibly, BUT NOT CERTAINLY, be multipart/mixed!!
Won't know until we actually process the potential attachment files.
In the meantime, prepare this first part (the message text) portion
of a multi-part message. It will just get overloaded later if no
attachment files end up getting included (tracked by incrementing
the counter 'AttachmentCount').
*/
sprintf (MimeBoundary, "----_=_%08.08X%08.08X",
BinTime[1], BinTime[0]);
if (HtmlTextPtr && HtmlTextPtr[0])
{
ContentTypePtr = "text/html";
MimeEncodedPtr = QuotedPrintableTextPtr;
TransferEncodingPtr = "quoted-printable";
}
else
if (PlainTextPtr && PlainTextPtr[0])
{
ContentTypePtr = "text/plain";
MimeEncodedPtr = PlainTextPtr;
TransferEncodingPtr = "7bit";
}
else
if (QuotedPrintableTextPtr && QuotedPrintableTextPtr[0])
{
ContentTypePtr = "text/plain";
MimeEncodedPtr = QuotedPrintableTextPtr;
TransferEncodingPtr = "quoted-printable";
}
else
ContentTypePtr = MimeEncodedPtr = TransferEncodingPtr = NULL;
/************************************/
/* "this message is in MIME format" */
/************************************/
/* use the 'tl2ptr' expressly so that it can be used to link later */
len = strlen(ThisMessageIsInMimeFormat);
TEXT_DATA_CALLOC (tl2ptr, len);
if (!tl2ptr) ErrorExit (vaxc$errno, FI_LI);
TEXT_DATA_TEXT(tl2ptr) = TEXT_DATA_SELF(tl2ptr);
strcpy (TEXT_DATA_TEXT(tl2ptr), ThisMessageIsInMimeFormat);
TEXT_DATA_LENGTH(tl2ptr) = len;
/* this IS the first part of the MIME body */
TEXT_DATA_NEXT (&cdptr->MimeBody) = tl2ptr;
if (MimeEncodedPtr)
{
/****************/
/* message text */
/****************/
if (WatchEnabled)
{
WatchThis ("ATTACH (message text)", fnptr);
WatchThis ("MIME TYPE !AZ", ContentTypePtr);
WatchThis ("MIME TRANSFER !AZ", TransferEncodingPtr);
}
/* first will point to the MIME part header */
TEXT_DATA_CALLOC (tl1ptr, 2048);
if (!tl1ptr) ErrorExit (vaxc$errno, FI_LI);
/* link the "this message..." to this new part */
if (tl2ptr) tl2ptr->NextPtr = tl1ptr;
/* second will point to the MIME part encoded content */
TEXT_DATA_CALLOC (tl2ptr, 0);
if (!tl2ptr) ErrorExit (vaxc$errno, FI_LI);
TEXT_DATA_TEXT(tl1ptr) = TEXT_DATA_SELF(tl1ptr);
STRINIT (TEXT_DATA_TEXT(tl1ptr), TEXT_DATA_SIZE(tl1ptr))
STRCAT ("\r\n--")
STRCAT (MimeBoundary)
STRCAT ("\r\nContent-Type: ")
STRCAT (ContentTypePtr)
STRCAT ("; charset=\"")
STRCAT (CharSetPtr)
STRCAT ("\"\r\nContent-Transfer-Encoding: ")
STRCAT (TransferEncodingPtr)
STRCAT ("\r\n\r\n")
STRNULL
TEXT_DATA_LENGTH (tl1ptr) = sptr - TEXT_DATA_TEXT (tl1ptr);
if (STROVF) ErrorExit (SS$_BUGCHECK, FI_LI);
TEXT_DATA_TEXT (tl2ptr) = MimeEncodedPtr;
TEXT_DATA_LENGTH (tl2ptr) = strlen(TEXT_DATA_TEXT (tl2ptr));
TEXT_DATA_NEXT (tl1ptr) = tl2ptr;
if (Debug)
fprintf (stdout, "|%s|\n|%s|\n",
TEXT_DATA_TEXT(tl1ptr), TEXT_DATA_TEXT(tl2ptr));
}
}
/*************************/
/* forwarded attachments */
/*************************/
if (FwdCount)
{
CallMailMessageGet (muptr, NULL);
if (VMSnok (muptr->MailVmsStatus))
{
StatusMessage (FI_LI, 1, "MAIL: %s.", SysGetMsg(muptr->MailVmsStatus));
return (FALSE);
}
MessageBodyProcess (vmptr);
for (cnt = 1; cnt <= FwdCount; cnt++)
{
sprintf (ScratchBuffer, "FORM_COMPOSE_FWD_%d", cnt);
CGIVARNULL (cptr, ScratchBuffer);
if (!cptr) continue;
/********************/
/* checkbox checked */
/********************/
AttachFileCount++;
sprintf (ScratchBuffer, "FORM_COMPOSE_FWD_NAME_%d", cnt);
CGIVARNULL (cptr, ScratchBuffer);
if (!cptr) ErrorExit (SS$_BUGCHECK, FI_LI);
for (mdptr = vmptr->MimeDataPtr; mdptr; mdptr = mdptr->NextMimePtr)
{
if (!(mdptr->NamePtr || mdptr->FileNamePtr)) continue;
if (mdptr->NamePtr)
NamePtr = mdptr->NamePtr;
else
NamePtr = mdptr->FileNamePtr;
if (!strcmp (NamePtr, cptr)) break;
}
if (!mdptr)
{
StatusMessage (FI_LI, 1, "%s", SysGetMsg(SS$_BUGCHECK));
return (FALSE);
}
ContentTypePtr = mdptr->ContentTypePtr;
TransferEncodingPtr = mdptr->TransferEncodingPtr;
if (!NamePtr || !ContentTypePtr || !TransferEncodingPtr)
{
StatusMessage (FI_LI, 1, "%s", SysGetMsg(SS$_BUGCHECK));
return (FALSE);
}
if (WatchEnabled)
{
WatchThis ("MIME NAME !AZ", NamePtr);
WatchThis ("MIME TYPE !AZ", ContentTypePtr);
WatchThis ("MIME TRANSFER !AZ", TransferEncodingPtr);
}
/* first will point to the MIME part header */
TEXT_DATA_CALLOC (tl1ptr, 512);
if (!tl1ptr) ErrorExit (vaxc$errno, FI_LI);
/* if there was a previous part then link it to this new part */
if (tl2ptr) tl2ptr->NextPtr = tl1ptr;
/* second will point to the MIME part encoded content */
TEXT_DATA_CALLOC (tl2ptr, 0);
if (!tl2ptr) ErrorExit (vaxc$errno, FI_LI);
TEXT_DATA_TEXT(tl1ptr) = TEXT_DATA_SELF(tl1ptr);
STRINIT (TEXT_DATA_TEXT(tl1ptr), TEXT_DATA_SIZE(tl1ptr))
STRCAT ("\r\n--")
STRCAT (MimeBoundary)
STRCAT ("\r\nContent-Type: ")
STRCAT (ContentTypePtr)
STRCAT (";\r\n name=\"")
STRCAT (NamePtr)
STRCAT ("\"\r\nContent-Transfer-Encoding: ")
STRCAT (TransferEncodingPtr)
STRCAT ("\r\nContent-Disposition: attachment;\r\n filename=\"")
STRCAT (NamePtr)
STRCAT ("\"\r\n\r\n")
STRNULL
TEXT_DATA_LENGTH (tl1ptr) = sptr - TEXT_DATA_TEXT (tl1ptr);
if (STROVF) ErrorExit (SS$_BUGCHECK, FI_LI);
/* terminate the MIME content just for these purposes */
mdptr->PartContentPtr[mdptr->PartContentLength] = '\0';
TEXT_DATA_TEXT (tl2ptr) = mdptr->PartContentPtr;
TEXT_DATA_LENGTH (tl2ptr) = mdptr->PartContentLength;
/* if this is the first part of the MIME body */
if (!TEXT_DATA_NEXT (&cdptr->MimeBody))
TEXT_DATA_NEXT (&cdptr->MimeBody) = tl1ptr;
TEXT_DATA_NEXT (tl1ptr) = tl2ptr;
if (Debug)
fprintf (stdout, "%d\n|%s|\n|%s|\n",
AttachFileCount, TEXT_DATA_TEXT(tl1ptr),
TEXT_DATA_TEXT(tl2ptr));
}
}
/********************/
/* attachment files */
/********************/
while (fnptr)
{
/* get the digits from the file name */
for (cptr = fnptr; *cptr; cptr++);
while (cptr > fnptr && *cptr != ']') cptr--;
if (*cptr == ']') cptr++;
while (*cptr && !isdigit(*cptr)) cptr++;
zptr = (sptr = AttId) + sizeof(AttId);
while (isdigit(*cptr) && sptr < zptr) *sptr++ = *cptr++;
if (sptr > zptr) ErrorExit (SS$_BUGCHECK, FI_LI);
*sptr = '\0';
if (WatchEnabled) WatchThis ("ATTACH !AZ", fnptr);
/* check if the attachment checkbox is currently checked */
sprintf (ScratchBuffer, "FORM_PART_CBX_%s", AttId);
CGIVARNULL (sptr, ScratchBuffer);
/* if not checked just continue */
if (!sptr)
{
fnptr = FileSpecSearch (FALSE, NULL, NULL);
continue;
}
/********************/
/* checkbox checked */
/********************/
AttachFileCount++;
fp = fopen (fnptr, "r", "ctx=bin");
if (!fp)
{
status = vaxc$errno;
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(status));
return (FALSE);
}
if (fstat (fileno(fp), &FstatBuffer))
{
status = vaxc$errno;
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(status));
return (FALSE);
}
FileSizeBytes = FstatBuffer.st_size;
DataPtr = CgiLibVeeMemCalloc (FileSizeBytes);
if (!DataPtr)
{
status = vaxc$errno;
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(status));
return (FALSE);
}
DataLength = read (fileno(fp), DataPtr, FileSizeBytes);
if (DataLength <= 0)
{
status = vaxc$errno;
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(status));
return (FALSE);
}
fclose (fp);
NamePtr = ContentTypePtr = NULL;
if (!strncmp (DataPtr, "[soyMAIL-version]", 17))
{
sptr = DataPtr + 17;
while (*sptr) sptr++;
sptr++;
if (!strncmp (sptr, "[name]", 6))
{
NamePtr = sptr += 6;
while (*sptr) sptr++;
sptr++;
if (!strncmp (sptr, "[type]", 6))
{
ContentTypePtr = sptr += 6;
while (*sptr) sptr++;
sptr++;
if (!strncmp (sptr, "[content]", 9)) sptr += 9;
FileSizeBytes -= sptr - DataPtr;
}
}
}
if (!NamePtr || !ContentTypePtr)
{
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(SS$_BUGCHECK));
return (FALSE);
}
if (!strncmp (cptr, "text/", 5))
{
if (WatchEnabled)
WatchThis ("MIME QUOTED-PRINTABLE !UL bytes", FileSizeBytes);
MimeEncodedPtr = MimeEncQuotedPrintable (sptr, FileSizeBytes);
if (!MimeEncodedPtr)
{
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(SS$_BUGCHECK));
return (FALSE);
}
TransferEncodingPtr = "quoted-printable";
}
else
{
if (WatchEnabled) WatchThis ("MIME BASE64 !UL bytes", FileSizeBytes);
MimeEncodedPtr = MimeEncBase64 (sptr, FileSizeBytes, "\r\n");
if (!MimeEncodedPtr)
{
StatusMessage (FI_LI, 1, "%s: %s.", AttId, SysGetMsg(SS$_BUGCHECK));
return (FALSE);
}
TransferEncodingPtr = "base64";
}
if (WatchEnabled)
{
WatchThis ("MIME NAME !AZ", NamePtr);
WatchThis ("MIME TYPE !AZ", ContentTypePtr);
WatchThis ("MIME TRANSFER !AZ", TransferEncodingPtr);
}
/* first will point to the MIME part header */
TEXT_DATA_CALLOC (tl1ptr, 512);
if (!tl1ptr) ErrorExit (vaxc$errno, FI_LI);
/* if there was a previous part then link it to this new part */
if (tl2ptr) tl2ptr->NextPtr = tl1ptr;
/* second will point to the MIME part encoded content */
TEXT_DATA_CALLOC (tl2ptr, 0);
if (!tl2ptr) ErrorExit (vaxc$errno, FI_LI);
TEXT_DATA_TEXT(tl1ptr) = TEXT_DATA_SELF(tl1ptr);
STRINIT (TEXT_DATA_TEXT(tl1ptr), TEXT_DATA_SIZE(tl1ptr))
STRCAT ("\r\n--")
STRCAT (MimeBoundary)
STRCAT ("\r\nContent-Type: ")
STRCAT (ContentTypePtr)
STRCAT (";\r\n name=\"")
STRCAT (NamePtr)
STRCAT ("\"\r\nContent-Transfer-Encoding: ")
STRCAT (TransferEncodingPtr)
STRCAT ("\r\nContent-Disposition: attachment;\r\n filename=\"")
STRCAT (NamePtr)
STRCAT ("\"\r\n\r\n")
STRNULL
TEXT_DATA_LENGTH (tl1ptr) = sptr - TEXT_DATA_TEXT (tl1ptr);
if (STROVF) ErrorExit (SS$_BUGCHECK, FI_LI);
TEXT_DATA_TEXT (tl2ptr) = MimeEncodedPtr;
TEXT_DATA_LENGTH (tl2ptr) = strlen(TEXT_DATA_TEXT (tl2ptr));
/* if this is the first part of the MIME body */
if (!TEXT_DATA_NEXT (&cdptr->MimeBody))
TEXT_DATA_NEXT (&cdptr->MimeBody) = tl1ptr;
TEXT_DATA_NEXT (tl1ptr) = tl2ptr;
if (Debug)
fprintf (stdout, "%d\n|%s|\n|%s|\n",
AttachFileCount, TEXT_DATA_TEXT(tl1ptr),
TEXT_DATA_TEXT(tl2ptr));
/* free the attachment file content */
CgiLibVeeMemFree (DataPtr);
fnptr = FileSpecSearch (FALSE, NULL, NULL);
}
/******************************/
/* end of (any) attachment(s) */
/******************************/
if (AttachFileCount)
{
/* INCLUDED ATTACHMENT(S), add the final trailing MIME boundary */
TEXT_DATA_CALLOC (tl3ptr, 128);
if (!tl3ptr) ErrorExit (vaxc$errno, FI_LI);
TEXT_DATA_TEXT(tl3ptr) = TEXT_DATA_SELF(tl3ptr);
STRINIT (TEXT_DATA_SELF(tl3ptr), TEXT_DATA_SIZE(tl3ptr))
STRCAT ("\r\n--")
STRCAT (MimeBoundary)
STRCAT ("--\r\n")
STRNULL
TEXT_DATA_LENGTH (tl3ptr) = sptr - TEXT_DATA_TEXT (tl3ptr);
if (STROVF) ErrorExit (SS$_BUGCHECK, FI_LI);
TEXT_DATA_NEXT (tl2ptr) = tl3ptr;
}
else
{
/* NO ATTACHMENTS, make the text body in-line */
TEXT_DATA_CALLOC (tl1ptr, 0);
if (!tl1ptr) ErrorExit (vaxc$errno, FI_LI);
TEXT_DATA_TEXT (tl1ptr) = MimeEncodedPtr;
TEXT_DATA_LENGTH (tl1ptr) = strlen(TEXT_DATA_TEXT (tl1ptr));
/* if this is the only part of the MIME body */
TEXT_DATA_NEXT (&cdptr->MimeBody) = tl1ptr;
}
/***********************************/
/* create an RFC822 message header */
/***********************************/
zptr = (sptr = HeaderBuffer) + sizeof(HeaderBuffer);
CGIVARNULL (CgiServerNamePtr, "SERVER_NAME");
if (!CgiServerNamePtr) CgiServerNamePtr = "?";
CGIVARNULL (CgiRemoteHostPtr, "REMOTE_HOST");
if (!CgiRemoteHostPtr) CgiRemoteHostPtr = "?";
CGIVARNULL (CgiRemoteAddrPtr, "REMOTE_ADDR");
if (!CgiRemoteAddrPtr) CgiRemoteAddrPtr = "?.?.?.?";
CGIVARNULL (CgiRemotePortPtr, "REMOTE_PORT");
if (!CgiRemotePortPtr) CgiRemotePortPtr = "?";
CGIVARNULL (CgiHttpXForwardedForPtr, "HTTP_X_FORWARDED_FOR");
zptr = (sptr = ScratchBuffer) + sizeof(ScratchBuffer);
STRCAT ("from SOYMAIL (")
if (strcmp (CgiRemoteHostPtr, CgiRemoteAddrPtr))
{
/* resolved host name in REMOTE_HOST */
STRCAT (CgiRemoteHostPtr)
STRCAT (" [")
STRCAT (CgiRemoteAddrPtr)
STRCAT ("]")
}
else
{
/* try to resolve host name from address */
cptr = MtaHostNameByAddr (CgiRemoteAddrPtr);
if (cptr)
{
STRCAT (cptr)
STRCAT (" ")
}
STRCAT ("[")
STRCAT (CgiRemoteAddrPtr)
STRCAT ("]")
}
if (CgiHttpXForwardedForPtr)
{
STRCAT (" forwarded for ")
STRCAT (CgiHttpXForwardedForPtr)
}
STRCAT (") by ")
STRCAT (LocalHostName)
STRCAT (" (")
STRCAT (SoftwareId)
STRCAT (") with HTTP; ")
STRCAT (MtaRfcBinDate(NULL,NULL))
STRNULL
if (STROVF)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
zptr = (sptr = HeaderBuffer) + sizeof(HeaderBuffer);
len = InetMailFoldRfc822Header (sptr, zptr-sptr,
"Received:", ScratchBuffer);
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
sptr += sprintf (sptr,
"Message-ID: <%s.%s.%08.08x%08.08x.soymail@%s>\r\nDate: %s\r\n",
CgiRemoteAddrPtr, CgiRemotePortPtr,
BinTime[1], BinTime[0], LocalHostName,
ComposeRfcDate());
if (cdptr->InReplyToPtr)
{
len = InetMailFoldRfc822Header (sptr, zptr-sptr,
"In-Reply-To:", cdptr->InReplyToPtr);
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
}
if (cdptr->ReferencesPtr)
{
len = InetMailFoldRfc822Header (sptr, zptr-sptr,
"References:", cdptr->ReferencesPtr);
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
}
len = InetMailFoldRfc822Header (sptr, zptr-sptr, "Subject:",
MimeEncIsoString(cdptr->SubjPtr,
CharSetPtr));
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
if (len)
sptr += len;
else
STRCAT ("Subject: (none)\r\n")
len = InetMailFoldRfc822Header (sptr, zptr-sptr, "From:",
MimeEncIsoString(cdptr->FromPtr,CharSetPtr));
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
if (cdptr->ReplyToPtr && cdptr->ReplyToPtr[0])
{
len = InetMailFoldRfc822Header (sptr, zptr-sptr, "Reply-to:",
MimeEncIsoString(cdptr->ReplyToPtr,CharSetPtr));
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
}
len = InetMailFoldRfc822Header (sptr, zptr-sptr, "To:",
MimeEncIsoString(cdptr->ToPtr,
CharSetPtr));
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
len = InetMailFoldRfc822Header (sptr, zptr-sptr, "CC:",
MimeEncIsoString(cdptr->CcPtr,
CharSetPtr));
if (len < 0)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
sptr += len;
if (cdptr->BccPtr && cdptr->BccPtr[0]) STRCAT ("BCC:\r\n")
STRCAT ("MIME-Version: 1.0\r\n")
if (AttachFileCount)
{
/* INCLUDED ATTACHMENT(S) so ended up being multipart/mixed */
STRCAT ("Content-Type: multipart/mixed;\r\n boundary=\"")
STRCAT (MimeBoundary)
STRCAT ("\"\r\n")
}
else
if (HtmlTextPtr)
{
/* NO ATTACHMENT(S) so just inline content */
STRCAT ("Content-Type: text/html; charset=")
STRCAT (CharSetPtr)
STRCAT ("\r\nContent-Transfer-Encoding: quoted-printable\r\n")
}
else
if (QuotedPrintableTextPtr)
{
/* ditto */
STRCAT ("Content-Type: text/plain; charset=")
STRCAT (CharSetPtr)
STRCAT ("\r\nContent-Transfer-Encoding: quoted-printable\r\n")
}
else
{
/* ditto again */
STRCAT ("Content-Type: text/plain; charset=")
STRCAT (CharSetPtr)
STRCAT ("\r\nContent-Transfer-Encoding: 7bit\r\n")
}
STRCAT ("X-Mailer: ")
STRCAT (SoftwareId)
STRCAT ("\r\n\r\n")
STRNULL
if (STROVF)
{
StatusMessage (FI_LI, 1, "RFC822: %s.", SysGetMsg(SS$_RESULTOVF));
return (FALSE);
}
len = sptr - HeaderBuffer;
sptr = CgiLibVeeMemCalloc (len);
if (!sptr) ErrorExit (vaxc$errno, FI_LI);
memcpy (sptr, HeaderBuffer, len+1);
if (WatchEnabled) WatchThis ("RFC822 HEADER\n!AZ", HeaderBuffer);
TEXT_DATA_TEXT (&cdptr->MimeHeader) = sptr;
TEXT_DATA_SIZE (&cdptr->MimeHeader) = len+1;
TEXT_DATA_LENGTH (&cdptr->MimeHeader) = len;
return (TRUE);
}
/*****************************************************************************/
/*
Send the mail message contained in the 'compose data'.
*/
void ComposeSendMessage (REQUEST_DATA *rdptr)
{
int len, status;
char *cptr, *sptr, *zptr,
*AddrListPtr,
*SentItemsFileNamePtr,
*SentItemsFromPtr,
*SmtpServerPtr;
char UpCaseRemoteUser [256];
COMPOSE_DATA *cdptr;
USER_OPTIONS *uoptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeSendMessage()\n");
cdptr = &rdptr->ComposeData;
uoptr = &rdptr->UserOptions;
for (cptr = cdptr->ToPtr; *cptr && isspace(*cptr); cptr++);
if (!*cptr)
{
StatusMessage (FI_LI, 1, "%s", LangFor("compose_no_recipient"));
return;
}
/* ensure each of the addresses are comma-delimitted */
cdptr->ToPtr = AddressListMassage (cdptr->ToPtr, TRUE);
cdptr->CcPtr = AddressListMassage (cdptr->CcPtr, TRUE);
cdptr->BccPtr = AddressListMassage (cdptr->BccPtr, TRUE);
if (!cdptr->FromPtr) cdptr->FromPtr = cdptr->SelfPtr;
/* if it looks like one or more RFC822 addresses */
if (AddressIsRfc(cdptr->ToPtr) ||
AddressIsRfc(cdptr->CcPtr) ||
AddressIsRfc(cdptr->BccPtr) ||
AddressIsRfc(cdptr->ReplyToPtr))
{
/************************/
/* send via an SMTP MTA */
/************************/
if (AddressIsVms(cdptr->ToPtr) ||
AddressIsVms(cdptr->CcPtr) ||
AddressIsVms(cdptr->BccPtr) ||
AddressIsVms(cdptr->ReplyToPtr))
{
StatusMessage (FI_LI, 1, "%s", LangFor("compose_either_or"));
return;
}
ComposeMime (rdptr);
/* create a single list of all the addresses for the MTA SMTP server */
len = strlen(cdptr->ToPtr) +
strlen(cdptr->CcPtr) +
strlen(cdptr->BccPtr) + 8;
AddrListPtr = CgiLibVeeMemCalloc (len);
if (!AddrListPtr) ErrorExit (vaxc$errno, FI_LI);
sprintf (AddrListPtr, "%s%s%s%s%s",
cdptr->ToPtr,
cdptr->CcPtr[0] ? "\n" : "", cdptr->CcPtr,
cdptr->BccPtr[0] ? "\n" : "", cdptr->BccPtr);
SmtpServerPtr = SoyMailConfig.SmtpServerHost;
if (!SmtpServerPtr) SmtpServerPtr = "localhost";
cptr = MtaMsgSmtpToServer (SmtpServerPtr,
SentItemsFromPtr = cdptr->FromPtr,
AddrListPtr,
NULL,
&cdptr->MimeHeader,
NULL,
&cdptr->MimeBody);
if (cptr)
StatusMessage (FI_LI, 1, "SMTP: %s", HTML_ESCAPE(cptr));
else
if (uoptr->FolderSentItems[0])
{
/* message sent OK, place it into the "sent Items" folder */
SentItemsFileNamePtr = SoyMailTempFileName();
status = MtaMsgToFile (SentItemsFileNamePtr,
SentItemsFromPtr, cdptr->ToPtr,
cdptr->CcPtr, cdptr->SubjPtr,
&cdptr->MimeHeader,
&cdptr->MimeBody);
if (VMSok (status))
status = CallMailCopyFile (&VmsMailUser,
"MAIL", uoptr->FolderSentItems,
SentItemsFileNamePtr);
if (VMSnok (status))
StatusMessage (FI_LI, 1, "%s: %s.",
uoptr->FolderSentItems, SysGetMsg(status));
while (!remove (SentItemsFileNamePtr));
}
}
else
{
/****************************************/
/* otherwise send via VMS callable mail */
/****************************************/
if (cdptr->BccPtr && cdptr->BccPtr[0])
{
StatusMessage (FI_LI, 1, "%s: %s",
LangFor("compose_bcc_vms_address"),
cdptr->BccPtr);
return;
}
else
if (cdptr->ReplyToPtr && cdptr->ReplyToPtr[0])
{
StatusMessage (FI_LI, 1, "%s: %s",
LangFor("compose_reply_to_vms_address"),
cdptr->ReplyToPtr);
return;
}
/* ensure that the body of the message is correctly wrapped */
cdptr->TextPtr = ComposeBodyTextMassage (cdptr->TextPtr,
cdptr->WrapAt,
uoptr->QuoteReply);
/* autogenous authentication login may mean this is in lower-case */
zptr = (sptr = UpCaseRemoteUser) + sizeof(UpCaseRemoteUser)-1;
for (cptr = rdptr->RemoteUser;
*cptr && sptr < zptr;
*sptr++ = toupper(*cptr++));
*sptr = '\0';
cptr = SendMailMessage (SentItemsFromPtr = UpCaseRemoteUser,
cdptr->ToPtr,
cdptr->CcPtr,
cdptr->SubjPtr,
cdptr->TextPtr);
if (cptr)
StatusMessage (FI_LI, 1, "MAIL: %s", cptr);
else
if (uoptr->FolderSentItems[0])
{
/* message sent OK, place it into the "sent Items" folder */
SentItemsFileNamePtr = SoyMailTempFileName();
status = SendMailToFile (SentItemsFileNamePtr,
SentItemsFromPtr, cdptr->ToPtr,
cdptr->CcPtr, cdptr->SubjPtr,
cdptr->TextPtr);
if (VMSok (status))
status = CallMailCopyFile (&VmsMailUser,
"MAIL", uoptr->FolderSentItems,
SentItemsFileNamePtr);
if (VMSnok (status))
StatusMessage (FI_LI, 1, "%s: %s.",
uoptr->FolderSentItems, SysGetMsg(status));
while (!remove (SentItemsFileNamePtr));
}
}
if (!cptr)
{
/* if the 'delete all attachments after sending' checkbox is */
CGIVARNULL (cptr, "FORM_ATTACH_CBX_DELETE");
if (cptr) AttachDelete (rdptr, NULL);
StatusMessage (FI_LI, -1, "%s", LangFor("compose_sent_ok"));
cdptr->AlreadySent = TRUE;
}
}
/*****************************************************************************/
/*
*/
void ComposeSendClose (REQUEST_DATA *rdptr)
{
char *cptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeSendClose()\n");
CGIVAR (cptr, "FORM_COMPOSE_SEND_CLOSE_CHILD");
if (cptr && *cptr)
{
/* close the child window */
CgiLibResponseHeader (200, "text/html",
"Script-Control: X-content-encoding-gzip=0\n%s",
rdptr->LoginSetCookiePtr);
fprintf (stdout,
"\n");
}
else
{
/* go back to the message list */
MessageFolderPage (rdptr);
}
}
/*****************************************************************************/
/*
Load a signature file. If enabled by soyMAIL configuration check for either
one or both
[SMTP-from]
[SMTP-reply-to]
To set the corresponding message header fields. This allows for a form of
mail 'persona' where the one user can have multiple mailing identities. These
must be the first lines in the file.
*/
void ComposeSigFileLoad
(
REQUEST_DATA *rdptr,
char *SigFileName
)
{
int cnt;
char *cptr, *sptr, *zptr;
char buf [256];
COMPOSE_DATA *cdptr;
VMS_MAIL_USER *muptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeSigFileLoad()\n");
muptr = &VmsMailUser;
cdptr = &rdptr->ComposeData;
OptionsSigFileLoad (rdptr, SigFileName);
if (!muptr->SignaturePtr || !muptr->SignatureLength) return;
if (SigFileName) StatusMessage (FI_LI, 0, LangFor("compose_sign_done"));
/* is it enabled? value can be -1, 0, 1 */
if (SoyMailConfig.ComposeUserFrom <= 0) return;
cnt = 0;
cptr = muptr->SignaturePtr;
while (*cptr == '[')
{
if (strsame (cptr, "[SMTP-from]", 11))
{
for (cptr += 11; *cptr && *cptr != '\n' && isspace(*cptr); cptr++);
if (*cptr && *cptr != '\n')
{
zptr = (sptr = buf) + sizeof(buf)-1;
while (*cptr && *cptr != '\n' && sptr < zptr) *sptr++ = *cptr++;
*sptr = '\0';
if (buf[0])
{
cdptr->FromPtr = CgiLibVeeMemCalloc (sptr-buf+1);
if (!cdptr->FromPtr) ErrorExit (vaxc$errno, FI_LI);
strcpy (cdptr->FromPtr, buf);
cnt++;
}
}
}
else
if (strsame (cptr, "[SMTP-reply-to]", 15))
{
for (cptr += 15; *cptr && *cptr != '\n' && isspace(*cptr); cptr++);
if (*cptr && *cptr != '\n')
{
zptr = (sptr = buf) + sizeof(buf)-1;
while (*cptr && *cptr != '\n' && sptr < zptr) *sptr++ = *cptr++;
*sptr = '\0';
if (buf[0])
{
cdptr->ReplyToPtr = CgiLibVeeMemCalloc (sptr-buf+1);
if (!cdptr->ReplyToPtr) ErrorExit (vaxc$errno, FI_LI);
strcpy (cdptr->ReplyToPtr, buf);
cnt++;
}
}
}
while (*cptr && *cptr != '\n') cptr++;
if (*cptr) cptr++;
}
if (cnt)
{
muptr->SignatureLength -= cptr - muptr->SignaturePtr;
muptr->SignaturePtr = cptr;
}
}
/*****************************************************************************/
/*
Check for the JavaScript created and set form field CLIENT_TIME and use this to
set the message origination date/time if available (and makes sense).
Otherwise just fall back to the time/zone VMS system soyMAIL is running on.
*/
char* ComposeRfcDate ()
{
int cnt, status;
int IntTime [6];
unsigned long BinTime [2];
unsigned short NumTime [7];
char *cptr, *sptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeRfcDate()\n");
CGIVARNULL (cptr, "FORM_CLIENT_TIME");
if (!cptr) return (MtaRfcBinDate(NULL,NULL));
cnt = sscanf (cptr, "%d:%d:%d:%d:%d:%d:",
&IntTime[0], &IntTime[1], &IntTime[2],
&IntTime[3], &IntTime[4], &IntTime[5]);
if (Debug) fprintf (stdout, "sscanf() %d\n", cnt);
if (cnt != 6) return (MtaRfcBinDate(NULL,NULL));
NumTime[0] = IntTime[0];
NumTime[1] = IntTime[1];
NumTime[2] = IntTime[2];
NumTime[3] = IntTime[3];
NumTime[4] = IntTime[4];
NumTime[5] = IntTime[5];
NumTime[6] = 0;
status = lib$cvt_vectim (&NumTime, &BinTime);
if (Debug) fprintf (stdout, "lib$cvt_vectim() %%X%08.08X\n", status);
if (VMSnok (status)) return (MtaRfcBinDate(NULL,NULL));
for (sptr = cptr; *sptr; sptr++);
while (sptr > cptr && *sptr != ':') sptr--;
if (*sptr != ':') return (MtaRfcBinDate(NULL,NULL));
return (MtaRfcBinDate(BinTime,sptr+1));
}
/*****************************************************************************/
/*
Return the next value from that supplied in the parameter.
Initially call with -1 to begin sequence.
*/
int ComposeWrapAt
(
int WrapAt,
USER_OPTIONS *uoptr
)
{
static int ValueCount;
static int WrapAtValue [16];
int idx, idx2, value;
char *cptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeWrapAt() %d\n", WrapAt);
if (!ValueCount)
{
if (!(cptr = uoptr->ComposeWrapAt)[0])
if (!(cptr = SoyMailConfig.ComposeWrapAt))
cptr = DEFAULT_WRAP_AT;
for (idx = 0; idx < 15;)
{
while (*cptr && !isdigit(*cptr)) cptr++;
if (!*cptr) break;
WrapAtValue[idx] = atoi(cptr);
while (*cptr && isdigit(*cptr)) cptr++;
for (idx2 = 0; idx2 < idx; idx2++)
if (WrapAtValue[idx2] == WrapAtValue[idx]) break;
if (idx2 >= idx) idx++;
}
ValueCount = idx;
}
if (WrapAt < 0) return (WrapAtValue[0]);
for (idx = 0; idx < ValueCount-1; idx++)
if (WrapAtValue[idx] == WrapAt)
return (WrapAtValue[idx+1]);
return (-1);
}
/*****************************************************************************/
/*
Return the next value from that supplied in the parameter.
Initially call with -1 to begin sequence.
*/
int ComposeEditRows
(
int EditRows,
USER_OPTIONS *uoptr
)
{
static int PrevUsageCount = -1,
ValueCount;
static int EditRowsValue [16];
int idx, idx2, value;
char *cptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeEditRows() %d\n", EditRows);
if (CgiPlusUsageCount != PrevUsageCount)
{
PrevUsageCount = CgiPlusUsageCount;
if (!(cptr = uoptr->ComposeEditRows)[0])
if (!(cptr = SoyMailConfig.ComposeEditRows))
cptr = DEFAULT_EDIT_ROWS;
for (idx = 0; idx < sizeof(EditRowsValue)/sizeof(int); idx++)
{
while (*cptr && !isdigit(*cptr)) cptr++;
if (!*cptr) break;
EditRowsValue[idx] = atoi(cptr);
while (*cptr && isdigit(*cptr)) cptr++;
}
ValueCount = idx;
}
if (EditRows <= 0) return (EditRowsValue[0]);
for (idx = 0; idx < ValueCount-1; idx++)
if (EditRowsValue[idx])
if (EditRowsValue[idx] == EditRows)
return (EditRowsValue[idx+1]);
return (-1);
}
/*****************************************************************************/
/*
Return the next value from that supplied in the parameter.
Initially call with -1 to begin sequence.
*/
int ComposeEditCols
(
int EditCols,
USER_OPTIONS *uoptr
)
{
static int PrevUsageCount = -1,
ValueCount;
static int EditColsValue [16];
int idx, idx2, value;
char *cptr;
/*********/
/* begin */
/*********/
if (Debug) fprintf (stdout, "ComposeEditCols() %d\n", EditCols);
if (CgiPlusUsageCount != PrevUsageCount)
{
PrevUsageCount = CgiPlusUsageCount;
if (!(cptr = uoptr->ComposeEditCols)[0])
if (!(cptr = SoyMailConfig.ComposeEditCols))
cptr = DEFAULT_EDIT_COLS;
for (idx = 0; idx < sizeof(EditColsValue)/sizeof(int); idx++)
{
while (*cptr && !isdigit(*cptr)) cptr++;
if (!*cptr) break;
EditColsValue[idx] = atoi(cptr);
while (*cptr && isdigit(*cptr)) cptr++;
}
ValueCount = idx;
}
if (EditCols <= 0) return (EditColsValue[0]);
for (idx = 0; idx < ValueCount-1; idx++)
if (EditColsValue[idx])
if (EditColsValue[idx] == EditCols)
return (EditColsValue[idx+1]);
return (-1);
}
/*****************************************************************************/
/*
Open a new page with an approximation of the received message.
*/
char* ComposePreviewMessage (REQUEST_DATA *rdptr)
{
int cnt, status,
ReadPreference,
WrapAt;
char *aptr, *cptr, *sptr, *zptr,
*CharSetPtr,
*TextPtr;
PRINT_MEM *pmptr;
COMPOSE_DATA *cdptr;
MIME_DATA *mdptr;
REQUEST_DATA *sdptr;
USER_OPTIONS *uoptr;
VMS_MAIL_MSG *vmptr;
VMS_MAIL_USER *muptr;
/*********/
/* begin */
/*********/
if (WatchEnabled) WatchThis ("ComposePreviewMessage()");
muptr = &VmsMailUser;
uoptr = &rdptr->UserOptions;
sdptr = (REQUEST_DATA*)rdptr->StateDataPtr;
vmptr = &muptr->VmsMailMsg;
cdptr = &rdptr->ComposeData;
pmptr = (PRINT_MEM*)cdptr->PreviewMem;
memset (pmptr, 0, sizeof(PRINT_MEM));
if (SoyMailConfig.ComposeUserFrom > 0)
{
/* only when enabled (1) not when display (-1) */
CGIVARNULL (cdptr->FromPtr, "FORM_COMPOSE_FROM");
if (!cdptr->FromPtr) cdptr->FromPtr = cdptr->SelfPtr;
/* ensure it's not empty (or effectively empty) */
for (cptr = cdptr->FromPtr; *cptr && isspace(*cptr); cptr++);
if (!*cptr) cdptr->FromPtr = cdptr->SelfPtr;
}
CGIVARNULL (cptr, "FORM_COMPOSE_WRAP_AT");
if (cptr) WrapAt = atoi(cptr);
CGIVAR (CharSetPtr, "FORM_COMPOSE_CHARSET");
aptr = "ltr";
if (CharSetPtr && CharSetPtr[0] == '<')
{
aptr = "rtl";
CharSetPtr++;
}
PrintMem (pmptr,
"%s\n\
\n\
\n\
%s\
\n\
\n\
\n",
DocType,
CgiLibXUACompatible(NULL),
SoftwareEnv,
CgiEnvironmentPtr,
SoftwareCopy);
if (!(CharSetPtr && CharSetPtr[0])) CharSetPtr = rdptr->CharSetPtr;
if (CharSetPtr && CharSetPtr[0])
PrintMem (pmptr,
"\n\
\n",
CharSetPtr, CharSetPtr);
/* basic soyMAIL styles */
PrintMem (pmptr,
"\n",
SOY_PATH, "soymail.css", SoyMailQueryVersion);
PrintMem (pmptr,
"\n",
uoptr->FontFamily,
uoptr->FontSize);
PrintMem (pmptr,
"%s %s\n\
\n\n\
\n\
\n\