/*****************************************************************************/ /* folder.c Provide HTML form selection lists and buttons for VMS Mail files/folders. COPYRIGHT --------- Copyright (C) 2005-2024 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 --------------- 10-JAN-2020 MGD FolderRecent() maintain list of most recent folders 07-JUL-2008 MGD refine PMDF IMAP folder (.MAILBOX) processing 27-JAN-2007 MGD specially process PMDF IMAP folder subdirectories 30-DEC-2006 MGD remove "(none)" folder list options 27-DEC-2006 MGD FolderButtonListEach() simplify button width calculation 21-OCT-2006 MGD multiple Mail file [copy][move] destination selectors provide all files (drawers) and associated folders 20-JUL-2006 MGD try to make font width allowances for monospace 04-JUL-2006 MGD FolderButtonListEach() refine (perhaps) button width kludge 09-APR-2006 MGD FolderOpenSingleFileListEach() support public wildcard folder configuration with MAIL and NEWMAIL prohibition 06-APR-2006 MGD remove default MAIL and NEWMAIL folders 02-APR-2006 MGD FolderOpenSelect() modifications for public wildcard access 07-FEB-2006 MGD folder buttons for left-side of message listing 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 #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 "folder.h" #include "mainmenu.h" #include "newmail.h" #include "other.h" #include "message.h" #define FI_LI __FILE__, __LINE__ /********************/ /* external storage */ /********************/ extern BOOL Debug, WatchEnabled; extern int VmsVersion; extern char CurrentVmsTimeString[], SoftwareId[], SoftwareVn[]; extern USER_OPTIONS UserOptions; extern REQUEST_DATA RequestData; extern VMS_MAIL_USER VmsMailUser; /*****************************************************************************/ /* Reset (empty) the mail file and folder lists. Called upon certain triggers and periodically. */ void FolderListReset (REQUEST_DATA *rdptr) { int cnt, status; char *cptr, *sptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ muptr = &VmsMailUser; if (WatchEnabled) WatchThis ("FolderListReset()"); if (muptr->MailFolderList.ListPtr) { CgiLibVeeMemFree (muptr->MailFolderList.ListPtr); muptr->MailFolderList.ListPtr = NULL; muptr->MailFolderList.ListSize = muptr->MailFolderList.ListLength = muptr->MailFolderList.ListCount = 0; } if (muptr->DestFolderList.ListPtr) { CgiLibVeeMemFree (muptr->DestFolderList.ListPtr); muptr->DestFolderList.ListPtr = NULL; muptr->DestFolderList.ListSize = muptr->DestFolderList.ListLength = muptr->DestFolderList.ListCount = 0; } } /*****************************************************************************/ /* Get the list of mail files and a list of folders in the default and destination mail file (as applicable). This is quite messy as only one mail file may be open at a time so we must dance around the primary mail file and folder list. */ void FolderListInit (REQUEST_DATA *rdptr) { int cnt, len, status; char *cptr; USER_OPTIONS *uoptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; if (WatchEnabled) WatchThis ("FolderListInit() all:!UL pmdf:!UL", uoptr->AllMailFiles, uoptr->PmdfImap); if (uoptr->AllMailFiles && !muptr->MailFileList.ListPtr) CallMailFileList (muptr); if (!muptr->MailFolderList.ListPtr) { status = CallMailFolderList (muptr, FALSE, uoptr->PmdfImap); if (VMSnok (status)) { if (muptr->MailVmsStatus == MAIL$_OPENIN && muptr->MailFileDeletedCount) StatusMessage (FI_LI, -1, LangFor("mail_file_deleted"), rdptr->MailFileName); else if (uoptr->PmdfImap && (status & 0x80000000)) StatusMessage (FI_LI, 1, "IMAP: %s.", SysGetMsg(status & 0x7fffffff)); else StatusMessage (FI_LI, 1, "MAIL: %s.", SysGetMsg(status)); } time ((unsigned long*)&rdptr->FolderRefreshSeconds); } if (!muptr->DestFolderList.ListPtr) { if (!uoptr->AllMailFiles || !strcmp (rdptr->MailFileName, rdptr->DestMailFileName)) { /* clone the mail folder list */ if (WatchEnabled) WatchThis ("clone"); muptr->DestFolderList.ListCount = muptr->MailFolderList.ListCount; muptr->DestFolderList.ListLength = muptr->MailFolderList.ListLength; muptr->DestFolderList.ListSize = muptr->MailFolderList.ListLength + 1; muptr->DestFolderList.ListPtr = CgiLibVeeMemCalloc (muptr->DestFolderList.ListSize); if (!muptr->DestFolderList.ListPtr) ErrorExit (vaxc$errno, FI_LI); if (muptr->MailFolderList.ListPtr) memcpy (muptr->DestFolderList.ListPtr, muptr->MailFolderList.ListPtr, muptr->DestFolderList.ListSize); time ((unsigned long*)&rdptr->FolderRefreshSeconds); } else { /* will handle all the opening and closing of the dest mail file */ status = CallMailFolderList (muptr, TRUE, uoptr->PmdfImap); if (VMSnok (status)) /* quite possible a specified mail file does not exist (yet) */ if (status != MAIL$_OPENIN) StatusMessage (FI_LI, 1, "MAIL: %s.", SysGetMsg(status)); time ((unsigned long*)&rdptr->FolderRefreshSeconds); } } /* find the length of the longest mail file name */ muptr->MailFolderMaxLen = 0; cptr = muptr->MailFileList.ListPtr; for (cnt = muptr->MailFileList.ListCount; cnt; cnt--) { if ((len = strlen(cptr)) > muptr->MailFolderMaxLen) muptr->MailFolderMaxLen = len; while (*cptr) cptr++; cptr++; } muptr->DestFolderMaxLen = muptr->MailFolderMaxLen; /* integrate with the length of the longest folder name */ cptr = muptr->MailFolderList.ListPtr; for (cnt = muptr->MailFolderList.ListCount; cnt; cnt--) { if ((len = strlen(cptr)) > muptr->MailFolderMaxLen) muptr->MailFolderMaxLen = len; while (*cptr) cptr++; cptr++; } /* and with the length of the longest destination folder name */ cptr = muptr->DestFolderList.ListPtr; for (cnt = muptr->DestFolderList.ListCount; cnt; cnt--) { if ((len = strlen(cptr)) > muptr->DestFolderMaxLen) muptr->DestFolderMaxLen = len; while (*cptr) cptr++; cptr++; } if (WatchEnabled) { fprintf (stdout, "MAIL: %d (%d)\n", muptr->MailFolderList.ListCount, muptr->MailFolderMaxLen); cptr = muptr->MailFolderList.ListPtr; for (cnt = muptr->MailFolderList.ListCount; cnt; cnt--) { fprintf (stdout, "%2d |%s|\n", strlen(cptr), cptr); while (*cptr) cptr++; cptr++; } fprintf (stdout, "DEST: %d (%d)\n", muptr->DestFolderList.ListCount, muptr->DestFolderMaxLen); cptr = muptr->DestFolderList.ListPtr; for (cnt = muptr->DestFolderList.ListCount; cnt; cnt--) { fprintf (stdout, "%2d |%s|\n", strlen(cptr), cptr); while (*cptr) cptr++; cptr++; } } } /*****************************************************************************/ /* Generate a selection list for the available mail folders and [open] button. If private access then include the [9 new] button. */ void FolderOpenSelect (REQUEST_DATA *rdptr) { int status; char newBuf [256]; USER_OPTIONS *uoptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("FolderOpenSelect()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; fprintf (stdout, "\n\ \n\   \n\  \n", LangFor("open"), CLICK_STARTWORKING); if (rdptr->PrivateAccess) fprintf (stdout, "  \n", newBuf, NewMailInclude(rdptr) ? " onclick=\"refreshNewMail(-1);return false;\"" : CLICK_STARTWORKING); fprintf (stdout, "\n\n"); } /*****************************************************************************/ /* Provide a selection list for the message folders. */ void FolderOpenListEach (REQUEST_DATA *rdptr) { int cnt; char *cptr, *sptr, *tptr; USER_OPTIONS *uoptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("FolderOpenListEach()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; if (uoptr->PmdfImap) FolderPmdfImapListEach (rdptr, FALSE); else if (uoptr->AllMailFiles || muptr->MailFileList.ListCount > 1) FolderMultiFileListEach (rdptr, FALSE); else FolderSingleFileListEach (rdptr, FALSE); } /*****************************************************************************/ /* Provide a selection list for the message action destination folders. */ void FolderDestListEach (REQUEST_DATA *rdptr) { int cnt; char *cptr, *sptr, *tptr; USER_OPTIONS *uoptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("FolderDestListEach()"); muptr = &VmsMailUser; uoptr = &rdptr->UserOptions; if (uoptr->PmdfImap) FolderPmdfImapListEach (rdptr, TRUE); else if (uoptr->AllMailFiles || muptr->MailFileList.ListCount > 1) FolderMultiFileListEach (rdptr, TRUE); else FolderSingleFileListEach (rdptr, TRUE); } /*****************************************************************************/ /* Only a single MAIL.MAI file or optioned to only show MAIL.MAI. List each folder. */ void FolderSingleFileListEach ( REQUEST_DATA *rdptr, BOOL DestFolder ) { int fldcnt, ListCount; char *cptr, *fldptr, *selptr, *FolderNamePtr; VMS_MAIL_LIST *mlptr; VMS_MAIL_USER *muptr; /*********/ /* begin */ /*********/ if (WatchEnabled) WatchThis ("FolderSingleFileListEach()"); muptr = &VmsMailUser; if (DestFolder) { mlptr = &muptr->RecentDestFolderList; FolderNamePtr = rdptr->DestFolderName; } else { mlptr = &muptr->RecentMailFolderList; FolderNamePtr = rdptr->FolderName; } if (!rdptr->NewMessages && !strcmp (FolderNamePtr, "NEWMAIL")) fputs ("