/*****************************************************************************/
/*
                                   help.c

The help module uses the script image to provide "content-sensitive" help when
accessed using the [Help] button from the in-use script.  Once on the help page
it continues to 'wrap' the help information and use the main menu buttons  to
allow selection of the various help pages associated with each of the help
buttons.  The help page (under JavaScript) is provided in a separate pop-up
window.

The relevant help is provided by accessing separate HTML files containing
marked-up information, one per help topic.  A filename is generated using
the logical name SOYMAIL_HELP, the name of the topic, an underscore, and the
language abbreviation selected by the user option.  For example the English
language 'compose' topic file would be SOYMAIL_HELP:COMPOSE_EN.HTML, and the
Spanish equivalent (if it exists) SOYMAIL_HELP:COMPOSE_ES.HTML.  If the user
option language is not found the module then generates the English language
file name and attempts (hopefully successfully) to access that.  In this manner
language-specific help files can easily  be added with an automatic fall-back
to the English language equivalent.  This is slightly more expensive than
static pages but offers much greater functionality.

The current english language files that should (must) exist are:

  AUTHOR_EN.HTML     help language-specific author information
  HELP_EN.HTML       primary, overview help file ([Help] on the help page)
  OPEN_EN.HTML       folder selector and [Open] button
  NEW_EN.HTML        [0 New] button
  SEARCH_EN.HTML     [Search] mail searching
  OPTIONS_EN.HTML    [Options] soyMAIL user and VMS Mail options
  CONTACTS_EN.HTML   [Contacts] contact maintenance
  COMPOSE_EN.HTML    [Compose] message composition and sending
  LOGOUT_EN.HTML     [Logout] server session logout
  LOGOUT2_EN.HTML    [Logout] autogenous login session logout

Not surprisingly, most of these relate to the main menu buttons.

There is an optional file that when present is included towards the bottom of
the [help] button (initial) text (the content from from file HELP_<lang>.HTML). 
This file should be named (note the leading underscore)

  _SITE_<lang>.HTML

and is intended to supplement the initial soyMAIL help page with site-specific
information, links, etc.  The soyMAIL package will never include a file with
such a name in the help subdirectory.


PUBLIC ACCESS TO HELP
---------------------
Is available via the consolidated help page (provided by HelpAll() without the
print dialog) using the script path and '?help' query string.

  /cgi-bin/soymail?help

The administrator set public user options or an additional keyword providing
the language can select (any) language-specific help.

  /cgi-bin/soymail?help+de


COPYRIGHT
---------
Copyright (C) 2005-2025 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
---------------
16-OCT-2013  MGD  include TinyMCE version with HelpAbout()
15-APR-2007  MGD  HelpAbout() add resolved client host name
26-DEC-2006  MGD  HelpPageRequest() autogenous login
20-JUN-2006  MGD  HelpAbout() now has a disk quota report item
14-FEB-2006  MGD  main menu now has a [close] button, remove help [close]
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 <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* VMS related header files */
#include <descrip.h>
#include <rmsdef.h>
#include <ssdef.h>
#include <stsdef.h>

/* application header file */
#include <soymail.h>
#include <config.h>
#include <mta.h>
#include <request.h>

#define FI_LI "HELP", __LINE__

/* global storage */

char *HelpTopics [] = {
   "help", "open", "new", "message", "search",
   "compose", "contacts", "options", "logout", "author",
   NULL
};

/* external storage */

extern BOOL  Debug,
             WatchEnabled;

extern int  VmsVersion;

extern short  CurrentVmsNumTime[];

extern char  CopyrightDate[],
             DocType[],
             SoftwareCopy[],
             SoftwareEnv[],
             SoftwareVn[];

extern CONFIG_DATA  SoyMailConfig;
extern VMS_MAIL_USER  VmsMailUser;

/* prototypes */

int  sys$getsyiw (__unknown_params);

/****************************************************************************/
/*
*/ 

BOOL HelpPageRequest (REQUEST_DATA *rdptr)

{
   char  *cptr, *sptr;

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "HelpPageRequest()\n");

   /* first context-sensitive help */
   switch (rdptr->PrevPageIdent)
   {
      case PAGE_FOLDER :   sptr = "help";     break;
      case PAGE_SEARCH :   sptr = "search";   break;
      case PAGE_OPTIONS :  sptr = "options";  break;
      case PAGE_CONTACTS : sptr = "contacts"; break;
      case PAGE_COMPOSE :  sptr = "compose";  break;
      case PAGE_MESSAGE :  sptr = "message";  break;
      case PAGE_HELP :     sptr = NULL;       break;
      default:             sptr = "help";
   }

   if (!sptr)
   {
      /* from the help page itself */
      CGIVARNULL (cptr, "FORM_MAIN_BTN");
      if (cptr)
      {
         if (LangSame ("open", cptr))
            sptr = "open";
         else
         if (LangSame ("new", cptr+2))  /* "[0 New]" */
            sptr = "new";
         else
         if (LangSame ("search", cptr))
            sptr = "search";
         else
         if (LangSame ("options", cptr))
            sptr = "options";
         else
         if (LangSame ("contacts", cptr))
            sptr = "contacts";
         else
         if (LangSame ("compose", cptr))
            sptr = "compose";
         else
         if (LangSame ("logout", cptr))
         {
            if (SoyMailConfig.LoginSecret)
               sptr = "login_logout";
            else
               sptr = "logout";
         }
         else
         if (LangSame ("help", cptr))
            sptr = "help";
         else
            ErrorExit (SS$_BUGCHECK, FI_LI);
      }

      if (!cptr)
      {
         CGIVARNULL (cptr, "FORM_HELP_BTN");
         if (cptr)
         {
            /* and this comes from a button added to the help page */
            if (LangSame ("about", cptr))
            {
               HelpAbout (rdptr);
               return (TRUE);
            }
            else
            if (LangSame ("print", cptr))
            {
               HelpAll (rdptr);
               return (TRUE);
            }
            else
               ErrorExit (SS$_BUGCHECK, FI_LI);
         }
      }

      if (!cptr)
      {
         /* this is never generated from soyMAIL, only from 'open' help text */
         CGIVARNULL (cptr, "FORM_MESSAGE_BTN");
         if (cptr) sptr = cptr;
      }

      if (!cptr) sptr = "help";
   }

   if (rdptr->PrevPageIdent != PAGE_HELP)
   {
      cptr = SoyMailConfig.InitialGreeting;
      if (!cptr) cptr = LangFor("greeting");
      if (!cptr) cptr = NULL;
   }
   else
      cptr = NULL;

   if (cptr)
      StatusMessage (FI_LI, 0, "%s", cptr);
   else
      StatusMessage (FI_LI, 0, "%s %s",
                     LangFor(sptr),
                     LangFor("page_opened"));

   /* kludge this so it always appears to have come from help page! */
   rdptr->PrevPageIdent = PAGE_HELP;

   HelpPage (rdptr, sptr);

   return (TRUE);
}

/*****************************************************************************/
/*
Provide a content-sensitive (topic-specific) help page.
*/

void HelpPage
(
REQUEST_DATA *rdptr,
char *TopicName
)
{
   int  status,
        LocalTextLength,
        TopicTextLength;
   char  *cptr,
         *LocalTextPtr,
         *TopicTextPtr;
   USER_OPTIONS  *uoptr;

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "HelpPage() |%s|\n", TopicName);

   uoptr = &rdptr->UserOptions;

   status = HelpTopic (TopicName, uoptr->Language,
                       &TopicTextPtr, &TopicTextLength);
   if (VMSnok (status))
      StatusMessage (FI_LI, 1, "%s: %s.", TopicName, SysGetMsg(status));

   if (strsame (TopicName, "help", -1))
   {
      HelpTopic ("_site", uoptr->Language, &LocalTextPtr, &LocalTextLength);
      if (!LocalTextPtr) LocalTextPtr = "";
   }
   else
      LocalTextPtr = "";

   MainMenuPageBegin (rdptr, PAGE_HELP);
   MainMenuBar (rdptr);
   StatusInfoPanel (rdptr);

   fprintf (stdout,
"<!-- help text begin -->\n\
<p class=\"css_p06\">\
<table width=\"100%%\" cellpadding=\"0\" \
cellspacing=\"10\" class=\"css_panel_3\">\n\
<tr><td align=\"left\">\
%s\
%s%s\
</td></tr>\n\
<tr><td align=\"right\">\
<input class=\"css_button_panel_1\" type=\"submit\" \
name=\"help_btn\" value=\"%s\">&nbsp;\n\
<input class=\"css_button_panel_1\" type=\"submit\" \
name=\"help_btn\" value=\"%s\">&nbsp;\n\
</td></tr>\n\
</table>\n\
<!-- help text end -->\n\n",
            TopicTextPtr,
            LocalTextPtr ? "<p class=\"css_p20\">" : "", LocalTextPtr,
            LangFor("about"),
            LangFor("print"));

   MainMenuPageEnd (rdptr);
}

/*****************************************************************************/
/*
Create and display a page that contains the content of all the help topic files
contained in and presented in the order specified by the HelpTopics[] array. 
This is used as the source of a private access print, or as the public access
documentation page.
*/

void HelpAll (REQUEST_DATA *rdptr)

{
   int  idx, status,
        LocalTextLength,
        TopicTextLength;
   char  *cptr, *tnptr,
         *LocalTextPtr,
         *TopicTextPtr;
   USER_OPTIONS  *uoptr;

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "HelpAll()\n");

   uoptr = &rdptr->UserOptions;

   /* generate the page */
   if (rdptr->CharSetPtr) CgiLibResponseSetCharset (rdptr->CharSetPtr);

   CgiLibResponseHeader (200, "text/html", "%s", rdptr->LoginSetCookiePtr);

   fprintf (stdout,
"%s\n\
<html>\n\
<head>\n\
%s\
<meta name=\"generator\" content=\"%s\">\n\
<meta name=\"copyright\" content=\"%s - Apache-2.0 licensed\">\n",
            DocType,
            CgiLibXUACompatible(NULL),
            SoftwareEnv,
            SoftwareCopy);

   SoyMailStyleStuff (rdptr, "print");

   fprintf (stdout,
"<title>%s</title>\n\
</head>\n\n\
<body%s>\n\
\n\
<table width=\"100%%\" cellpadding=\"5\" align=\"center\">\n\
<tr><td align=\"center\">\n\
<table style=\"border-style:solid; border-width:1px; \
border-left-width:0px; border-right-width:0px; border-color:#000000;\">\n\
<tr><td style=\"text-align:center; font-size:140%%; font-weight:bold; \
padding-left:25px; padding-right:25px;\">\
<span style=\"letter-spacing:1px;\">so</span>\
<span style=\"letter-spacing:2px;\">yMAIL</span>\
&nbsp;&nbsp;%s\
</td></tr>\n\
</table>\n\
</td></tr>\n\n",
            SoyMailPageTitle(rdptr),
            /* automatically bring up a print dialog for private access */
            rdptr->PrivateAccess ?
               /* setTimeout() gives Firefox 1.5 a chance to render the page */
               " onload=\"setTimeout(\'print()\',500);\"" : "",
            LangFor("help"));

   for (idx = 0; tnptr = HelpTopics[idx]; idx++)
   {
      if (!strcmp ("logout", tnptr))
      {
         if (SoyMailConfig.LoginSecret)
            tnptr = "login_logout";
         else
            tnptr = "logout";
      }

      status = HelpTopic (tnptr, uoptr->Language,
                          &TopicTextPtr, &TopicTextLength);

      if (strsame (tnptr, "help", -1))
      {
         HelpTopic ("local", uoptr->Language, &LocalTextPtr, &LocalTextLength);
         if (!LocalTextPtr) LocalTextPtr = "";
      }
      else
         LocalTextPtr = "";

      if (VMSnok (status))
         fprintf (stdout,
"<tr><td><p class=\"css_p20\">%s &quot;%s&quot;: %s.</td></tr>",
                  LangFor("help"), tnptr, SysGetMsg(status));
      else
         fprintf (stdout, "<tr><td><p class=\"css_p20\">%s%s%s</td></tr>",
                  TopicTextPtr, LocalTextPtr ? "<p class=\"css_p20\">" : "",
                  LocalTextPtr);
   }

   fprintf (stdout,
"<tr><td align=\"center\">\n\
<p class=\"css_p20\">\
<b>soyMAIL &nbsp;-&nbsp; Copyright &copy; %s Mark G. Daniel</b><p>\n\
Licensed under the <b>Apache License</b>, Version 2.0 (the \"License\");<br>\n\
you may not use this software except in compliance with the License.<br>\n\
You may obtain a copy of the License at\n\
<a style=\"display:block;margin:0.5em;\" \
target=\"_blank\" href=\"https://www.apache.org/licenses/LICENSE-2.0\">\
https://www.apache.org/licenses/LICENSE-2.0</a>\n\
Unless required by applicable law or agreed to in writing, software \
distributed under the License is distributed on an <br>\n\
\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, \
either express or implied.<br>\n\
See the License for the specific language governing permissions and \
limitations under the License.\n\
</td></tr>\n\
\
</table>\n\
</body>\n\
</html>\n",
            CopyrightDate);
}

/*****************************************************************************/
/*
Retrieve the content from a help topic file.  If a file providing the the
user's optional language is not available fall back to the English language
version (which should always exist).  Return a VMS status code related to the
file access.
*/

int HelpTopic
(
char *TopicName,
char *LangName,
char **TextPtrPtr,
int *TextLengthPtr
)
{
   int  status,
        TextLength;
   char  *cptr,
         *TextPtr;
   char  FileName [256];

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "HelpTopic()\n");

   sprintf (FileName, "SOYMAIL_HELP:%s_%s.HTML", TopicName, LangName);
   for (cptr = FileName; *cptr; cptr++) *cptr = toupper(*cptr);
   status = ReadFileIntoMemory (FileName, &TextPtr, &TextLength);
   if (VMSnok (status))
   {
      if (status == RMS$_FNF && !strsame (LangName, "en", -1))
      {
         sprintf (FileName, "SOYMAIL_HELP:%s_EN.HTML", TopicName);
         for (cptr = FileName; *cptr; cptr++) *cptr = toupper(*cptr);
         status = ReadFileIntoMemory (FileName, &TextPtr, &TextLength);
      }
      if (VMSnok (status))
      {
         TextPtr = "";
         TextLength = 0;
      }
   }
   *TextPtrPtr = TextPtr;
   *TextLengthPtr = TextLength;
   return (status);
}

/*****************************************************************************/
/*
A help page containing information about the versions of soyMAIL, CGILIB, and
the client and server environment in which it's being used.
*/

void HelpAbout (REQUEST_DATA *rdptr)

{
#define SYI$_VERSION 4096

   static char  SyiVersion [16];
   static VMS_ITEM_LIST3 SyiItems [] = {
      { 8, SYI$_VERSION, &SyiVersion, 0 },
      { 0,0,0,0 }
   };

   int  status;
   char  *cptr,
         *CgiRemoteAddrPtr,
         *CgiRemoteHostPtr;
   char  DiskQuota [256];
   VMS_MAIL_USER *muptr;

   /*********/
   /* begin */
   /*********/

   if (Debug) fprintf (stdout, "HelpAbout()\n");

   RequestVmsMailContext (rdptr);
   CallMailGetUserProfile (muptr = &VmsMailUser);
   status = CallMailUserDiskQuota (muptr);
   if (VMSnok (status))
      sprintf (DiskQuota, "%s.", SysGetMsg(status));
   else
   {
      if (muptr->DiskQuotaPerm == (unsigned long)-1)
         strcpy (DiskQuota, LangFor("disabled"));
      else
      if (muptr->DiskQuotaPerm)
         sprintf (DiskQuota, "%d / %dMB (%d%%)",
                  muptr->DiskQuotaUsed >> 11, muptr->DiskQuotaPerm >> 11,
                  muptr->DiskQuotaUsed * 100 / muptr->DiskQuotaPerm);
      else
         strcpy (DiskQuota, "0 / 0MB (0%)");
   }

   if (VMSnok (status = sys$getsyiw (0, 0, 0, &SyiItems, 0, 0, 0)))
      ErrorExit (status, FI_LI);

   CGIVAR (CgiRemoteAddrPtr, "REMOTE_ADDR");
   CGIVAR (CgiRemoteHostPtr, "REMOTE_HOST");
   if (!strcmp (CgiRemoteAddrPtr, CgiRemoteHostPtr))
   {
      /* try to resolve host name from address */
      cptr = MtaHostNameByAddr (CgiRemoteAddrPtr);
      if (cptr) CgiRemoteHostPtr = cptr;
   }

   cptr = SoyMailConfig.InitialGreeting;
   if (!cptr) cptr = LangFor("greeting");
   if (*cptr)
      StatusMessage (FI_LI, 0, "%s", cptr);
   else
      StatusMessage (FI_LI, 0, "%s %s",
                     LangFor("about"),
                     LangFor("page_opened"));

   MainMenuPageBegin (rdptr, rdptr->PrevPageIdent);
   MainMenuBar (rdptr);
   StatusInfoPanel (rdptr);

   fprintf (stdout,
"<!-- about begin -->\n\
<p class=\"css_p06\">\
<table width=\"100%%\" cellpadding=\"0\" \
cellspacing=\"10\" class=\"css_panel_3\">\n\
<tr><td align=\"center\"><b><u>%s</u></b></td></tr>\n\
<tr><td align=\"center\">\n\
<table cellpadding=\"0\" cellspacing=\"2\" border=\"0\">\n\
<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s, VMS %s</td></tr>\n\
<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s</td></tr>\n\
<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s [%s]</td></tr>\n\
<tr><td class=\"css_tabhdr\">%s:</td>",
          LangFor("about_soymail"),
          LangFor("about_version"), SoftwareEnv, SyiVersion,
          LangFor("about_environment"), CgiLibVar("SERVER_SOFTWARE"),
          LangFor("about_server"),
          CgiLibVar("SERVER_NAME"), CgiLibVar("SERVER_ADDR"),
          LangFor("about_client"));

   if (!strcmp (CgiRemoteAddrPtr, CgiRemoteHostPtr))
      fprintf (stdout, "<td class=\"css_tabdat\">[%s]</td></tr>\n",
               CgiRemoteAddrPtr);
   else
      fprintf (stdout, "<td class=\"css_tabdat\">%s [%s]</td></tr>\n",
               CgiRemoteHostPtr, CgiRemoteAddrPtr);

   cptr = CgiLibVarNull ("HTTP_X_FORWARDED");
   if (!cptr) cptr = CgiLibVarNull ("HTTP_FORWARDED");
   if (cptr && *cptr)
      fprintf (stdout, 
"<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s</td></tr>\n",
               LangFor("about_forwarded"), HTML_ESCAPE(cptr));

   cptr = SoyMailConfig.HelpAboutSite;
   if (!cptr || !*cptr) cptr = LangFor("about_info");

   fprintf (stdout,
"<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s</td></tr>\n\
<tr><td class=\"css_tabhdr\">TinyMCE:</td>\
<td id=\"about_TinyMCE\" class=\"css_tabdat\">%s</td></tr>\n\
<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s</td></tr>\n\
<tr><td class=\"css_tabhdr\">%s:</td><td class=\"css_tabdat\">%s</td></tr>\n\
</td></tr>\n\
</table>\n\
<tr><td align=\"center\">\n\
<b>soyMAIL &nbsp;-&nbsp; Copyright &copy; %s Mark G. Daniel</b><p>\n\
Licensed under the <b>Apache License</b>, Version 2.0 (the \"License\");<br>\n\
you may not use this software except in compliance with the License.\n\
You may obtain a copy of the License at\n\
<a style=\"display:block;margin:0.5em;\" \
target=\"_blank\" href=\"https://www.apache.org/licenses/LICENSE-2.0\">\
https://www.apache.org/licenses/LICENSE-2.0</a>\n\
Unless required by applicable law or agreed to in writing, software \
distributed under the License is distributed on an<br>\n\
\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, \
either express or implied.<br>\n\
See the License for the specific language governing permissions and \
limitations under the License.\n\
</td></tr>\n\
<tr><td align=\"right\">\
</td></tr>\n\
</table>\n\
<script language=\"JavaScript\">aboutTinyMCE();</script>\n\
<!-- about end -->\n\n",
            LangFor("about_agent"), HTML_ESCAPE(CgiLibVar("HTTP_USER_AGENT")),
            LangFor("disabled"),
            LangFor("about_disk_quota"), DiskQuota,
            LangFor("about_site"), cptr,
            CopyrightDate);

   MainMenuPageEnd (rdptr);
}

/*****************************************************************************/

