Newer
Older
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
this.promptToContinueListingMessages = (valueUpper == "TRUE");
else if (settingUpper == "PROMPTCONFIRMREADMESSAGE")
this.promptToReadMessage = (valueUpper == "TRUE");
else if (settingUpper == "MSGLISTDISPLAYTIME")
this.msgList_displayMessageDateImported = (valueUpper == "IMPORTED");
else if (settingUpper == "MSGAREALIST_LASTIMPORTEDMSG_TIME")
this.msgAreaList_lastImportedMsg_showImportTime = (valueUpper == "IMPORTED");
else if (settingUpper == "STARTMODE")
{
if ((valueUpper == "READER") || (valueUpper == "READ"))
this.startMode = READER_MODE_READ;
else if ((valueUpper == "LISTER") || (valueUpper == "LIST"))
this.startMode = READER_MODE_LIST;
}
else if (settingUpper == "TABSPACES")
{
var numSpaces = +value;
// If greater than 0, then set this.numTabSpaces
if (numSpaces > 0)
this.numTabSpaces = numSpaces;
}
else if (settingUpper == "PAUSEAFTERNEWMSGSCAN")
this.pauseAfterNewMsgScan = (valueUpper == "TRUE");
else if (settingUpper == "READINGPOSTONSUBBOARDINSTEADOFGOTONEXT")
this.readingPostOnSubBoardInsteadOfGoToNext = (valueUpper == "TRUE");
else if (settingUpper == "AREACHOOSERHDRFILENAMEBASE")
this.areaChooserHdrFilenameBase = value;
else if (settingUpper == "AREACHOOSERHDRMAXLINES")
{
var maxNumLines = +value;
if (maxNumLines > 0)
this.areaChooserHdrMaxLines = maxNumLines;
}
else if (settingUpper == "THEMEFILENAME")
{
// First look for the theme config file in the sbbs/mods
// directory, then sbbs/ctrl, then the same directory as
// this script.
themeFilename = system.mods_dir + value;
if (!file_exists(themeFilename))
themeFilename = system.ctrl_dir + value;
if (!file_exists(themeFilename))
themeFilename = gStartupPath + value;
}

nightfox
committed
else if (settingUpper == "DISPLAYAVATARS")
this.displayAvatars = (valueUpper == "TRUE");
else if (settingUpper == "RIGHTJUSTIFYAVATARS")
this.rightJustifyAvatar = (valueUpper == "TRUE");
else if (settingUpper == "MSGLISTSORT")
{
if (valueUpper == "WRITTEN")
this.msgListSort = MSG_LIST_SORT_DATETIME_WRITTEN;
}
}
}
cfgFile.close();
}
else
{
// Was unable to read the configuration file. Output a warning to the user
// that defaults will be used and to notify the sysop.
console.print("\x01n");
console.crlf();
console.print("\x01w\x01hUnable to open the configuration file: \x01y" + this.cfgFilename);
console.crlf();
console.print("\x01wDefault settings will be used. Please notify the sysop.");
mswait(2000);
}
// If a theme filename was specified, then read the colors & strings
// from it.
if (themeFilename.length > 0)
{
var themeFile = new File(themeFilename);
if (themeFile.open("r"))
{
var fileLine = null; // A line read from the file
var equalsPos = 0; // Position of a = in the line
var commentPos = 0; // Position of the start of a comment
var setting = null; // A setting name (string)
var value = null; // To store a value for a setting (string)
var onlySyncAttrsRegexWholeWord = new RegExp("^(\x01[krgybmcw01234567hinpq,;\.dtl<>\[\]asz])+$", 'i');
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
while (!themeFile.eof)
{
// Read the next line from the config file.
fileLine = themeFile.readln(2048);
// fileLine should be a string, but I've seen some cases
// where it isn't, so check its type.
if (typeof(fileLine) != "string")
continue;
// If the line starts with with a semicolon (the comment
// character) or is blank, then skip it.
if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0))
continue;
// If the line has a semicolon anywhere in it, then remove
// everything from the semicolon onward.
commentPos = fileLine.indexOf(";");
if (commentPos > -1)
fileLine = fileLine.substr(0, commentPos);
// Look for an equals sign, and if found, separate the line
// into the setting name (before the =) and the value (after the
// equals sign).
equalsPos = fileLine.indexOf("=");
if (equalsPos > 0)
{
// Read the setting (without leading/trailing spaces) & value
setting = trimSpaces(fileLine.substr(0, equalsPos), true, false, true);
value = fileLine.substr(equalsPos+1);
// Colors
if ((setting == "msgListHeaderMsgGroupTextColor") || (setting == "msgListHeaderMsgGroupNameColor") ||
(setting == "msgListHeaderSubBoardTextColor") || (setting == "msgListHeaderMsgSubBoardName") ||
(setting == "msgListColHeader") ||
(setting == "msgListMsgNumColor") || (setting == "msgListFromColor") ||
(setting == "msgListToColor") || (setting == "msgListSubjectColor") ||
(setting == "msgListDateColor") || (setting == "msgListTimeColor") ||
(setting == "msgListToUserMsgNumColor") || (setting == "msgListToUserFromColor") ||
(setting == "msgListToUserToColor") || (setting == "msgListToUserSubjectColor") ||
(setting == "msgListToUserDateColor") || (setting == "msgListToUserTimeColor") ||
(setting == "msgListFromUserMsgNumColor") || (setting == "msgListFromUserFromColor") ||
(setting == "msgListFromUserToColor") || (setting == "msgListFromUserSubjectColor") ||
(setting == "msgListFromUserDateColor") || (setting == "msgListFromUserTimeColor") ||
(setting == "msgListHighlightBkgColor") || (setting == "msgListMsgNumHighlightColor") ||
(setting == "msgListFromHighlightColor") || (setting == "msgListToHighlightColor") ||
(setting == "msgListSubjHighlightColor") || (setting == "msgListDateHighlightColor") ||
(setting == "msgListTimeHighlightColor") || (setting == "lightbarMsgListHelpLineBkgColor") ||
(setting == "lightbarMsgListHelpLineGeneralColor") || (setting == "lightbarMsgListHelpLineHotkeyColor") ||
(setting == "lightbarMsgListHelpLineParenColor") || (setting == "tradInterfaceContPromptMainColor") ||
(setting == "tradInterfaceContPromptHotkeyColor") || (setting == "tradInterfaceContPromptUserInputColor") ||
(setting == "msgBodyColor") || (setting == "readMsgConfirmColor") ||
(setting == "readMsgConfirmNumberColor") ||
(setting == "afterReadMsg_ListMorePromptColor") ||
(setting == "tradInterfaceHelpScreenColor") || (setting == "areaChooserMsgAreaNumColor") ||
(setting == "areaChooserMsgAreaDescColor") || (setting == "areaChooserMsgAreaNumItemsColor") ||
(setting == "areaChooserMsgAreaHeaderColor") || (setting == "areaChooserSubBoardHeaderColor") ||
(setting == "areaChooserMsgAreaMarkColor") || (setting == "areaChooserMsgAreaLatestDateColor") ||
(setting == "areaChooserMsgAreaLatestTimeColor") || (setting == "areaChooserMsgAreaBkgHighlightColor") ||
(setting == "areaChooserMsgAreaNumHighlightColor") || (setting == "areaChooserMsgAreaDescHighlightColor") ||
(setting == "areaChooserMsgAreaDateHighlightColor") || (setting == "areaChooserMsgAreaTimeHighlightColor") ||
(setting == "areaChooserMsgAreaNumItemsHighlightColor") || (setting == "lightbarAreaChooserHelpLineBkgColor") ||
(setting == "lightbarAreaChooserHelpLineGeneralColor") || (setting == "lightbarAreaChooserHelpLineHotkeyColor") ||
(setting == "lightbarAreaChooserHelpLineParenColor") || (setting == "scrollbarBGColor") ||
(setting == "scrollbarScrollBlockColor") || (setting == "enhReaderPromptSepLineColor") ||
(setting == "enhReaderHelpLineBkgColor") || (setting == "enhReaderHelpLineGeneralColor") ||
(setting == "enhReaderHelpLineHotkeyColor") || (setting == "enhReaderHelpLineParenColor") ||
(setting == "hdrLineLabelColor") || (setting == "hdrLineValueColor") ||
(setting == "selectedMsgMarkColor") || (setting == "msgListScoreColor") ||
(setting == "msgListToUserScoreColor") || (setting == "msgListFromUserScoreColor") ||
(setting == "msgListScoreHighlightColor") || (setting == "msgHdrMsgNumColor") ||
(setting == "msgHdrFromColor") || (setting == "msgHdrToColor") ||
(setting == "msgHdrToUserColor") || (setting == "msgHdrSubjColor") ||
(setting == "msgHdrDateColor"))
{
// Trim leading & trailing spaces from the value when
// setting a color. Also, replace any instances of "\x01"
// with the Synchronet attribute control character.
Eric Oulashin
committed
if (onlySyncAttrsRegexWholeWord.test(value))
this.colors[setting] = trimSpaces(value, true, false, true).replace(/\\x01/g, "\x01");
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
}
// Text values
else if ((setting == "scrollbarBGChar") ||
(setting == "scrollbarScrollBlockChar") ||
(setting == "goToPrevMsgAreaPromptText") ||
(setting == "goToNextMsgAreaPromptText") ||
(setting == "newMsgScanText") ||
(setting == "newToYouMsgScanText") ||
(setting == "allToYouMsgScanText") ||
(setting == "goToMsgNumPromptText") ||
(setting == "msgScanCompleteText") ||
(setting == "msgScanAbortedText") ||
(setting == "deleteMsgNumPromptText") ||
(setting == "editMsgNumPromptText") ||
(setting == "noMessagesInSubBoardText") ||
(setting == "noSearchResultsInSubBoardText") ||
(setting == "invalidMsgNumText") ||
(setting == "readMsgNumPromptText") ||
(setting == "msgHasBeenDeletedText") ||
(setting == "noKludgeLinesForThisMsgText") ||
(setting == "searchingPersonalMailText") ||
(setting == "searchingSubBoardAbovePromptText") ||
(setting == "searchingSubBoardText") ||
(setting == "searchTextPromptText") ||
(setting == "fromNamePromptText") ||
(setting == "toNamePromptText") ||
(setting == "abortedText") ||
(setting == "loadingPersonalMailText") ||
(setting == "msgDelConfirmText") ||
(setting == "msgUndelConfirmText") ||
(setting == "selectedMsgsUndeletedText") ||
(setting == "msgDeletedText") ||
(setting == "msgUndeletedText") ||
(setting == "cannotDeleteMsgText_notYoursNotASysop") ||
(setting == "cannotDeleteMsgText_notLastPostedMsg") ||
(setting == "msgEditConfirmText") ||
(setting == "noPersonalEmailText") ||
(setting == "postOnSubBoard"))
{
// Replace any instances of "\x01" with the Synchronet
// attribute control character
this.text[setting] = value.replace(/\\x01/g, "\x01");
}
}
}
themeFile.close();
// Ensure that scrollbarBGChar and scrollbarScrollBlockChar are
// only one character. If they're longer, use only the first
// character.
if (this.text.scrollbarBGChar.length > 1)
this.text.scrollbarBGChar = this.text.scrollbarBGChar.substr(0, 1);
if (this.text.scrollbarScrollBlockChar.length > 1)
this.text.scrollbarScrollBlockChar = this.text.scrollbarScrollBlockChar.substr(0, 1);
}
else
{
// Was unable to read the theme file. Output a warning to the user
// that defaults will be used and to notify the sysop.
this.cfgFileSuccessfullyRead = false;
console.print("\x01n");
console.crlf();
console.print("\x01w\x01hUnable to open the theme file: \x01y" + themeFilename);
console.crlf();
console.print("\x01wDefault settings will be used. Please notify the sysop.");
mswait(2000);
}
}
}

Eric Oulashin
committed
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
// For the DigDistMsgReader class: Reads the user settings file
//
// Parameters:
// pOnlyTwitlist: Optional boolean - Whether or not to only read the user's twitlist. Defaults to false.
function DigDistMsgReader_ReadUserSettingsFile(pOnlyTwitlist)
{
var onlyTwitList = (typeof(pOnlyTwitlist) === "boolean" ? pOnlyTwitlist : false);
// Open the user's personal twit list file, if it exists
var userTwitlistFile = new File(gUserTwitListFilename);
if (userTwitlistFile.open("r"))
{
while (!userTwitlistFile.eof)
{
// Read the next line from the config file.
var fileLine = userTwitlistFile.readln(2048);
// fileLine should be a string, but I've seen some cases
// where for some reason it isn't. If it's not a string,
// then continue onto the next line.
if (typeof(fileLine) != "string")
continue;
// If the line starts with with a semicolon (the comment
// character) or is blank, then skip it.
if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0))
continue;
// In case there are any commas, split on commas. Add all names to the user's twitlist
var names = fileLine.split(",");
for (var i = 0; i < names.length; ++i)
{
var twitListNameEntry = names[i].trim().toLowerCase(); // Lowercase for case-insensitive comparisons
if (twitListNameEntry.length > 0)
this.userSettings.twitList.push(twitListNameEntry);
}
}
userTwitlistFile.close();
}
/*
if (!onlyTwitList)
{
// Open the user settings file, if it exists
var userSettingsFile = new File(gUserSettingsFilename);
if (userSettingsFile.open("r"))
{
var settingsMode = "behavior";
var equalsPos = 0; // Position of a = in the line
var commentPos = 0; // Position of the start of a comment
var setting = null; // A setting name (string)
var settingUpper = null; // Upper-case setting name
var value = null; // A value for a setting (string)
var valueUpper = null; // Upper-cased value
while (!userSettingsFile.eof)
{
// Read the next line from the config file.
var fileLine = userSettingsFile.readln(2048);
// fileLine should be a string, but I've seen some cases
// where for some reason it isn't. If it's not a string,
// then continue onto the next line.
if (typeof(fileLine) != "string")
continue;
// If the line starts with with a semicolon (the comment
// character) or is blank, then skip it.
if ((fileLine.substr(0, 1) == ";") || (fileLine.length == 0))
continue;
// If in the "behavior" section, then set the behavior-related variables.
if (fileLine.toUpperCase() == "[BEHAVIOR]")
{
settingsMode = "behavior";
continue;
}
// If the line has a semicolon anywhere in it, then remove
// everything from the semicolon onward.
commentPos = fileLine.indexOf(";");
if (commentPos > -1)
fileLine = fileLine.substr(0, commentPos);
// Look for an equals sign, and if found, separate the line
// into the setting name (before the =) and the value (after the
// equals sign).
equalsPos = fileLine.indexOf("=");
if (equalsPos > 0)
{
// Read the setting & value, and trim leading & trailing spaces.
setting = trimSpaces(fileLine.substr(0, equalsPos), true, false, true);
settingUpper = setting.toUpperCase();
value = trimSpaces(fileLine.substr(equalsPos+1), true, false, true);
valueUpper = value.toUpperCase();
if (settingsMode == "behavior")
{
if (settingUpper == "SOMETHING")
this.userSettings.something = (valueUpper == "TRUE");
}
}
}
userSettingsFile.close();
}
}
*/
}
// For the DigDistMsgReader class: Lets the user edit an existing message.
//
// Parameters:
// pMsgIndex: The index of the message to edit
//
// Return value: An object with the following parameters:
// userCannotEdit: Boolean - True if the user can't edit, false if they can
// userConfirmed: Boolean - Whether or not the user confirmed editing
// msgEdited: Boolean - Whether or not the message was edited
// newMsgIdx: The index (offset) of the new (edited) message that was saved.
// If the message wasn't edited/saved, this will be -1.
function DigDistMsgReader_EditExistingMsg(pMsgIndex)
{
var returnObj = {
userCannotEdit: false,
userConfirmed: false,
msgEdited: false,
newMsgIdx: -1
};
// Open the sub-board
var msgbase = new MsgBase(this.subBoardCode);
if (!msgbase.open())
{
console.print("\x01n\x01h\x01wCan't open the sub-board\x01n");
console.crlf();
console.pause();
return returnObj;
}
// Only let the user edit the message if they're a sysop or
// if they wrote the message.
var msgHeader = this.GetMsgHdrByIdx(pMsgIndex, false, msgbase);
Eric Oulashin
committed
if (!user.is_sysop && (msgHeader.from != user.name) && (msgHeader.from != user.alias) && (msgHeader.from != user.handle))
{
console.print("\x01n\x01h\x01wCannot edit message #\x01y" + +(pMsgIndex+1) +
" \x01wbecause it's not yours or you're not a sysop.");
console.crlf();
console.pause();
returnObj.userCannotEdit = true;
return returnObj;
}
// Confirm the action with the user (default to no).
Eric Oulashin
committed
returnObj.userConfirmed = !console.noyes(replaceAtCodesInStr(format(this.text.msgEditConfirmText, +(pMsgIndex+1))));
if (!returnObj.userConfirmed)
{
msgbase.close();
return returnObj;
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
8419
8420
8421
// Make use of bbs.edit_msg() if the function exists (it was added in
// Synchronet 3.18c). Otherwise, edit the old way.
if (typeof(bbs.edit_msg) === "function")
{
if (!bbs.edit_msg(msgHeader))
{
var grpIdx = msg_area.sub[this.subBoardCode].grp_index;
var areaDesc = msg_area.grp_list[grpIdx].description + " - " + msg_area.sub[this.subBoardCode].description;
var logMsg = user.alias + " was unable to edit message number " + msgHeader.number + " in " + areaDesc;
log(LOG_ERROR, logMsg);
bbs.log_str(logMsg);
}
}
else
this.EditExistingMessageOldWay(msgbase, msgHeader, pMsgIndex);
msgbase.close();
return returnObj;
}
// Helper for DigDistMsgReader_EditExistingMsg(): Edits an existing message by writing it
// to a temporary file, having the user edit that, and saving it as a new message.
// This was done before the bbs.edit_msg() function existed (it was added in Synchronet
// 3.18c).
//
// Parameters:
// pMsgbase: The MessageBase object. Assumed to be open.
// pOrigMsgHdr: The header of the original message
// pMsgIndex: The index of the message to edit
function DigDistMsgReader_EditExistingMessageOldWay(pMsgbase, pOrigMsgHdr, pMsgIndex)
{
// Dump the message body to a temporary file in the node dir
//var originalMsgBody = pMsgbase.get_msg_body(true, pMsgIndex, false, false, true, true);
var originalMsgBody;
var tmpMsgHdr = this.GetMsgHdrByIdx(pMsgIndex, false, pMsgbase);
var msgHdrIsBogus = (tmpMsgHdr.hasOwnProperty("isBogus") ? tmpMsgHdr.isBogus : false);
if (msgHdrIsBogus)
originalMsgBody = pMsgbase.get_msg_body(true, pMsgIndex, false, false, true, true);
else
originalMsgBody = pMsgbase.get_msg_body(false, tmpMsgHdr.number, false, false, true, true);
var tempFilename = system.node_dir + "DDMsgLister_message.txt";
var tmpFile = new File(tempFilename);
if (tmpFile.open("w"))
{
var wroteToTempFile = tmpFile.write(word_wrap(originalMsgBody, 79));
tmpFile.close();
// If we were able to write to the temp file, then let the user
// edit the file.
if (wroteToTempFile)
{
// The following lines set some attributes in the bbs object
// in an attempt to make the "To" name and subject appear
// correct in the editor.
// TODO: On May 14, 2013, Digital Man said bbs.msg_offset will
// probably be removed because it doesn't provide any benefit.
// bbs.msg_number is a unique message identifier that won't
// change, so it's probably best for scripts to use bbs.msg_number
// instead of offsets.
bbs.msg_to = pOrigMsgHdr.to;
bbs.msg_to_ext = pOrigMsgHdr.to_ext;
bbs.msg_subject = pOrigMsgHdr.subject;
bbs.msg_offset = pOrigMsgHdr.offset;
bbs.msg_number = pOrigMsgHdr.number;
// Let the user edit the temporary file
console.editfile(tempFilename);
// Load the temp file back into msgBodyColor and have pMsgbase
// save the message.
if (tmpFile.open("r"))
{
var newMsgBody = tmpFile.read();
tmpFile.close();
// If the new message body is different from the original message
// body, then go ahead and save the message and mark the original
// message for deletion. (Checking the new & original message
// bodies seems to be the only way to check to see if the user
// aborted out of the message editor.)
if (newMsgBody != originalMsgBody)
{
var newHdr = { to: pOrigMsgHdr.to, to_ext: pOrigMsgHdr.to_ext, from: pOrigMsgHdr.from,
from_ext: pOrigMsgHdr.from_ext, attr: pOrigMsgHdr.attr,
subject: pOrigMsgHdr.subject };
var savedNewMsg = pMsgbase.save_msg(newHdr, newMsgBody);
// If the message was successfully saved, then mark the original
// message for deletion and output a message to the user.
if (savedNewMsg)
{
returnObj.msgEdited = true;
returnObj.newMsgIdx = pMsgbase.total_msgs - 1;
var message = "\x01n\x01cThe edited message has been saved as a new message.";
if (pMsgbase.remove_msg(true, pMsgIndex))
message += " The original has been\r\nmarked for deletion.";
else
message += " \x01h\x01yHowever, the original\r\ncould not be marked for deletion.";
message += "\r\n\x01p";
console.print(message);
}
else
console.print("\r\n\x01n\x01h\x01yError: \x01wFailed to save the new message\r\n\x01p");
}
}
else
{
console.print("\r\n\x01n\x01h\x01yError: \x01wUnable to read the temporary file\r\n");
console.print("Filename: \x01b" + tempFilename + "\r\n");
console.pause();
}
}
else
{
console.print("\r\n\x01n\x01h\x01yError: \x01wUnable to write to temporary file\r\n");
console.print("Filename: \x01b" + tempFilename + "\r\n");
console.pause();
}
}
else
{
console.print("\r\n\x01n\x01h\x01yError: \x01wUnable to open a temporary file for writing\r\n");
console.print("Filename: \x01b" + tempFilename + "\r\n");
console.pause();
}
// Delete the temporary file from disk.
tmpFile.remove();
}
// For the DigDistMsgReader Class: Returns whether or not the user can delete
// their messages in the sub-board (distinct from being able to delete only
// their last message).
function DigDistMsgReader_CanDelete()
{
Eric Oulashin
committed
var canDelete = user.is_sysop || this.readingPersonalEmail;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
if (msgbase.cfg != null)
canDelete = canDelete || ((msgbase.cfg.settings & SUB_DEL) == SUB_DEL);
msgbase.close();
}
return canDelete;
}
// For the DigDistMsgReader Class: Returns whether or not the user can delete
// the last message they posted in the sub-board.
function DigDistMsgReader_CanDeleteLastMsg()
{
Eric Oulashin
committed
var canDelete = user.is_sysop;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
if (msgbase.cfg != null)
canDelete = canDelete || ((msgbase.cfg.settings & SUB_DELLAST) == SUB_DELLAST);
msgbase.close();
}
return canDelete;
}
// For the DigDistMsgReader Class: Returns whether or not the user can edit
// messages.
function DigDistMsgReader_CanEdit()
{
Eric Oulashin
committed
var canEdit = user.is_sysop;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
if (msgbase.cfg != null)
canEdit = canEdit || ((msgbase.cfg.settings & SUB_EDIT) == SUB_EDIT);
msgbase.close();
}
return canEdit;
}
// For the DigDistMsgReader Class: Returns whether or not message quoting
// is enabled.
function DigDistMsgReader_CanQuote()
{
Eric Oulashin
committed
var canQuote = this.readingPersonalEmail || user.is_sysop;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
if (msgbase.cfg != null)
canQuote = canQuote || ((msgbase.cfg.settings & SUB_QUOTE) == SUB_QUOTE);
msgbase.close();
}
return canQuote;
}
// For the DigDistMsgReader Class: Displays the stock Synchronet message header file for
// a given message header.
//
// Parameters:
// pMsgHdr: The message header object
function DigDistMsgReader_DisplaySyncMsgHeader(pMsgHdr)
{
if ((pMsgHdr == null) || (typeof(pMsgHdr) != "object"))
return;
// Note: The message header has the following fields:
// 'number': The message number
// 'offset': The message offset
// 'to': Who the message is directed to (string)
// 'from' Who wrote the message (string)
// 'subject': The message subject (string)
// 'date': The date - Full text (string)
8592
8593
8594
8595
8596
8597
8598
8599
8600
8601
8602
8603
8604
8605
8606
8607
8608
8609
8610
8611
8612
8613
8614
8615
8616
8617
8618
8619
8620
8621
8622
8623
8624
8625
8626
8627
8628
8629
8630
8631
8632
8633
8634
8635
8636
8637
// Generate a string containing the message's import date & time.
//var dateTimeStr = strftime("%Y-%m-%d %H:%M:%S", msgHeader.when_imported_time)
// Use the date text in the message header, without the time
// zone offset at the end.
var dateTimeStr = pMsgHdr["date"].replace(/ [-+][0-9]+$/, "");
// Check to see if there is a msghdr file in the sbbs/text/menu
// directory. If there is, then use it to display the message
// header information. Otherwise, output a default message header.
var msgHdrFileOpened = false;
var msgHdrFilename = this.GetMsgHdrFilenameFull();
if (msgHdrFilename.length > 0)
{
var msgHdrFile = new File(msgHdrFilename);
if (msgHdrFile.open("r"))
{
msgHdrFileOpened = true;
var fileLine = null; // To store a line read from the file
while (!msgHdrFile.eof)
{
// Read the next line from the header file
fileLine = msgHdrFile.readln(2048);
// fileLine should be a string, but I've seen some cases
// where it isn't, so check its type.
if (typeof(fileLine) != "string")
continue;
// Since we're displaying the message information ouside of Synchronet's
// message read prompt, this script now has to parse & replace some of
// the @-codes in the message header line, since Synchronet doesn't know
// that the user is reading a message.
console.putmsg(this.ParseMsgAtCodes(fileLine, pMsgHdr, null, dateTimeStr, false, true));
console.crlf();
}
msgHdrFile.close();
}
}
// If the msghdr file didn't open (or doesn't exist), then output the default
// header.
if (!msgHdrFileOpened)
{
// Generate a string describing the message attributes, then output the default
// header.
var allMsgAttrStr = makeAllMsgAttrStr(pMsgHdr);

Eric Oulashin
committed
console.print("\x01n\x01w" + charStr(HORIZONTAL_DOUBLE, 78));
console.crlf();

Eric Oulashin
committed
var horizSingleFive = charStr(HORIZONTAL_SINGLE, 5);
console.print("\x01n\x01w" + horizSingleFive + "\x01cFrom\x01w\x01h: \x01b" + pMsgHdr["from"].substr(0, console.screen_columns-12));
console.crlf();

Eric Oulashin
committed
console.print("\x01n\x01w" + horizSingleFive + "\x01cTo \x01w\x01h: \x01b" + pMsgHdr["to"].substr(0, console.screen_columns-12));
console.crlf();

Eric Oulashin
committed
console.print("\x01n\x01w" + horizSingleFive + "\x01cSubj\x01w\x01h: \x01b" + pMsgHdr["subject"].substr(0, console.screen_columns-12));
console.crlf();

Eric Oulashin
committed
console.print("\x01n\x01w" + horizSingleFive + "\x01cDate\x01w\x01h: \x01b" + dateTimeStr.substr(0, console.screen_columns-12));
console.crlf();

Eric Oulashin
committed
console.print("\x01n\x01w" + horizSingleFive + "\x01cAttr\x01w\x01h: \x01b" + allMsgAttrStr.substr(0, console.screen_columns-12));
console.crlf();
}
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
}
// For the DigDistMsgReader class: Returns the name of the msghdr file in the
// sbbs/text/menu directory. If the user's terminal supports ANSI, this first
// checks to see if an .ans version exists. Otherwise, checks to see if an
// .asc version exists. If neither are found, this function will return an
// empty string.
function DigDistMsgReader_GetMsgHdrFilenameFull()
{
// If the user's terminal supports ANSI and msghdr.ans exists
// in the text/menu directory, then use that one. Otherwise,
// if msghdr.asc exists, then use that one.
var ansiFileName = "menu/msghdr.ans";
var asciiFileName = "menu/msghdr.asc";
var msgHdrFilename = "";
if (console.term_supports(USER_ANSI) && file_exists(system.text_dir + ansiFileName))
msgHdrFilename = system.text_dir + ansiFileName;
else if (file_exists(system.text_dir + asciiFileName))
msgHdrFilename = system.text_dir + asciiFileName;
return msgHdrFilename;
}
// For the DigDistMsgReader class: Returns the number of messages in the current
// sub-board. This will be either the number of headers in this.msgSearchHdrs
// for the current sub-board (if non-empty and a search type specified) or
// msgbase.total_msgs.
//
// Parameters:
// pMsgbase: Optional - A MessageBase object
// pCheckDeletedAttributes: Optional boolean - Whether or not to check the
// 'deleted' attributes of the messages and not
// count deleted messages. Defaults to false.
//
// Return value: The number of messages
function DigDistMsgReader_NumMessages(pMsgbase, pCheckDeletedAttributes)
{
var checkDeletedAttributes = (typeof(pCheckDeletedAttributes) == "boolean" ? pCheckDeletedAttributes : false);
var msgbase = null;
var closeMsgbaseInThisFunc = false;
if ((pMsgbase != null) && (typeof(pMsgbase) == "object"))
msgbase = pMsgbase;
else
{
msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
closeMsgbaseInThisFunc = true;
else
return 0;
}
var numMsgs = 0;
if (this.SearchingAndResultObjsDefinedForCurSub())
numMsgs = this.msgSearchHdrs[this.subBoardCode].indexed.length;
else if (this.hdrsForCurrentSubBoard.length > 0)
numMsgs = this.hdrsForCurrentSubBoard.length;
else if ((msgbase != null) && msgbase.is_open)

nightfox
committed
{
//numMsgs = msgbase.total_msgs;

nightfox
committed
// Count the number of readable messages in the messagebase (i.e.,
// messages that are not deleted, unvalidated, or null headers)
numMsgs = 0;
var totalNumMsgs = msgbase.total_msgs;
for (var msgIdx = 0; msgIdx < totalNumMsgs; ++msgIdx)

nightfox
committed
{
if (isReadableMsgHdr(msgbase.get_msg_header(true, msgIdx, false), this.subBoardCode))

nightfox
committed
++numMsgs;
}
}
8721
8722
8723
8724
8725
8726
8727
8728
8729
8730
8731
8732
8733
8734
8735
8736
8737
8738
8739
8740
8741
// If the caller wants to check the deleted attributes, then do so.
if ((numMsgs > 0) && checkDeletedAttributes)
{
var msgHdr;
var originalNumMsgs = numMsgs;
for (var msgIdx = 0; msgIdx < originalNumMsgs; ++msgIdx)
{
msgHdr = this.GetMsgHdrByIdx(msgIdx);
if ((msgHdr.attr & MSG_DELETE) == MSG_DELETE)
{
--numMsgs;
if (numMsgs < 0)
{
numMsgs = 0;
break;
}
}
}
}
if (closeMsgbaseInThisFunc)
msgbase.close();
8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771
8772
return numMsgs;
}
// For the DigDistMsgReader class: Returns whether there are any non-deleted
// messages in the current sub-board.
//
// Return value: Boolean - Whether or not there are any non-deleted messages
// in the current sub-board.
function DigDistMsgReader_NonDeletedMessagesExist()
{
var messagesExist = false;
var numMsgs = this.NumMessages();
if (numMsgs > 0)
{
var msgHdr;
for (var msgIdx = 0; (msgIdx < numMsgs) && !messagesExist; ++msgIdx)
{
msgHdr = this.GetMsgHdrByIdx(msgIdx);
if ((msgHdr.attr & MSG_DELETE) == 0)
{
messagesExist = true;
break;
}
}
}
return messagesExist;
}
// For the DigDistMsgReader class: Returns the highest message number (1-based), either from this.msgSearchHdrs
// (if it has search results for the current sub-board) or msgbase. If
// there are no search results for the current sub-board in this.msgSearchHdrs,
// the highest message number is the same as the total number of messages
// in the sub-board (unless the Synchronet standard ever changes..).
function DigDistMsgReader_HighestMessageNum()
{
var highestMessageNum = 0;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
highestMessageNum = msgbase.total_msgs;
msgbase.close();
}
if (this.msgSearchHdrs.hasOwnProperty(this.subBoardCode) && (this.msgSearchHdrs[this.subBoardCode].indexed.length > 0))
highestMessageNum = this.msgSearchHdrs[this.subBoardCode].indexed.length;
return highestMessageNum;
}
// For the DigDistMsgReader class: Returns whether or not a message number (1-based)
// is a valid and existing message number. This is intended for validating user
// input where not all the message numbers are consecutive.
//
// Parameters:
// pMsgNum: The message number to validate
//
// Return value: Boolean - Whether or not the message number
function DigDistMsgReader_IsValidMessageNum(pMsgNum)
{
// The message numbers start at 1
if (pMsgNum < 1)
return false;
// If there are search results for the current sub-board, then check to see if
// the message number exists in its indexed array. Otherwise, check with
// msgbase.
var msgNumIsValid = false;
if (this.SearchingAndResultObjsDefinedForCurSub())
msgNumIsValid = ((pMsgNum > 0) && (pMsgNum <= this.msgSearchHdrs[this.subBoardCode].indexed.length));
else
{
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
msgNumIsValid = ((pMsgNum > 0) && (pMsgNum <= msgbase.total_msgs));
msgbase.close();
}
}
return msgNumIsValid;
}
// For the DigDistMsgReader class: Returns a message header by index. Will look
// in this.msgSearchHdrs if it's not empty, then in this.hdrsForCurrentSubBoard
// if it's not empty, then from msgbase.
//
// Parameters:
// pMsgIdx: The message index (0-based)
// pExpandFields: Whether or not to expand fields. Defaults to false.
// pMsgbase: Optional - An open MsgBase object. If not passed, the sub-board will be opened in this method.
function DigDistMsgReader_GetMsgHdrByIdx(pMsgIdx, pExpandFields, pMsgbase)
{
var expandFields = (typeof(pExpandFields) == "boolean" ? pExpandFields : false);
var msgHdr = null;
if (this.msgSearchHdrs.hasOwnProperty(this.subBoardCode) &&
(this.msgSearchHdrs[this.subBoardCode].indexed.length > 0))
{
if ((pMsgIdx >= 0) && (pMsgIdx < this.msgSearchHdrs[this.subBoardCode].indexed.length))
{
if (expandFields)
msgHdr = this.msgSearchHdrs[this.subBoardCode].indexed[pMsgIdx];
else
msgHdr = getHdrFromMsgbase(pMsgbase, this.subBoardCode, false, this.msgSearchHdrs[this.subBoardCode].indexed[pMsgIdx].number, expandFields);
}
else if (this.hdrsForCurrentSubBoard.length > 0)
{
if ((pMsgIdx >= 0) && (pMsgIdx < this.hdrsForCurrentSubBoard.length))
if (expandFields)
msgHdr = this.hdrsForCurrentSubBoard[pMsgIdx];
else
msgHdr = getHdrFromMsgbase(pMsgbase, this.subBoardCode, false, this.hdrsForCurrentSubBoard[pMsgIdx].number, expandFields);
}
else
msgHdr = getHdrFromMsgbase(pMsgbase, this.subBoardCode, true, pMsgIdx, pExpandFields);
if (msgHdr == null)
msgHdr = getBogusMsgHdr();
}
// For the DigDistMsgReader class: Returns a message header by message number
// (1-based). Will look in this.msgSearchHdrs if it's not empty, then in
// this.hdrsForCurrentSubBoard if it's not empty, then from msgbase.
//
// Parameters:
// pMsgNum: The message number (1-based)
// pExpandFields: Whether or not to expand fields. Defaults to false.
//
// Return value: The message header for the message number, or null on error
function DigDistMsgReader_GetMsgHdrByMsgNum(pMsgNum, pExpandFields)
{
var msgHdr = null;
if (this.msgSearchHdrs.hasOwnProperty(this.subBoardCode) &&
(this.msgSearchHdrs[this.subBoardCode].indexed.length > 0))
{
if ((pMsgNum > 0) && (pMsgNum <= this.msgSearchHdrs[this.subBoardCode].indexed.length))
msgHdr = this.msgSearchHdrs[this.subBoardCode].indexed[pMsgNum-1];
}
else if (this.hdrsForCurrentSubBoard.length > 0)
{
if ((pMsgNum > 0) && (pMsgNum <= this.hdrsForCurrentSubBoard.length))
msgHdr = this.hdrsForCurrentSubBoard.length[pMsgNum-1];
}
else
{
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
if ((pMsgNum > 0) && (pMsgNum <= msgbase.total_msgs))
{
var expandFields = (typeof(pExpandFields) == "boolean" ? pExpandFields : false);
msgHdr = msgbase.get_msg_header(true, pMsgNum-1, expandFields);
}
msgbase.close();
}
}
if (msgHdr == null)
msgHdr = getBogusMsgHdr();
return msgHdr;
}
// For the DigDistMsgReader class: Returns a message header by absolute message
// number. If there is a problem, this method will return null.
//
// Parameters:
// pMsgNum: The absolute message number
// pExpandFields: Whether or not to expand fields. Defaults to false.
// pGetVoteInfo: Whether or not to get voting information. Defaults to false.
//
// Return value: The message header for the message number, or null on error
function DigDistMsgReader_GetMsgHdrByAbsoluteNum(pMsgNum, pExpandFields, pGetVoteInfo)
{
var msgHdr = null;
var msgbase = new MsgBase(this.subBoardCode);
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);
msgbase.close();
}
if (msgHdr == null)
msgHdr = getBogusMsgHdr();
return msgHdr;
}
// For the DigDistMsgReader class: Takes an absolute message number and returns
// its message index (offset). On error, returns -1.
//
// Parameters:
// pMsgNum: The absolute message number
//
// Return value: The message's index. On error, returns -1.
function DigDistMsgReader_AbsMsgNumToIdx(pMsgNum)
{
var msgIdx = -1;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
msgIdx = absMsgNumToIdx(msgbase, pMsgNum);
msgbase.close();
}
return msgIdx;
}
// For the DigDistMsgReader class: Takes a message index and returns
// its absolute message number. On error, returns -1.
//
// Parameters:
// pMsgIdx: The message index
//
// Return value: The message's absolute message number. On error, returns -1.
function DigDistMsgReader_IdxToAbsMsgNum(pMsgIdx)
{
var msgIdx = -1;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
msgIdx = idxToAbsMsgNum(msgbase, pMsgIdx);
msgbase.close();
}
return msgIdx;
}
// This function takes an absolute message number for a given messagebase objectand
// and returns the message index (offset). On error, returns -1.
//
// Parameters:
// pMsgbase: The messagebase object from which to retrieve the message header
// pMsgNum: The absolute message number
//
// Return value: The message's index, or -1 on error.
function absMsgNumToIdx(pMsgbase, pMsgNum)
{
if ((pMsgbase == null) || (typeof(pMsgbase) != "object"))
return -1;
if (!pMsgbase.is_open)
return -1;

nightfox
committed
if (typeof(pMsgNum) != "number")
return -1;
var messageIdx = 0;
// If pMsgNum is 0xffffffff (0xffffffff, or ~0), that is a special value
// for the user's scan_ptr meaning it should point to the latest message
// in the messagebase.
if (pMsgNum == 0xffffffff)
messageIdx = pMsgbase.total_msgs - 1; // Or this.NumMessages() - 1 but can't because this isn't a class member function
else
{
var msgHdr = pMsgbase.get_msg_header(false, pMsgNum, false);
if ((msgHdr == null) && gCmdLineArgVals.verboselogging)
{
writeToSysAndNodeLog("Message area " + pMsgbase.cfg.code + ": Tried to get message header for absolute message number " +
pMsgNum + " but got a null header object.");