Newer
Older
text = text.replace(/\|g\|S\|G/g, "\1h\1g\1" + "2"); // Bright green on green
text = text.replace(/\|g\|S\|C/g, "\1h\1c\1" + "2"); // Bright cyan on green
text = text.replace(/\|g\|S\|R/g, "\1h\1r\1" + "2"); // Bright red on green
text = text.replace(/\|g\|S\|M/g, "\1h\1m\1" + "2"); // Bright magenta on green
text = text.replace(/\|g\|S\|Y/g, "\1h\1y\1" + "2"); // Yellow on green
text = text.replace(/\|g\|S\|W/g, "\1h\1w\1" + "2"); // Bright white on green
// Cyan background
text = text.replace(/\|c\|S\|k/g, "\1n\1k\1" + "6"); // Black on cyan
text = text.replace(/\|c\|S\|b/g, "\1n\1b\1" + "6"); // Blue on cyan
text = text.replace(/\|c\|S\|g/g, "\1n\1g\1" + "6"); // Green on cyan
text = text.replace(/\|c\|S\|c/g, "\1n\1c\1" + "6"); // Cyan on cyan
text = text.replace(/\|c\|S\|r/g, "\1n\1r\1" + "6"); // Red on cyan
text = text.replace(/\|c\|S\|m/g, "\1n\1m\1" + "6"); // Magenta on cyan
text = text.replace(/\|c\|S\|y/g, "\1n\1y\1" + "6"); // Yellow/brown on cyan
text = text.replace(/\|c\|S\|w/g, "\1n\1w\1" + "6"); // White on cyan
text = text.replace(/\|c\|S\|d/g, "\1h\1k\1" + "6"); // Bright black on cyan
text = text.replace(/\|c\|S\|B/g, "\1h\1b\1" + "6"); // Bright blue on cyan
text = text.replace(/\|c\|S\|G/g, "\1h\1g\1" + "6"); // Bright green on cyan
text = text.replace(/\|c\|S\|C/g, "\1h\1c\1" + "6"); // Bright cyan on cyan
text = text.replace(/\|c\|S\|R/g, "\1h\1r\1" + "6"); // Bright red on cyan
text = text.replace(/\|c\|S\|M/g, "\1h\1m\1" + "6"); // Bright magenta on cyan
text = text.replace(/\|c\|S\|Y/g, "\1h\1y\1" + "6"); // Yellow on cyan
text = text.replace(/\|c\|S\|W/g, "\1h\1w\1" + "6"); // Bright white on cyan
// Red background
text = text.replace(/\|r\|S\|k/g, "\1n\1k\1" + "1"); // Black on red
text = text.replace(/\|r\|S\|b/g, "\1n\1b\1" + "1"); // Blue on red
text = text.replace(/\|r\|S\|g/g, "\1n\1g\1" + "1"); // Green on red
text = text.replace(/\|r\|S\|c/g, "\1n\1c\1" + "1"); // Cyan on red
text = text.replace(/\|r\|S\|r/g, "\1n\1r\1" + "1"); // Red on red
text = text.replace(/\|r\|S\|m/g, "\1n\1m\1" + "1"); // Magenta on red
text = text.replace(/\|r\|S\|y/g, "\1n\1y\1" + "1"); // Yellow/brown on red
text = text.replace(/\|r\|S\|w/g, "\1n\1w\1" + "1"); // White on red
text = text.replace(/\|r\|S\|d/g, "\1h\1k\1" + "1"); // Bright black on red
text = text.replace(/\|r\|S\|B/g, "\1h\1b\1" + "1"); // Bright blue on red
text = text.replace(/\|r\|S\|G/g, "\1h\1g\1" + "1"); // Bright green on red
text = text.replace(/\|r\|S\|C/g, "\1h\1c\1" + "1"); // Bright cyan on red
text = text.replace(/\|r\|S\|R/g, "\1h\1r\1" + "1"); // Bright red on red
text = text.replace(/\|r\|S\|M/g, "\1h\1m\1" + "1"); // Bright magenta on red
text = text.replace(/\|r\|S\|Y/g, "\1h\1y\1" + "1"); // Yellow on red
text = text.replace(/\|r\|S\|W/g, "\1h\1w\1" + "1"); // Bright white on red
// Magenta background
text = text.replace(/\|m\|S\|k/g, "\1n\1k\1" + "5"); // Black on magenta
text = text.replace(/\|m\|S\|b/g, "\1n\1b\1" + "5"); // Blue on magenta
text = text.replace(/\|m\|S\|g/g, "\1n\1g\1" + "5"); // Green on magenta
text = text.replace(/\|m\|S\|c/g, "\1n\1c\1" + "5"); // Cyan on magenta
text = text.replace(/\|m\|S\|r/g, "\1n\1r\1" + "5"); // Red on magenta
text = text.replace(/\|m\|S\|m/g, "\1n\1m\1" + "5"); // Magenta on magenta
text = text.replace(/\|m\|S\|y/g, "\1n\1y\1" + "5"); // Yellow/brown on magenta
text = text.replace(/\|m\|S\|w/g, "\1n\1w\1" + "5"); // White on magenta
text = text.replace(/\|m\|S\|d/g, "\1h\1k\1" + "5"); // Bright black on magenta
text = text.replace(/\|m\|S\|B/g, "\1h\1b\1" + "5"); // Bright blue on magenta
text = text.replace(/\|m\|S\|G/g, "\1h\1g\1" + "5"); // Bright green on magenta
text = text.replace(/\|m\|S\|C/g, "\1h\1c\1" + "5"); // Bright cyan on magenta
text = text.replace(/\|m\|S\|R/g, "\1h\1r\1" + "5"); // Bright red on magenta
text = text.replace(/\|m\|S\|M/g, "\1h\1m\1" + "5"); // Bright magenta on magenta
text = text.replace(/\|m\|S\|Y/g, "\1h\1y\1" + "5"); // Yellow on magenta
text = text.replace(/\|m\|S\|W/g, "\1h\1w\1" + "5"); // Bright white on magenta
// Brown background
text = text.replace(/\|y\|S\|k/g, "\1n\1k\1" + "3"); // Black on brown
text = text.replace(/\|y\|S\|b/g, "\1n\1b\1" + "3"); // Blue on brown
text = text.replace(/\|y\|S\|g/g, "\1n\1g\1" + "3"); // Green on brown
text = text.replace(/\|y\|S\|c/g, "\1n\1c\1" + "3"); // Cyan on brown
text = text.replace(/\|y\|S\|r/g, "\1n\1r\1" + "3"); // Red on brown
text = text.replace(/\|y\|S\|m/g, "\1n\1m\1" + "3"); // Magenta on brown
text = text.replace(/\|y\|S\|y/g, "\1n\1y\1" + "3"); // Yellow/brown on brown
text = text.replace(/\|y\|S\|w/g, "\1n\1w\1" + "3"); // White on brown
text = text.replace(/\|y\|S\|d/g, "\1h\1k\1" + "3"); // Bright black on brown
text = text.replace(/\|y\|S\|B/g, "\1h\1b\1" + "3"); // Bright blue on brown
text = text.replace(/\|y\|S\|G/g, "\1h\1g\1" + "3"); // Bright green on brown
text = text.replace(/\|y\|S\|C/g, "\1h\1c\1" + "3"); // Bright cyan on brown
text = text.replace(/\|y\|S\|R/g, "\1h\1r\1" + "3"); // Bright red on brown
text = text.replace(/\|y\|S\|M/g, "\1h\1m\1" + "3"); // Bright magenta on brown
text = text.replace(/\|y\|S\|Y/g, "\1h\1y\1" + "3"); // Yellow on brown
text = text.replace(/\|y\|S\|W/g, "\1h\1w\1" + "3"); // Bright white on brown
// White background
text = text.replace(/\|w\|S\|k/g, "\1n\1k\1" + "7"); // Black on white
text = text.replace(/\|w\|S\|b/g, "\1n\1b\1" + "7"); // Blue on white
text = text.replace(/\|w\|S\|g/g, "\1n\1g\1" + "7"); // Green on white
text = text.replace(/\|w\|S\|c/g, "\1n\1c\1" + "7"); // Cyan on white
text = text.replace(/\|w\|S\|r/g, "\1n\1r\1" + "7"); // Red on white
text = text.replace(/\|w\|S\|m/g, "\1n\1m\1" + "7"); // Magenta on white
text = text.replace(/\|w\|S\|y/g, "\1n\1y\1" + "7"); // Yellow/brown on white
text = text.replace(/\|w\|S\|w/g, "\1n\1w\1" + "7"); // White on white
text = text.replace(/\|w\|S\|d/g, "\1h\1k\1" + "7"); // Bright black on white
text = text.replace(/\|w\|S\|B/g, "\1h\1b\1" + "7"); // Bright blue on white
text = text.replace(/\|w\|S\|G/g, "\1h\1g\1" + "7"); // Bright green on white
text = text.replace(/\|w\|S\|C/g, "\1h\1c\1" + "7"); // Bright cyan on white
text = text.replace(/\|w\|S\|R/g, "\1h\1r\1" + "7"); // Bright red on white
text = text.replace(/\|w\|S\|M/g, "\1h\1m\1" + "7"); // Bright magenta on white
text = text.replace(/\|w\|S\|Y/g, "\1h\1y\1" + "7"); // Yellow on white
text = text.replace(/\|w\|S\|W/g, "\1h\1w\1" + "7"); // Bright white on white
// Colors on black background
17099
17100
17101
17102
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112
17113
17114
17115
17116
17117
17118
17119
17120
17121
17122
17123
17124
17125
17126
17127
17128
17129
17130
text = text.replace(/\|k/g, "\1n\1k\1" + "0"); // Black on black
text = text.replace(/\|k\|S\|k/g, "\1n\1k\1" + "0"); // Black on black
text = text.replace(/\|b/g, "\1n\1b\1" + "0"); // Blue on black
text = text.replace(/\|k\|S\|b/g, "\1n\1b\1" + "0"); // Blue on black
text = text.replace(/\|g/g, "\1n\1g\1" + "0"); // Green on black
text = text.replace(/\|k\|S\|g/g, "\1n\1g\1" + "0"); // Green on black
text = text.replace(/\|c/g, "\1n\1c\1" + "0"); // Cyan on black
text = text.replace(/\|k\|S\|c/g, "\1n\1c\1" + "0"); // Cyan on black
text = text.replace(/\|r/g, "\1n\1r\1" + "0"); // Red on black
text = text.replace(/\|k\|S\|r/g, "\1n\1r\1" + "0"); // Red on black
text = text.replace(/\|m/g, "\1n\1m\1" + "0"); // Magenta on black
text = text.replace(/\|k\|S\|m/g, "\1n\1m\1" + "0"); // Magenta on black
text = text.replace(/\|y/g, "\1n\1y\1" + "0"); // Yellow/brown on black
text = text.replace(/\|k\|S\|y/g, "\1n\1y\1" + "0"); // Yellow/brown on black
text = text.replace(/\|w/g, "\1n\1w\1" + "0"); // White on black
text = text.replace(/\|k\|S\|w/g, "\1n\1w\1" + "0"); // White on black
text = text.replace(/\|d/g, "\1h\1k\1" + "0"); // Bright black on black
text = text.replace(/\|k\|S\|d/g, "\1h\1k\1" + "0"); // Bright black on black
text = text.replace(/\|B/g, "\1h\1b\1" + "0"); // Bright blue on black
text = text.replace(/\|k\|S\|B/g, "\1h\1b\1" + "0"); // Bright blue on black
text = text.replace(/\|G/g, "\1h\1g\1" + "0"); // Bright green on black
text = text.replace(/\|k\|S\|G/g, "\1h\1g\1" + "0"); // Bright green on black
text = text.replace(/\|C/g, "\1h\1c\1" + "0"); // Bright cyan on black
text = text.replace(/\|k\|S\|C/g, "\1h\1c\1" + "0"); // Bright cyan on black
text = text.replace(/\|R/g, "\1h\1r\1" + "0"); // Bright red on black
text = text.replace(/\|k\|S\|R/g, "\1h\1r\1" + "0"); // Bright red on black
text = text.replace(/\|M/g, "\1h\1m\1" + "0"); // Bright magenta on black
text = text.replace(/\|k\|S\|M/g, "\1h\1m\1" + "0"); // Bright magenta on black
text = text.replace(/\|Y/g, "\1h\1y\1" + "0"); // Yellow on black
text = text.replace(/\|k\|S\|Y/g, "\1h\1y\1" + "0"); // Yellow on black
text = text.replace(/\|W/g, "\1h\1w\1" + "0"); // Bright white on black
text = text.replace(/\|k\|S\|W/g, "\1h\1w\1" + "0"); // Bright white on black
17131
17132
17133
17134
17135
17136
17137
17138
17139
17140
17141
17142
17143
17144
17145
17146
17147
17148
17149
17150
return text;
}
else
return pText; // No Celerity-style attribute codes found, so just return the text.
}
// Converts Renegade attribute (color) codes to Synchronet attribute codes.
//
// Parameters:
// pText: A string containing the text to convert
//
// Return value: The text with the color codes converted
function renegadeAttrsToSyncAttrs(pText)
{
// First, see if the text has any Renegade-style attribute codes at
// all. We'll be performing a bunch of search & replace commands,
// so we don't want to do all that work for nothing.. :)
if (/\|[0-3][0-9]/.test(pText))
{
17151
17152
17153
17154
17155
17156
17157
17158
17159
17160
17161
17162
17163
17164
17165
17166
17167
17168
17169
17170
17171
17172
17173
17174
17175
17176
17177
17178
17179
17180
17181
17182
var text = pText.replace(/\|00/g, "\1n\1k"); // Normal black
text = text.replace(/\|01/g, "\1n\1b"); // Normal blue
text = text.replace(/\|02/g, "\1n\1g"); // Normal green
text = text.replace(/\|03/g, "\1n\1c"); // Normal cyan
text = text.replace(/\|04/g, "\1n\1r"); // Normal red
text = text.replace(/\|05/g, "\1n\1m"); // Normal magenta
text = text.replace(/\|06/g, "\1n\1y"); // Normal brown
text = text.replace(/\|07/g, "\1n\1w"); // Normal white
text = text.replace(/\|08/g, "\1n\1k\1h"); // High intensity black
text = text.replace(/\|09/g, "\1n\1b\1h"); // High intensity blue
text = text.replace(/\|10/g, "\1n\1g\1h"); // High intensity green
text = text.replace(/\|11/g, "\1n\1c\1h"); // High intensity cyan
text = text.replace(/\|12/g, "\1n\1r\1h"); // High intensity red
text = text.replace(/\|13/g, "\1n\1m\1h"); // High intensity magenta
text = text.replace(/\|14/g, "\1n\1y\1h"); // Yellow (high intensity brown)
text = text.replace(/\|15/g, "\1n\1w\1h"); // High intensity white
text = text.replace(/\|16/g, "\1" + "0"); // Background black
text = text.replace(/\|17/g, "\1" + "4"); // Background blue
text = text.replace(/\|18/g, "\1" + "2"); // Background green
text = text.replace(/\|19/g, "\1" + "6"); // Background cyan
text = text.replace(/\|20/g, "\1" + "1"); // Background red
text = text.replace(/\|21/g, "\1" + "5"); // Background magenta
text = text.replace(/\|22/g, "\1" + "3"); // Background brown
text = text.replace(/\|23/g, "\1" + "7"); // Background white
text = text.replace(/\|24/g, "\1i\1w\1" + "0"); // Blinking white on black
text = text.replace(/\|25/g, "\1i\1w\1" + "4"); // Blinking white on blue
text = text.replace(/\|26/g, "\1i\1w\1" + "2"); // Blinking white on green
text = text.replace(/\|27/g, "\1i\1w\1" + "6"); // Blinking white on cyan
text = text.replace(/\|28/g, "\1i\1w\1" + "1"); // Blinking white on red
text = text.replace(/\|29/g, "\1i\1w\1" + "5"); // Blinking white on magenta
text = text.replace(/\|30/g, "\1i\1w\1" + "3"); // Blinking white on yellow/brown
text = text.replace(/\|31/g, "\1i\1w\1" + "7"); // Blinking white on white
17183
17184
17185
17186
17187
17188
17189
17190
17191
17192
17193
17194
17195
17196
17197
17198
17199
17200
17201
17202
17203
17204
return text;
}
else
return pText; // No Renegade-style attribute codes found, so just return the text.
}
// Converts ANSI attribute codes to Synchronet attribute codes.
//
// Parameters:
// pText: A string containing the text to convert
//
// Return value: The text with the color codes converted
function ANSIAttrsToSyncAttrs(pText)
{
// TODO: Test & update this some more.. Not sure if this is working 100% right.
// Web pages with ANSI code information:
// http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html
// http://ascii-table.com/ansi-escape-sequences.php
// http://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences
// First, see if the text has any ANSI attribute codes at all. We'll be
17205
17206
17207
17208
17209
17210
17211
17212
17213
17214
17215
17216
17217
17218
17219
17220
17221
17222
17223
17224
17225
17226
17227
17228
17229
17230
17231
17232
17233
17234
17235
17236
17237
17238
17239
17240
17241
17242
17243
17244
17245
17246
17247
// performing a bunch of search & replace commands, so we don't want to do
// all that work for nothing.
if (textHasANSICodes(pText))
{
var text = "";
var tempDirExists = true;
// Temporary (to get it to run the old way for now)
tempDirExists = false;
/*
var readerTmpDir = backslash(system.node_dir + "DDMsgReaderTemp");
if (!file_exists(readerTmpDir))
tempDirExists = mkdir(readerTmpDir);
*/
if (tempDirExists)
{
var wroteTempFile = true;
var tmpFileName = readerTmpDir + "tmpMessage.ans";
var msgTmpFile = new File(tmpFileName);
if (msgTmpFile.open("w"))
{
wroteTempFile = msgTmpFile.write(pText);
msgTmpFile.close();
}
// If the temp file was written, then convert it to Synchronet
// attributes using ans2asc.
if (wroteTempFile)
{
var convertedTempFileName = readerTmpDir + "tmpMessage.asc";
var cmdLine = system.exec_dir + "ans2asc \"" + tmpFileName + "\" \""
+ convertedTempFileName + "\"";
// Note: Both system.exec(cmdLine) and
// bbs.exec(cmdLine, EX_NATIVE, gStartupPath) could be used to
// execute the command, but system.exec() seems noticeably faster.
system.exec(cmdLine);
var convertedTmpFile = new File(convertedTempFileName);
if (convertedTmpFile.open("r"))
{
text = convertedTmpFile.read();
convertedTmpFile.close();
}
}
deltree(readerTmpDir);
}
else // Convert ANSI codes to Synchronet attributes & remove unwanted ANSI codes
text = cvtANSIToSyncAndRemoveUnwantedANSI(text);
return text;
}
else
return pText; // No ANSI codes found, so just return the text.
}

nightfox
committed
//////////////////////////////////////////////////////////////////////////////
// Returns whether or not some text has any ANSI codes in it.
//
// Parameters:
// pText: The text to test
//
// Return value: Boolean - Whether or not the text has ANSI codes in it
function textHasANSICodes(pText)
{
return(/\[[0-9]+[mM]/.test(pText) || /\[[0-9]+(;[0-9]+)+[mM]/.test(pText) ||
/\[[0-9]+[aAbBcCdD]/.test(pText) || /\[[0-9]+;[0-9]+[hHfF]/.test(pText) ||
/\[[sSuUkK]/.test(pText) || /\[2[jJ]/.test(pText));
/*
var regex1 = new RegExp(ascii(27) + "\[[0-9]+[mM]");
var regex2 = new RegExp(ascii(27) + "\[[0-9]+(;[0-9]+)+[mM]");
var regex3 = new RegExp(ascii(27) + "\[[0-9]+[aAbBcCdD]");
var regex4 = new RegExp(ascii(27) + "\[[0-9]+;[0-9]+[hHfF]");
var regex5 = new RegExp(ascii(27) + "\[[sSuUkK]");
var regex6 = new RegExp(ascii(27) + "\[2[jJ]");
return(regex1.test(pText) || regex2.test(pText) || regex3.test(pText) ||
regex4.test(pText) || regex5.test(pText) || regex6.test(pText));
*/
}
// Returns the index of the last ANSI code in a string.
//
// Parameters:

nightfox
committed
// pStr: The string to search in
// pANSIRegexes: An array of regular expressions to use for searching for ANSI codes
//
// Return value: The index of the last ANSI code in the string, or -1 if not found

nightfox
committed
function idxOfLastANSICode(pStr, pANSIRegexes)
{
var lastANSIIdx = -1;

nightfox
committed
for (var i = 0; i < pANSIRegexes.length; ++i)
{

nightfox
committed
var lastANSIIdxTmp = regexLastIndexOf(pStr, pANSIRegexes[i]);
if (lastANSIIdxTmp > lastANSIIdx)
lastANSIIdx = lastANSIIdxTmp;
}
return lastANSIIdx;
}
17302
17303
17304
17305
17306
17307
17308
17309
17310
17311
17312
17313
17314
17315
17316
17317
17318
17319
17320
// Returns the index of the first ANSI code in a string.
//
// Parameters:
// pStr: The string to search in
// pANSIRegexes: An array of regular expressions to use for searching for ANSI codes
//
// Return value: The index of the first ANSI code in the string, or -1 if not found
function idxOfFirstANSICode(pStr, pANSIRegexes)
{
var firstANSIIdx = -1;
for (var i = 0; i < pANSIRegexes.length; ++i)
{
var firstANSIIdxTmp = regexFirstIndexOf(pStr, pANSIRegexes[i]);
if (firstANSIIdxTmp > firstANSIIdx)
firstANSIIdx = firstANSIIdxTmp;
}
return firstANSIIdx;
}

nightfox
committed
17321
17322
17323
17324
17325
17326
17327
17328
17329
17330
17331
17332
17333
17334
17335
17336
17337
17338
17339
// Returns the number of times an ANSI code is matched in a string.
//
// Parameters:
// pStr: The string to search in
// pANSIRegexes: An array of regular expressions to use for searching for ANSI codes
//
// Return value: The number of ANSI code matches in the string
function countANSICodes(pStr, pANSIRegexes)
{
var ANSICount = 0;
for (var i = 0; i < pANSIRegexes.length; ++i)
{
var matches = pStr.match(pANSIRegexes[i]);
if (matches != null)
ANSICount += matches.length;
}
return ANSICount;
}
// Removes ANSI codes from a string.
//
// Parameters:
// pStr: The string to remove ANSI codes from

nightfox
committed
// pANSIRegexes: An array of regular expressions to use for searching for ANSI codes
//
// Return value: A version of the string without ANSI codes

nightfox
committed
function removeANSIFromStr(pStr, pANSIRegexes)
{
if (typeof(pStr) != "string")
return "";
var theStr = pStr;

nightfox
committed
for (var i = 0; i < pANSIRegexes.length; ++i)
theStr = theStr.replace(pANSIRegexes[i], "");
17355
17356
17357
17358
17359
17360
17361
17362
17363
17364
17365
17366
17367
17368
17369
17370
17371
17372
17373
17374
17375
17376
17377
17378
17379
17380
17381
17382
17383
17384
return theStr;
}
// Returns the last index in a string where a regex is found.
// From this page:
// http://stackoverflow.com/questions/273789/is-there-a-version-of-javascripts-string-indexof-that-allows-for-regular-expr
//
// Parameters:
// pStr: The string to search
// pRegex: The regular expression to match in the string
// pStartPos: Optional - The starting position in the string. If this is not
// passed, then the end of the string will be used.
//
// Return value: The last index in the string where the regex is found, or -1 if not found.
function regexLastIndexOf(pStr, pRegex, pStartPos)
{
pRegex = (pRegex.global) ? pRegex : new RegExp(pRegex.source, "g" + (pRegex.ignoreCase ? "i" : "") + (pRegex.multiLine ? "m" : ""));
if (typeof(pStartPos) == "undefined")
pStartPos = pStr.length;
else if (pStartPos < 0)
pStartPos = 0;
var stringToWorkWith = pStr.substring(0, pStartPos + 1);
var lastIndexOf = -1;
var nextStop = 0;
while ((result = pRegex.exec(stringToWorkWith)) != null)
{
lastIndexOf = result.index;
pRegex.lastIndex = ++nextStop;
}
return lastIndexOf;
17387
17388
17389
17390
17391
17392
17393
17394
17395
17396
17397
17398
17399
17400
17401
17402
17403
17404
17405
17406
// Returns the first index in a string where a regex is found.
//
// Parameters:
// pStr: The string to search
// pRegex: The regular expression to match in the string
//
// Return value: The first index in the string where the regex is found, or -1 if not found.
function regexFirstIndexOf(pStr, pRegex)
{
pRegex = (pRegex.global) ? pRegex : new RegExp(pRegex.source, "g" + (pRegex.ignoreCase ? "i" : "") + (pRegex.multiLine ? "m" : ""));
var indexOfRegex = -1;
var nextStop = 0;
while ((result = pRegex.exec(pStr)) != null)
{
indexOfRegex = result.index;
pRegex.lastIndex = ++nextStop;
}
return indexOfRegex;
}
// Converts ANSI ;-delimited modes (such as [Value;...;Valuem) to Synchronet
// attribute codes
//
// Parameters:
// pText: The text with ANSI ;-delimited modes to convert
//
// Return value: The text with ANSI ;-delimited codes converted to Synchronet attributes
17414
17415
17416
17417
17418
17419
17420
17421
17422
17423
17424
17425
17426
17427
17428
17429
17430
17431
17432
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442
17443
17444
17445
17446
17447
17448
17449
17450
17451
17452
function ANSIMultiConvertToSyncCodes(pText)
{
var multiMatches = pText.match(/\[[0-9]+(;[0-9]+)+m/g);
if (multiMatches == null)
return pText;
var updatedText = pText;
for (var i = 0; i < multiMatches.length; ++i)
{
// Copy the string, with the [ removed from the beginning and the
// trailing 'm' removed
var text = multiMatches[i].substr(2);
text = text.substr(0, text.length-1);
var codes = text.split(";");
var syncCodes = "";
for (var idx = 0; idx < codes.length; ++idx)
{
if (codes[idx] == "0") // All attributes off
syncCodes += "\1n";
else if (codes[idx] == "1") // Bold on (high intensity)
syncCodes += "\1h";
else if (codes[idx] == "5") // Blink on
syncCodes += "\1i";
else if (codes[idx] == "30") // Black foreground
syncCodes += "\1k";
else if (codes[idx] == "31") // Red foreground
syncCodes += "\1r";
else if (codes[idx] == "32") // Green foreground
syncCodes += "\1g";
else if (codes[idx] == "33") // Yellow foreground
syncCodes += "\1y";
else if (codes[idx] == "34") // Blue foreground
syncCodes += "\1b";
else if (codes[idx] == "35") // Magenta foreground
syncCodes += "\1m";
else if (codes[idx] == "36") // Cyan foreground
syncCodes += "\1c";
else if (codes[idx] == "37") // White foreground
syncCodes += "\1w";
else if (codes[idx] == "40") // Black background
else if (codes[idx] == "41") // Red background
else if (codes[idx] == "42") // Green background
else if (codes[idx] == "43") // Yellow background
else if (codes[idx] == "44") // Blue background
else if (codes[idx] == "45") // Magenta background
else if (codes[idx] == "46") // Cyan background
else if (codes[idx] == "47") // White background
}
updatedText = updatedText.replace(multiMatches[i], syncCodes);
}
return updatedText;
}
17474
17475
17476
17477
17478
17479
17480
17481
17482
17483
17484
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496
17497
17498
17499
17500
17501
17502
17503
17504
17505
17506
17507
17508
17509
17510
17511
17512
17513
17514
17515
// Converts Synchronet attribute codes to ANSI ;-delimited modes (such as [Value;...;Valuem)
//
// Parameters:
// pText: The text with Synchronet codes to convert
//
// Return value: The text with Synchronet attributes converted to ANSI ;-delimited codes
function syncAttrCodesToANSI(pText)
{
// First, see if the text has any Synchronet attribute codes at
// all. We'll be performing a bunch of search & replace commands,
// so we don't want to do all that work for nothing.. :)
if (hasSyncAttrCodes(pText))
{
var ANSIESCCodeStart = "[";
var newText = pText.replace(/\1n/gi, ANSIESCCodeStart + "0m"); // Normal
newText = newText.replace(/\1-/gi, ANSIESCCodeStart + "0m"); // Normal
newText = newText.replace(/\1_/gi, ANSIESCCodeStart + "0m"); // Normal
newText = newText.replace(/\1h/gi, ANSIESCCodeStart + "1m"); // High intensity/bold
newText = newText.replace(/\1i/gi, ANSIESCCodeStart + "5m"); // Blinking on
newText = newText.replace(/\1f/gi, ANSIESCCodeStart + "5m"); // Blinking on
newText = newText.replace(/\1k/gi, ANSIESCCodeStart + "30m"); // Black foreground
newText = newText.replace(/\1r/gi, ANSIESCCodeStart + "31m"); // Red foreground
newText = newText.replace(/\1g/gi, ANSIESCCodeStart + "32m"); // Green foreground
newText = newText.replace(/\1y/gi, ANSIESCCodeStart + "33m"); // Yellow/brown foreground
newText = newText.replace(/\1b/gi, ANSIESCCodeStart + "34m"); // Blue foreground
newText = newText.replace(/\1m/gi, ANSIESCCodeStart + "35m"); // Magenta foreground
newText = newText.replace(/\1c/gi, ANSIESCCodeStart + "36m"); // Cyan foreground
newText = newText.replace(/\1w/gi, ANSIESCCodeStart + "37m"); // White foreground
newText = newText.replace(/\1[0]/gi, ANSIESCCodeStart + "40m"); // Black background
newText = newText.replace(/\1[1]/gi, ANSIESCCodeStart + "41m"); // Red background
newText = newText.replace(/\1[2]/gi, ANSIESCCodeStart + "42m"); // Green background
newText = newText.replace(/\1[3]/gi, ANSIESCCodeStart + "43m"); // Yellow/brown background
newText = newText.replace(/\1[4]/gi, ANSIESCCodeStart + "44m"); // Blue background
newText = newText.replace(/\1[5]/gi, ANSIESCCodeStart + "45m"); // Magenta background
newText = newText.replace(/\1[6]/gi, ANSIESCCodeStart + "46m"); // Cyan background
newText = newText.replace(/\1[7]/gi, ANSIESCCodeStart + "47m"); // White background
return newText;
}
else
return pText; // No Synchronet-style attribute codes found, so just return the text.
}
17516
17517
17518
17519
17520
17521
17522
17523
17524
17525
17526
17527
17528
17529
17530
17531
17532
17533
17534
17535
17536
17537
17538
17539
17540
17541
17542
17543
17544
17545
17546
17547
17548
17549
17550
17551
17552
17553
17554
17555
17556
17557
17558
17559
17560
17561
17562
17563
17564
// Given some text, this converts ANSI color codes to Synchronet codes and
// removes unwanted ANSI codes (such as cursor movement codes, etc.).
//
// Parameters:
// pText: A string to process
//
// Return value: A version of the string with Synchronet color codes converted to
// Synchronet attribute codes and unwanted ANSI codes removed
function cvtANSIToSyncAndRemoveUnwantedANSI(pText)
{
// Attributes
var txt = pText.replace(/\[0[mM]/g, "\1n"); // All attributes off
txt = txt.replace(/\[1[mM]/g, "\1h"); // Bold on (use high intensity)
txt = txt.replace(/\[5[mM]/g, "\1i"); // Blink on
// Foreground colors
txt = txt.replace(/\[30[mM]/g, "\1k"); // Black foreground
txt = txt.replace(/\[31[mM]/g, "\1r"); // Red foreground
txt = txt.replace(/\[32[mM]/g, "\1g"); // Green foreground
txt = txt.replace(/\[33[mM]/g, "\1y"); // Yellow foreground
txt = txt.replace(/\[34[mM]/g, "\1b"); // Blue foreground
txt = txt.replace(/\[35[mM]/g, "\1m"); // Magenta foreground
txt = txt.replace(/\[36[mM]/g, "\1c"); // Cyan foreground
txt = txt.replace(/\[37[mM]/g, "\1w"); // White foreground
// Background colors
txt = txt.replace(/\[40[mM]/g, "\1" + "0"); // Black background
txt = txt.replace(/\[41[mM]/g, "\1" + "1"); // Red background
txt = txt.replace(/\[42[mM]/g, "\1" + "2"); // Green background
txt = txt.replace(/\[43[mM]/g, "\1" + "3"); // Yellow background
txt = txt.replace(/\[44[mM]/g, "\1" + "4"); // Blue background
txt = txt.replace(/\[45[mM]/g, "\1" + "5"); // Magenta background
txt = txt.replace(/\[46[mM]/g, "\1" + "6"); // Cyan background
txt = txt.replace(/\[47[mM]/g, "\1" + "7"); // White background
// Convert ;-delimited modes (such as [Value;...;Valuem)
txt = ANSIMultiConvertToSyncCodes(txt);
// Remove ANSI codes that are not wanted (such as moving the cursor, etc.)
txt = txt.replace(/\[[0-9]+[aA]/g, ""); // Cursor up
txt = txt.replace(/\[[0-9]+[bB]/g, ""); // Cursor down
txt = txt.replace(/\[[0-9]+[cC]/g, ""); // Cursor forward
txt = txt.replace(/\[[0-9]+[dD]/g, ""); // Cursor backward
txt = txt.replace(/\[[0-9]+;[0-9]+[hH]/g, ""); // Cursor position
txt = txt.replace(/\[[0-9]+;[0-9]+[fF]/g, ""); // Cursor position
txt = txt.replace(/\[[sS]/g, ""); // Restore cursor position
txt = txt.replace(/\[2[jJ]/g, ""); // Erase display
txt = txt.replace(/\[[kK]/g, ""); // Erase line
txt = txt.replace(/\[=[0-9]+[hH]/g, ""); // Set various screen modes
txt = txt.replace(/\[=[0-9]+[lL]/g, ""); // Reset various screen modes
return txt;
}
17565
17566
17567
17568
17569
17570
17571
17572
17573
17574
17575
17576
17577
17578
17579
17580
17581
17582
17583
17584
17585
17586
17587
17588
17589
17590
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610
17611
17612
// Returns whether a given message group index & sub-board index (or the current ones,
// based on bbs.curgrp and bbs.cursub) are for the last message sub-board on the system.
//
// Parameters:
// pGrpIdx: Optional - The index of the message group. If not specified, this will
// default to bbs.curgrp. If bbs.curgrp is not defined in that case,
// then this method will return false.
// pSubIdx: Optional - The index of the message sub-board. If not specified, this will
// default to bbs.cursub. If bbs.cursub is not defined in that case,
// then this method will return false.
//
// Return value: Boolean - Whether or not the current/given message group index & sub-board
// index are for the last message sub-board on the system. If there
// are any issues with any of the values (including bbs.curgrp or
// bbs.cursub), this method will return false.
function curMsgSubBoardIsLast(pGrpIdx, pSubIdx)
{
var curGrp = 0;
if (typeof(pGrpIdx) == "number")
curGrp = pGrpIdx;
else if (typeof(bbs.curgrp) == "number")
curGrp = bbs.curgrp;
else
return false;
var curSub = 0;
if (typeof(pSubIdx) == "number")
curSub = pSubIdx;
else if (typeof(bbs.cursub) == "number")
curSub = bbs.cursub;
else
return false;
return (curGrp == msg_area.grp_list.length-1) && (curSub == msg_area.grp_list[msg_area.grp_list.length-1].sub_list.length-1);
}
// Parses arguments, where each argument in the given array is in the format
// -arg=val. If the value is the string "true" or "false", then the value will
// be a boolean. Otherwise, the value will be a string.
//
// Parameters:
// pArgArr: An array of strings containing values in the format -arg=val
//
// Return value: An object containing the argument values. The index will be
// the argument names, converted to lowercase. The values will
// be either the string argument values or boolean values, depending
// on the formats of the arguments passed in.
function parseArgs(pArgArr)
{
// Set default values for parameters that are just true/false values
var argVals = {
chooseareafirst: false,
personalemail: false,
onlynewpersonalemail: false,
personalemailsent: false,
verboselogging: false,
suppresssearchtypetext: false
};
17622
17623
17624
17625
17626
17627
17628
17629
17630
17631
17632
17633
17634
17635
17636
17637
17638
17639
17640
17641
17642
// Sanity checking for pArgArr - Make sure it's an array
if ((typeof(pArgArr) != "object") || (typeof(pArgArr.length) != "number"))
return argVals;
// Go through pArgArr looking for strings in the format -arg=val and parse them
// into objects in the argVals array.
var equalsIdx = 0;
var argName = "";
var argVal = "";
var argValLower = ""; // For case-insensitive "true"/"false" matching
var argValIsTrue = false;
for (var i = 0; i < pArgArr.length; ++i)
{
// We're looking for strings that start with "-", except strings that are
// only "-".
if ((typeof(pArgArr[i]) != "string") || (pArgArr[i].length == 0) ||
(pArgArr[i].charAt(0) != "-") || (pArgArr[i] == "-"))
{
continue;
}
17644
17645
17646
17647
17648
17649
17650
17651
17652
17653
17654
17655
17656
17657
17658
17659
17660
17661
17662
17663
// Look for an = and if found, split the string on the =
equalsIdx = pArgArr[i].indexOf("=");
// If a = is found, then split on it and add the argument name & value
// to the array. Otherwise (if the = is not found), then treat the
// argument as a boolean and set it to true (to enable an option).
if (equalsIdx > -1)
{
argName = pArgArr[i].substring(1, equalsIdx).toLowerCase();
argVal = pArgArr[i].substr(equalsIdx+1);
argValLower = argVal.toLowerCase();
// If the argument value is the word "true" or "false", then add it as a
// boolean. Otherwise, add it as a string.
argValIsTrue = (argValLower == "true");
if (argValIsTrue || (argValLower == "false"))
argVals[argName] = argValIsTrue;
else
argVals[argName] = argVal;
}
else // An equals sign (=) was not found. Add as a boolean set to true to enable the option.
{
argName = pArgArr[i].substr(1).toLowerCase();
if ((argName == "chooseareafirst") || (argName == "personalemail") ||
(argName == "personalemailsent") || (argName == "allpersonalemail") ||
(argName == "verboselogging") || (argName == "suppresssearchtypetext") ||
(argName == "onlynewpersonalemail"))
{
argVals[argName] = true;
}
}
}
// Sanity checking
// If the arguments include personalEmail and personalEmail is enabled,
// then check to see if a search type was specified - If so, only allow
// keyword search and from name search.
if (argVals.hasOwnProperty("personalemail") && argVals.personalemail)
{
// If a search type is specified, only allow keyword search & from name
// search
if (argVals.hasOwnProperty("search"))
{
var searchValLower = argVals.search.toLowerCase();
if ((searchValLower != "keyword_search") && (searchValLower != "from_name_search"))
delete argVals.search;
}
}
17690
17691
17692
17693
17694
17695
17696
17697
17698
17699
17700
17701
17702
17703
17704
17705
17706
17707
17708
17709
17710
17711
17712
17713
17714
// If the arguments include userNum, make sure the value is all digits. If so,
// add altUserNum to the arguments as a number type for user matching when looking
// for personal email to the user.
if (argVals.hasOwnProperty("usernum"))
{
if (/^[0-9]+$/.test(argVals.usernum))
{
var specifiedUserNum = Number(argVals.usernum);
// If the specified number is different than the current logged-in
// user, then load the other user account and read their name and
// alias and also store their user number in the arg vals as a
// number.
if (specifiedUserNum != user.number)
{
var theUser = new User(specifiedUserNum);
argVals.altUserNum = theUser.number;
argVals.altUserName = theUser.name;
argVals.altUserAlias = theUser.alias;
}
else
delete argVals.usernum;
}
else
delete argVals.usernum;
}
return argVals;
}
// Returns a string describing all message attributes (main, auxiliary, and net).
//
// Parameters:
// pMsgHdr: A message header object.
//
// Return value: A string describing all of the message attributes
function makeAllMsgAttrStr(pMsgHdr)
{
if ((pMsgHdr == null) || (typeof(pMsgHdr) != "object"))
return "";
var msgAttrStr = makeMainMsgAttrStr(pMsgHdr.attr);
var auxAttrStr = makeAuxMsgAttrStr(pMsgHdr.auxattr);
if (auxAttrStr.length > 0)
{
if (msgAttrStr.length > 0)
msgAttrStr += ", ";
msgAttrStr += auxAttrStr;
}
var netAttrStr = makeNetMsgAttrStr(pMsgHdr.netattr);
if (netAttrStr.length > 0)
{
if (msgAttrStr.length > 0)
msgAttrStr += ", ";
msgAttrStr += netAttrStr;
}
return msgAttrStr;
}
// Returns a string describing the main message attributes. Makes use of the
// gMainMsgAttrStrs object for the main message attributes and description
// strings.
//
// Parameters:
// pMainMsgAttrs: The bit field for the main message attributes
// (normally, the 'attr' property of a header object)
// pIfEmptyString: Optional - A string to use if there are no attributes set
//
// Return value: A string describing the main message attributes
function makeMainMsgAttrStr(pMainMsgAttrs, pIfEmptyString)
{
var msgAttrStr = "";
if (typeof(pMainMsgAttrs) == "number")
{
for (var prop in gMainMsgAttrStrs)
{
if ((pMainMsgAttrs & prop) == prop)
{
if (msgAttrStr.length > 0)
msgAttrStr += ", ";
msgAttrStr += gMainMsgAttrStrs[prop];
}
}
}
if ((msgAttrStr.length == 0) && (typeof(pIfEmptyString) == "string"))
msgAttrStr = pIfEmptyString;
return msgAttrStr;
}
// Returns a string describing auxiliary message attributes. Makes use of the
// gAuxMsgAttrStrs object for the auxiliary message attributes and description
// strings.
//
// Parameters:
// pAuxMsgAttrs: The bit field for the auxiliary message attributes
// (normally, the 'auxattr' property of a header object)
// pIfEmptyString: Optional - A string to use if there are no attributes set
//
// Return value: A string describing the auxiliary message attributes
function makeAuxMsgAttrStr(pAuxMsgAttrs, pIfEmptyString)
{
var msgAttrStr = "";
if (typeof(pAuxMsgAttrs) == "number")
{
for (var prop in gAuxMsgAttrStrs)
{
if ((pAuxMsgAttrs & prop) == prop)
{
if (msgAttrStr.length > 0)
msgAttrStr += ", ";
msgAttrStr += gAuxMsgAttrStrs[prop];
}
}
}
if ((msgAttrStr.length == 0) && (typeof(pIfEmptyString) == "string"))
msgAttrStr = pIfEmptyString;
return msgAttrStr;
}
// Returns a string describing network message attributes. Makes use of the
// gNetMsgAttrStrs object for the network message attributes and description
// strings.
//
// Parameters:
// pNetMsgAttrs: The bit field for the network message attributes
// (normally, the 'netattr' property of a header object)
// pIfEmptyString: Optional - A string to use if there are no attributes set
//
// Return value: A string describing the network message attributes
function makeNetMsgAttrStr(pNetMsgAttrs, pIfEmptyString)
{
var msgAttrStr = "";
if (typeof(pNetMsgAttrs) == "number")
{
for (var prop in gNetMsgAttrStrs)
{
if ((pNetMsgAttrs & prop) == prop)
{
if (msgAttrStr.length > 0)
msgAttrStr += ", ";
msgAttrStr += gNetMsgAttrStrs[prop];
}
}
}
if ((msgAttrStr.length == 0) && (typeof(pIfEmptyString) == "string"))
msgAttrStr = pIfEmptyString;
17835
17836
17837
17838
17839
17840
17841
17842
17843
17844
17845
17846
17847
17848
17849
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859
17860
17861
17862
17863
17864
17865
17866
17867
17868
17869
17870
17871
17872
17873
17874
17875
17876
17877
17878
17879
17880
17881
17882
17883
17884
return msgAttrStr;
}
// Given a sub-board code, this function returns a sub-board's group and name.
// If the given sub-board code is "mail", then this will return "Personal mail".
//
// Parameters:
// pSubBoardCode: An internal sub-board code
//
// Return value: A string containing the sub-board code group & name, or
// "Personal email" if it's the personal email sub-board
function subBoardGrpAndName(pSubBoardCode)
{
if (typeof(pSubBoardCode) != "string")
return "";
var subBoardGrpAndName = "";
if (pSubBoardCode == "mail")
subBoardGrpAndName = "Personal mail";
else
{
subBoardGrpAndName = msg_area.sub[pSubBoardCode].grp_name + " - "
+ msg_area.sub[pSubBoardCode].name;
}
return subBoardGrpAndName;
}
// Returns whether a given string matches the current user's name, handle, or alias.
// Does a case-insensitive match.
//
// Parameters:
// pStr: The string to match against the user's name/handle/alias
//
// Return value: Boolean - Whether or not the string matches the current user's name,
// handle, or alias
function userNameHandleAliasMatch(pStr)
{
if (typeof(pStr) != "string")
return false;
var strUpper = pStr.toUpperCase();
return ((strUpper == user.name.toUpperCase()) || (strUpper == user.handle.toUpperCase()) || (strUpper == user.alias.toUpperCase()));
}
// Writes a log message to the system log (using LOG_INFO log level) and to the
// node log. This will prepend the text "Digital Distortion Message Reader ("
// + user.alias + "): " to the log message.
//
// Parameters:
// pMessage: The message to log
// pLogLevel: The log level. Optional - Defaults to LOG_INFO.
function writeToSysAndNodeLog(pMessage, pLogLevel)
{
if (typeof(pMessage) != "string")
return;
var logMessage = "Digital Distortion Message Reader (" + user.alias + "): " + pMessage;
var logLevel = (typeof(pLogLevel) == "number" ? pLogLevel : LOG_INFO);
log(logLevel, logMessage);
bbs.log_str(logMessage);
}
17897
17898
17899
17900
17901
17902
17903
17904
17905
17906
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917
17918
17919
17920
17921
17922
// This function looks up and returns a sub-board code from the sub-board number.
// If no matching sub-board is found, this will return an empty string.
//
// Parameters:
// pSubBoardNum: A sub-board number
//
// Return value: The sub-board code. If no matching sub-board is found, an empty
// string will be returned.
function getSubBoardCodeFromNum(pSubBoardNum)
{
// Ensure we're using a numeric type for the sub-board number
// (in case pSubBoardNum is a string rather than a number)
var subNum = Number(pSubBoardNum);
var subBoardCode = "";
for (var subCode in msg_area.sub)
{
if (msg_area.sub[subCode].number == subNum)
{
subBoardCode = subCode;
break;
}
}
return subBoardCode;
}
// Separates message text and any attachment data.
// This is for message headers generated in version 3.16 and earlier of Synchronet.
// In version 3.17 and later, Synchronet added auxiliary attributes (auxattr)
// MSG_FILEATTACH and MSG_MIMEATTACH as well as the function bbs.download_msg_attachments(msgHdr)
// which will allow a user to download attachments in a message.
17928
17929
17930
17931
17932
17933
17934
17935
17936
17937
17938
17939
17940
17941
17942
17943
17944
17945
17946
17947
17948
17949
17950
17951
17952
17953
17954
//
// Parameters:
// pMsgHdr: The message header object
// pMsgText: The text of a message
// pGetB64Data: Optional boolean - Whether or not to get the Base64-encoded
// data for base64-encoded attachments (i.e., in multi-part MIME
// emails). Defaults to true.
//
// Return value: An object containing the following properties:
// msgText: The text of the message, without any of the
// attachment base64-encoded data, etc. If
// the message doesn't have any attachments, then
// this will likely be the same as pMsgText.
// attachments: An array of objects containing the following properties
// for each attachment:
// B64Data: Base64-encoded file data - Only for attachments
// that were attached as base64 in the message (i.e.,
// in a multi-part MIME message). If the attachment
// was uploaded to the user's Synchronet mailbox,
// then the object won't have the B64Data property.
// filename: The name of the attached file
// fullyPathedFilename: The full path & filename of the
// attached file saved on the BBS machine
// errorMsg: An error message if anything went wrong. If
// nothing went wrong, this will be an empty string.
function determineMsgAttachments(pMsgHdr, pMsgText, pGetB64Data)
{
var retObj = {
msgText: "",
attachments: [],
errorMsg: ""
};
// Keep track of the user's inbox directory: sbbs/data/file/<userNum>.in
var userInboxDir = backslash(backslash(system.data_dir + "file") + format("%04d.in", user.number));
// If the message subject is a filename that exists in the user's
// inbox directory, then add its filename to the list of attached
// filenames that will be returned
var fullyPathedAttachmentFilename = userInboxDir + pMsgHdr.subject;
if (file_exists(fullyPathedAttachmentFilename))
{
retObj.attachments.push({ filename: pMsgHdr.subject,
fullyPathedFilename: fullyPathedAttachmentFilename });
}
// The message to prepend onto the message text if the message has attachments
var msgHasAttachmentsTxt = "\1n\1g\1h- This message contains one or more attachments. Press CTRL-A to download.\1n\r\n"
+ "\1n\1g\1h--------------------------------------------------------------------------\1n\r\n";
// Sanity checking
if (typeof(pMsgText) != "string")
{
// If there are any attachments, prepend the message text with a message
// saying that the message contains attachments.
if (msgHdrHasAttachmentFlag(pMsgHdr) || retObj.attachments.length > 0)
retObj.msgText = msgHasAttachmentsTxt + retObj.msgText;
return retObj;
}
// If the message text doesn't include a line starting with -- and a
// line starting with "Content-type:", then then just return the
// the same text in retObj.
//var hasMultiParts = /--\S+\s*Content-Type:/.test(pMsgText);
//var hasMultiParts = ((dashDashIdx > -1) && (/Content-Type/.test(pMsgText)));
var dashDashIdx = pMsgText.indexOf("--");
var hasMultiParts = ((dashDashIdx > -1) && (pMsgText.indexOf("Content-Type", dashDashIdx+1) > dashDashIdx));
if (!hasMultiParts)
{
//retObj.msgText = pMsgText;
// If there are any attachments, prepend the message text with a message
// saying that the message contains attachments.
if (msgHdrHasAttachmentFlag(pMsgHdr) || retObj.attachments.length > 0)
retObj.msgText = msgHasAttachmentsTxt + pMsgText;