Skip to content
Snippets Groups Projects
Commit 5f9b0a2d authored by echicken's avatar echicken :chicken:
Browse files

Methods for XJS forum, and some cleanup.

parent 8e3ee18a
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
require('sbbsdefs.js', 'MSG_DELETE');
require('xjs.js', 'xjs_compile');
load(settings.web_lib + 'mime-decode.js');
load(settings.web_lib + 'avatars.js');
var avatars = new Avatars();
function listGroups() {
const response = [];
......@@ -40,36 +43,11 @@ function listSubs(group) {
moderated_ars: sub.moderated_ars,
is_moderated: sub.is_moderated,
scan_ptr: sub.scan_ptr,
scan_cfg: sub.scan_cfg
scan_cfg: sub.scan_cfg,
};
});
}
function listThreads(sub, offset, count) {
offset = parseInt(offset);
if (isNaN(offset) || offset < 0) return false;
count = parseInt(count);
if (isNaN(count) || count < 1) return false;
var threads = getMessageThreads(sub, settings.max_messages);
if (offset >= threads.order.length) return false;
var stop = Math.min(threads.order.length, offset + count);
var ret = { total: threads.order.length, threads : [] };
for (var n = offset; n < stop; n++) {
var thread = threads.thread[threads.order[n]];
var msgs = Object.keys(thread.messages);
thread.first = thread.messages[msgs[0]];
thread.last = thread.messages[msgs[msgs.length - 1]];
thread.messages = msgs.length;
ret.threads.push(thread);
}
return ret;
}
function getNewestMessageInSub(sub) {
const mb = new MsgBase(sub.code);
if (!mb.open()) return;
......@@ -81,7 +59,7 @@ function getNewestMessageInSub(sub) {
ret = {
from: h.from,
subject: h.subject,
when_written_time: h.when_written_time,
date: h.when_written_time, // should just be a timestamp; all date formatting should be client-side in forum.xjs
};
break;
}
......@@ -95,7 +73,6 @@ function getNewestMessagePerSub(grp) {
return msg_area.grp_list[grp].sub_list.reduce(function (a, c) {
const s = getNewestMessageInSub(c);
if (s !== undefined) a[c.code] = s;
log(LOG_DEBUG, JSON.stringify(s));
return a;
}, {});
}
......@@ -103,22 +80,24 @@ function getNewestMessagePerSub(grp) {
function getSubUnreadCount(sub) {
var ret = {
scanned: 0,
total: 0
total: 0,
};
if (typeof msg_area.sub[sub] === 'undefined') return ret;
if (msg_area.sub[sub] === undefined) return ret;
try {
var ua = crc16_calc(user.alias.toLowerCase());
var un = crc16_calc(user.name.toLowerCase());
var ud = crc16_calc(user.number);
var sy = msg_area.sub[sub].scan_cfg&SCAN_CFG_YONLY;
var sn = msg_area.sub[sub].scan_cfg&SCAN_CFG_NEW;
var msgBase = new MsgBase(sub);
msgBase.open();
for (var m = msg_area.sub[sub].scan_ptr + 1; m <= msgBase.last_msg; m++) {
var i = msgBase.get_msg_index(m);
if (i === null || i.attr&MSG_DELETE || i.attr&MSG_NODISP) continue;
if ((sy && (i.to === ua || i.to === un || (sub === 'mail' && i.to == ud))) || sn) ret.scanned++;
var h = msgBase.get_msg_header(m);
if (h === null || h.attr&MSG_DELETE || h.attr&MSG_NODISP) continue;
if ((sy && (h.to_ext === user.number || h.to === user.alias || h.to === user.name)) || sn) ret.scanned++;
ret.total++;
ret.newest = {
from: h.from,
subject: h.subject,
date: h.when_written_time
};
}
msgBase.close();
} catch (err) {
......@@ -139,7 +118,7 @@ function getGroupUnreadCount(group) {
scanned : 0,
total : 0
};
if (typeof msg_area.grp_list[group] === 'undefined') return ret;
if (msg_area.grp_list[group] === undefined) return ret;
msg_area.grp_list[group].sub_list.forEach(function (sub) {
var count = getSubUnreadCount(sub.code);
ret.scanned += count.scanned;
......@@ -158,7 +137,7 @@ function getGroupUnreadCounts() {
function getUnreadInThread(sub, thread, mkeys) {
if (typeof thread == 'number') {
var threads = getMessageThreads(sub, settings.max_messages);
if (typeof threads.thread[thread] == 'undefined') return 0;
if (threads.thread[thread] === undefined) return 0;
thread = threads.thread[thread];
}
var count = 0;
......@@ -170,6 +149,7 @@ function getUnreadInThread(sub, thread, mkeys) {
}
function getThreadVoteTotals(thread, mkeys) {
if (!mkeys) mkeys = Object.keys(thread.messages); // Not sure why it doesn't just do this already - does anything else call getThreadVoteTotals?
return mkeys.reduce(function (a, c, i) {
if (thread.messages[c].upvotes > 0) {
if (i == 0) a.up.p++;
......@@ -184,58 +164,88 @@ function getThreadVoteTotals(thread, mkeys) {
}, { up: { p: 0, t: 0 }, down: { p: 0, t: 0 }, total: 0 });
}
// { [thread_id]: { total, unread, votes: { up: { parent, total }, down: { parent, total }, total }, newest } }
function getThreadStats(sub, offset, page_size, guest) {
// Called from lib/events/forum.js to scan a sub for updates
// Very similar to listThreads, but the reply is smaller and there is no paging/offset
function getThreadStats(sub, guest) {
const threads = getMessageThreads(sub, settings.max_messages);
const ret = {};
if (!offset) offset = 0;
if (!page_size) page_size = threads.order.length - offset;
offset = offset * page_size;
var stop = Math.min(threads.order.length, offset + page_size);
for (var n = offset; n < stop; n++) {
var thread = threads.thread[threads.order[n]];
var mkeys = Object.keys(thread.messages);
ret[threads.order[n]] = {
total: mkeys.length,
const ret = {
sub: sub.code,
scan_cfg: sub.scan_cfg,
};
threads.order.forEach(function (e) {
const thread = threads.thread[e];
const mkeys = Object.keys(thread.messages);
ret[e] = {
id: e,
last: {
from: thread.messages[mkeys[mkeys.length - 1]].from,
when_written_time: thread.messages[mkeys[mkeys.length - 1]].when_written_time,
},
messages: mkeys.length,
unread: guest ? 0 : getUnreadInThread(sub, thread, mkeys),
votes: getThreadVoteTotals(thread, mkeys),
newest: {
from: thread.messages[mkeys[mkeys.length - 1]].from,
date: system.timestr(thread.messages[mkeys[mkeys.length - 1]].when_written_time)
}
};
});
return ret;
}
function listThreads(sub, count, after) {
count = parseInt(count, 10);
if (isNaN(count) || count < 1) return false;
var threads = getMessageThreads(sub, settings.max_messages);
var offset = 0;
if (after) offset = threads.order.indexOf(after) + 1;
var msgs;
var thread;
var stop = Math.min(threads.order.length, offset + count);
var ret = { total: threads.order.length, threads : [] };
if (sub.scan_cfg&SCAN_CFG_NEW) {
ret.scan_cfg = 'new';
} else if (sub.scan_cfg&SCAN_CFG_YONLY) {
ret.scan_cfg = 'you_only';
}
for (var n = offset; n < stop; n++) {
thread = threads.thread[threads.order[n]];
msgs = Object.keys(thread.messages);
ret.threads.push({
id: thread.id,
subject: thread.subject,
first: thread.messages[msgs[0]],
last: thread.messages[msgs[msgs.length - 1]],
messages: msgs.length,
unread: is_user() ? getUnreadInThread(sub, thread) : 0,
votes: getThreadVoteTotals(thread),
});
}
return ret;
}
function getVotesInThread(sub, thread) {
var ret = { t : { u : 0, d : 0 }, m : {} };
if (typeof msg_area.sub[sub] === 'undefined') return ret;
if (msg_area.sub[sub] === undefined) return ret;
if (typeof thread === 'number') {
var threads = getMessageThreads(sub, settings.max_messages);
if (typeof threads.thread[thread] === 'undefined') return ret;
if (threads.thread[thread] === undefined) return ret;
thread = threads.thread[thread];
}
var msgBase = new MsgBase(sub);
if (!msgBase.open()) return ret;
Object.keys(thread.messages).forEach(
function (m) {
if (thread.messages[m].upvotes > 0 ||
thread.messages[m].downvotes > 0
) {
ret.t.up += thread.messages[m].upvotes;
ret.t.down += thread.messages[m].downvotes;
ret.m[thread.messages[m].number] = {
u : thread.messages[m].upvotes,
d : thread.messages[m].downvotes,
v : msgBase.how_user_voted(
thread.messages[m].number,
msgBase.cfg.settings&SUB_NAME ? user.name : user.alias
)
};
}
Object.keys(thread.messages).forEach(function (m) {
if (thread.messages[m].upvotes > 0 || thread.messages[m].downvotes > 0) {
ret.t.up += thread.messages[m].upvotes;
ret.t.down += thread.messages[m].downvotes;
ret.m[thread.messages[m].number] = {
u: thread.messages[m].upvotes,
d: thread.messages[m].downvotes,
v: msgBase.how_user_voted(thread.messages[m].number, msgBase.cfg.settings&SUB_NAME ? user.name : user.alias),
};
}
);
});
msgBase.close();
return ret;
}
......@@ -243,40 +253,36 @@ function getVotesInThread(sub, thread) {
function getVotesInThreads(sub) {
var threads = getMessageThreads(sub, settings.max_messages);
var ret = {};
Object.keys(threads.thread).forEach(
function(t) {
Object.keys(threads.thread[t].messages).forEach(
function (m, i) {
if (threads.thread[t].messages[m].upvotes < 1 &&
threads.thread[t].messages[m].downvotes < 1
) {
return;
}
if (typeof ret[t] === 'undefined') {
ret[t] = { p : { u : 0, d : 0 }, t : { u : 0, d : 0 } };
if (i < 1) {
ret[t].p.u = threads.thread[t].messages[m].upvotes;
ret[t].p.d = threads.thread[t].messages[m].downvotes;
}
}
ret[t].t.u += threads.thread[t].messages[m].upvotes;
ret[t].t.d += threads.thread[t].messages[m].downvotes;
Object.keys(threads.thread).forEach(function (t) {
Object.keys(threads.thread[t].messages).forEach(function (m, i) {
if (threads.thread[t].messages[m].upvotes < 1 && threads.thread[t].messages[m].downvotes < 1) return;
if (ret[t] === undefined) {
ret[t] = { p: { u: 0, d: 0 }, t: { u: 0, d: 0 } };
if (i < 1) {
ret[t].p.u = threads.thread[t].messages[m].upvotes;
ret[t].p.d = threads.thread[t].messages[m].downvotes;
}
);
}
);
}
ret[t].t.u += threads.thread[t].messages[m].upvotes;
ret[t].t.d += threads.thread[t].messages[m].downvotes;
});
});
return ret;
}
function getUserPollData(sub, id) {
var ret = { answers : 0, tally : [], show_results : false };
if (typeof msg_area.sub[sub] === 'undefined') return ret;
var ret = {
answers: 0,
tally: [],
show_results: false,
};
if (msg_area.sub[sub] === undefined) return ret;
id = parseInt(id);
if (isNaN(id)) return ret;
var msgBase = new MsgBase(sub);
if (!msgBase.open()) return ret;
// var header = msgBase.get_msg_header(id);
// Temporary use of get_all_msg_headers() to get header.tally for polls
// Temporary use of get_all_msg_headers() to get header.tally for polls -- lol, "temporary"
var headers = msgBase.get_all_msg_headers();
var header = null;
for (var h in headers) {
......@@ -290,10 +296,7 @@ function getUserPollData(sub, id) {
return ret;
}
if (header.tally && Array.isArray(header.tally)) ret.tally = header.tally;
ret.answers = msgBase.how_user_voted(
header.number,
msgBase.cfg.settings&SUB_NAME ? user.name : user.alias
);
ret.answers = msgBase.how_user_voted(header.number, msgBase.cfg.settings&SUB_NAME ? user.name : user.alias);
msgBase.close();
var pollAttr = header.auxattr&POLL_RESULTS_MASK;
if (header.from === user.alias || header.from === user.name) {
......@@ -309,32 +312,19 @@ function getUserPollData(sub, id) {
}
function getMailHeaders(sent, ascending) {
if (typeof sent !== 'undefined' &&
sent &&
user.security.restrictions&UFLAG_K
) {
return []; // They'll just see nothing. Provide actual feedback? Does anyone use REST K?
}
if (sent !== undefined && sent && user.security.restrictions&UFLAG_K) return []; // They'll just see nothing. Provide actual feedback? Does anyone use REST K?
var headers = [];
var msgBase = new MsgBase('mail');
if (!msgBase.open()) return headers;
for (var m = msgBase.first_msg; m <= msgBase.last_msg; m++) {
var h = msgBase.get_msg_header(m);
if (h === null || h.attr&MSG_DELETE) continue;
if ( (typeof sent != 'undefined' && sent) &&
h.from_ext != user.number
) {
continue;
} else if (
(typeof sent == 'undefined' || !sent) &&
h.to_ext != user.number
) {
continue;
}
if ((sent !== undefined && sent) && h.from_ext != user.number) continue;
if ((sent === undefined || !sent) && h.to_ext != user.number) continue;
headers.push(h);
}
msgBase.close();
if (typeof ascending === 'undefined' || !ascending) headers.reverse();
if (ascending === undefined || !ascending) headers.reverse(); // not sure why the double !checks re: ascending and sent
return headers;
}
......@@ -347,7 +337,7 @@ function get_mail_headers(filter, ascending) {
headers: [],
sent: { read: 0, unread: 0 },
spam: { read: 0, unread: 0 },
inbox: { read: 0, unread: 0 }
inbox: { read: 0, unread: 0 },
};
if (filter == 'sent' && user.security.restrictions&UFLAG_K) return ret; // I don't remember what this is for.
const msg_base = new MsgBase('mail');
......@@ -376,8 +366,8 @@ function get_mail_headers(filter, ascending) {
function mimeDecode(header, body, code) {
const ret = {
type : '',
body : []
type: '',
body: [],
};
const msg = mime_decode(header, body, code);
if (msg.inlines) {
......@@ -404,8 +394,8 @@ function mimeDecode(header, body, code) {
function getMailBody(number) {
var ret = {
type : '',
body : ''
type: '',
body: ''
};
number = Number(number);
......@@ -455,10 +445,11 @@ function getSignature() {
if (!file_exists(fn)) return '';
var f = new File(fn);
f.open('r');
if(js.global.utf8_encode)
var signature = utf8_encode(f.read());
else
if (js.global.utf8_encode) {
var signature = utf8_encode(f.read());
} else {
var signature = ascii_str(f.read());
}
f.close();
return signature;
}
......@@ -576,9 +567,7 @@ function postReply(sub, body, pid) {
thread_back: pHeader.number,
};
if (sub === 'mail') {
if (typeof pHeader.from_net_addr !== 'undefined') {
header.to_net_addr = pHeader.from_net_addr;
}
if (typeof pHeader.from_net_addr !== 'undefined') header.to_net_addr = pHeader.from_net_addr;
ret = postMail(header, body);
} else {
ret = postMessage(sub, header, body);
......@@ -591,16 +580,9 @@ function postReply(sub, body, pid) {
function postPoll(sub, subject, votes, results, answers, comments) {
if (user.alias == settings.guest || user.security.restrictions&UFLAG_V) {
return false;
}
if (typeof msg_area.sub[sub] === 'undefined' || !msg_area.sub[sub].can_post) {
return false;
}
if (user.alias == settings.guest || user.security.restrictions&UFLAG_V) return false;
if (typeof msg_area.sub[sub] === 'undefined' || !msg_area.sub[sub].can_post) return false;
if (typeof subject !== 'string' || subject.length < 1) return false;
if (!Array.isArray(answers) || answers.length < 2) return false;
votes = parseInt(votes);
......@@ -608,38 +590,34 @@ function postPoll(sub, subject, votes, results, answers, comments) {
if (votes > answers) votes = answers;
results = parseInt(results);
if (isNaN(results) || results < 0 || results > 3) {
return false;
}
if (isNaN(results) || results < 0 || results > 3) return false;
var header = {
attr : MSG_POLL,
subject : subject.substr(0, LEN_TITLE),
from : msg_area.sub[sub].settings&SUB_AONLY ? "Anonymous" : (msg_area.sub[sub].settings&SUB_NAME ? user.name : user.alias),
from_ext : user.number,
to : 'All',
field_list : [],
auxattr : (results<<POLL_RESULTS_SHIFT) | MSG_HFIELDS_UTF8,
votes : votes
attr: MSG_POLL,
subject: subject.substr(0, LEN_TITLE),
from: msg_area.sub[sub].settings&SUB_AONLY ? 'Anonymous' : (msg_area.sub[sub].settings&SUB_NAME ? user.name : user.alias),
from_ext: user.number,
to: 'All',
field_list: [],
auxattr: (results<<POLL_RESULTS_SHIFT) | MSG_HFIELDS_UTF8,
votes: votes
};
if (Array.isArray(comments)) {
comments.forEach(
function (e) {
header.field_list.push(
{ type : SMB_COMMENT, data : e.substr(0, LEN_TITLE) }
);
}
);
comments.forEach(function (e) {
header.field_list.push({
type: SMB_COMMENT,
data: e.substr(0, LEN_TITLE),
});
});
}
answers.forEach(
function (e) {
header.field_list.push(
{ type : SMB_POLL_ANSWER, data : e.substr(0, LEN_TITLE) }
);
}
);
answers.forEach(function (e) {
header.field_list.push({
type: SMB_POLL_ANSWER,
data: e.substr(0, LEN_TITLE),
});
});
var msgBase = new MsgBase(sub);
if (!msgBase.open()) return false;
......@@ -656,16 +634,12 @@ function postPoll(sub, subject, votes, results, answers, comments) {
// - This is another sub on which the user is an operator
function deleteMessage(sub, number) {
number = parseInt(number);
if (typeof msg_area.sub[sub] === 'undefined' && sub !== 'mail') {
return false;
}
if (msg_area.sub[sub] === undefined && sub !== 'mail') return false;
var msgBase = new MsgBase(sub);
if (!msgBase.open()) return false;
var header = msgBase.get_msg_header(number);
if (header === null) return false;
if (sub === 'mail' &&
(header.to_ext == user.number || header.from_ext == user.number)
) {
if (sub === 'mail' && (header.to_ext == user.number || header.from_ext == user.number)) {
var ret = msgBase.remove_msg(number);
} else if (sub !== 'mail' && msg_area.sub[sub].is_operator) {
var ret = msgBase.remove_msg(number);
......@@ -677,31 +651,25 @@ function deleteMessage(sub, number) {
}
function deleteMail(numbers) {
if (typeof numbers === 'undefined' || !Array.isArray(numbers)) return false;
if (numbers === undefined || !Array.isArray(numbers)) return false;
var msgBase = new MsgBase('mail');
if (!msgBase.open()) return false;
numbers.forEach(
function (e) {
e = parseInt(e);
if (isNaN(e) || e < msgBase.first_msg || e > msgBase.last_msg) return;
var header = msgBase.get_msg_header(e);
if (header === null) return;
if (header.to_ext == user.number || header.from_ext == user.number) {
msgBase.remove_msg(e);
}
numbers.forEach(function (e) {
e = parseInt(e);
if (isNaN(e) || e < msgBase.first_msg || e > msgBase.last_msg) return;
var header = msgBase.get_msg_header(e);
if (header === null) return;
if (header.to_ext == user.number || header.from_ext == user.number) {
msgBase.remove_msg(e);
}
);
});
msgBase.close();
return true;
}
function voteMessage(sub, number, up) {
if (typeof msg_area.sub[sub] === 'undefined' && sub !== 'mail') {
return false;
}
if (user.alias == settings.guest || user.security.restrictions&UFLAG_V) {
return false;
}
if (typeof msg_area.sub[sub] === 'undefined' && sub !== 'mail') return false;
if (user.alias == settings.guest || user.security.restrictions&UFLAG_V) return false;
if (msg_area.sub[sub].settings&SUB_NOVOTING) return false;
number = parseInt(number);
if (isNaN(number)) return false;
......@@ -714,16 +682,14 @@ function voteMessage(sub, number, up) {
msgBase.close();
return false;
}
var uv = msgBase.how_user_voted(
header.number, msgBase.cfg.settings&SUB_NAME ? user.name : user.alias
);
var uv = msgBase.how_user_voted(header.number, msgBase.cfg.settings&SUB_NAME ? user.name : user.alias);
if (uv === 0) {
var vh = {
'from' : msgBase.cfg.settings&SUB_NAME ? user.name : user.alias,
'from_ext' : user.number,
'from_net_type' : NET_NONE,
'thread_back' : header.number,
'attr' : up ? MSG_UPVOTE : MSG_DOWNVOTE
from: msgBase.cfg.settings&SUB_NAME ? user.name : user.alias,
from_ext: user.number,
from_net_type: NET_NONE,
thread_back: header.number,
attr: up ? MSG_UPVOTE : MSG_DOWNVOTE,
};
var ret = msgBase.vote_msg(vh);
}
......@@ -734,44 +700,30 @@ function voteMessage(sub, number, up) {
function submitPollAnswers(sub, number, answers) {
if (typeof msg_area.sub[sub] === 'undefined') return false;
if (msg_area.sub[sub].settings&SUB_NOVOTING) return false;
if (user.alias == settings.guest || user.security.restrictions&UFLAG_V) {
return false;
}
if (user.alias == settings.guest || user.security.restrictions&UFLAG_V) return false;
number = parseInt(number);
if (isNaN(number)) return false;
var msgBase = new MsgBase(sub);
if (!msgBase.open()) return false;
var ret = false;
var header = msgBase.get_msg_header(number);
if (header !== null &&
header.attr&MSG_POLL &&
!(header.auxattr&POLL_CLOSED) &&
answers.length > 0 &&
( answers.length <= header.votes ||
(answers.length == 1 && header.votes == 0)
)
) {
var uv = msgBase.how_user_voted(
number, msgBase.cfg.settings&SUB_NAME ? user.name : user.alias
);
if (header !== null && header.attr&MSG_POLL && !(header.auxattr&POLL_CLOSED) && answers.length > 0 && (answers.length <= header.votes || (answers.length == 1 && header.votes == 0))) {
var uv = msgBase.how_user_voted(number, msgBase.cfg.settings&SUB_NAME ? user.name : user.alias);
if (uv === 0) {
var a = 0;
answers.forEach(
function (e) {
e = parseInt(e);
if (isNaN(e) || e < 0 || e > 15) return;
a|=(1<<e);
}
);
ret = msgBase.vote_msg(
{ 'from' : msgBase.cfg.settings&SUB_NAME ? user.name : user.alias,
'from_ext' : user.number,
'from_net_type' : NET_NONE,
'thread_back' : number,
'attr' : MSG_VOTE,
'votes' : a
}
);
answers.forEach(function (e) {
e = parseInt(e);
if (isNaN(e) || e < 0 || e > 15) return;
a|=(1<<e);
});
ret = msgBase.vote_msg({
from: msgBase.cfg.settings&SUB_NAME ? user.name : user.alias,
from_ext: user.number,
from_net_type: NET_NONE,
thread_back: number,
attr: MSG_VOTE,
votes: a,
});
}
}
msgBase.close();
......@@ -781,18 +733,15 @@ function submitPollAnswers(sub, number, answers) {
// Deuce's URL-ifier
function linkify(body) {
urlRE = /(?:https?|ftp|telnet|ssh|gopher|rlogin|news):\/\/[^\s'"'<>()]*|[-\w.+]+@(?:[-\w]+\.)+[\w]{2,6}/gi;
body = body.replace(
urlRE,
function (str) {
var ret=''
var p=0;
var link=str.replace(/\.*$/, '');
var linktext=link;
if (link.indexOf('://') === -1) link = 'mailto:' + link;
return ('<a class="ulLink" href="' + link + '">' + linktext + '</a>' + str.substr(linktext.length));
}
);
return (body);
body = body.replace(urlRE, function (str) {
var ret = '';
var p = 0;
var link = str.replace(/\.*$/, '');
var linktext = link;
if (link.indexOf('://') === -1) link = 'mailto:' + link;
return ('<a class="ulLink" href="' + link + '">' + linktext + '</a>' + str.substr(linktext.length));
});
return body;
}
// Somewhat modified version of Deuce's "magical quoting stuff" from v3
......@@ -801,47 +750,37 @@ function quotify(body) {
var blockquote_start = '<blockquote>';
var blockquote_end = '</blockquote>';
var lines = body.split(/\r?\n/);
body = '';
var quote_depth=0;
var prefixes = [];
for (l in lines) {
const ret = body.split(/\r?\n/).reduce(function (a, c) {
var line = '';
var line_prefix = '';
var m = lines[l].match(/^((?:\s?[^\s]{0,3}&gt;\s?)+)/);
var m = c.match(/^((?:\s?[^\s]{0,3}&gt;\s?)+)/);
if (m !== null) {
var new_prefixes = m[1].match(/\s?[^\s]{0,3}&gt;\s?/g);
var p;
var broken = false;
line = lines[l];
var broken = false;
var new_prefixes = m[1].match(/\s?[^\s]{0,3}&gt;\s?/g);
line = c;
// If the new length is smaller than the old one, close the extras
for (p = new_prefixes.length; p < prefixes.length; p++) {
if (quote_depth < 1) continue;
line_prefix = line_prefix + blockquote_end;
quote_depth--;
}
for (p in new_prefixes) {
// Remove prefix from start of line
line = line.substr(new_prefixes[p].length);
if (typeof prefixes[p] === "undefined") {
if (prefixes[p] === undefined) {
/* New depth */
line_prefix = line_prefix + blockquote_start;
quote_depth++;
} else if (broken) {
line_prefix = line_prefix + blockquote_start;
quote_depth++;
} else if (prefixes[p].replace(/^\s*(.*?)\s*$/,"$1") != new_prefixes[p].replace(/^\s*(.*?)\s*$/,"$1")) {
} else if (prefixes[p].replace(/^\s*(.*?)\s*$/, '$1') != new_prefixes[p].replace(/^\s*(.*?)\s*$/, '$1')) {
// Close all remaining old prefixes and start one new one
var o;
for (o = p; o < prefixes.length && o < new_prefixes.length; o++) {
for (var o = p; o < prefixes.length && o < new_prefixes.length; o++) {
if (quote_depth > 0) {
line_prefix = blockquote_end + line_prefix;
quote_depth--;
......@@ -852,33 +791,27 @@ function quotify(body) {
broken = true;
}
}
prefixes = new_prefixes.slice();
line = line_prefix + line;
} else {
for (p = 0; p < prefixes.length; p++) {
if (quote_depth < 1) continue;
line_prefix = line_prefix + blockquote_end;
quote_depth--;
}
prefixes = [];
line = line_prefix + lines[l];
line = line_prefix + c;
}
body = body + line + "\r\n";
}
return a + line + '\r\n';
}, '');
if (quote_depth !== 0) {
for (;quote_depth > 0; quote_depth--) {
body += blockquote_end;
ret += blockquote_end;
}
}
return body.replace(/\<\/blockquote\>\r\n<blockquote\>/g, "\r\n");
return ret.replace(/\<\/blockquote\>\r\n<blockquote\>/g, '\r\n');
}
......@@ -948,7 +881,7 @@ function setScanCfg(sub, cfg) {
SCAN_CFG_YONLY
];
if (typeof msg_area.sub[sub] === 'undefined') return false;
if (msg_area.sub[sub] === undefined) return false;
cfg = parseInt(cfg);
if (isNaN(cfg) || cfg < 0 || cfg > 2) return false;
......@@ -962,14 +895,17 @@ function setScanCfg(sub, cfg) {
function getMessageThreads(sub, max) {
var threads = { thread : {}, order : [] };
var threads = {
thread: {},
order: [],
};
var subjects = {};
if (typeof msg_area.sub[sub] === 'undefined') return threads;
if (msg_area.sub[sub] === undefined) return threads;
if (!msg_area.sub[sub].can_read) return threads;
function addToThread(thread_id, header, subject) {
if (typeof subject !== 'undefined') subjects[subject] = thread_id;
if (subject !== undefined) subjects[subject] = thread_id;
if (header.when_written_time > threads.thread[thread_id].newest) {
threads.thread[thread_id].newest = header.when_written_time;
}
......@@ -977,42 +913,33 @@ function getMessageThreads(sub, max) {
threads.thread[thread_id].unread++;
}
threads.thread[thread_id].messages[header.number] = {
attr : header.attr,
auxattr : header.auxattr,
number : header.number,
from : (header.attr&MSG_ANONYMOUS) ? "Anonymous" : (header.is_utf8 ? header.from : utf8_encode(header.from)),
from_ext : header.from_ext,
from_net_addr : header.from_net_addr,
to : header.is_utf8 ? header.to : utf8_encode(header.to),
when_written_time : header.when_written_time,
upvotes : (header.attr&MSG_POLL ? 0 : (header.upvotes || 0)),
downvotes : (header.attr&MSG_POLL ? 0 : (header.downvotes || 0)),
attr: header.attr,
auxattr: header.auxattr,
number: header.number,
from: (header.attr&MSG_ANONYMOUS) ? "Anonymous" : (header.is_utf8 ? header.from : utf8_encode(header.from)),
from_ext: header.from_ext,
from_net_addr: header.from_net_addr,
to: header.is_utf8 ? header.to : utf8_encode(header.to),
when_written_time: header.when_written_time,
upvotes: (header.attr&MSG_POLL ? 0 : (header.upvotes || 0)),
downvotes: (header.attr&MSG_POLL ? 0 : (header.downvotes || 0)),
is_utf8: header.is_utf8
};
if (header.attr&MSG_POLL) {
header.field_list.sort(
function (a, b) {
if (a.type === 0x62) return -1;
if (b.type === 0x62) return 1;
return 0;
}
);
header.field_list.sort(function (a, b) {
if (a.type === 0x62) return -1;
if (b.type === 0x62) return 1;
return 0;
});
threads.thread[thread_id].messages[header.number].poll_comments = [];
threads.thread[thread_id].messages[header.number].poll_answers = [];
header.field_list.forEach(
function (e) {
switch (e.type) {
case SMB_COMMENT:
threads.thread[thread_id].messages[header.number].poll_comments.push(e);
break;
case SMB_POLL_ANSWER:
threads.thread[thread_id].messages[header.number].poll_answers.push(e);
break;
default:
break;
}
header.field_list.forEach(function (e) {
if (e.type === SMB_COMMENT) {
threads.thread[thread_id].messages[header.number].poll_comments.push(e);
} else if (e.type === SMB_POLL_ANSWER) {
threads.thread[thread_id].messages[header.number].poll_answers.push(e);
}
);
});
threads.thread[thread_id].messages[header.number].votes = header.votes;
threads.thread[thread_id].messages[header.number].tally = header.tally || [];
threads.thread[thread_id].messages[header.number].subject = header.subject;
......@@ -1048,48 +975,65 @@ function getMessageThreads(sub, max) {
msgBase.close();
if (!headers) return threads;
Object.keys(headers).forEach(
function(h) {
if (headers[h] === null || headers[h].attr&MSG_DELETE) {
delete headers[h];
return;
}
if (settings.forum_no_spam && is_spam(header)) {
delete headers[h];
return;
}
if (sub === 'mail' &&
headers[h].to !== user.alias &&
headers[h].to !== user.name &&
headers[h].to_ext !== user.number &&
headers[h].from !== user.alias &&
headers[h].from !== user.name &&
headers[h].from_ext !== user.number
) {
delete headers[h];
return;
}
Object.keys(headers).forEach(function (h) {
var subject = headers[h].subject.replace(/^(re:\s*)*/ig, '');
if (headers[h] === null || headers[h].attr&MSG_DELETE) {
delete headers[h];
return;
}
if (typeof subjects[subject] !== 'undefined') {
if (settings.forum_no_spam && is_spam(header)) {
delete headers[h];
return;
}
addToThread(subjects[subject], headers[h]);
if (sub === 'mail' &&
headers[h].to !== user.alias &&
headers[h].to !== user.name &&
headers[h].to_ext !== user.number &&
headers[h].from !== user.alias &&
headers[h].from !== user.name &&
headers[h].from_ext !== user.number
) {
delete headers[h];
return;
}
} else if (headers[h].thread_id !== 0) {
var subject = headers[h].subject.replace(/^(re:\s*)*/ig, '');
if (typeof threads.thread[headers[h].thread_id]
!== 'undefined'
) {
addToThread(headers[h].thread_id, headers[h], subject);
} else {
threads.thread[headers[h].thread_id] = {
id: headers[h].thread_id,
newest : 0,
if (subjects[subject] !== undefined) {
addToThread(subjects[subject], headers[h]);
} else if (headers[h].thread_id !== 0) {
if (threads.thread[headers[h].thread_id] === undefined) {
threads.thread[headers[h].thread_id] = {
id: headers[h].thread_id,
newest: 0,
subject: headers[h].subject,
messages: {},
votes: {
up: 0,
down: 0
},
unread: 0
};
}
addToThread(headers[h].thread_id, headers[h], subject);
} else if (headers[h].thread_back !== 0) {
if (threads.thread[headers[h].thread_back] !== undefined) {
addToThread(headers[h].thread_back, headers[h], subject);
} else {
var threaded = false;
for (var t in threads.thread) {
if (threads.thread[t].messages[headers[h].thread_back] !== undefined) {
addToThread(t, headers[h], subject);
threaded = true;
break;
}
}
if (!threaded) {
threads.thread[headers[h].thread_back] = {
id: headers[h].thread_back,
newest: 0,
subject: headers[h].subject,
messages: {},
votes: {
......@@ -1098,69 +1042,27 @@ function getMessageThreads(sub, max) {
},
unread: 0
};
addToThread(headers[h].thread_id, headers[h], subject);
}
} else if (headers[h].thread_back !== 0) {
if (typeof threads.thread[headers[h].thread_back]
!== 'undefined'
) {
addToThread(headers[h].thread_back, headers[h], subject);
} else {
var threaded = false;
for (var t in threads.thread) {
if (typeof
threads.thread[t].messages[headers[h].thread_back]
!== 'undefined'
) {
addToThread(t, headers[h], subject);
threaded = true;
break;
}
}
if (!threaded) {
threads.thread[headers[h].thread_back] = {
id: headers[h].thread_back,
newest: 0,
subject: headers[h].subject,
messages: {},
votes: {
up: 0,
down: 0
},
unread: 0
};
addToThread(
headers[h].thread_back,
headers[h],
subject
);
}
}
} else {
threads.thread[headers[h].number] = {
id: headers[h].number,
newest: 0,
subject: headers[h].subject,
messages: {},
votes: {
up: 0,
down: 0
},
unread: 0
};
addToThread(headers[h].number, headers[h], subject);
}
delete headers[h];
} else {
threads.thread[headers[h].number] = {
id: headers[h].number,
newest: 0,
subject: headers[h].subject,
messages: {},
votes: {
up: 0,
down: 0
},
unread: 0
};
addToThread(headers[h].number, headers[h], subject);
}
);
delete headers[h];
});
threads.order = Object.keys(threads.thread).sort(function (a, b) {
return threads.thread[b].newest - threads.thread[a].newest;
......@@ -1170,15 +1072,54 @@ function getMessageThreads(sub, max) {
}
function getMessageThread(sub, thread, count, after) {
thread = parseInt(thread, 10);
if (isNaN(thread)) return [];
count = parseInt(count, 10);
if (isNaN(count)) return [];
const t = getMessageThreads(sub, settings.max_messages).thread[thread];
const mkeys = Object.keys(t.messages);
var m; // Current message
var r = 0; // Messages returned
var n = 0; // Index into t.messages
if (after) n = mkeys.indexOf(after) + 1;
const msgBase = new MsgBase(sub);
return function threadIterator() {
if (r >= count || n >= mkeys.length) {
if (msgBase.is_open) msgBase.close();
return null; // Done
}
if (!msgBase.is_open && !msgBase.open()) {
throw new Error('Failed to open ' + sub);
}
m = t.messages[mkeys[n]];
const body = msgBase.get_msg_body(m.number);
if (body === null) {
n++;
return threadIterator();
}
if (r == 0) m.subject = t.subject;
m.body = formatMessage(body);
n++;
r++;
return m;
}
}
function isValidRequest() {
if (Request.has_param('group')) {
const grp = Request.get_param('group');
if (typeof msg_area.grp_list[grp] == 'undefined') return false;
if (msg_area.grp_list[grp] === undefined) return false;
if (!user.compare_ars(msg_area.grp_list[grp].ars)) return false;
}
if (Request.has_param('sub')) {
const sub = Request.get_param('sub');
if (typeof msg_area.sub[sub] == 'undefined') return false;
if (msg_area.sub[sub] === undefined) return false;
}
return true;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment