/*****************************************************************************/ /* public.c For public access ... Displays a list of messages in a folder. Displays the contents of a message (header, body, links to attachments). Displays a 'print-view' (more suitable for printing) of a message. Displays the raw message (header+body, or header alone). Of course with limitations and in a format that is suitable for public access! COPYRIGHT --------- Copyright (C) 2005-2023 Mark G.Daniel This program, comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it under the conditions of the GNU GENERAL PUBLIC LICENSE, version 3, or any later version. VERSION HISTORY --------------- 04-NOV-2014 MGD bugfix; PublicPageBegin() FORM_ACCEPT_CHARSET 09-JUN-2013 MGD PublicFooter() and [public-footer] 19-JUL-2006 MGD PublicMessageFolderList() user optional message ordering 27-APR-2006 MGD bugfix; PublicMessageRequest() detect [search] button 03-APR-2005 MGD significant rework to rationalise public and private significant changes to support public wildcard folders 30-MAR-2006 MGD PublicMessagePage() precede each message part/attachment with an anchor/link for right-click browser save-as 28-FEB-2006 MGD major refinements to public access 01-FEB-2005 MGD initial */ /*****************************************************************************/ #ifdef SOYMAIL_VMS_V7 #undef _VMS_V6_SOURCE #define _VMS_V6_SOURCE #undef __VMS_VER #define __VMS_VER 70000000 #undef __CRTL_VER #define __CRTL_VER 70000000 #endif #pragma nomember_alignment /* standard C header files */ #include #include #include #include #include /* VMS related header files */ #include #include #include #include /* application header file */ #include "soymail.h" #include "attach.h" #include "callmail.h" #include "cgilib.h" #include "compose.h" #include "config.h" #include "html.h" #include "mainmenu.h" #include "other.h" #include "public.h" #include "message.h" #include "request.h" /* can't get the include dependencies settled (this'll do in the interim) */ int ComposeWrapAt (int, USER_OPTIONS*); #define FI_LI __FILE__, __LINE__ /* global storage */ /* external storage */ extern BOOL Debug, WatchEnabled; extern int VmsVersion; extern char *CgiEnvironmentPtr; extern char CurrentVmsTimeString[], DocType[], SoftwareCopy[], SoftwareEnv[], SoftwareId[], SoftwareVn[]; extern CONFIG_DATA SoyMailConfig; extern REQUEST_DATA RequestData; extern VMS_MAIL_USER VmsMailUser; /* ad hoc prototypes */ int lib$day_of_week(__unknown_params); int sys$fao(__unknown_params); /****************************************************************************/ /* Parse the buttons associated with the public folder message list. */ void PublicFolderRequest (REQUEST_DATA *rdptr) { int cnt, hash; char *cptr, *sptr, *zptr, *MsgRangeListPtr; char MsgBtnString [32], MsgCbxString [32], MsgHashString [32]; VMS_MAIL_USER *muptr; USER_OPTIONS *uoptr; REQUEST_DATA *sdptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicFolderRequest()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; sdptr = (REQUEST_DATA*)rdptr->StateDataPtr; rdptr->MassageMessage = uoptr->MassageRead; /* the string containing comma-separated message id dot hashes */ CGIVAR (MsgRangeListPtr, "FORM_MSG_RANGE_LIST"); /*****************/ /* search button */ /*****************/ CGIVARNULL (cptr, "FORM_MAIN_BTN"); if (cptr && *cptr) { /* searching can be disabled */ rdptr->SearchData.InProgress = FALSE; if (LangSame ("search", cptr) || LangSame ("search_new", cptr)) { if (SearchPageRequest (rdptr)) return; } } /*****************************/ /* individual message button */ /*****************************/ CGIVARNULL (cptr, "FORM_MSG_BTN"); if (cptr) { rdptr->MessageId = atol(cptr); rdptr->MessageHash = MessageRangeString (rdptr->MessageId, MsgRangeListPtr); PublicMessagePage (rdptr); return; } /************************/ /* popup message button */ /************************/ CGIVARNULL (cptr, "FORM_MSG_BTN_POPUP"); if (cptr && (cnt = atol(cptr))) { rdptr->MessageId = cnt; rdptr->MessageHash = MessageRangeString (rdptr->MessageId, MsgRangeListPtr); PublicMessagePage (rdptr); return; } /*****************/ /* message range */ /*****************/ /* the range button or range 'onchange=' */ CGIVARNULL (cptr, "FORM_RANGE_MSGS"); if (!cptr) CGIVARNULL (cptr, "FORM_RANGE_LIST_CHANGE"); if (cptr && *cptr) CGIVARNULL (cptr, "FORM_RANGE_LIST"); /* also check that the range list is not empty */ if (cptr && *cptr) { rdptr->RangeIdStart = atoi(cptr); while (*cptr && *cptr != '-') cptr++; if (*cptr) { cptr++; rdptr->RangeIdCount = atoi(cptr); rdptr->RangeIdCount -= rdptr->RangeIdStart - 1; } else rdptr->RangeIdCount = uoptr->MessagesPerPage; rdptr->RangeIdVector = +1; PublicFolderPage (rdptr); return; } /******************************/ /* previous range of messages */ /******************************/ CGIVARNULL (cptr, "FORM_RANGE_PREV"); if (cptr) { /* get the lowest id in the list and start one less than that */ rdptr->RangeIdStart = MessageRangeString (-1, MsgRangeListPtr); if (rdptr->RangeIdStart <= 1) { rdptr->RangeIdStart = sdptr->RangeIdStart; StatusMessage (FI_LI, 1, LangFor("no_more_messages")); } else rdptr->RangeIdStart--; rdptr->RangeIdCount = uoptr->MessagesPerPage; rdptr->RangeIdVector = -1; PublicFolderPage (rdptr); return; } /**************************/ /* next range of messages */ /**************************/ CGIVARNULL (cptr, "FORM_RANGE_NEXT"); if (cptr) { /* the highest id is always the first one in the string */ rdptr->RangeIdStart = atoi(MsgRangeListPtr) + 1; if (rdptr->RangeIdStart >= sdptr->FolderMessageCount) { /* just go back to the start of whatever we had before */ rdptr->RangeIdStart = sdptr->RangeIdStart; StatusMessage (FI_LI, 1, LangFor("no_more_messages")); } rdptr->RangeIdCount = uoptr->MessagesPerPage; rdptr->RangeIdVector = +1; PublicFolderPage (rdptr); return; } /******************************/ /* default to latest messages */ /******************************/ rdptr->RangeIdStart = RANGE_MOST_RECENT; rdptr->RangeIdCount = uoptr->MessagesPerPage; PublicFolderPage (rdptr); } /****************************************************************************/ /* Parse the buttons from the public message display page. */ void PublicMessageRequest (REQUEST_DATA *rdptr) { static char SingleMessageList [32]; char *cptr, *sptr, *zptr; USER_OPTIONS *uoptr; REQUEST_DATA *sdptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicMessageRequest()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; sdptr = (REQUEST_DATA*)rdptr->StateDataPtr; rdptr->MassageMessage = uoptr->MassageRead; /*****************/ /* search button */ /*****************/ CGIVARNULL (cptr, "FORM_MAIN_BTN"); if (cptr && *cptr) { /* searching can be disabled */ rdptr->SearchData.InProgress = FALSE; if (LangSame ("search", cptr) || LangSame ("search_new", cptr)) { if (SearchPageRequest (rdptr)) return; } } if (rdptr->PublicWildcard) { /*******************/ /* wildcard public */ /*******************/ CGIVARNULL (cptr, "FORM_FOLDER_LIST_CHANGE"); if (cptr && *cptr == 't') { PublicFolderRequest (rdptr); return; } CGIVARNULL (cptr, "FORM_MAIN_BTN"); if (cptr && *cptr) { rdptr->SearchData.InProgress = FALSE; if (LangSame ("open", cptr)) { PublicFolderRequest (rdptr); return; } } } /****************************/ /* previous/at/next message */ /****************************/ CGIVARNULL (cptr, "FORM_MSG_PREV"); if (cptr) { rdptr->MessageId = sdptr->MessageId; if (rdptr->MessageId > 1) rdptr->MessageId--; else StatusMessage (FI_LI, 1, LangFor("no_more_messages")); rdptr->MessageHash = 0; PublicMessagePage (rdptr); return; } CGIVARNULL (cptr, "FORM_MSG_FOLDER_AT"); if (cptr) { rdptr->RangeIdCount = uoptr->MessagesPerPage; for (rdptr->RangeIdStart = sdptr->FolderMessageCount; rdptr->RangeIdStart >= sdptr->MessageId; rdptr->RangeIdStart -= rdptr->RangeIdCount); rdptr->RangeIdStart++; if (rdptr->RangeIdStart < 1) rdptr->RangeIdStart = 1; PublicFolderPage (rdptr); return; } CGIVARNULL (cptr, "FORM_MSG_NEXT"); if (cptr) { rdptr->MessageId = sdptr->MessageId; if (rdptr->MessageId < sdptr->FolderMessageCount) rdptr->MessageId++; else StatusMessage (FI_LI, 1, LangFor("no_more_messages")); rdptr->MessageHash = 0; PublicMessagePage (rdptr); return; } /********************/ /* specific message */ /********************/ CGIVARNULL (cptr, "FORM_MSG_ID_HASH"); if (cptr) { rdptr->MessageId = atol(cptr); while (*cptr && *cptr != '.') cptr++; if (*cptr) cptr++; if (!*cptr) ErrorExit (SS$_BUGCHECK, FI_LI);; rdptr->MessageHash = atol(cptr); } /*****************/ /* message parts */ /*****************/ CGIVARNULL (cptr, "FORM_PART_BTN"); if (cptr) { zptr = (sptr = rdptr->AttachmentName) + sizeof(rdptr->AttachmentName)-1; while (*cptr && sptr < zptr) *sptr++ = *cptr++; *sptr = '\0'; /* if the attachment is successfully accessed then just finish up */ if (MessagePart (rdptr)) return; PublicMessagePage (rdptr); return; } /************************/ /* message read buttons */ /************************/ CGIVARNULL (cptr, "FORM_MSG_PRINT"); if (!cptr) CGIVARNULL (cptr, "FORM_MSG_PRINT_POPUP"); if (cptr) { if (MessagePrintView (rdptr)) return; PublicMessagePage (rdptr); return; } CGIVARNULL (cptr, "FORM_MSG_RAW"); if (!cptr) CGIVARNULL (cptr, "FORM_MSG_RAW_POPUP"); if (cptr) { if (MessageRawView (rdptr)) return; PublicMessagePage (rdptr); return; } CGIVARNULL (cptr, "FORM_MSG_HDR"); if (!cptr) CGIVARNULL (cptr, "FORM_MSG_HDR_POPUP"); if (cptr) { if (MessageHdrView (rdptr)) return; PublicMessagePage (rdptr); return; } /**************/ /* HTML/plain */ /**************/ CGIVARNULL (cptr, "FORM_MSG_READ_PREF"); if (cptr) { /* one is on, minus one is off, zero is not set! */ if (LangSame ("message_read_html", cptr)) rdptr->MessageReadPreference = OPTIONS_READ_PLAIN2_HTML1; if (LangSame ("message_read_plain", cptr)) rdptr->MessageReadPreference = OPTIONS_READ_PLAIN1_HTML2; PublicMessagePage (rdptr); return; } /****************/ /* message wrap */ /****************/ CGIVARNULL (cptr, "FORM_MSG_WRAP"); if (cptr) { while (*cptr && !isdigit(*cptr)) cptr++; rdptr->MassageMessage = atoi(cptr); /* use the read preference from the previous request */ rdptr->MessageReadPreference = sdptr->MessageReadPreference; PublicMessagePage (rdptr); return; } /*********************/ /* message ID in URL */ /*********************/ PublicMessagePage (rdptr); } /*****************************************************************************/ /* Generate the HTML for a public page (folder message list or message display). */ void PublicPageBegin ( REQUEST_DATA *rdptr, int ThisPageIdent ) { static char OperaChild0 [] = "\n", OperaChild1 [] = "\n"; char *cptr, *OperaChildPtr, *UserNamePtr; USER_OPTIONS *uoptr; REQUEST_DATA *sdptr; VMS_MAIL_MSG *vmptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicPageBegin()"); uoptr = &rdptr->UserOptions; muptr = &VmsMailUser; vmptr = &muptr->VmsMailMsg; sdptr = (REQUEST_DATA*)rdptr->StateDataPtr; if (!rdptr->ThisPageIdent) rdptr->ThisPageIdent = ThisPageIdent; if (rdptr->CharSetPtr) CgiLibResponseSetCharset (rdptr->CharSetPtr); if (rdptr->PublicAuthorized) CgiLibResponseHeader (200, "text/html", "%s", rdptr->LoginSetCookiePtr); else CgiLibResponseHeader (200, "text/html"); fprintf (stdout, "%s\n\ \n\ \n\ %s\ \n\ \n\ \n\ \n", DocType, CgiLibXUACompatible(NULL), SoftwareEnv, CgiEnvironmentPtr, SoftwareCopy, LangFor("lang_name"), LangFor("lang_author")); /* used to support some of the enhanced functionality */ SoyMailJavaScriptStuff (rdptr); SoyMailStyleStuff (rdptr, uoptr->Theme); OperaChildPtr = ""; if (rdptr->UserAgent == SOY_USER_AGENT_OPERA) { OperaChildPtr = OperaChild0; if (!strcmp (rdptr->CgiRequestMethodPtr, "POST")) { CGIVARNULL (cptr, "FORM_OPERA_CHILD"); if (!cptr || *cptr == '0') OperaChildPtr = OperaChild1; } } fprintf (stdout, "%s\n\ \n\ \n\ \n\
\n\ %s\ \n\ \n\ \n
\n\n", SoyMailPageTitle(rdptr), rdptr->FormAction, uoptr->ComposeCharSets[0] ? uoptr->ComposeCharSets : "utf-8", OperaChildPtr); } /*****************************************************************************/ /* */ void PublicPageEnd (REQUEST_DATA *rdptr) { /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicPageEnd()"); fprintf (stdout, "
\n\n"); RequestPublicStateSave (rdptr); fputs ("
\n", stdout); StatTimer (TRUE); fputs ("\n\n", stdout); } /*****************************************************************************/ /* Equvalent to the main menu panel in private access soyMAIL. */ void PublicPageTitle (REQUEST_DATA *rdptr) { char *cptr, *Title1Ptr, *Title2Ptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicPageTitle()"); fprintf (stdout, "\n\ \n\ \n\
\n\ \n"); fprintf (stdout, "\n\ \n"); if (rdptr->PublicWildcard || SoyMailConfig.SearchEnabled) fprintf (stdout, "\n"); Title2Ptr = NULL; if (SoyMailConfig.PageTitle1) { Title1Ptr = SoyMailConfig.PageTitle1; if (rdptr->PublicAccessTitle[0]) Title2Ptr = rdptr->PublicAccessTitle; else if (SoyMailConfig.PageTitle2) Title2Ptr = SoyMailConfig.PageTitle2; } else if (rdptr->PublicAccessTitle[0]) Title1Ptr = rdptr->PublicAccessTitle; else Title1Ptr = rdptr->CgiPathInfoPtr; if (Title1Ptr && Title2Ptr) fprintf (stdout, "\ ", Title1Ptr, Title2Ptr); else fprintf (stdout, "", Title1Ptr); fprintf (stdout, "\n\ \n\
  "); SoyMailLogo (rdptr); fprintf (stdout, "  \n\n"); if (rdptr->PublicWildcard) { FolderListInit (rdptr); FolderOpenSelect (rdptr); } if (SoyMailConfig.SearchEnabled) fprintf (stdout, " \n", LangFor("search")); fprintf (stdout, "\n", LangFor("close")); if (rdptr->PublicAuthorized && SoyMailConfig.LoginSecret) { if (SoyMailConfig.LogoutDisabled) fprintf (stdout, " \n", LangFor("logout")); else fprintf (stdout, " \n", LangFor("logout"), LANG_FOR_CONFIRM("login_confirm_logout")); } if (rdptr->PublicWildcard || SoyMailConfig.SearchEnabled) fprintf (stdout, "%s %s %s 
\n\
\n\ \n\n"); } /*****************************************************************************/ /* Display the basic message folder and message list page. */ void PublicMessageFolderList (REQUEST_DATA *rdptr) { int cnt, idx, status; char *cptr, *sptr, *zptr; char FromBuffer [256], SubjBuffer [256]; USER_OPTIONS *uoptr; VMS_MAIL_MSG *vmptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicMessageFolderList()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; vmptr = &muptr->VmsMailMsg; fprintf (stdout, "

\ \n\ \n"); /******************/ /* message ranges */ /******************/ MessageRangeSelect (rdptr); if (!vmptr->MessageSelectedCount) { /****************/ /* empty folder */ /****************/ rdptr->RangeIdStart = rdptr->RangeIdCount = 0; fprintf (stdout, "
\n"); MessageListFooter (); fprintf (stdout, "\n\ \n\ \n\n"); return; } /********************/ /* list of messages */ /********************/ fprintf (stdout, "\n\ \n\ \ \n\ \n\ \n\ \ \ \ \ \n", rdptr->MsgIdListPtr, LangFor("received"), LangFor("from"), LangFor("subject")); if (uoptr->MessageOrder < 0) { /* find the last entry in the list */ for (vmptr = muptr->MessageList; vmptr && vmptr->NextPtr; vmptr = vmptr->NextPtr); } else vmptr = muptr->MessageList; while (vmptr) { if (Debug) fprintf (stdout, "%%X%08.08X id:%d size:%d hash:%d\n|%s|\n|%s|\n|%s|\n|%s|\n|%s|\n\n", muptr->MailVmsStatus, vmptr->CurrentId, vmptr->SizeInRecords, vmptr->MessageHash, vmptr->Date, vmptr->From, vmptr->Subject, vmptr->To, vmptr->Cc); zptr = (sptr = FromBuffer) + sizeof(FromBuffer)-1; for (cptr = vmptr->From; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; MimeDecIsoString (FromBuffer); FromBuffer[40] = ']'; FromBuffer[41] = '\0'; zptr = (sptr = SubjBuffer) + sizeof(SubjBuffer)-1; for (cptr = vmptr->Subject; *cptr && sptr < zptr; *sptr++ = *cptr++); *sptr = '\0'; MimeDecIsoString (SubjBuffer); SubjBuffer[60] = ']'; SubjBuffer[61] = '\0'; /* this mix of styles to get both Mozilla and MSIE to look right! */ fprintf (stdout, "\ \ \ \ \ \ \n", vmptr->CurrentId, vmptr->CurrentId, vmptr->CurrentId, InetMailRfcVmsDate(vmptr->Date), HTML_ADDR(FromBuffer), vmptr->Subject[0] ? HTML_TEXT(SubjBuffer) : LangFor("(none)")); if (uoptr->MessageOrder < 0) vmptr = vmptr->PrevPtr; else vmptr = vmptr->NextPtr; } fprintf (stdout, "
%s%s%s
\ \ \  %17.17s%s%s
\n\ \n\ \n\ \n\n"); MessageListFooter (); } /*****************************************************************************/ /* Display the basic public message list page. */ void PublicFolderPage (REQUEST_DATA *rdptr) { USER_OPTIONS *uoptr; REQUEST_DATA *sdptr; VMS_MAIL_MSG *vmptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicFolderPage()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; vmptr = &muptr->VmsMailMsg; sdptr = (REQUEST_DATA*)rdptr->StateDataPtr; if (!rdptr->RangeIdStart) { rdptr->RangeIdStart = sdptr->RangeIdStart; rdptr->RangeIdCount = sdptr->RangeIdCount; if (!rdptr->RangeIdStart) { /* no previous range to fall back on */ rdptr->RangeIdStart = 1; rdptr->RangeIdCount = RANGE_MOST_RECENT; } } if (!rdptr->RangeIdCount) rdptr->RangeIdCount = RANGE_MOST_RECENT; muptr->MailVmsStatus = SS$_NORMAL; MessageListInit (rdptr); PublicPageBegin (rdptr, PAGE_FOLDER); PublicPageTitle (rdptr); StatusInfoPanel (rdptr); PublicMessageFolderList (rdptr); PublicFooter (rdptr); PublicPageEnd (rdptr); } /*****************************************************************************/ /* Display the public format message header and body page. */ void PublicMessagePage (REQUEST_DATA *rdptr) { int status; REQUEST_DATA *sdptr; USER_OPTIONS *uoptr; VMS_MAIL_MSG *vmptr; VMS_MAIL_USER *muptr; VMS_MAIL_USER UserData; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicMessagePage()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; vmptr = &muptr->VmsMailMsg; sdptr = (REQUEST_DATA*)rdptr->StateDataPtr; rdptr->FolderMessageCount = sdptr->FolderMessageCount; vmptr->MessageId = rdptr->MessageId; vmptr->ConfirmHash = rdptr->MessageHash; CallMailMessageGet (muptr, NULL); /* in case a message hash was not supplied use the one just generated */ rdptr->MessageHash = vmptr->MessageHash; if (VMSnok (muptr->MailVmsStatus)) { if (muptr->MailVmsStatus == MAIL$_OPENIN) { /* error opening external message file */ StatusMessage (FI_LI, 1, "MAIL: %s %s", SysGetMsg(MAIL$_OPENIN), vmptr->ExtId); } else { if (muptr->MailVmsStatus == SS$_BADCHECKSUM || muptr->MailVmsStatus == MAIL$_NOMOREMSG) StatusMessage (FI_LI, 1, "%s", LangFor("message_checksum")); else StatusMessage (FI_LI, 1, "MAIL: %s.", SysGetMsg(muptr->MailVmsStatus)); } PublicFolderPage (rdptr); return; } MessageContentIdentify (rdptr); PublicPageBegin (rdptr, PAGE_MESSAGE); PublicPageTitle (rdptr); StatusInfoPanel (rdptr); PublicMessageButtons (rdptr); MessageHeader (rdptr); MessageBodyText (rdptr); MessageAttachments (rdptr); PublicPageEnd (rdptr); } /*****************************************************************************/ /* Display the buttons associated with the message. */ void PublicMessageButtons (REQUEST_DATA *rdptr) { int value; USER_OPTIONS *uoptr; VMS_MAIL_MSG *vmptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("PublicMessageButtons()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; vmptr = &muptr->VmsMailMsg; fprintf (stdout, "\n\

\ \n\ \n\
\n\ \ \ \n\ \ \ \n\ \ \ \n\ \ \n\ \n\ \n", LangFor("print"), LangFor("raw"), vmptr->LooksLikeRfc ? "" : "onclick=\"return notApplicable();\"", vmptr->LooksLikeRfc ? "onclick=\"targetBlank();\"" : "onclick=\"return notApplicable();\"", LangFor("header"), vmptr->LooksLikeRfc ? "" : "onclick=\"return notApplicable();\"", vmptr->LooksLikeRfc ? "onclick=\"targetBlank();\"" : "onclick=\"return notApplicable();\"", LangFor("prev"), CLICK_NOMORE(vmptr->MessageId == 1), LangFor("folder_at"), CLICK_STARTWORKING, LangFor("next"), CLICK_NOMORE(vmptr->MessageId == rdptr->FolderMessageCount)); if (rdptr->ReadPlainText && rdptr->HtmlTextIsPresent) { fprintf (stdout, " \n", LangFor("message_read_html")); } else if (rdptr->ReadHtmlText && rdptr->PlainTextIsPresent) { fprintf (stdout, " \n", LangFor("message_read_plain")); } if (rdptr->ReadPlainText) { value = ComposeWrapAt (rdptr->MassageMessage, uoptr); if (value < 0) value = ComposeWrapAt (value, uoptr); if (value) fprintf (stdout, "\n", LangFor("message_massage_on"), value); else fprintf (stdout, "\n", LangFor("message_massage_off")); } fprintf (stdout, "
\n\ \n\n"); } /*****************************************************************************/ /* */ void PublicFooter (REQUEST_DATA *rdptr) { /*********/ /* begin */ /*********/ if (!SoyMailConfig.PublicFooter) return; fprintf (stdout, "\n\

\n\ \n\ \n\
\ %s\n\
\n\ \n\n", SoyMailConfig.PublicFooter); } /****************************************************************************/