Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Synchronet
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Main
Synchronet
Commits
d540b1f6
Commit
d540b1f6
authored
2 years ago
by
Eric Oulashin
Committed by
Rob Swindell
2 years ago
Browse files
Options
Downloads
Patches
Plain Diff
DDMsgReader: When viewing message headers, now shows all available message header values
parent
12569e6d
No related branches found
No related tags found
2 merge requests
!463
MRC mods by Codefenix (2024-10-20)
,
!288
DDMsgReader: When viewing message headers, now shows all available message header values
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
xtrn/DDMsgReader/DDMsgReader.js
+497
-345
497 additions, 345 deletions
xtrn/DDMsgReader/DDMsgReader.js
xtrn/DDMsgReader/readme.txt
+2
-2
2 additions, 2 deletions
xtrn/DDMsgReader/readme.txt
xtrn/DDMsgReader/revision_history.txt
+3
-0
3 additions, 0 deletions
xtrn/DDMsgReader/revision_history.txt
with
502 additions
and
347 deletions
xtrn/DDMsgReader/DDMsgReader.js
+
497
−
345
View file @
d540b1f6
...
...
@@ -128,6 +128,9 @@
* Bug fix: When getting header lines to view, ensure the header lines
* are not too wide for the user's terminal. Header lines that are too
* long will be split into no more than 2 lines.
* 2023-04-25 Eric Oulashin Version 1.73a
* Refactored the functions for getting message header lines. Also, now
* all message header information is retrieved.
*/
"use strict";
...
...
@@ -228,13 +231,14 @@ require("dd_lightbar_menu.js", "DDLightbarMenu");
require("html2asc.js", 'html2asc');
require("attr_conv.js", "convertAttrsToSyncPerSysCfg");
require("graphic.js", 'Graphic');
require("smbdefs.js", "SMB_POLL_ANSWER");
load('822header.js');
var ansiterm = require("ansiterm_lib.js", 'expand_ctrl_a');
// Reader version information
var READER_VERSION = "1.73";
var READER_DATE = "2023-04-
17
";
var READER_VERSION = "1.73
a
";
var READER_DATE = "2023-04-
25
";
// Keyboard key codes for displaying on the screen
var UP_ARROW = ascii(24);
...
...
@@ -491,13 +495,10 @@ var gFileAttachDir = backslash(system.node_dir + "DDMsgReader_Attachments");
if (file_exists(gFileAttachDir))
deltree(gFileAttachDir);
// See if the avatar support file
s are
available, and load
them
if so
// See if the avatar support file
is
available, and load
is
if so
var gAvatar = null;
if (file_exists(backslash(system.exec_dir) + "load/smbdefs.js") && file_exists(backslash(system.exec_dir) + "load/avatar_lib.js"))
{
require("smbdefs.js", "SMB_POLL_ANSWER");
if (file_exists(backslash(system.exec_dir) + "load/avatar_lib.js"))
gAvatar = load({}, "avatar_lib.js");
}
// User twitlist filename (and settings filename)
var gUserTwitListFilename = backslash(system.data_dir + "user") + format("%04d", user.number) + ".DDMsgReader_twitlist";
...
...
@@ -854,6 +855,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
this.PromptAndDeleteOrUndeleteMessage = DigDistMsgReader_PromptAndDeleteOrUndeleteMessage;
this.PromptAndDeleteOrUndeleteSelectedMessages = DigDistMsgReader_PromptAndDeleteOrUndeleteSelectedMessages;
this.GetExtdMsgHdrInfo = DigDistMsgReader_GetExtdMsgHdrInfo;
this.GetMsgHdrFieldListText = DigDistMsgReader_GetMsgHdrFieldListText;
this.GetMsgInfoForEnhancedReader = DigDistMsgReader_GetMsgInfoForEnhancedReader;
this.GetLastReadMsgIdxAndNum = DigDistMsgReader_GetLastReadMsgIdxAndNum;
this.GetScanPtrMsgIdx = DigDistMsgReader_GetScanPtrMsgIdx;
...
...
@@ -1028,6 +1030,7 @@ function DigDistMsgReader(pSubBoardCode, pScriptArgs)
invalidMsgNumText: "\x01n\x01y\x01hInvalid message number: %d",
readMsgNumPromptText: "\x01n\x01g\x01h\x01i* \x01n\x01cRead message #: \x01h",
msgHasBeenDeletedText: "\x01n\x01h\x01g* \x01yMessage #\x01w%d \x01yhas been deleted.",
noHdrLinesForThisMsgText: "\x01n\x01h\x01yThere are no header lines for this message.",
noKludgeLinesForThisMsgText: "\x01n\x01h\x01yThere are no kludge lines for this message.",
searchingPersonalMailText: "\x01w\x01hSearching personal mail\x01n",
searchTextPromptText: "\x01cEnter the search text\x01g\x01h:\x01n\x01c ",
...
...
@@ -5564,7 +5567,8 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
// Get an array of the extended header info/kludge lines and then
// allow the user to scroll through them.
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(msgHeader, (retObj.lastKeypress == this.enhReaderKeys.showKludgeLines));
var onlyKludgeLines = (retObj.lastKeypress == this.enhReaderKeys.showKludgeLines);
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(this.subBoardCode, msgHeader.number, onlyKludgeLines);
if (extdHdrInfoLines.length > 0)
{
if (this.userSettings.useEnhReaderScrollbar)
...
...
@@ -5598,8 +5602,9 @@ function DigDistMsgReader_ReadMessageEnhanced_Scrollable(msgHeader, allowChgMsgA
}
else
{
// There are no kludge lines for this message
this.DisplayEnhReaderError(replaceAtCodesInStr(this.text.noKludgeLinesForThisMsgText), msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
// There are no header/kludge lines for this message
var msgText = onlyKludgeLines ? this.text.noKludgeLinesForThisMsgText : this.text.noHdrLinesForThisMsgText;
this.DisplayEnhReaderError(replaceAtCodesInStr(msgText), msgInfo.messageLines, topMsgLineIdx, msgLineFormatStr);
console.gotoxy(originalCurPos);
writeMessage = false;
}
...
...
@@ -6770,7 +6775,7 @@ function DigDistMsgReader_ReadMessageEnhanced_Traditional(msgHeader, allowChgMsg
console.crlf();
// Get an array of the extended header info/kludge lines and then
// display them.
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(
msgHead
er, (retObj.lastKeypress == this.enhReaderKeys.showKludgeLines));
var extdHdrInfoLines = this.GetExtdMsgHdrInfo(
this.subBoardCode, msgHeader.numb
er, (retObj.lastKeypress == this.enhReaderKeys.showKludgeLines));
if (extdHdrInfoLines.length > 0)
{
console.crlf();
...
...
@@ -8597,6 +8602,7 @@ function DigDistMsgReader_ReadConfigFile()
(setting == "invalidMsgNumText") ||
(setting == "readMsgNumPromptText") ||
(setting == "msgHasBeenDeletedText") ||
(setting == "noHdrLinesForThisMsgText") ||
(setting == "noKludgeLinesForThisMsgText") ||
(setting == "searchingPersonalMailText") ||
(setting == "searchingSubBoardAbovePromptText") ||
...
...
@@ -9302,8 +9308,8 @@ function DigDistMsgReader_GetMsgHdrByAbsoluteNum(pMsgNum, pExpandFields, pGetVot
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
var expandFields = (typeof(pExpandFields) == "boolean" ? pExpandFields : false);
var getVoteInfo = (typeof(pGetVoteInfo) == "boolean" ? pGetVoteInfo : false);
var expandFields = (typeof(pExpandFields) ==
=
"boolean" ? pExpandFields : false);
var getVoteInfo = (typeof(pGetVoteInfo) ==
=
"boolean" ? pGetVoteInfo : false);
msgHdr = msgbase.get_msg_header(false, pMsgNum, expandFields, getVoteInfo);
msgbase.close();
}
...
...
@@ -9311,6 +9317,22 @@ function DigDistMsgReader_GetMsgHdrByAbsoluteNum(pMsgNum, pExpandFields, pGetVot
msgHdr = getBogusMsgHdr();
return msgHdr;
}
function DumpMsgHdr(pSubCode, pMsgNum, pExpandFields, pGetVoteInfo)
{
var hdrLines = [];
var msgHdr = null;
var msgbase = new MsgBase(pSubCode);
if (msgbase.open())
{
var expandFields = (typeof(pExpandFields) === "boolean" ? pExpandFields : false);
var getVoteInfo = (typeof(pGetVoteInfo) === "boolean" ? pGetVoteInfo : false);
msgHdr = msgbase.get_msg_header(false, pMsgNum, expandFields, getVoteInfo);
if (msgHdr != null)
hdrLines = msgbase.dump_msg_header(msgHdr);
msgbase.close();
}
return hdrLines;
}
// For the DigDistMsgReader class: Takes an absolute message number and returns
// its message index (offset). On error, returns -1.
...
...
@@ -12081,7 +12103,7 @@ function DigDistMsgReader_ListSubBoardsInMsgGroup_Traditional(pGrpIndex, pMarkIn
this.WriteSubBrdListHdrLine(grpIndex);
console.crlf();
printf(this.subBoardListHdrPrintfStr, "Sub #", "Name", "# Posts", "Latest date & time");
console.
print("\x01n")
;
console.
attributes = "N"
;
// List each sub-board in the message group.
var searchText = (typeof(pSearchText) == "string" ? pSearchText.toUpperCase() : "");
...
...
@@ -12538,27 +12560,46 @@ function DigDistMsgReader_BuildSubBoardPrintfInfoForGrp(pGrpIndex)
// retrieves will only be retrieved if they exist in the given message header.
//
// Parameters:
// pMsgHdr: A message header
// pSubCodeOrMsgbase: An internal sub-board code of the messagebase, or a MsgBase object representing
// the sub-board the message is in (assumed to be open)
// pMsgNum: The message number of the message headers to retrieve
// pKludgeOnly: Boolean - Whether or not to only get the kludge lines. If false,
// then all header fields will be retrieved.
// pUseColors: Optional boolean: Whether or not to add colors to the strings. Defaults to true.
// pWordWrap: Optional boolean: Whether or not to word-wrap the header lines to the user's
// terminal width. Defaults to true.
// pPrependHdrLabelLines: Optional boolean - Whether or not to prepend a couple lines labeling
// that these are header/kludge lines. Defaults to true.
//
// Return value: An array of strings containing the extended message header information
function DigDistMsgReader_GetExtdMsgHdrInfo(p
MsgHdr, pKludgeOnly
)
function DigDistMsgReader_GetExtdMsgHdrInfo(p
SubCodeOrMsgbase, pMsgNum, pKludgeOnly, pUseColors, pWordWrap, pPrependHdrLabelLines
)
{
// If pMsgHdr is not valid, then just return an empty array.
if (typeof(pMsgHdr) != "object")
if (typeof(pMsgNum) !== "number")
return [];
// Get the message header with fields expanded so we can get the most info possible.
var msgHdr = this.GetMsgHdrByAbsoluteNum(pMsgHdr.number, true, true);
var msgHdr = null;
if (typeof(pSubCodeOrMsgbase) === "string")
{
var msgbase = new MsgBase(pSubCodeOrMsgbase);
if (msgbase.open())
{
msgHdr = msgbase.get_msg_header(false, pMsgNum, true, true);
msgbase.close();
}
}
else if (typeof(pSubCodeOrMsgbase) === "object" && pSubCodeOrMsgbase.hasOwnProperty("get_msg_header") && pSubCodeOrMsgbase.is_open)
msgHdr = pSubCodeOrMsgbase.get_msg_header(false, pMsgNum, true, true);
if (msgHdr == null)
return [];
// The message header retrieved that way might not have vote information,
// so copy any additional header information from this.hdrsForCurrentSubBoard
// if there's a header there for this message.
if (this.hdrsForCurrentSubBoardByMsgNum.hasOwnProperty(pMsg
Hdr.number
))
if (this.hdrsForCurrentSubBoardByMsgNum.hasOwnProperty(pMsg
Num
))
{
var tmpHdrIdx = this.hdrsForCurrentSubBoardByMsgNum[pMsg
Hdr.number
];
var tmpHdrIdx = this.hdrsForCurrentSubBoardByMsgNum[pMsg
Num
];
if (this.hdrsForCurrentSubBoard.hasOwnProperty(tmpHdrIdx))
{
for (var hdrProp in this.hdrsForCurrentSubBoard[tmpHdrIdx])
...
...
@@ -12569,29 +12610,207 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pMsgHdr, pKludgeOnly)
}
}
var kludgeOnly = (typeof(pKludgeOnly) == "boolean" ? pKludgeOnly : false);
var useColors = (typeof(pUseColors) === "boolean" ? pUseColors : true);
var wordWrap = (typeof(pWordWrap) === "boolean" ? pWordWrap : true);
var prependHdrLabelLines = (typeof(pPrependHdrLabelLines) === "boolean" ? pPrependHdrLabelLines : true);
var msgHdrInfoLines = [];
var hdrInfoLineFields = [];
var kludgeOnly = (typeof(pKludgeOnly) == "boolean" ? pKludgeOnly : false);
var formatStr;
if (useColors)
formatStr = "\x01n" + this.colors.hdrLineLabelColor + "%s: \x01n" + this.colors.hdrLineValueColor + "%-s";
else
formatStr = "%s: %-s";
// Make an array of objects with 'prop' and 'textArray' fields; this array will be sorted by prop
var msgInfoObjs = [];
for (var prop in msgHdr)
{
if (prop == "field_list")
{
//var fieldListLines = this.GetMsgHdrFieldListText(msgHdr[prop], true);
//for (var i = 0; i < fieldListLines.length; ++i)
// msgHdrInfoLines.push(fieldListLines[i]);
var fieldListObj = GetMsgHdrFieldListObj(msgHdr.field_list);
var fieldListKeys = Object.keys(msgHdr);
fieldListKeys.sort();
for (var fieldListProp in fieldListObj)
//for (var fieldListKeyIdx = 0; fieldListKeyIdx < fieldListKeys.length; ++fieldListKeyIdx)
{
//var fieldListProp = fieldListKeys[fieldListKeyIdx];
//msgHdrInfoLines.push(format(formatStr, fieldListProp, fieldListObj[fieldListProp]));
if (Array.isArray(fieldListObj[fieldListProp]))
{
var tmpTxtLines = [];
if (fieldListObj[fieldListProp].length > 0)
{
//msgHdrInfoLines.push(format(formatStr, fieldListProp, fieldListObj[fieldListProp][0]));
tmpTxtLines.push(format(formatStr, fieldListProp, fieldListObj[fieldListProp][0]));
for (var i = 1; i < fieldListObj[fieldListProp].length; ++i)
{
//msgHdrInfoLines.push(fieldListObj[fieldListProp][i]);
tmpTxtLines.push(fieldListObj[fieldListProp][i]);
}
}
msgInfoObjs.push({
'prop': fieldListProp,
'textArray': tmpTxtLines
});
}
else
{
//msgHdrInfoLines.push(format(formatStr, fieldListProp, fieldListObj[fieldListProp]));
msgInfoObjs.push({
'prop': fieldListProp,
'textArray': [ format(formatStr, fieldListProp, fieldListObj[fieldListProp]) ]
})
}
}
}
else
{
var addIt = kludgeOnly ? MsgHdrPropIsKludgeLine(prop) : true;
if (addIt)
{
// Remove underscores from the property for the label
var propLabel = prop.replace(/_/g, " ");
// Apply good-looking capitalization to the property label
if ((propLabel == "id") || (propLabel == "ftn tid"))
propLabel = propLabel.toUpperCase();
else if (propLabel == "ftn area")
propLabel = "FTN Area";
else if (propLabel == "ftn pid")
propLabel = "Program ID";
else if (propLabel == "thread id")
propLabel = "Thread ID";
else if (propLabel == "attr")
propLabel = "Attributes";
else if (propLabel == "auxattr")
propLabel = "Auxiliary attributes";
else if (propLabel == "netattr")
propLabel = "Network attributes";
else
propLabel = capitalizeFirstChar(propLabel);
// Value
var propValue = "";
if (typeof(msgHdr[prop]) === "function") // Such as get_rfc822_header
continue;
if (prop == "when_written_time") //itemValue = system.timestr(msgHdr.when_written_time);
propValue = system.timestr(msgHdr.when_written_time) + " " + system.zonestr(msgHdr.when_written_zone);
else if (prop == "when_imported_time") //propValue = system.timestr(msgHdr.when_imported_time);
propValue = system.timestr(msgHdr.when_imported_time) + " " + system.zonestr(msgHdr.when_imported_zone);
else if ((prop == "when_imported_zone") || (prop == "when_written_zone"))
propValue = system.zonestr(msgHdr[prop]);
else if (prop == "attr")
propValue = makeMainMsgAttrStr(msgHdr[prop], "None");
else if (prop == "auxattr")
propValue = makeAuxMsgAttrStr(msgHdr[prop], "None");
else if (prop == "netattr")
propValue = makeNetMsgAttrStr(msgHdr[prop], "None");
else
propValue = msgHdr[prop];
if (typeof(propValue) === "string")
{
// Replace tabs with spaces, and strip CRLF characters
// TODO: Should CRLF characters actually be split into separate lines?
propValue = propValue.trim().replace(/\t/g, " ").replace(/[^\x20-\x7E]/g, '');
propValue = propValue.replace(/\r\n/g, "");
propValue = propValue.replace(/\n/g, "").replace(/\r/g, "");
}
//msgHdrInfoLines.push(format(formatStr, propLabel, propValue));
msgInfoObjs.push({
'prop': propLabel,
'textArray': [ format(formatStr, propLabel, propValue) ]
})
}
}
}
// Sort the header lines alphabetically
msgInfoObjs.sort(function(pA, pB)
{
if (pA.prop < pB.prop)
return -1;
else if (pA.prop == pB.prop)
return 0;
else
return 1;
});
for (var i = 0; i < msgInfoObjs.length; ++i)
{
for (var j = 0; j < msgInfoObjs[i].textArray.length; ++j)
msgHdrInfoLines.push(msgInfoObjs[i].textArray[j]);
}
// Free some memory
for (var prop in msgInfoObjs)
delete msgInfoObjs[prop];
// If the caller wants to word-wrap, make sure the header lines aren't too long for the
// user's terminal. And leave a column for the scrollbar.
var hdrInfoLinesWrapped;
if (wordWrap)
{
hdrInfoLinesWrapped = [];
var maxLen = console.screen_columns - 1;
var colorFormatStr = "\x01n" + this.colors.hdrLineLabelColor + "%-s: \x01n" + this.colors.hdrLineValueColor + "%-s";
for (var i = 0; i < msgHdrInfoLines.length; ++i)
{
//var wrappedLines = word_wrap(msgHdrInfoLines[i], maxLen).split("\n");
var wrappedLines = lfexpand(word_wrap(msgHdrInfoLines[i], maxLen)).split("\r\n");
for (var wrappedI = 0; wrappedI < wrappedLines.length; ++wrappedI)
{
if (wrappedLines[wrappedI].length == 0) continue;
hdrInfoLinesWrapped.push(wrappedLines[wrappedI]);
}
}
}
else // No word wrapping
hdrInfoLinesWrapped = msgHdrInfoLines;
// If some info lines were added, then insert a header line & blank line to
// the beginning of the array, and remove the last empty line from the array.
if (hdrInfoLinesWrapped.length > 0)
{
if (prependHdrLabelLines)
{
if (kludgeOnly)
{
hdrInfoLineFields.push({ field: "ftn_msgid", label: "MSG ID:" });
hdrInfoLineFields.push({ field: "X-FTN-MSGID", label: "MSG ID:" });
hdrInfoLineFields.push({ field: "ftn_reply", label: "Reply ID:" });
hdrInfoLineFields.push({ field: "X-FTN-REPLY", label: "Reply ID:" });
hdrInfoLineFields.push({ field: "ftn_area", label: "Area tag:" });
hdrInfoLineFields.push({ field: "X-FTN-AREA", label: "Area tag:" });
hdrInfoLineFields.push({ field: "ftn_flags", label: "Flags:" });
hdrInfoLineFields.push({ field: "ftn_pid", label: "Program ID:" });
hdrInfoLineFields.push({ field: "ftn_tid", label: "Tosser ID:" });
hdrInfoLineFields.push({ field: "X-FTN-TID", label: "Tosser ID:" });
hdrInfoLineFields.push({ field: "X-FTN-Kludge", label: "Kludge:" });
hdrInfoLineFields.push({ field: "X-FTN-SEEN-BY", label: "Seen-By:" });
hdrInfoLineFields.push({ field: "X-FTN-PATH", label: "Path:" });
hdrInfoLineFields.push({ field: "when_written_time", label: "When written time:" });
hdrInfoLineFields.push({ field: "when_imported_time", label: "When imported time:" });
hdrInfoLinesWrapped.splice(0, 0, "\x01n\x01c\x01hMessage Information/Kludge Lines\x01n");
hdrInfoLinesWrapped.splice(1, 0, "\x01n\x01g\x01h--------------------------------\x01n");
}
else
{
hdrInfoLinesWrapped.splice(0, 0, "\x01n\x01c\x01hMessage Headers\x01n");
hdrInfoLinesWrapped.splice(1, 0, "\x01n\x01g\x01h---------------\x01n");
}
}
if (hdrInfoLinesWrapped[hdrInfoLinesWrapped.length-1].length == 0)
hdrInfoLinesWrapped.pop();
}
return hdrInfoLinesWrapped;
}
// For the DDMsgReader class: Helper for GetExtdMsgHdrInfo() - Gets
// text lines for the field_list property in a message header
//
// Parameters:
// pHdrFieldList: The value of the field_list property in a message header
// pUseColors: Boolean - Whether or not to add attribute codes to the lines
//
// Return value: An array with text lines for the field list, with colors
// for displaying message header information
function DigDistMsgReader_GetMsgHdrFieldListText(pHdrFieldList, pUseColors)
{
var textLines = [];
// This function returns the number of non-blank lines in a header info array.
//
// Return value: An object with the following properties:
...
...
@@ -12648,21 +12867,12 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pMsgHdr, pKludgeOnly)
return itemCount;
}
// Get the header fields
var addTheField = true;
var customFieldLabel = "";
var propCounter = 1;
for (var prop in msgHdr)
{
addTheField = true;
customFieldLabel = "";
var fieldsAndValues = {};
if (prop == "field_list")
{
var hdrFieldLabel = "";
var lastHdrFieldLabel = null;
var addBlankLineAfterIdx = -1;
for (var fieldI = 0; fieldI <
msg
Hdr
.f
ield
_l
ist.length; ++fieldI)
for (var fieldI = 0; fieldI <
p
Hdr
F
ield
L
ist.length; ++fieldI)
{
// TODO: Some field types can be in the array multiple times but only
// the last is valid. For those, only get the last one:
...
...
@@ -12673,8 +12883,13 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pMsgHdr, pKludgeOnly)
// 36 (Reply To extended)
// 37 (Reply To position)
// 38 (Reply To Organization)
hdrFieldLabel = "\x01n" + this.colors.hdrLineLabelColor + msgHdrFieldListTypeToLabel(msgHdr.field_list[fieldI].type) + "\x01n";
var infoLineWrapped = msgHdr.field_list[fieldI].data;
if (pUseColors)
hdrFieldLabel = "\x01n" + this.colors.hdrLineLabelColor + msgHdrFieldListTypeToLabel(pHdrFieldList[fieldI].type) + "\x01n";
else
hdrFieldLabel = msgHdrFieldListTypeToLabel(pHdrFieldList[fieldI].type);
hdrFieldLabel = hdrFieldLabel.replace(/\t/g, " ");
fieldsAndValues[hdrFieldLabel] = true; // TODO: Change to the actual text
var infoLineWrapped = pHdrFieldList[fieldI].data;
var infoLineWrappedArray = lfexpand(infoLineWrapped).split("\r\n");
var hdrArrayNonBlankLines = findHdrFieldDataArrayNonBlankLines(infoLineWrappedArray);
if (hdrArrayNonBlankLines.numNonBlankLines > 0)
...
...
@@ -12682,16 +12897,21 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pMsgHdr, pKludgeOnly)
if (hdrArrayNonBlankLines.numNonBlankLines == 1)
{
var addExtraBlankLineAtEnd = false;
var hdrItem = "\x01n" + this.colors.hdrLineValueColor + infoLineWrappedArray[hdrArrayNonBlankLines.firstNonBlankLineIdx] + "\x01n";
var hdrItem = "";
if (pUseColors)
hdrItem = "\x01n" + this.colors.hdrLineValueColor + infoLineWrappedArray[hdrArrayNonBlankLines.firstNonBlankLineIdx] + "\x01n";
else
hdrItem = infoLineWrappedArray[hdrArrayNonBlankLines.firstNonBlankLineIdx];
hdrItem = hdrItem.replace(/\t/g, " ");
// If the header field label is different, then add it to the
// header info lines
if ((lastHdrFieldLabel == null) || (hdrFieldLabel != lastHdrFieldLabel))
{
var numFieldItemsWithSameType = fieldListCountSameTypes(
msg
Hdr
.f
ield
_l
ist, fieldI);
var numFieldItemsWithSameType = fieldListCountSameTypes(
p
Hdr
F
ield
L
ist, fieldI);
if (numFieldItemsWithSameType > 1)
{
msgHdrInfo
Lines.push("");
msgHdrInfo
Lines.push(hdrFieldLabel);
text
Lines.push("");
text
Lines.push(hdrFieldLabel);
addExtraBlankLineAtEnd = true;
addBlankLineAfterIdx = fieldI + numFieldItemsWithSameType - 1;
}
...
...
@@ -12701,19 +12921,22 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pMsgHdr, pKludgeOnly)
numFieldItemsWithSameType = -1;
}
}
if (strip_ctrl(hdrItem).length < this.msgAreaWidth)
msgHdrInfoLines.push(hdrItem);
textLines.push(hdrItem);
/*
if (console.strlen((hdrItem) < this.msgAreaWidth)
textLines.push(hdrItem);
else
{
// If the header field label is different, then add a blank line
// to the header info lines
if ((lastHdrFieldLabel == null) || (hdrFieldLabel != lastHdrFieldLabel))
msgHdrInfo
Lines.push("");
msgHdrInfo
Lines.push(hdrFieldLabel);
msgHdrInfo
Lines.push(infoLineWrappedArray[hdrArrayNonBlankLines.firstNonBlankLineIdx]);
text
Lines.push("");
text
Lines.push(hdrFieldLabel);
//text
Lines.push(infoLineWrappedArray[hdrArrayNonBlankLines.firstNonBlankLineIdx]);
if ((lastHdrFieldLabel == null) || (hdrFieldLabel != lastHdrFieldLabel))
msgHdrInfo
Lines.push("");
text
Lines.push("");
}
*/
}
else
{
...
...
@@ -12721,165 +12944,158 @@ function DigDistMsgReader_GetExtdMsgHdrInfo(pMsgHdr, pKludgeOnly)
// header info lines
if ((lastHdrFieldLabel == null) || (hdrFieldLabel != lastHdrFieldLabel))
{
msgHdrInfo
Lines.push("");
msgHdrInfo
Lines.push(hdrFieldLabel);
text
Lines.push("");
text
Lines.push(hdrFieldLabel);
}
var infoLineWrapped =
msg
Hdr
.f
ield
_l
ist[fieldI].data;
var infoLineWrapped =
p
Hdr
F
ield
L
ist[fieldI].data;
var infoLineWrappedArray = lfexpand(infoLineWrapped).split("\r\n");
var preAttrs = pUseColors ? "\x01n" + this.colors.hdrLineValueColor : "";
var postAttrs = pUseColors ? "\x01n" : "";
for (var lineIdx = 0; lineIdx < infoLineWrappedArray.length; ++lineIdx)
{
if (infoLineWrappedArray[lineIdx].length > 0)
msgHdrInfoLines.push(
infoLineWrappedArray[lineIdx]);
textLines.push(preAttrs +
infoLineWrappedArray[lineIdx]
+ postAttrs
);
}
// If the header field label is different, then add a blank line to the
// header info lines
if ((lastHdrFieldLabel == null) || (hdrFieldLabel != lastHdrFieldLabel))
msgHdrInfo
Lines.push("");
text
Lines.push("");
}
if (addBlankLineAfterIdx == fieldI)
msgHdrInfo
Lines.push("");
text
Lines.push("");
}
lastHdrFieldLabel = hdrFieldLabel;
}
}
else
{
// See if we should add this field
addTheField = true;
if (hdrInfoLineFields.length > 0)
// For each line, replace tabs with spaces, remove any unprintable characters,
// and in case any line has any CRLF characters, split the lines on CRLF
for (var i = 0; i < textLines.length; ++i)
{
addTheField = false;
for (var infoLineFieldIdx = 0; infoLineFieldIdx < hdrInfoLineFields.length; ++infoLineFieldIdx)
textLines[i] = textLines[i].replace(/\t/g, " ");
//textLines[i] = textLines[i].replace(/\r|\n/g, "");
var array = textLines[i].split("\r\n");
if (array.length > 1)
{
if (prop == hdrInfoLineFields[infoLineFieldIdx].field)
textLines[i] = array[0];
for (var array2Idx = 1; array2Idx < array.length; ++array2Idx)
{
addTheField = true;
customFieldLabel = hdrInfoLineFields[infoLineFieldIdx].label;
break;
if (array[array2Idx].length > 0)
textLines.splice(i+array2Idx, 0, array[array2Idx]);
}
}
//textLines[i] = textLines[i].replace(/[^\x20-\x7E]/g, ''); // Remove unprintable characters
}
if (!addTheField)
continue;
var propLabel = "";
if (customFieldLabel.length > 0)
propLabel = "\x01n" + this.colors.hdrLineLabelColor + customFieldLabel + "\x01n";
else
{
// Remove underscores from the property for the label
propLabel = prop.replace(/_/g, " ");
// Apply good-looking capitalization to the property label
if ((propLabel == "id") || (propLabel == "ftn tid"))
propLabel = propLabel.toUpperCase();
else if (propLabel == "ftn area")
propLabel = "FTN Area";
else if (propLabel == "ftn pid")
propLabel = "Program ID";
else if (propLabel == "thread id")
propLabel = "Thread ID";
else if (propLabel == "attr")
propLabel = "Attributes";
else if (propLabel == "auxattr")
propLabel = "Auxiliary attributes";
else if (propLabel == "netattr")
propLabel = "Network attributes";
else
propLabel = capitalizeFirstChar(propLabel);
// Add the label color and trailing colon to the label text
propLabel = "\x01n" + this.colors.hdrLineLabelColor + propLabel + ":\x01n";
return textLines;
}
var infoLineWrapped = word_wrap(msgHdr[prop], this.msgAreaWidth);
var infoLineWrappedArray = lfexpand(infoLineWrapped).split("\r\n");
var itemValue = "";
for (var lineIdx = 0; lineIdx < infoLineWrappedArray.length; ++lineIdx)
// Helper for GetExtdMsgHdrInfo() - For the "field_list"
// property of a message header, this gathers the field labels & values into an
// object (where the object properties are the labels)
//
// Parameters:
// pHdrFieldArray: The value of the field_list property in a message header
// (this is normally an array of objects containing 'type' and
// 'data' properties)
//
// Return value: An object where the properties are the field labels, and the
// value for each is usually an array of strings
function GetMsgHdrFieldListObj(pHdrFieldArray)
{
if (infoLineWrappedArray[lineIdx].length > 0)
if (!Array.isArray(pHdrFieldArray))
return {};
// This function returns the number of non-blank lines in a header info array.
//
// Return value: An object with the following properties:
// numNonBlankLines: The number of non-blank lines in the array
// firstNonBlankLineIdx: The index of the first non-blank line
// lastNonBlankLineIdx: The index of the last non-blank line
function findHdrFieldDataArrayNonBlankLines(pHdrArray)
{
// Set itemValue to the value that should be displayed
if (typeof(msgHdr[prop]) === "function") // Such as get_rfc822_header
continue;
else if (prop == "when_written_time") //itemValue = system.timestr(msgHdr.when_written_time);
itemValue = system.timestr(msgHdr.when_written_time) + " " + system.zonestr(msgHdr.when_written_zone);
else if (prop == "when_imported_time") //itemValue = system.timestr(msgHdr.when_imported_time);
itemValue = system.timestr(msgHdr.when_imported_time) + " " + system.zonestr(msgHdr.when_imported_zone);
else if ((prop == "when_imported_zone") || (prop == "when_written_zone"))
itemValue = system.zonestr(msgHdr[prop]);
else if (prop == "attr")
itemValue = makeMainMsgAttrStr(msgHdr[prop], "None");
else if (prop == "auxattr")
itemValue = makeAuxMsgAttrStr(msgHdr[prop], "None");
else if (prop == "netattr")
itemValue = makeNetMsgAttrStr(msgHdr[prop], "None");
else
itemValue = infoLineWrappedArray[lineIdx];
// Add the value color to the value text
itemValue = "\x01n" + this.colors.hdrLineValueColor + itemValue + "\x01n";
var retObj = {
numNonBlankLines: 0,
firstNonBlankLineIdx: -1,
lastNonBlankLineIdx: -1
};
var hdrItem = propLabel + " " + itemValue;
if (strip_ctrl(hdrItem).length < this.msgAreaWidth)
msgHdrInfoLines.push(hdrItem);
else
for (var lineIdx = 0; lineIdx < pHdrArray.length; ++lineIdx)
{
// If this isn't the first header property, then add an empty
// line to the info lines array for spacing
if (propCounter > 1)
msgHdrInfoLines.push("");
msgHdrInfoLines.push(propLabel);
// In case the item value is too long to fit into the
// message reading area, split it and add all the split lines.
var itemValueWrapped = word_wrap(itemValue, this.msgAreaWidth);
var itemValueWrappedArray = lfexpand(itemValueWrapped).split("\r\n");
for (var lineIdx2 = 0; lineIdx2 < itemValueWrappedArray.length; ++lineIdx2)
if (pHdrArray[lineIdx].length > 0)
{
if (itemValueWrappedArray[lineIdx2].length > 0)
msgHdrInfoLines.push(itemValueWrappedArray[lineIdx2]);
}
// If this isn't the first header property, then add an empty
// line to the info lines array for spacing
if (propCounter > 1)
msgHdrInfoLines.push("");
}
}
++retObj.numNonBlankLines;
if (retObj.firstNonBlankLineIdx == -1)
retObj.firstNonBlankLineIdx = lineIdx;
retObj.lastNonBlankLineIdx = lineIdx;
}
}
++propCounter
;
return retObj
;
}
// If some info lines were added, then insert a header line & blank line to
// the beginning of the array, and remove the last empty line from the array.
if (msgHdrInfoLines.length > 0)
var fieldListObj = {};
for (var fieldI = 0; fieldI < pHdrFieldArray.length; ++fieldI)
{
if (kludgeOnly)
// TODO: Some field types can be in the array multiple times but only
// the last is valid. For those, only get the last one:
// 32 (Reply To)
// 33 (Reply To agent)
// 34 (Reply To net type)
// 35 (Reply To net address)
// 36 (Reply To extended)
// 37 (Reply To position)
// 38 (Reply To Organization)
var hdrFieldLabel = msgHdrFieldListTypeToLabel(pHdrFieldArray[fieldI].type, false);
hdrFieldLabel = hdrFieldLabel.replace(/\t/g, " ");
// Add the data to fieldListObj, with the label as the property
//fieldListObj[hdrFieldLabel] = pHdrFieldArray[fieldI].data.replace(/\t/g, " ");
// Make the data an array of strings, split based on CRLF characters
var infoLineWrappedArray = lfexpand(pHdrFieldArray[fieldI].data).replace(/\t/g, " ").split("\r\n");
// If any of the strings starts with a date/time ("WhenExported" or "WhenImported"),
// then format it so that the date & time are more readable
for (var i = 0; i < infoLineWrappedArray.length; ++i)
{
if ((infoLineWrappedArray[i].indexOf("WhenExported") == 0 || infoLineWrappedArray[i].indexOf("WhenImported") == 0) && infoLineWrappedArray[i].length >= 28)
{
msgHdrInfoLines.splice(0, 0, "\x01n\x01c\x01hMessage Information/Kludge Lines\x01n");
msgHdrInfoLines.splice(1, 0, "\x01n\x01g\x01h--------------------------------\x01n");
//system.timestr(msgHdr.when_imported_time) + " " + system.zonestr(msgHdr.when_imported_zone)
var firstPart = infoLineWrappedArray[i].substr(0, 14);
var yearStr = infoLineWrappedArray[i].substr(14, 4);
var monthStr = infoLineWrappedArray[i].substr(18, 2);
var dayStr = infoLineWrappedArray[i].substr(20, 2);
var hourStr = infoLineWrappedArray[i].substr(22, 2);
var minStr = infoLineWrappedArray[i].substr(24, 2);
var secStr = infoLineWrappedArray[i].substr(26, 2);
var remaining = infoLineWrappedArray[i].substr(28);
infoLineWrappedArray[i] = format("%s%s-%s-%s %s:%s:%s %s", firstPart, yearStr, monthStr, dayStr, hourStr, minStr, secStr, remaining);
}
}
if (!fieldListObj.hasOwnProperty(hdrFieldLabel))
fieldListObj[hdrFieldLabel] = infoLineWrappedArray;
else
{
msgHdrInfoLines.splice(0, 0, "\x01n\x01c\x01hMessage Headers\x01n");
msgHdrInfoLines.splice(1, 0, "\x01n\x01g\x01h---------------\x01n");
// Append to the data already there
fieldListObj[hdrFieldLabel].push("");
for (var i = 0; i < infoLineWrappedArray.length; ++i)
fieldListObj[hdrFieldLabel].push(infoLineWrappedArray[i]);
}
if (msgHdrInfoLines[msgHdrInfoLines.length-1].length == 0)
msgHdrInfoLines.pop();
}
// Make sure the header lines aren't too long for the user's terminal.
// Leave a column for the scrollbar.
var maxLen = console.screen_columns - 1;
var hdrInfoLinesWrapped = [];
for (var i = 0; i < msgHdrInfoLines.length; ++i)
{
var wrappedLines = word_wrap(msgHdrInfoLines[i], maxLen).split("\n");
for (var wrappedI = 0; wrappedI < wrappedLines.length; ++wrappedI)
{
if (console.strlen(wrappedLines[wrappedI]) > 0)
hdrInfoLinesWrapped.push(wrappedLines[wrappedI]);
}
return fieldListObj;
}
return hdrInfoLinesWrapped;
// Returns whether a message header property name can be considered a "kludge line"
function MsgHdrPropIsKludgeLine(pPropName)
{
if (typeof(pPropName) !== "string" || pPropName.length == 0)
return false;
var propNameUpper = pPropName.toUpperCase();
return (propNameUpper == "FTN_MSGID" || propNameUpper == "X-FTN-MSGID" || propNameUpper == "FTN_REPLY" ||
propNameUpper == "X-FTN-REPLY" || propNameUpper == "FTN_AREA" || propNameUpper == "X-FTN-AREA" ||
propNameUpper == "FTN_FLAGS" || propNameUpper == "FTN_PID" || propNameUpper == "FTN_TID" ||
propNameUpper == "X-FTN-TID" || propNameUpper == "X-FTN-KLUDGE" ||
propNameUpper == "X-FTN-SEEN-BY" || propNameUpper == "X-FTN-PATH" ||
propNameUpper == "WHEN_WRITTEN_TIME" || propNameUpper == "WHEN_IMPORTED_TIME");
}
// For the DigDistMsgReader class: Gets & prepares message information for
...
...
@@ -14666,32 +14882,15 @@ function DigDistMsgReader_SaveMsgToFile(pMsgHdr, pFilename)
if (msgbase.open())
{
var msgBody = msgbase.get_msg_body(false, pMsgHdr.number, false, false, true, true);
var hdrLines = this.GetExtdMsgHdrInfo(msgbase, pMsgHdr.number, false, false, false, false);
msgbase.close();
var messageSaveFile = new File(pFilename);
if (messageSaveFile.open("w"))
{
// Write some header information to the file
if (pMsgHdr.hasOwnProperty("from"))
messageSaveFile.writeln("From: " + pMsgHdr.from);
if (pMsgHdr.hasOwnProperty("to"))
messageSaveFile.writeln(" To: " + pMsgHdr.to);
if (pMsgHdr.hasOwnProperty("subject"))
messageSaveFile.writeln("Subj: " + pMsgHdr.subject);
/*
if (pMsgHdr.hasOwnProperty("when_written_time"))
messageSaveFile.writeln(strftime("Date: %Y-%m-%d %H:%M:%S", msgHeader.when_written_time));
*/
if (pMsgHdr.hasOwnProperty("date"))
messageSaveFile.writeln("Date: " + pMsgHdr.date);
if (pMsgHdr.hasOwnProperty("from_net_addr"))
messageSaveFile.writeln("From net address: " + pMsgHdr.from_net_addr);
if (pMsgHdr.hasOwnProperty("to_net_addr"))
messageSaveFile.writeln("To net address: " + pMsgHdr.to_net_addr);
if (pMsgHdr.hasOwnProperty("id"))
messageSaveFile.writeln("ID: " + pMsgHdr.id);
if (pMsgHdr.hasOwnProperty("reply_id"))
messageSaveFile.writeln("Reply ID: " + pMsgHdr.reply_id);
// Write the header information to the file
for (var i = 0; i < hdrLines.length; ++i)
messageSaveFile.writeln(hdrLines[i]);
messageSaveFile.writeln("===============================");
// If the message body has ANSI, then use the Graphic object to strip it
...
...
@@ -18302,102 +18501,54 @@ function quoteStrWithSpaces(pStr)
// Return value: A text label for the field (a string)
function msgHdrFieldListTypeToLabel(pFieldListType, pIncludeTrailingColon)
{
// The page at this URL lists the header field types:
// http://synchro.net/docs/smb.html#Header Field Types:
var fieldTypeLabel = "Unknown (" + pFieldListType.toString() + ")";
var fieldTypeLabel = "";
switch (pFieldListType)
{
case 0: // Sender
fieldTypeLabel = "Sender";
break;
case 1: // Sender Agent
fieldTypeLabel = "Sender Agent";
break;
case 2: // Sender net type
fieldTypeLabel = "Sender Net Type";
break;
case 3: // Sender Net Address
fieldTypeLabel = "Sender Net Address";
break;
case 4: // Sender Agent Extension
fieldTypeLabel = "Sender Agent Extension";
break;
case 5: // Sending agent (Sender POS)
fieldTypeLabel = "Sender Agent";
break;
case 6: // Sender organization
fieldTypeLabel = "Sender Organization";
case SMB_COMMENT:
fieldTypeLabel = "Comment";
break
case SMB_POLL_ANSWER:
fieldTypeLabel = "Poll answer";
break;
case
16
: //
Author
fieldTypeLabel = "
Author
";
case
0x64
: //
SMB_GROUP
fieldTypeLabel = "
Group
";
break;
case
17: // Author Agent
fieldTypeLabel = "
Author Agent
";
case
FIDOCTRL:
fieldTypeLabel = "
FIDO control
";
break;
case 18: // Author Net Type
fieldTypeLabel = "Author Net Type";
break;
case 19: // Author Net Address
fieldTypeLabel = "Author Net Address";
break;
case 20: // Author Extension
fieldTypeLabel = "Author Extension";
break;
case 21: // Author Agent (Author POS)
fieldTypeLabel = "Author Agent";
break;
case 22: // Author Organization
fieldTypeLabel = "Author Organization";
break;
case 32: // Reply To
fieldTypeLabel = "Reply To";
break;
case 33: // Reply To agent
fieldTypeLabel = "Reply To Agent";
break;
case 34: // Reply To net type
fieldTypeLabel = "Reply To net type";
break;
case 35: // Reply To net address
fieldTypeLabel = "Reply To net address";
case FIDOSEENBY:
fieldTypeLabel = "Seen-by";
break;
case
36: // Reply To extension
fieldTypeLabel = "
Reply To (extended)
";
case
FIDOPATH:
fieldTypeLabel = "
FIDO Path
";
break;
case
37: // Reply To position
fieldTypeLabel = "R
eply To position
";
case
RFC822HEADER:
fieldTypeLabel = "R
FCC822 Header
";
break;
case 3
8
: // R
eply To organization (0x26 hex)
fieldTypeLabel = "R
eply To organization
";
case
0xB
3: // R
FC822TO
fieldTypeLabel = "R
FC822 To
";
break;
case
48
: // R
ecipient (0x30 hex)
fieldTypeLabel = "R
ecipient
";
case
0xB6
: // R
FC822CC
fieldTypeLabel = "R
FC822 CC
";
break;
case
162
: //
Seen-by
fieldTypeLabel = "
Seen-by
";
case
0xB7
: //
RFC822ORG
fieldTypeLabel = "
RFC822 Org
";
break;
case
163
: //
Path
fieldTypeLabel = "
Path
";
case
0xB4
: //
RFC822FROM
fieldTypeLabel = "
RFC822 From
";
break;
case
176
: // RFC
C
822
Header
fieldTypeLabel = "RFC
C
822
Header
";
case
0xB5
: // RFC822
REPLYTO
fieldTypeLabel = "RFC822
Reply To
";
break;
case
177
: // RFC822
MSGID
fieldTypeLabel = "RFC822
MSGID
";
case
0xB8
: // RFC822
SUBJECT
fieldTypeLabel = "RFC822
Subject
";
break;
case
178: // RFC822 REPLYID
fieldTypeLabel = "
RFC822 REPLYID
";
case
SMTPRECEIVED:
fieldTypeLabel = "
SMTP Received
";
break;
case 240: // UNKNOWN
fieldTypeLabel = "UNKNOWN";
break;
case 241: // UNKNOWNASCII
case 0xF1: // UNKNOWNASCII
fieldTypeLabel = "UNKNOWN (ASCII)";
break;
case 255:
fieldTypeLabel = "UNUSED";
break;
default:
fieldTypeLabel = "Unknown (" + pFieldListType.toString() + ")";
break;
...
...
@@ -21700,6 +21851,7 @@ function clearScreenRectangle(pX, pY, pWidth, pHeight)
}
}
///////////////////////////////////////////////////////////////////////////////////
// For debugging: Writes some text on the screen at a given location with a given pause.
...
...
This diff is collapsed.
Click to expand it.
xtrn/DDMsgReader/readme.txt
+
2
−
2
View file @
d540b1f6
Digital Distortion Message Reader
Version 1.73
Release date: 2023-04-
17
Version 1.73
a
Release date: 2023-04-
25
by
...
...
This diff is collapsed.
Click to expand it.
xtrn/DDMsgReader/revision_history.txt
+
3
−
0
View file @
d540b1f6
...
...
@@ -5,6 +5,9 @@ Revision History (change log)
=============================
Version Date Description
------- ---- -----------
1.73a 2023-04-25 For viewing message headers, now all message header
information is displayed & sorted alphabetically by field
name (same with saving a message to a file).
1.73 2023-04-17 Bug fix: When getting header lines to view, ensure the
header lines are not too wide for the user's terminal.
Header lines that are too long will be split into no more
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment