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