Newer
Older
{
var retObj = {
msgAreaGood: true,
errorMsg: ""
};
13006
13007
13008
13009
13010
13011
13012
13013
13014
13015
13016
13017
13018
13019
13020
13021
13022
13023
13024
13025
13026
13027
13028
13029
13030
13031
13032
13033
13034
13035
13036
13037
13038
13039
13040
// Get the internal code of the sub-board from the given group & sub-board
// indexes
var subCode = msg_area.grp_list[pGrpIdx].sub_list[pSubIdx].code;
// If a search is specified that would populate the search results, then do
// a search in the given sub-board.
if (this.SearchTypePopulatesSearchResults())
{
// See if we can use pCurPos to move the cursor before displaying messages
var useCurPos = (console.term_supports(USER_ANSI) && (typeof(pCurPos) == "object") &&
(typeof(pCurPos.x) == "number") && (typeof(pCurPos.y) == "number"));
// TODO: In case new messages were posted in this sub-board, it might help
// to check the current number of messages vs. the previous number of messages
// and search the new messages if there are more.
// Determine whether or not to search - If there are no search results for
// the given sub-board already, then do a search in the sub-board.
var doSearch = true;
if (this.msgSearchHdrs.hasOwnProperty(subCode) &&
(typeof(this.msgSearchHdrs[subCode]) == "object") &&
(typeof(this.msgSearchHdrs[subCode].indexed) != "undefined"))
{
doSearch = (this.msgSearchHdrs[subCode].indexed.length == 0);
}
if (doSearch)
{
if (useCurPos)
{
console.gotoxy(pCurPos);
console.cleartoeol("\1n");
console.gotoxy(pCurPos);
}
console.print("\1n\1h\1wSearching\1i...\1n");
this.msgSearchHdrs[subCode] = searchMsgbase(subCode, this.searchType, this.searchString, this.readingPersonalEmailFromUser);
// If there are no messages, then set the return object variables to indicate so.
if (this.msgSearchHdrs[subCode].indexed.length == 0)
{
retObj.msgAreaGood = false;
retObj.errorMsg = "No search results found";
13047
13048
13049
13050
13051
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
}
}
}
else
{
// No search is specified. Just check to see if there are any messages
// to read in the given sub-board.
var msgBase = new MsgBase(subCode);
if (msgBase.open())
{
if (msgBase.total_msgs == 0)
{
retObj.msgAreaGood = false;
retObj.errorMsg = "No messages in that message area";
}
msgBase.close();
}
}
return retObj;
}
// For the DigDistMsgReader class: Validates a message if the sub-board
// requires message validation.
//
// Parameters:
// pSubBoardCode: The internal code of the sub-board
// pMsgNum: The message number
//
// Return value: Boolean - Whether or not validating the message was successful
function DigDistMsgReader_ValidateMsg(pSubBoardCode, pMsgNum)
{
if (!msg_area.sub[pSubBoardCode].is_moderated)
return true;
var validationSuccessful = false;
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
var msgHdr = msgbase.get_msg_header(false, pMsgNum, false);
if (msgHdr != null)
{
if ((msgHdr.attr & MSG_VALIDATED) == 0)
{
msgHdr.attr |= MSG_VALIDATED;
validationSuccessful = msgbase.put_msg_header(false, msgHdr.number, msgHdr);
}
else
validationSuccessful = true;
}
msgbase.close();
}
return validationSuccessful;
}
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
// For the DigDistMsgReader class: Gets the current sub-board's group name and description.
//
// Return value: An object with the following properties:
// grpName: The group name
// grpDesc: The group description
function DigDistMsgReader_GetGroupNameAndDesc()
{
var retObj = {
grpName: "",
grpDesc: ""
}
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
retObj.grpName = msgbase.cfg.grp_name;
retObj.grpDesc = msgbase.cfg.description;
msgbase.close();
}
return retObj;
}
13124
13125
13126
13127
13128
13129
13130
13131
13132
13133
13134
13135
13136
13137
13138
13139
13140
13141
13142
13143
13144
13145
13146
13147
13148
13149
13150
13151
13152
13153
13154
13155
13156
13157
13158
13159
13160
13161
13162
13163
13164
13165
13166
// For the DigDistMsgReader class: Writes message lines to a file on the BBS
// machine.
//
// Parameters:
// pMsgHdr: The header object for the message
// pFilename: The name of the file to write the message to
// pStripCtrl: Boolean - Whether or not to remove Synchronet control
// codes from the message lines
// pMsgLines: An array containing the message lines
// pAttachments: An array containing attachment information (as returned by determineMsgAttachments())
//
// Return value: An object containing the following properties:
// succeeded: Boolean - Whether or not the file was successfully written
// errorMsg: String - On failure, will contain the reason it failed
function DigDistMsgReader_SaveMsgToFile(pMsgHdr, pFilename, pStripCtrl, pMsgLines, pAttachments)
{
// Sanity checking
if (typeof(pFilename) != "string")
return({ succeeded: false, errorMsg: "Filename parameter not a string"});
if (pFilename.length == 0)
return({ succeeded: false, errorMsg: "Empty filename given"});
// If no message lines are passed in, then get the message lines now.
var msgLines = pMsgLines;
var attachments = pAttachments;
if ((pMsgLines == null) || (typeof(pMsgLines) != "object"))
{
if (typeof(pMsgHdr) == "object")
{
// Get the message text, interpret any @-codes in it, replace tabs with spaces
// to prevent weirdness when displaying the message lines, and word-wrap the
// text so that it looks good on the screen,
//GetMsgInfoForEnhancedReader(pMsgHdr, pWordWrap, pDetermineAttachments, pGetB64Data)
//var msgInfo = this.GetMsgInfoForEnhancedReader(pMsgHdr, false, false, false);
var msgInfo = this.GetMsgInfoForEnhancedReader(pMsgHdr, true, true, true);
msgLines = msgInfo.messageLines;
if (msgInfo.hasOwnProperty("attachments"))
attachments = msgInfo.attachments;
}
else
return({ succeeded: false, errorMsg: "No message lines and null header object"});
}
var retObj = {
succeeded: true,
errorMsg: ""
};
13171
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186
13187
13188
13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265
13266
13267
13268
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279
// If there are message attachments, then treat pFilename as a directory and
// create the directory for saving both the message text & attachments.
// Then, save the attachments to that directory.
var msgTextFilename = pFilename;
if ((attachments != null) && (attachments.length > 0))
{
if (file_isdir(pFilename))
{
if (file_exists(pFilename))
return({ succeeded: false, errorMsg: "Can't make directory: File with that name exists"});
}
else
{
if (!mkdir(pFilename))
return({ succeeded: false, errorMsg: "Failed to create directory"});
}
// The name of the file to save the message text will be called "messageText.txt"
// in the save directory.
var savePathWithTrailingSlash = backslash(pFilename);
msgTextFilename = savePathWithTrailingSlash + "messageText.txt";
// Save the attachments to the directory
var saveFileError = "";
for (var attachIdx = 0; (attachIdx < attachments.length) && (saveFileError.length == 0); ++attachIdx)
{
var destFilename = savePathWithTrailingSlash + attachments[attachIdx].filename;
// If the file info has base64 data, then decode & save it to the directory.
// Otherwise, the file was probably uploaded to the user's mailbox in Synchronet,
// so copy the file to the save directory.
if (attachments[attachIdx].hasOwnProperty("B64Data"))
{
var attachedFile = new File(destFilename);
if (attachedFile.open("wb"))
{
attachedFile.base64 = true;
if (!attachedFile.write(attachments[attachIdx].B64Data))
saveFileError = "\1n\1cFailed to save " + attachments[attachIdx].filename;
attachedFile.close();
}
}
else
{
// There is no base64 data for the file, so it's probably in the
// user's mailbox in Synchronet, so copy it to the save directory.
if (file_exists(attachments[attachIdx].fullyPathedFilename))
{
if (!file_copy(attachments[attachIdx].fullyPathedFilename, destFilename))
saveFileError = "Failed to copy " + attachments[attachIdx].filename;
}
else
saveFileError = "File " + attachments[attachIdx].fullyPathedAttachmentFilename + " doesn't exist";
}
}
if (saveFileError.length > 0)
return({ succeeded: false, errorMsg: saveFileError });
}
var messageSaveFile = new File(msgTextFilename);
if (messageSaveFile.open("w"))
{
// Write some header information to the file
if (typeof(pMsgHdr) == "object")
{
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);
messageSaveFile.writeln("===============================");
}
// Write the message body to the file
if (pStripCtrl)
{
for (var msgLineIdx = 0; msgLineIdx < msgLines.length; ++msgLineIdx)
messageSaveFile.writeln(strip_ctrl(msgLines[msgLineIdx]));
}
else
{
for (var msgLineIdx = 0; msgLineIdx < msgLines.length; ++msgLineIdx)
messageSaveFile.writeln(msgLines[msgLineIdx]);
}
messageSaveFile.close();
}
else
{
retObj.succeeded = false;
retObj.errorMsg = "Unable to open the message file for writing";
}
return retObj;
}
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297
13298
// For the DigDistMsgReader class: Toggles whether a message has been 'selected'
// (i.e., for things like batch delete, etc.)
//
// Parameters:
// pSubCode: The internal sub-board code of the message sub-board where the
// message resides
// pMsgIdx: The index of the message to toggle
// pSelected: Optional boolean to explictly specify whether the message should
// be selected. If this is not provided (or is null), then this
// message will simply toggle the selection state of the message.
function DigDistMsgReader_ToggleSelectedMessage(pSubCode, pMsgIdx, pSelected)
{
// Sanity checking
if (typeof(pSubCode) != "string") return;
if (typeof(pMsgIdx) != "number") return;
// If the 'selected message' object doesn't have the sub code index,
// then add it.
if (!this.selectedMessages.hasOwnProperty(pSubCode))
this.selectedMessages[pSubCode] = {};
13300
13301
13302
13303
13304
13305
13306
13307
13308
13309
13310
13311
13312
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322
13323
13324
13325
13326
13327
13328
13329
13330
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
// If pSelected is a boolean, then it specifies the specific selection
// state of the message (true = selected, false = not selected).
if (typeof(pSelected) == "boolean")
{
if (pSelected)
{
if (!this.selectedMessages[pSubCode].hasOwnProperty(pMsgIdx))
this.selectedMessages[pSubCode][pMsgIdx] = true;
}
else
{
if (this.selectedMessages[pSubCode].hasOwnProperty(pMsgIdx))
delete this.selectedMessages[pSubCode][pMsgIdx];
}
}
else
{
// pSelected is not a boolean, so simply toggle the selection state of
// the message.
// If the object for the given sub-board code contains the message
// index, then remove it. Otherwise, add it.
if (this.selectedMessages[pSubCode].hasOwnProperty(pMsgIdx))
delete this.selectedMessages[pSubCode][pMsgIdx];
else
this.selectedMessages[pSubCode][pMsgIdx] = true;
}
}
// For the DigDistMsgReader class: Returns whether a message (by sub-board code & index)
// is selected (i.e., for batch delete, etc.).
//
// Parameters:
// pSubCode: The internal sub-board code of the message sub-board where the
// message resides
// pMsgIdx: The index of the message to toggle
//
// Return value: Boolean - Whether or not the given message has been selected
function DigDistMsgReader_MessageIsSelected(pSubCode, pMsgIdx)
{
return (this.selectedMessages.hasOwnProperty(pSubCode) && this.selectedMessages[pSubCode].hasOwnProperty(pMsgIdx));
}
// For the DigDistMsgReader class: Checks to see if all selected messages can
// be deleted (i.e., whether the user has permission to delete all of them).
function DigDistMsgReader_AllSelectedMessagesCanBeDeleted()
{
// If the user has sysop access, then they should be able to delete messages.
Eric Oulashin
committed
if (user.is_sysop)
13349
13350
13351
13352
13353
13354
13355
13356
13357
13358
13359
13360
13361
13362
13363
13364
13365
13366
13367
13368
13369
13370
13371
13372
13373
13374
13375
13376
13377
13378
13379
13380
13381
13382
13383
13384
13385
13386
return true;
var userCanDeleteAllSelectedMessages = true;
var msgBase = null;
for (var subBoardCode in this.selectedMessages)
{
// If the current sub-board is personal mail, then the user can delete
// those messages. Otherwise, check the sub-board configuration to see
// if the user can delete messages in the sub-board.
if (subBoardCode != "mail")
{
msgBase = new MsgBase(subBoardCode);
if (msgBase.open())
{
userCanDeleteAllSelectedMessages = userCanDeleteAllSelectedMessages && ((msgBase.cfg.settings & SUB_DEL) == SUB_DEL);
msgBase.close();
}
}
if (!userCanDeleteAllSelectedMessages)
break;
}
return userCanDeleteAllSelectedMessages;
}
// For the DigDistMsgReader class: Marks the 'selected messages' (in
// this.selecteMessages) as deleted. Returns an object with the following
// properties:
// deletedAll: Boolean - Whether or not all messages were successfully marked
// for deletion
// failureList: An object containing indexes of messages that failed to get
// marked for deletion, indexed by internal sub-board code, then
// containing messages indexes as properties. Reasons for failing
// to mark messages deleted can include the user not having permission
// to delete in a sub-board, failure to open the sub-board, etc.
function DigDistMsgReader_DeleteSelectedMessages()
{
var retObj = {
deletedAll: true,
failureList: {}
};
var msgBase = null;
var msgHdr = null;
var msgWasDeleted = false;
for (var subBoardCode in this.selectedMessages)
{
msgBase = new MsgBase(subBoardCode);
if (msgBase.open())
{
// Allow the user to delete the messages if they're the sysop, they're
// reading their personal mail, or the sub-board allows deleting messages.
Eric Oulashin
committed
if (user.is_sysop || (subBoardCode == "mail") || ((msgBase.cfg.settings & SUB_DEL) == SUB_DEL))
{
for (var msgIdx in this.selectedMessages[subBoardCode])
{
// It seems that msgIdx is a string, so make sure we have a
// numeric version.
var msgIdxNumber = +msgIdx;
// If doing a search (this.msgSearchHdrs has the sub-board code),
// then get the message header by index from there. Otherwise,
// use the message base object to get the message by index.
if (this.msgSearchHdrs.hasOwnProperty(subBoardCode) &&
(this.msgSearchHdrs[subBoardCode].indexed.length > 0))
{
if ((msgIdxNumber >= 0) && (msgIdxNumber < this.msgSearchHdrs[subBoardCode].indexed.length))
msgHdr = this.msgSearchHdrs[subBoardCode].indexed[msgIdxNumber];
}

nightfox
committed
else if (this.hdrsForCurrentSubBoard.length > 0)
{
if ((msgIdxNumber >= 0) && (msgIdxNumber < this.hdrsForCurrentSubBoard.length))
msgHdr = this.hdrsForCurrentSubBoard[msgIdxNumber];
}
else
{
if ((msgIdxNumber >= 0) && (msgIdxNumber < msgBase.total_msgs))
msgHdr = msgBase.get_msg_header(true, msgIdxNumber, false);
}
// If we got the message header, then mark it for deletion.
// If the message header wasn't marked as deleted, then add
// the message index to the return object.
if (msgHdr != null)
{
//msgWasDeleted = msgBase.remove_msg(true, msgHdr.offset);
msgWasDeleted = msgBase.remove_msg(false, msgHdr.number);
}
else
msgWasDeleted = false;
if (msgWasDeleted)
{

nightfox
committed
// Refresh the message header in the header arrays (if it
// exists there) and remove the message index from the
// selectedMessages object

nightfox
committed
this.RefreshHdrInSavedArrays(msgIdxNumber, MSG_DELETE, subBoardCode);
delete this.selectedMessages[subBoardCode][msgIdx];

nightfox
committed
// Delete any vote response messages that may exist for this message
var voteDelRetObj = deleteVoteMsgs(msgBase, msgHdr.number, msgHdr.id, (subBoardCode == "mail"));

nightfox
committed
// TODO: If the main messages was deleted, does it matter if vote response messages
// are deleted?
if (!voteDelRetObj.allVoteMsgsDeleted)
{
retObj.deletedAll = false;
if (!retObj.failureList.hasOwnProperty(subBoardCode))
retObj.failureList[subBoardCode] = [];

nightfox
committed
retObj.failureList[subBoardCode].push(msgIdxNumber);
}
}
else
{
retObj.deletedAll = false;
if (!retObj.failureList.hasOwnProperty(subBoardCode))
retObj.failureList[subBoardCode] = [];
13463
13464
13465
13466
13467
13468
13469
13470
13471
13472
13473
13474
13475
13476
13477
13478
13479
retObj.failureList[subBoardCode].push(msgIdxNumber);
}
}
// If the sub-board index array no longer has any properties (i.e.,
// all messages in the sub-board were marked as deleted), then remove
// the sub-board property from this.selectedMessages
if (Object.keys(this.selectedMessages[subBoardCode]).length == 0)
delete this.selectedMessages[subBoardCode];
}
else
{
// The user doesn't have permission to delete messages
// in this sub-board.
// Create an entry in retObj.failureList indexed by the
// sub-board code to indicate failure to delete all
// messages in the sub-board.
retObj.deletedAll = false;
retObj.failureList[subBoardCode] = [];
}
msgBase.close();
}
else
{
// Failure to open the sub-board.
// Create an entry in retObj.failureList indexed by the
// sub-board code to indicate failure to delete all messages
// in the sub-board.
retObj.deletedAll = false;
retObj.failureList[subBoardCode] = [];
13493
13494
13495
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
}
}
return retObj;
}
// For the DigDistMsgReader class: Returns the number of selected messages
function DigDistMsgReader_NumSelectedMessages()
{
var numSelectedMsgs = 0;
for (var subBoardCode in this.selectedMessages)
numSelectedMsgs += Object.keys(this.selectedMessages[subBoardCode]).length;
return numSelectedMsgs;
}

nightfox
committed
// Allows the user to forward a message to an email address or
// another user. This function is interactive with the user.
//
// Parameters:
// pMsgHeader: The header of the message being forwarded
// pMsgBody: The body text of the message
//
// Return value: A blank string on success or a string containing a
// message upon failure.
function DigDistMsgReader_ForwardMessage(pMsgHdr, pMsgBody)
{
if (typeof(pMsgHdr) != "object")
return "Invalid message header given";
var retStr = "";

Eric Oulashin
committed

nightfox
committed
console.print("\1n");
console.crlf();
console.print("\1cUser name/number/email address\1h:\1n");
console.crlf();
var msgDest = console.getstr(console.screen_columns - 1, K_LINE);
console.print("\1n");
console.crlf();
if (msgDest.length > 0)
{
var tmpMsgbase = new MsgBase("mail");
if (tmpMsgbase.open())
{
// If the given message body is not a string, then get the
// message body from the messagebase.
if (typeof(pMsgBody) != "string")
{
var msgbase = new MsgBase(this.subBoardCode);
if (msgbase.open())
{
pMsgBody = msgbase.get_msg_body(false, pMsgHdr.number, false, false, true, true);
msgbase.close();
}
else
return "Unable to open the sub-board to get the message body";
}

nightfox
committed
13552
13553
13554
13555
13556
13557
13558
13559
13560
13561
13562
13563
13564
13565
13566
13567
13568
13569
13570
13571
13572
// Prepend some lines to the message body to describe where
// the message came from originally.
var newMsgBody = "This is a forwarded message from " + system.name + "\n";
newMsgBody += "Forwarded by: " + user.alias;
if (user.alias != user.name)
newMsgBody += " (" + user.name + ")";
newMsgBody += "\n";
if (this.subBoardCode == "mail")
newMsgBody += "From " + user.name + "'s personal email\n";
else
{
newMsgBody += "From sub-board: "
+ msg_area.grp_list[msg_area.sub[this.subBoardCode].grp_index].description
+ ", " + msg_area.sub[this.subBoardCode].description + "\n";
}
newMsgBody += "From: " + pMsgHdr.from + "\n";
newMsgBody += "To: " + pMsgHdr.to + "\n";
newMsgBody += "Subject: " + pMsgHdr.subject + "\n";
newMsgBody += "==================================\n\n";
newMsgBody += pMsgBody;
// Ask whether to edit the message before forwarding it,
13574
13575
13576
13577
13578
13579
13580
13581
13582
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595
13596
13597
13598
13599
13600
13601
13602
13603
13604
13605
13606
13607
13608
13609
13610
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621
// and use console.editfile(filename) to edit it.
if (!console.noyes("Edit the message before sending"))
{
var baseWorkDir = system.node_dir + "DDMsgReader_Temp";
deltree(baseWorkDir + "/");
if (mkdir(baseWorkDir))
{
// TODO: Let the user edit the message, then read it
// and set newMsgBody to it
var tmpMsgFilename = baseWorkDir + "/message.txt";
// Write the current message to the file
var wroteMsgToTmpFile = false;
var outFile = new File(tmpMsgFilename);
if (outFile.open("w"))
{
wroteMsgToTmpFile = outFile.write(newMsgBody, newMsgBody.length);
outFile.close();
}
if (wroteMsgToTmpFile)
{
// Let the user edit the file, and if successful,
// read it in to newMsgBody
if (console.editfile(tmpMsgFilename))
{
var inFile = new File(tmpMsgFilename);
if (inFile.open("r"))
{
newMsgBody = inFile.read(inFile.length);
inFile.close();
}
}
}
else
{
console.print("\1n\1cFailed to write message to a file for editing\1n");
console.crlf();
console.pause();
}
}
else
{
console.print("\1n\1cCouldn't create temporary directory\1n");
console.crlf();
console.pause();
}
}
// End New (editing message)

nightfox
committed
// Create part of a header object which will be used when saving/sending
// the message. The destination ("to" informatoin) will be filled in
// according to the destination type.
var destMsgHdr = { to_net_type: NET_NONE, from: user.name,
replyto: user.name, subject: "Fwd: " + pMsgHdr.subject };
if (user.netmail.length > 0)

Eric Oulashin
committed
{

nightfox
committed
destMsgHdr.replyto_net_addr = user.netmail;

Eric Oulashin
committed
}

nightfox
committed
else

Eric Oulashin
committed
{

nightfox
committed
destMsgHdr.replyto_net_addr = user.email;

Eric Oulashin
committed
}

nightfox
committed
//destMsgHdr.when_written_time =
//destMsgHdr.when_written_zone = system.timezone;
//destMsgHdr.when_written_zone_offset =
var confirmedForwardMsg = true;
// If the destination is in the format anything@anything, then
// accept it as the message destination. It could be an Internet
// address (someone@somewhere.com), FidoNet address (sysop@1:327/4),
// or a QWK address (someone@HOST).
// We could specifically use gEmailRegex and gFTNEmailregex to test
// msgDest, but just using those would be too restrictive.
if (/^.*@.*$/.test(msgDest))

nightfox
committed
{
confirmedForwardMsg = console.yesno("Forward via email to " + msgDest);
if (confirmedForwardMsg)
{
console.print("\1n\1cForwarding via email to " + msgDest + "\1n");
console.crlf();
destMsgHdr.to = msgDest;
destMsgHdr.to_net_addr = msgDest;

Eric Oulashin
committed
destMsgHdr.to_net_type = netaddr_type(msgDest);

nightfox
committed
13657
13658
13659
13660
13661
13662
13663
13664
13665
13666
13667
13668
13669
13670
13671
13672
13673
13674
13675
13676
13677
13678
13679
13680
13681
13682
13683
13684
13685
13686
13687
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704
13705
}
}
else
{
// See if what the user entered is a user number/name/alias
var userNum = 0;
if (/^[0-9]+$/.test(msgDest))
{
userNum = +msgDest;
// Determine if the user entered a valid user number
var lastUserNum = (system.lastuser == undefined ? system.stats.total_users : system.lastuser + 1);
if ((userNum < 1) || (userNum >= lastUserNum))
{
userNum = 0;
console.print("\1h\1y* Invalid user number (" + msgDest + ")\1n");
console.crlf();
}
}
else // Try to get a user number assuming msgDest is a username/alias
userNum = system.matchuser(msgDest, true);
// If we have a valid user number, then we can forward the message.
if (userNum > 0)
{
var destUser = new User(userNum);
confirmedForwardMsg = console.yesno("Forward to " + destUser.alias + " (user " + destUser.number + ")");
if (confirmedForwardMsg)
{
destMsgHdr.to = destUser.alias;
// If the destination user has an Internet email address,
// ask the user if they want to send to the destination
// user's Internet email address
var sendToNetEmail = false;
if (destUser.netmail.length > 0)
{
sendToNetEmail = !console.noyes("Send to the user's Internet email (" + destUser.netmail + ")");
if (sendToNetEmail)
{
console.print("\1n\1cForwarding to " + destUser.netmail + "\1n");
console.crlf();
destMsgHdr.to = destUser.name;
destMsgHdr.to_net_addr = destUser.netmail;
destMsgHdr.to_net_type = NET_INTERNET;
}
}
if (!sendToNetEmail)
{
console.print("\1n\1cForwarding to " + destUser.alias + "\1n");
console.crlf();
destMsgHdr.to_ext = destUser.number;

Eric Oulashin
committed
destMsgHdr.to_net_type = NET_NONE;

nightfox
committed
13707
13708
13709
13710
13711
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
}
}
}
else
{
confirmedForwardMsg = false;
console.print("\1h\1y* Unknown destination\1n");
console.crlf();
}
}
var savedMsg = true;
if (confirmedForwardMsg)
savedMsg = tmpMsgbase.save_msg(destMsgHdr, newMsgBody);
else
{
console.print("\1n\1cCanceled\1n");
console.crlf();
}
tmpMsgbase.close();
if (!savedMsg)
{
console.print("\1h\1y* Failed to send the message!\1n");
console.crlf();
}
// Pause for user input so the user can see the messages written
console.pause();
}
else
retStr = "Failed to open email messagebase";
}
else
{
console.print("\1n\1cCanceled\1n");
console.crlf();
console.pause();
}
return retStr;
}

Eric Oulashin
committed
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768
13769
13770
13771
13772
13773
13774
13775
13776
13777
13778
13779
13780
13781
13782
13783
13784
13785
13786
13787
13788
13789
13790
13791
13792
13793
13794
13795
13796
function printMsgHdrInfo(pMsgHdr)
{
if (typeof(pMsgHdr) != "object")
return;
for (var prop in pMsgHdr)
{
if (prop == "to_net_type")
print(prop + ": " + toNetTypeToStr(pMsgHdr[prop]));
else
console.print(prop + ": " + pMsgHdr[prop]);
console.crlf();
}
}
function toNetTypeToStr(toNetType)
{
var toNetTypeStr = "Unknown";
if (typeof(toNetType) == "number")
{
switch (toNetType)
{
case NET_NONE:
toNetTypeStr = "Local";
break;
case NET_UNKNOWN:
toNetTypeStr = "Unknown networked";
break;
case NET_FIDO:
toNetTypeStr = "FidoNet";
break;
case NET_POSTLINK:
toNetTypeStr = "PostLink";
break;
case NET_QWK:
toNetTypeStr = "QWK";
break;
case NET_INTERNET:
toNetTypeStr = "Internet";
break;
default:
toNetTypeStr = "Unknown";
break;
}
}
return toNetTypeStr;
}
// For the DigDistMsgReader class: Lets the user vote on a message
//
// Parameters:
// pMsgHdr: The header of the mesasge being voted on
// pRemoveNLsFromVoteText: Optional boolean - Whether or not to remove newlines
// (and carriage returns) from the voting text from
// text.dat. Defaults to false.
//
// Return value: An object with the following properties:
// BBSHasVoteFunction: Boolean - Whether or not the system has
// the vote_msg function
// savedVote: Boolean - Whether or not the vote was saved
// userQuit: Boolean - Whether or not the user quit and didn't vote
// errorMsg: String - An error message, if something went wrong
// mnemonicsRequiredForErrorMsg: Boolean - Whether or not mnemonics is required to print the error message
// updatedHdr: The updated message header containing vote information.
// If something went wrong, this will be null.
function DigDistMsgReader_VoteOnMessage(pMsgHdr, pRemoveNLsFromVoteText)
var retObj = {
BBSHasVoteFunction: false,
savedVote: false,
userQuit: false,
errorMsg: "",
mnemonicsRequiredForErrorMsg: false,
updatedHdr: null
};

nightfox
committed
// Don't allow voting for personal email
if (this.subBoardCode == "mail")
{
retObj.errorMsg = "Can not vote on personal email";
return retObj;
}
// Check whether the user has the voting restiction
if ((user.security.restrictions & UFLAG_V) == UFLAG_V)
{
// Use the line from text.dat that says the user is not allowed to vote,
// and remove newlines from it.
retObj.errorMsg = "\1n" + bbs.text(typeof(R_Voting) != "undefined" ? R_Voting : 781).replace("\r\n", "").replace("\n", "").replace("\N", "").replace("\r", "").replace("\R", "").replace("\R\n", "").replace("\r\N", "").replace("\R\N", "");
return retObj;
}

nightfox
committed
var msgbase = new MsgBase(this.subBoardCode);
if (!msgbase.open())
{
return retObj;
}
// If the message vote function is not defined in the running verison of Synchronet,
// then just return.
retObj.BBSHasVoteFunction = (typeof(msgbase.vote_msg) == "function");
if (!retObj.BBSHasVoteFunction)
{
msgbase.close();
return retObj;
var removeNLsFromVoteText = (typeof(pRemoveNLsFromVoteText) === "boolean" ? pRemoveNLsFromVoteText : false)
// See if voting is allowed in the current sub-board
if ((msg_area.sub[this.subBoardCode].settings & SUB_NOVOTING) == SUB_NOVOTING)
{
retObj.errorMsg = bbs.text(typeof(VotingNotAllowed) != "undefined" ? VotingNotAllowed : 779);
if (removeNLsFromVoteText)
retObj.errorMsg = retObj.errorMsg.replace("\r\n", "").replace("\n", "").replace("\N", "").replace("\r", "").replace("\R", "").replace("\R\n", "").replace("\r\N", "").replace("\R\N", "");
retObj.mnemonicsRequiredForErrorMsg = true;
msgbase.close();
return retObj;
}
// If the message is a poll question and has the maximum number of votes
// already or is closed for voting, then don't let the user vote on it.
if ((pMsgHdr.attr & MSG_POLL) == MSG_POLL)
{
var userVotedMaxVotes = false;
var numVotes = (pMsgHdr.hasOwnProperty("votes") ? pMsgHdr.votes : 0);
if (typeof(msgbase.how_user_voted) === "function")
{
var votes = msgbase.how_user_voted(pMsgHdr.number, (msgbase.cfg.settings & SUB_NAME) == SUB_NAME ? user.name : user.alias);
// TODO: I'm not sure if this 'if' section is correct anymore for
// the latest 3.17 build of Synchronet (August 14, 2017)
// Digital Man said:
// In a poll message, the "votes" property specifies the maximum number of
// answers/votes per ballot (0 is the equivalent of 1).
// Max votes testing? :
// userVotedMaxVotes = (votes == pMsgHdr.votes);
13885
13886
13887
13888
13889
13890
13891
13892
13893
13894
13895
13896
13897
13898
13899
13900
13901
13902
13903
13904
13905
13906
if (votes >= 0)
{
if ((votes == 0) || (votes == 1))
userVotedMaxVotes = (votes == 3); // (1 << 0) | (1 << 1);
else
{
userVotedMaxVotes = true;
for (var voteIdx = 0; voteIdx <= numVotes; ++voteIdx)
{
if (votes && (1 << voteIdx) == 0)
{
userVotedMaxVotes = false;
break;
}
}
}
}
}
var pollIsClosed = ((pMsgHdr.auxattr & POLL_CLOSED) == POLL_CLOSED);
if (pollIsClosed)
{
retObj.errorMsg = "This poll is closed";
msgbase.close();
return retObj;
}
else if (userVotedMaxVotes)
{
retObj.errorMsg = bbs.text(typeof(VotedAlready) != "undefined" ? VotedAlready : 780);
if (removeNLsFromVoteText)
retObj.errorMsg = retObj.errorMsg.replace("\r\n", "").replace("\n", "").replace("\N", "").replace("\r", "").replace("\R", "").replace("\R\n", "").replace("\r\N", "").replace("\R\N", "");
retObj.mnemonicsRequiredForErrorMsg = true;
msgbase.close();
return retObj;
}
}
// If the user has voted on this message already, then set an error message and return.
if (this.HasUserVotedOnMsg(pMsgHdr.number))
{
retObj.errorMsg = bbs.text(typeof(VotedAlready) != "undefined" ? VotedAlready : 780);
if (removeNLsFromVoteText)
retObj.errorMsg = retObj.errorMsg.replace("\r\n", "").replace("\n", "").replace("\N", "").replace("\r", "").replace("\R", "").replace("\R\n", "").replace("\r\N", "").replace("\R\N", "");
retObj.mnemonicsRequiredForErrorMsg = true;
msgbase.close();
return retObj;
}
// New MsgBase method: vote_msg(). it takes a message header object
// (like save_msg), except you only need a few properties, in order of
// importarnce:
// attr: you need to have this set to MSG_UPVOTE, MSG_DOWNVOTE, or MSG_VOTE
// thread_back or reply_id: either of these must be set to indicate msg to vote on
// from: name of voter
// from_net_type and from_net_addr: if applicable
// Do some initial setup of the header for the vote message to be
// saved to the messagebase
var voteMsgHdr = {
thread_back: pMsgHdr.number,
reply_id: pMsgHdr.id,
from: (msgbase.cfg.settings & SUB_NAME) == SUB_NAME ? user.name : user.alias
};
if (pMsgHdr.from.hasOwnProperty("from_net_type"))
{
voteMsgHdr.from_net_type = pMsgHdr.from_net_type;
if (pMsgHdr.from_net_type != NET_NONE)
voteMsgHdr.from_net_addr = user.email;
}
// Input vote options from the user differently depending on whether
// the message is a poll or not
if ((pMsgHdr.attr & MSG_POLL) == MSG_POLL)
{
if (pMsgHdr.hasOwnProperty("field_list"))
{
console.clear("\1n");

nightfox
committed
var selectHdr = bbs.text(typeof(BallotHdr) != "undefined" ? BallotHdr : 791);
printf("\1n" + selectHdr + "\1n", pMsgHdr.subject);
var optionFormatStr = "\1n\1c\1h%2d\1n\1c: \1h%s\1n";
var optionNum = 1;
for (var fieldI = 0; fieldI < pMsgHdr.field_list.length; ++fieldI)
{
if (pMsgHdr.field_list[fieldI].type == SMB_POLL_ANSWER)
{
printf(optionFormatStr, optionNum++, pMsgHdr.field_list[fieldI].data);
console.crlf();
}
}
console.crlf();
// Get & process the selection from the user
var userInputNum = 0;
if (pMsgHdr.votes > 1)
{
// Support multiple answers from the user
console.print("\1n\1gYour vote numbers, separated by commas, up to \1h" + pMsgHdr.votes + "\1n\1g (Blank/Q=Quit):");
console.crlf();
console.print("\1c\1h");
var userInput = consoleGetStrWithValidKeys("0123456789,Q", null, false);
13983
13984
13985
13986
13987
13988
13989
13990
13991
13992
13993
13994
13995
13996
13997
13998
13999
14000
if ((userInput.length > 0) && (userInput.toUpperCase() != "Q"))
{
var userAnswers = userInput.split(",");
if (userAnswers.length > 0)
{
// Generate confirmation text and an array of numbers
// representing the user's choices, up to the number
// of responses allowed
var confirmText = "Vote ";
var voteNumbers = [];
for (var i = 0; (i < userAnswers.length) && (i < pMsgHdr.votes); ++i)
{
// Trim any whitespace from the user's response
userAnswers[i] = trimSpaces(userAnswers[i], true, true, true);
if (/^[0-9]+$/.test(userAnswers[i]))
{
voteNumbers.push(+userAnswers[i]);
confirmText += userAnswers[i] + ",";