Select Git revision
newslink.js
-
Rob Swindell authored
was printing the filename in uppercase if configured as such
Rob Swindell authoredwas printing the filename in uppercase if configured as such
To find the state of this project's repository at the time of any of these versions, check out the tags.
newslink.js 25.37 KiB
// newslink.js
// Synchronet Newsgroup Link/Gateway Module
// Configuration file (in ctrl/newslink.cfg) format:
// ;this line is a comment
// server servername
// port TCP port number (defaults to 119)
// user username (optional)
// pass password (optional)
// area subboard (internal code) newsgroup flags [attachment_dir]
// ...
// Defined area flags:
// x do not add tearlines & taglines to exported messages
// n do not add "From Newsgroup" text to imported messages
// t do not add tearline to imported messages
// a convert extended-ASCII chars to ASCII on imported messages
// r remove "Newsgroups:" header field from imported messages
// o over-write "Newsgroups:" header field for exported messages
// b decode binary attachments
// i import all (not just new articles)
// s no subject filtering
// m Moderate imported messages
const REVISION = "1.2";
printf("Synchronet NewsLink %s session started\r\n", REVISION);
var tearline = format("--- Synchronet %s%s-%s NewsLink %s\r\n"
,system.version,system.revision,system.platform,REVISION);
var tagline = format(" * %s - %s - telnet://%s\r\n"
,system.name,system.location,system.inetaddr);
var antispam = format(".remove-%s-this"
,random(50000).toString(36));
var cfg_fname = system.ctrl_dir + "newslink.cfg";
var global_flags = ""; // global flags - area flags applied to all areas
load("sbbsdefs.js");
load("newsutil.js"); // write_news_header() and parse_news_header()
var debug = false;
var slave = false;
var reader_mode = false;
var reset_import_ptrs = false; // Reset import pointers, import all messages
var update_import_ptrs = false; // Update import pointers, don't import anything
var reset_export_ptrs = false; // Reset export pointers, export all messages
var update_export_ptrs = false; // Update export pointers, don't export anything
var email_addresses = true; // Include e-mail addresses in headers
var import_amount = 0; // Import a fixed number of messages per group
var lines_per_yield = 5; // Release time-slices ever x number of lines
var yield_length = 1; // Length of yield (in milliseconds)
var max_newsgroups_per_article = 5; // Used for spam-detection
var unmangle = false;
var use_xover = true;
var connect_timeout = 30;
// Parse arguments
for(i=0;i<argc;i++) {
if(argv[i].toLowerCase()=="-d") // debug
debug = true;
else if(argv[i].toLowerCase()=="-ri") // reset import pointers (import all)
reset_import_ptrs = true;
else if(argv[i].toLowerCase()=="-ui") // update import pointers (import none)
update_import_ptrs = true;
else if(argv[i].toLowerCase()=="-re") // reset export pointers (export all)
reset_export_ptrs = true;
else if(argv[i].toLowerCase()=="-ue") // update export pointers (export none)
update_export_ptrs = true;
else if(argv[i].toLowerCase()=="-ne") // no e-mail addresses
email_addresses = false;
else if(argv[i].toLowerCase()=="-nm") // no mangling of e-mail addresses
antispam = "";
else if(argv[i].toLowerCase()=="-um") // un-mangle e-mail addresses when importing
unmangle = true;
else if(argv[i].toLowerCase()=="-nx") // no xover command when importing
use_xover = false;
else if(argv[i].toLowerCase()=="-ix") // import a fixed number of messages
{
import_amount = parseInt(argv[i+1]);
if(import_amount)
i++;
else
import_amount = 500; // default 500
}
else
cfg_fname = argv[i];
}
if(this.js==undefined) // v3.10?
js = { terminated: false };
else
js.auto_terminate = false;
// Write a string to the server socket
function write(str)
{
socket.send(str);
}
function writeln(str)
{
if(debug)
printf("cmd: %s\r\n",str);
write(str + "\r\n");
}
// RFC977 and RFC3977 clearly state 512-bytes per response line,
// but "Timelord" reported a problem with some news server sending
// > 512-byte response lines for the XOVER command
function readln()
{
rsp = socket.recvline(4096);
if(debug)
printf("rsp: %s\r\n",rsp);
return(rsp);
}
function unique_fname(dir,fname)
{
var new_fname=fname;
var file_num=0;
var ext;
while(file_exists(dir + new_fname) && file_num<1000) {
// generate unique name, if necessary
ext=fname.lastIndexOf('.');
if(ext<0)
ext="";
else
ext=fname.slice(ext);
// Convert filename.ext to filename.<article>.ext
new_fname=format("%.*s.%lu%s",fname.length-ext.length,fname,file_num++,ext);
}
return(dir + new_fname);
}
// Remove NewsLink anti-spam meature from e-mail address
function unmangle_addr(addr)
{
return addr.replace(/\.remove-\S+-this/,"");
}
var yield_calls=0;
function maybe_yield()
{
yield_calls++;
if(lines_per_yield && (yield_calls%lines_per_yield)==0) {
sleep(yield_length);
}
}
var host;
var port=119;
var username;
var password;
var interface_ip_address=0;
var port_set=false;
var tls=false;
var no_path=false;
var approved;
var area = {};
if(this.server!=undefined)
interface_ip_address=server.interface_ip_address;
/******************************/
/* Read/Parse the Config File */
/******************************/
cfg_file = new File(cfg_fname);
if(!cfg_file.open("r")) {
printf("!Error %d opening %s\r\n",errno,cfg_fname);
delete cfg_file;
exit(1);
}
while(!cfg_file.eof) {
line = cfg_file.readln();
if(line == null)
continue;
line = truncsp(line);
if(line==null || line[0] == ';' || !line.length || line==undefined)
continue;
str=line.split(/\s+/);
switch(str[0].toLowerCase()) {
case "disabled":
printf("!NewsLink DISABLED in %s\r\n",cfg_fname);
delete cfg_file;
exit();
case "server":
host=str[1];
break;
case "tls":
tls=true;
if(!port_set)
port=563;
break;
case "port":
port=parseInt(str[1]);
port_set=true;
break;
case "interface":
interface_ip_address=str[1];
break;
case "user":
username=str[1];
break;
case "pass":
password=str[1];
break;
case "flags":
global_flags=str[1];
break;
case "area":
area[str[1]] = { newsgroup: str[2], flags: str[3], attachment_dir: str[4] };
break;
case "auto_areas":
{
for(var s in msg_area.sub)
if((msg_area.sub[s].settings & SUB_INET) && !area[s])
area[s] = {};
break;
}
case "debug":
debug=true;
break;
case "unmangle":
unmangle=true;
break;
case "no_xover":
use_xover=false;
break;
case "no_path":
no_path=true;
break;
case "slave":
slave=true;
break;
case "reader_mode":
reader_mode = true;
break;
case "tagline":
str.shift(); // Remove first element (keyword)
tagline=str.join(' '); // Combine remaining elements (tagline)
tagline+="\r\n";
break;
case "lines_per_yield":
lines_per_yield=parseInt(str[1]);
break;
case "yield_length":
yield_length=parseInt(str[1]);
break;
case "max_newsgroups_per_article":
max_newsgroups_per_article=parseInt(str[1]);
break;
case "approved":
approved = str[1];
break;
default:
print("!UNRECOGNIZED configuration keyword: " + str[0]);
break;
}
}
cfg_file.close();
delete cfg_file;
printf("server: %s\r\n",host);
if(debug) {
printf("username: %s\r\n",username);
printf("password: %s\r\n",password);
}
if(host==undefined || !host.length) {
print("!No news server specified");
exit(1);
}
printf("Connecting to %s port %d ...\r\n",host,port);
socket = new Socket();
//socket.debug=true;
socket.bind(0,interface_ip_address);
if(!socket.connect(host, port, connect_timeout)) {
printf("!Error %d connecting to %s port %d\r\n"
,socket.last_error,host,port);
delete socket;
exit(1);
}
print("Connected");
if(tls) {
print("Negotiating TLS");
socket.ssl_session=true;
}
readln();
if(reader_mode) {
writeln("MODE READER");
readln();
}
if(username!=undefined && username.length) {
print("Authenticating...");
writeln(format("AUTHINFO USER %s",username));
readln();
if(password!=undefined && password.length) {
writeln(format("AUTHINFO PASS %s",password));
rsp = readln();
if(rsp==null || rsp[0]!='2') {
printf("!Authentication FAILURE: %s\r\n", rsp);
delete socket;
exit(1);
}
}
print("Authenticated");
}
if(slave) {
writeln("slave");
readln();
}
var stop_semaphore=system.data_dir+"newslink.stop";
file_remove(stop_semaphore);
function stop_sem_signaled()
{
if(file_exists(stop_semaphore)) {
log(stop_semaphore + " signaled");
return(true);
}
return(false);
}
/******************************/
/* Export and Import Messages */
/******************************/
var exported=0;
var imported=0;
var subimported=0;
var subpending=0;
var twitlist = [];
var f = new File(system.ctrl_dir + "twitlist.cfg");
if(f.open("r")) {
twitlist = f.readAll();
f.close();
}
function article_listed(list, article)
{
var i;
for(i in list)
if(list[i]==article)
return(list.splice(i,1));
return(false);
}
function save_ptr(ini_file, name, value)
{
/* Save Pointers */
if(!ini_file.open(ini_file.exists ? "r+":"w+"))
printf("!ERROR %d creating/opening %s\r\n",errno,ini_file.name);
else {
ini_file.iniSetValue("NewsLink", name, value);
ini_file.close();
}
}
printf("Scanning message bases...\r\n");
for(sub in area) {
if(!socket.is_connected)
break;
if(js.terminated || stop_sem_signaled())
break;
newsgroup = area[sub].newsgroup;
flags = area[sub].flags;
if(flags==undefined)
flags="";
flags += global_flags;
flags = flags.toLowerCase();
msgbase = new MsgBase(sub);
if(msgbase.open!=undefined && msgbase.open()==false) {
printf("!ERROR %s opening msgbase: %s\r\n",msgbase.last_error,sub);
delete msgbase;
continue;
}
// Use default newsgroup name if not configured
if(newsgroup==undefined || newsgroup.length<2)
newsgroup=msgbase.cfg.newsgroup;
attachment_dir=area[sub].attachment_dir;
if(attachment_dir==undefined)
attachment_dir=msgbase.cfg.data_dir+"attach";
mkdir(attachment_dir);
if(attachment_dir.substr(-1)!='/')
attachment_dir+="/";
printf("sub: %s, newsgroup: %s\r\n",sub,newsgroup);
/*********************/
/* Read Pointer File */
/*********************/
export_ptr = 0;
import_ptr = NaN; // Set to highest possible message number (by default)
if(flags.indexOf('i')>=0) // import all
import_ptr = 0;
ini_fname = msgbase.file + ".ini";
ini_file = new File(ini_fname);
if(ini_file.open("r")) {
export_ptr=ini_file.iniGetValue("NewsLink","export_ptr",export_ptr);
printf("%s export ptr: %ld\r\n",file_getname(ini_fname), export_ptr);
import_ptr=ini_file.iniGetValue("NewsLink","import_ptr",import_ptr);
printf("%s import ptr: %ld\r\n",file_getname(ini_fname),import_ptr);
ini_file.close();
}
if(reset_export_ptrs)
ptr = 0;
else if(update_export_ptrs)
ptr = msgbase.last_msg;
else
ptr = export_ptr;
if(ptr < msgbase.first_msg)
ptr = msgbase.first_msg;
else
ptr++;
/*************************/
/* EXPORT Local Messages */
/*************************/
if(debug)
print("exporting local messages");
last_msg=msgbase.last_msg;
for(;socket.is_connected
&& ptr<=last_msg
&& !js.terminated
&& !stop_sem_signaled()
;ptr++) {
if(this.console!=undefined)
console.line_counter = 0;
hdr = msgbase.get_msg_header(
/* retrieve by offset? */ false,
/* message number */ ptr
);
if(hdr == null) {
if(msgbase.status != 0)
alert("Error (" + msgbase.error + ") reading msg header #" + ptr);
continue;
}
if(!hdr.id) {
alert("Message #" + ptr + " is missing a Message-ID header field");
continue;
}
if(hdr.attr&MSG_DELETE) { /* marked for deletion */
if(debug)
printf("skipping deleting msg #" + ptr);
continue;
}
if(hdr.attr&MSG_MODERATED && !(hdr.attr&MSG_VALIDATED)) {
print("Stopping at unvalidated moderated message: " + ptr);
ptr--;
break;
}
if(hdr.attr&MSG_PRIVATE) { /* no private messages on NNTP */
if(debug)
printf("skipping deleted msg #" + ptr);
continue;
}
if(hdr.from_net_type==NET_INTERNET) { /* no dupe loop */
if(debug)
printf("skipping msg from the Internet #" + ptr);
continue;
}
if(hdr.from_net_type /* don't gate messages between net types */
&& msgbase.cfg!=undefined && !(msgbase.cfg.settings&SUB_GATE)) {
if(debug)
printf("skipping (not gating) networked message #" + ptr);
continue;
}
body = msgbase.get_msg_body(
false /* retrieve by offset */
,ptr /* message number */
,true /* remove ctrl-a codes */
,true /* rfc822 formatted text */
,true /* include tails */
);
if(body == null) {
printf("!FAILED to read message number %ld\r\n",ptr);
continue;
}
if(msgbase.cfg!=undefined && msgbase.cfg.settings&SUB_ASCII) {
/* Convert Ex-ASCII chars to approximate ASCII equivalents */
body = ascii_str(body);
hdr.subject = ascii_str(hdr.subject);
}
if(flags.indexOf('x')==-1) {
body += tearline;
body += tagline;
}
if(0)
writeln(format("IHAVE %s",hdr.id));
else
writeln("POST");
rsp = readln();
if(rsp==null || rsp[0]!='3') {
printf("!POST FAILURE: %s\r\n",rsp);
break;
}
if(!email_addresses)
writeln(format("From: %s@%s",hdr.from,newsgroup));
else if(hdr.from.indexOf('@')!=-1)
writeln(format("From: %s%s",hdr.from,antispam));
else if(hdr.from_net_type && hdr.from_net_addr!=null) {
if(hdr.from_net_addr.indexOf('@')!=-1)
writeln(format("From: \"%s\" <%s%s>"
,hdr.from
,hdr.from_net_addr,antispam));
else
writeln(format("From: \"%s\" <%s@%s%s>"
,hdr.from
,hdr.from.replace(/ /g,".").toLowerCase()
,hdr.from_net_addr,antispam));
}
else
writeln(format("From: \"%s\" <%s@%s%s>"
,hdr.from
,hdr.from.replace(/ /g,".").toLowerCase()
,system.inetaddr,antispam));
if(hdr.newsgroups==undefined || flags.indexOf('o')>=0)
hdr.newsgroups=newsgroup;
if(hdr.from_org==undefined && !hdr.from_net_type)
hdr.from_org=system.name;
write_news_header(hdr,writeln); // from newsutil.js
writeln("X-Gateway: "
+ system.inetaddr
+ " [Synchronet "
+ system.version + system.revision
+ "-" + system.platform + system.beta_version
+ " NewsLink " + REVISION
+ "]"
);
if(approved)
writeln("Approved: " + approved);
writeln("");
if(hdr.to.toLowerCase()!="all") {
writeln(" To: " + hdr.to);
}
write(body);
writeln(".");
rsp = readln();
if(rsp==null || rsp[0]!='2') {
printf("!POST FAILURE: %s\r\n",rsp);
break;
}
printf("Exported message %lu to newsgroup: %s\r\n",ptr,newsgroup);
exported++;
}
if(ptr > msgbase.last_msg)
ptr = msgbase.last_msg;
export_ptr = ptr;
save_ptr(ini_file, "export_ptr", export_ptr);
if(stop_sem_signaled())
break;
/***************************/
/* IMPORT Network Messages */
/***************************/
writeln(format("GROUP %s",newsgroup));
rsp = readln();
if(rsp==null || rsp[0]!='2') {
printf("!GROUP %s FAILURE: %s\r\n",newsgroup,rsp);
delete ini_file;
delete msgbase;
continue;
}
str = rsp.split(' ');
first_msg = parseInt(str[2]);
last_msg = parseInt(str[3]);
if(reset_import_ptrs)
ptr = 0;
else if(update_import_ptrs)
ptr = last_msg;
else if(import_amount)
ptr = last_msg - import_amount;
else
ptr = import_ptr;
printf("%s import ptr: %ld, first_msg: %ld, last_msg: %ld\r\n"
,newsgroup,ptr,first_msg,last_msg);
if(ptr < first_msg)
ptr = first_msg;
else {
if(ptr > last_msg || isNaN(ptr))
ptr = last_msg;
ptr++;
}
if(msgbase.cfg.max_msgs > 0 && last_msg - ptr > msgbase.cfg.max_msgs)
ptr = (last_msg - msgbase.cfg.max_msgs) + 1;
delete article_list;
subpending=0;
if(use_xover && ptr<=last_msg) {
writeln(format("XOVER %u-%u", ptr, last_msg));
if(parseInt(readln())==224) {
printf("Getting headers for articles %u through %u\r\n", ptr, last_msg);
article_list = new Array();
while((rsp=readln())!='.' && socket.is_connected && !js.terminated) {
if(rsp)
article_list.push(parseInt(rsp));
maybe_yield();
}
printf("%u new articles\r\n", article_list.length);
subpending=article_list.length;
}
}
subimported=0;
for(;socket.is_connected
&& ptr<=last_msg
&& !js.terminated
&& !stop_sem_signaled()
;ptr++) {
if(this.console!=undefined)
console.line_counter = 0;
if(this.article_list!=undefined && !article_listed(article_list,ptr)) {
subpending--;
continue;
}
printf("Retrieving %s article: %u\r\n", newsgroup, ptr);
writeln(format("ARTICLE %lu",ptr));
rsp = readln();
if(rsp==null || rsp[0]!='2') {
printf("!ARTICLE %lu ERROR: %s\r\n",ptr,rsp);
subpending--;
continue;
}
body="";
header=true;
var line;
var line_counter=0;
var recv_lines=0;
var file=undefined;
var hfields=[];
var md5;
while(socket.is_connected && !js.terminated) {
maybe_yield();
line = readln();
if(line==null) {
print("!TIMEOUT waiting for text line\r\n");
break;
}
recv_lines++;
if(debug)
printf("msgtxt: %s\r\n",line);
if(line==".") {
if(debug)
print("End of message text");
break;
}
if(line=="" && header) {
header=false;
continue;
}
if(header) {
if((line.charAt(0)==' ' || line.charAt(0)=='\t') && hfields.length) {
while(line.charAt(0)==' ' // trim prepended spaces
|| line.charAt(0)=='\t')
line=line.slice(1);
hfields[hfields.length-1] += line; // folded header field
} else
hfields.push(line);
continue;
}
/* Body text, append to 'body' */
if(line.charAt(0)=='.')
line=line.slice(1); // Skip prepended dots
body += line+"\r\n";
line_counter++;
if(flags.indexOf('b')>=0) { // decode attachments
if(file==undefined
&& line.substr(0,8)=="=ybegin "
&& line.indexOf(" line=")>0
&& (size=line.indexOf(" size="))>0
&& (name=line.indexOf(" name="))>0) {
printf("yenc header: %s\r\n",line);
size=parseInt(line.slice(size+6),10);
fname=file_getname(line.slice(name+6));
if((total=line.indexOf(" total="))>0)
total=parseInt(line.slice(total+7),10);
if(total>1) /* multipart */
continue;
/* part? */
if((part=line.indexOf(" part="))>0)
part=parseInt(line.slice(part+6),10);
if(part>1) /* multipart */
continue;
if(part>0) {
line = readln();
body += line+"\r\n";
printf("ypart header: %s\r\n",line);
if(line.substr(0,7)!="=ypart "
|| (begin=line.indexOf(" begin="))<1
|| (end=line.indexOf(" end="))<1) {
printf("!yEnc MALFORMED ypart line: %s\r\n",line);
continue;
}
if(begin!=1 || end!=size) /* multipart */
continue;
}
fname=unique_fname(attachment_dir,fname);
file=new File(fname);
file.yenc=true;
if(file.open("w+b"))
printf("Receiving/decoding attachment: %s\r\n",file.name);
else
printf("!ERROR %s opening %s\r\n",errno_str,file.name);
continue;
}
if(file==undefined && line.substr(0,6)=="begin ") {
// Parse uuencode header
arg=line.split(/\s+/);
arg.splice(0,2); // strip "begin 666 "
fname=file_getname(arg.join(" "));
fname=unique_fname(attachment_dir,fname);
file=new File(fname);
file.uue=true;
if(file.open("w+b"))
printf("Receiving/decoding attachment: %s\r\n",file.name);
else
printf("!ERROR %s opening %s\r\n",errno_str,file.name);
continue;
}
if(file!=undefined && file.is_open==true) {
if(file.uue && line=="end") {
md5=file.md5_hex;
file.close();
continue;
}
if(file.yenc && line.substr(0,6)=="=yend "
&& (part_size=line.indexOf(" size="))>0) {
part_size=parseInt(line.slice(part_size+6),10);
if(part_size!=size) { /* multi-part, ignore */
file.remove();
delete file;
continue;
}
if((crc32=line.indexOf(" pcrc32="))>0)
crc32=parseInt(line.slice(crc32+8),16);
else if((crc32=line.indexOf(" crc32="))>0)
crc32=parseInt(line.slice(crc32+7),16);
else
crc32=undefined;
if(crc32!=undefined) {
file_crc32=file.crc32;
if(crc32!=file_crc32) {
printf("!yEnc CRC-32 mismatch, actual: %08lX, trailer: %s\r\n"
,file_crc32,line);
file.remove();
delete file;
continue;
}
}
md5=file.md5_hex;
file.close();
continue;
}
if(!file.write(line))
printf("!ERROR decoding/writing: %s\r\n",line);
}
}
//print(line);
}
if(debug)
print("Parsing message header");
// Parse the message header
var hdr={ from: "", to: newsgroup, subject: "", id: "" };
for(h in hfields)
parse_news_header(hdr,hfields[h]); // from newsutil.js
if(hdr.extra_headers!=undefined
&& hdr.extra_headers["nntp-posting-host"]!=undefined
&& (system.trashcan("ip", hdr.extra_headers["nntp-posting-host"])
|| system.trashcan("ip-silent", hdr.extra_headers["nntp-posting-host"]))) {
print("!Filtered IP address in NNTP-Posting-Host header field: " + hdr.extra_headers["nntp-posting-host"]);
subpending--;
continue;
}
if(file!=undefined) {
if(debug)
print("Parsing attachment");
if(file.is_open==true) { /* Incomplete attachment? */
print("!Incomplete attachment: " + file_getname(file.name));
file.remove();
} else {
/* Search for duplicate MD5 */
print("Searching for duplicate file");
var duplicate=false;
md5_file=new File(attachment_dir + "md5.lst");
if(md5_file.open("r")) {
while(!md5_file.eof && !duplicate) {
str=md5_file.readln();
if(str==null)
break;
if(str.substr(0,32)==md5)
duplicate=true;
}
md5_file.close();
}
if(duplicate) {
printf("Duplicate MD5 digest found: %s\r\n",str);
if(file_remove(file.name))
printf("Duplicate file removed: %s\r\n",file.name);
else
printf("!ERROR removing duplicate file: %s\r\n",file.name);
subpending--;
continue;
}
/* Append MD5 to history file */
if(md5_file.open("a")) {
md5_file.printf("%s %s\n",md5,file_getname(file.name));
md5_file.close();
} else
printf("!ERROR %d (%s) creating/appending %s\r\n"
,errno, errno_str, md5_file.name);
subpending--;
continue;
}
}
if(debug)
print("Decoding body text");
body=decode_news_body(hdr, body);
if(truncsp(body).length==0) {
printf("Message %lu not imported (blank)\r\n",ptr);
subpending--;
continue;
}
if(max_newsgroups_per_article && hdr.newsgroups!=undefined) {
var ngarray=hdr.newsgroups.split(',');
if(ngarray.length>max_newsgroups_per_article) {
var reason = format("Too many newsgroups (%d): %s",ngarray.length, hdr.newsgroups);
printf("!%s\r\n",reason);
system.spamlog("NNTP","NOT IMPORTED",reason,hdr.from,host,hdr.to);
subpending--;
continue;
}
}
if(hdr.to==newsgroup && hdr.newsgroups!=undefined)
hdr.to=hdr.newsgroups;
// Duplicate/looped message detection here
if(hdr.id.indexOf('@' + system.inetaddr)!=-1) {
log(LOG_DEBUG, "Duplicate/looped message-ID: " + hdr.id);
subpending--;
continue;
}
if(hdr.path
&& hdr.path.indexOf(system.inetaddr)!=-1) {
log(LOG_DEBUG, "Duplicate/looped message path: " + hdr.path);
subpending--;
continue;
}
if(no_path && hdr.path)
delete hdr.path;
if(hdr.gateway
&& hdr.gateway.indexOf(system.inetaddr)!=-1) {
log(LOG_DEBUG, "Duplicate/looped message gateway: " + hdr.gateway);
subpending--;
continue;
}
if(flags.indexOf('s')==-1 && system.trashcan("subject",hdr.subject)) {
var reason = format("Blocked subject (%s)",hdr.subject);
printf("!%s\r\n",reason);
system.spamlog("NNTP","NOT IMPORTED",reason,hdr.from,host,hdr.to);
subpending--;
continue;
}
if(twitlist.length
&& (system.findstr(twitlist,hdr.from)
|| system.findstr(twitlist,hdr.from_net_addr)
|| system.findstr(twitlist,hdr.to))) {
printf("Filtering message from %s (%s) to %s\r\n", hdr.from, hdr.from_net_addr, hdr.to);
subpending--;
continue;
}
if(flags.indexOf('n')==-1)
body=format("\1n\1b\1hFrom Newsgroup\1n\1b: \1h\1c%s\1n\r\n\r\n",newsgroup) + body;
if(flags.indexOf('a')>=0) { // import ASCII only (convert ex-ASCII to ASCII)
body = ascii_str(body);
hdr.subject = ascii_str(hdr.subject);
}
if(flags.indexOf('r')>=0) // remove "Newsgroups:" header field
delete hdr.newsgroups;
if(hdr.from_net_addr && unmangle)
hdr.from_net_addr = unmangle_addr(hdr.from_net_addr);
hdr.from_net_type=NET_INTERNET;
// hdr.from_net_addr=hdr.from;
if(flags.indexOf('t')==-1)
body += tearline;
if(flags.indexOf('m')>=0)
hdr.attr |= MSG_MODERATED;
if(debug)
print("Saving message");
if(msgbase.save_msg(hdr,body)) {
imported++;
subimported++;
printf("Message %lu imported into %s (%lu of %lu total) %lu lines\r\n"
,ptr, sub, subimported, subpending, line_counter);
} else {
printf("!IMPORT %lu ERROR: %s\r\n", ptr, msgbase.last_error);
subpending--;
}
}
ptr--; /* point to last requested article number */
if(ptr > last_msg)
ptr = last_msg;
import_ptr = ptr;
save_ptr(ini_file, "import_ptr", import_ptr);
delete ini_file;
msgbase.close();
delete msgbase;
// if(flags.indexOf('b')>=0) // binary newsgroup
// load("binarydecoder.js",sub);
}
if(!socket.is_connected)
print("!DISCONNECTED BY SERVER");
else {
writeln("quit");
readln();
}
delete socket;
printf("Synchronet NewsLink %s session complete (%lu exported, %lu imported)\r\n"
,REVISION, exported, imported);
/* End of newslink.js */