Skip to content
Snippets Groups Projects
Commit 566ad8b7 authored by rswindell's avatar rswindell
Browse files

Actually combines and decodes (both UUE and yEnc) now.

parent 88278af8
No related branches found
No related tags found
No related merge requests found
...@@ -12,6 +12,9 @@ const REVISION = "$Revision$".split(' ')[1]; ...@@ -12,6 +12,9 @@ const REVISION = "$Revision$".split(' ')[1];
printf("Synchronet Binary Decoder %s session started\r\n", REVISION); printf("Synchronet Binary Decoder %s session started\r\n", REVISION);
lines_per_yield=5;
completed_files=0;
var ini_fname = system.ctrl_dir + "binarydecoder.ini"; var ini_fname = system.ctrl_dir + "binarydecoder.ini";
file = new File(ini_fname); file = new File(ini_fname);
...@@ -56,6 +59,8 @@ for(i in sub) { ...@@ -56,6 +59,8 @@ for(i in sub) {
if(attachment_dir.substr(-1)!='/') if(attachment_dir.substr(-1)!='/')
attachment_dir+="/"; attachment_dir+="/";
/* save for later */
msg_area.sub[sub[i].code].attachment_dir=attachment_dir;
/* Read MD5 list */ /* Read MD5 list */
md5_fname=attachment_dir + "md5.lst"; md5_fname=attachment_dir + "md5.lst";
...@@ -84,11 +89,14 @@ for(i in sub) { ...@@ -84,11 +89,14 @@ for(i in sub) {
parts_file.close(); parts_file.close();
} }
printf("Scanning %s\r\n",sub[i].code); printf("Scanning %s\r\n",msgbase.cfg.code);
for(;ptr<=msgbase.last_msg && bbs.online;ptr++) { last_msg=msgbase.last_msg;
for(;ptr<=last_msg && bbs.online;ptr++) {
printf("%s %ld\r\n",sub[i].code,ptr); console.inkey(); /* allow ^O toggle */
printf("%s %lu of %lu\r\n"
,msgbase.cfg.code, ptr, last_msg);
hdr = msgbase.get_msg_header( hdr = msgbase.get_msg_header(
/* retrieve by offset? */ false, /* retrieve by offset? */ false,
...@@ -118,49 +126,70 @@ for(i in sub) { ...@@ -118,49 +126,70 @@ for(i in sub) {
continue; continue;
} }
var part=0;
for(o in parts_list) {
obj=parts_list[o];
if(obj.codec=="uue"
&& (part=compare_subject(hdr.subject,obj.subject))!=0) {
fname=obj.name.toString();
file.uue=true;
}
}
var begin,end; var begin,end;
var first_line=0;
lines=body.split("\r\n"); lines=body.split("\r\n");
for(li=0;li<lines.length;li++) { for(li=0;li<lines.length;li++) {
if(lines_per_yield && li && (li%lines_per_yield)==0)
yield();
line=lines[li]; line=lines[li];
// line=truncstr(lines[li],"\r\n");
if(file.uue && line=="end") { if(file.uue && line=="end") {
if(!part) if(!part)
if(!complete_file(file,fname,attachment_dir)) if(!complete_file(file,fname,attachment_dir))
console.pause(); console.pause();
li--;
break; break;
} }
if(file.yenc && line.substr(0,6)=="=yend " if(file.yenc && line.substr(0,6)=="=yend "
&& (part_size=line.indexOf(" size="))>0) { && (part_size=line.indexOf(" size="))>0) {
printf("yEnc trailer: %s\r\n",line);
file.flush(); file.flush();
if(part) { if(part) {
if((end_part=line.indexOf(" part="))<0) { if((end_part=line.indexOf(" part="))<0) {
printf("!yEnd part number (%ld) missing in trailer: %s\r\n",part,line); printf("!yEnd part number (%ld) missing in trailer: %s\r\n"
,part,line);
continue; continue;
} }
end_part=parseInt(line.slice(end_part+6),10); end_part=parseInt(line.slice(end_part+6),10);
if(end_part!=part) { if(end_part!=part) {
printf("!yEnd part number mismatch, %ld in header, trailer: %s\r\n",part,line); printf("!yEnd part number mismatch, %ld in header, trailer: %s\r\n"
,part,line);
continue; continue;
} }
} }
part_size=parseInt(line.slice(part_size+6),10); part_size=parseInt(line.slice(part_size+6),10);
if(part_size!=end-(begin-1)) { if(part_size!=end-(begin-1)) {
printf("!yEnc part size mismatch, %ld in header, trailer: %s\r\n",end-(begin-1),line); printf("!yEnc part size mismatch, %ld in header, trailer: %s\r\n"
,end-(begin-1),line);
printf("begin=%ld end=%ld\r\n",begin,end); printf("begin=%ld end=%ld\r\n",begin,end);
continue; continue;
} }
if(part_size!=file.length) { if(part_size!=file.length) {
printf("!yEnc part size mismatch, actual: %ld, trailer: %s\r\n",file.length,line); printf("!yEnc part size mismatch, actual: %ld, trailer: %s\r\n"
,file.length,line);
continue; continue;
} }
if(!part && size!=part_size) { if(!part && size!=part_size) {
printf("!yEnc single part size mismatch: %ld in header, trailer: %s\r\n",size,line); printf("!yEnc single part size mismatch: %ld in header, trailer: %s\r\n"
,size,line);
continue; continue;
} }
...@@ -173,7 +202,8 @@ for(i in sub) { ...@@ -173,7 +202,8 @@ for(i in sub) {
file_crc32=file.crc32; file_crc32=file.crc32;
if(crc32!=undefined && crc32!=file_crc32) { if(crc32!=undefined && crc32!=file_crc32) {
printf("!yEnc part CRC-32 mismatch, actual: %08lX, trailer: %s\r\n",file_crc32,line); printf("!yEnc part CRC-32 mismatch, actual: %08lX, trailer: %s\r\n"
,file_crc32,line);
continue; continue;
} }
part_crc32=crc32; part_crc32=crc32;
...@@ -200,13 +230,15 @@ for(i in sub) { ...@@ -200,13 +230,15 @@ for(i in sub) {
file.length=0; /* truncate temp file */ file.length=0; /* truncate temp file */
file.yenc=false; file.yenc=false;
/* add to parts database */ /* add to parts database */
if(!add_part(parts_list,sub[i].code,hdr,fname,part,total,begin,end,part_crc32,size,crc32)) if(!add_part(parts_list,msgbase.cfg.code,hdr
,fname,"yenc" /* codec */
,part,total,first_line,li-1 /* last_line */
,begin,end,part_crc32,size,crc32))
console.pause(); console.pause();
continue; continue;
} }
if(!complete_file(file,fname,attachment_dir)) complete_file(file,fname,attachment_dir);
console.pause();
break; break;
} }
...@@ -223,6 +255,7 @@ for(i in sub) { ...@@ -223,6 +255,7 @@ for(i in sub) {
arg.splice(0,2); // strip "begin 666 " arg.splice(0,2); // strip "begin 666 "
fname=file_getname(arg.join(" ")); fname=file_getname(arg.join(" "));
file.uue=true; file.uue=true;
first_line=li+1;
continue; continue;
} }
...@@ -263,25 +296,30 @@ for(i in sub) { ...@@ -263,25 +296,30 @@ for(i in sub) {
end=size; end=size;
} }
file.yenc=true; file.yenc=true;
first_line=li+1;
continue; continue;
} }
} /* for(li in lines) */ } /* for(li in lines) */
if(file.is_open) { if(file.is_open && file.uue) {
file.close(); /* adds to parts database */
if(file.uue) { if(!add_part(parts_list,msgbase.cfg.code,hdr
/* adds to parts database */ ,fname,"uue" /* codec */
} ,part,undefined
file.remove(); ,first_line,li-1 /* last_line */
))
console.pause();
} }
file.remove();
delete file; delete file;
yield(); yield();
} /* for(ptr<=msg.last_msg) */ } /* for(ptr<=msg.last_msg) */
/* Save the scan pointer */ /* Save the scan pointer */
print("Saving scan pointer");
if(ptr_file.open("w")) if(ptr_file.open("w"))
ptr_file.writeln(ptr); ptr_file.writeln(ptr);
...@@ -289,6 +327,7 @@ for(i in sub) { ...@@ -289,6 +327,7 @@ for(i in sub) {
delete msgbase; delete msgbase;
/* Save Attachment MD5 history */ /* Save Attachment MD5 history */
print("Saving MD5 history");
if(md5_list.length) { if(md5_list.length) {
if(md5_file.open("w")) { if(md5_file.open("w")) {
md5_file.writeAll(md5_list); md5_file.writeAll(md5_list);
...@@ -297,6 +336,7 @@ for(i in sub) { ...@@ -297,6 +336,7 @@ for(i in sub) {
} }
/* Save Attachment CRC-32 history */ /* Save Attachment CRC-32 history */
print("Saving CRC-32 History");
if(crc_list.length) { if(crc_list.length) {
if(crc_file.open("w")) { if(crc_file.open("w")) {
crc_file.writeAll(crc_list); crc_file.writeAll(crc_list);
...@@ -305,15 +345,20 @@ for(i in sub) { ...@@ -305,15 +345,20 @@ for(i in sub) {
} }
/* Combine and decode parts */ /* Combine and decode parts */
print("Combining partial files");
combine_parts(parts_list); combine_parts(parts_list);
/* Save the Partial file/parts Database */ /* Save the Partial file/parts Database */
print("Saving partial file database");
parts_file.open("w"); parts_file.open("w");
for(o in parts_list) { for(o in parts_list) {
obj=parts_list[o]; obj=parts_list[o];
if(obj==undefined)
continue;
parts_file.writeln("[" + obj.name + "]"); parts_file.writeln("[" + obj.name + "]");
for(prop in obj) for(prop in obj)
parts_file.printf("%-15s=%s\r\n",prop,obj[prop]); parts_file.printf("%-20s=%s\r\n"
,prop.toString(), obj[prop].toString());
parts_file.writeln("; end of file: " + obj.name ); parts_file.writeln("; end of file: " + obj.name );
parts_file.writeln(); parts_file.writeln();
} }
...@@ -322,12 +367,59 @@ for(i in sub) { ...@@ -322,12 +367,59 @@ for(i in sub) {
} /* for(i in subs) */ } /* for(i in subs) */
printf("Synchronet Binary Decoder %s session complete (%lu files completed)\r\n"
,REVISION, completed_files);
exit(); /* all done */ exit(); /* all done */
/****************************************************************************/
/* Compares two message subjects (subj1==new msg, subj2=file in database */
/* returning 0 if they differ in anything but decimal digits (or identical) */
/* returning the parsed part number otherwise */
/****************************************************************************/
function compare_subject(subj1, subj2)
{
/* first compare lengths */
length=subj1.length;
if(!length)
return(0);
if(length!=subj2.length) /* must be same length */
return(0);
if(subj1==subj2) /* but not duplicate part */
return(0);
diff="";
for(i=0;i<length;i++) {
if(subj1.charAt(i)!=subj2.charAt(i))
diff+=(subj1.charAt(i)+subj2.charAt(i));
}
ascii_0=ascii('0');
ascii_9=ascii('9');
length=diff.length;
for(i=0;i<length;i++) {
ch=ascii(diff.charAt(i));
if(ch<ascii_0 || ch>ascii_9)
break;
}
if(i<length) /* differ in non-digit char */
return(0);
/* parse part number */
part=subj1.lastIndexOf('(');
if(part>=0)
part=parseInt(subj1.slice(part+1),10);
if(part>0)
return(part);
return(0);
}
/***********************************************************************************/ /***********************************************************************************/
/* Adds a part of a binary file to the parts database for later combine and decode */ /* Adds a part of a binary file to the parts database for later combine and decode */
/***********************************************************************************/ /***********************************************************************************/
function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32) function add_part(list,sub_code,hdr
,fname,codec,part,total
,first_line,last_line
,begin,end,pcrc32,size,crc32)
{ {
if(part<1) { /* must parse from subject (yuck) */ if(part<1) { /* must parse from subject (yuck) */
part=hdr.subject.lastIndexOf('('); part=hdr.subject.lastIndexOf('(');
...@@ -339,7 +431,7 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32 ...@@ -339,7 +431,7 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32
} }
printf("Parsed part number: %u\r\n",part); printf("Parsed part number: %u\r\n",part);
} }
if(total<part) { /* must parse from subject (yuck) */ if(total==undefined || total<part) { /* must parse from subject (yuck) */
total=hdr.subject.lastIndexOf('('); total=hdr.subject.lastIndexOf('(');
if(total>=0) { if(total>=0) {
subject=hdr.subject.slice(total+1); subject=hdr.subject.slice(total+1);
...@@ -357,46 +449,66 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32 ...@@ -357,46 +449,66 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32
/* Search database for existing file object */ /* Search database for existing file object */
var li; var li;
for(li=0; li<list.length; li++) for(li=0; li<list.length; li++)
if(list[li].name==fname && list[li].total==total if(list[li].name==fname && list[li].total==total && list[li].codec==codec
&& (size==undefined || list[li].size==size) && (size==undefined || list[li].size==size)
&& (crc32==undefined || parseInt(list[li].crc32,16)==crc32) && (crc32==undefined || parseInt(list[li].crc32,16)==crc32)
) { ) {
printf("%s found in database\r\n",fname); printf("%s found in database\r\n",fname.toString());
break; break;
} }
obj=list[li]; obj=list[li];
var time_str = system.timestr();
var time_hex = format("%lx",time());
if(obj==undefined) { /* new entry */ if(obj==undefined) { /* new entry */
printf("New parts database entry for: %s\r\n",fname); printf("New parts database entry for: %s\r\n",fname.toString());
printf("total=%u, size=%u, crc32=%lx\r\n",total,size,crc32); printf("total=%u, size=%u, crc32=%lx\r\n",total,size,crc32);
obj = { name: fname, total: total, parts: 0}; obj = { name: fname, codec: codec, parts: 0, total: total };
obj.subject=hdr.subject; /* save first subject for additional UUE parts */
obj.from=hdr.from;
/* yEnc file fields */ /* yEnc file fields */
if(size!=undefined) if(size!=undefined)
obj.size=size; obj.size=size;
if(crc32!=undefined) if(crc32!=undefined)
obj.crc32=format("%lx",crc32); obj.crc32=format("%lx",crc32);
/* Timestamp */
obj.created=time_str;
obj.created_time=time_hex
} }
/* Timestamp */
obj.updated=time_str;
obj.updated_time=time_hex;
/* part message info */ /* part message info */
prop=format("part%u.id",part); prop=format("part%u.id",part);
if(obj[prop]!=undefined) { if(obj[prop]!=undefined) {
printf("Part %u of %s already in database\r\n",part,fname); printf("Part %u of %s already in database\r\n",part,fname.toString());
return(false); return(true); // pretend we added it
} }
printf("Adding part %u/%u of %s to database\r\n",part,total,fname); printf("Adding part %u of %s-encoded file to database:\r\n",part,codec.toUpperCase());
printf("File: %s\r\n",fname);
obj[format("part%u.id",part)]=hdr.id; obj[format("part%u.id",part)]=hdr.id;
obj[format("part%u.sub",part)]=sub_code; obj[format("part%u.sub",part)]=sub_code;
obj[format("part%u.msg",part)]=hdr.number; obj[format("part%u.msg",part)]=hdr.number;
obj[format("part%u.from",part)]=hdr.from;
obj[format("part%u.subj",part)]=hdr.subject;
obj[format("part%u.date",part)]=hdr.date; obj[format("part%u.date",part)]=hdr.date;
obj[format("part%u.added",part)]=system.timestr(); obj[format("part%u.added",part)]=time_str;
obj[format("part%u.added_time",part)]=time_hex;
// obj[format("part%u.from",part)]=hdr.from;
// obj[format("part%u.subject",part)]=hdr.subject;
/* These save us the hassle of parsing again later */
obj[format("part%u.first_line",part)]=first_line;
obj[format("part%u.last_line",part)]=last_line;
/* yEnc part fields */ /* yEnc part fields */
if(begin!=undefined) if(begin!=undefined)
...@@ -405,12 +517,13 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32 ...@@ -405,12 +517,13 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32
obj[format("part%u.end",part)]=end; obj[format("part%u.end",part)]=end;
if(pcrc32!=undefined) if(pcrc32!=undefined)
obj[format("part%u.crc32",part)]=format("%lx",pcrc32); obj[format("part%u.crc32",part)]=format("%lx",pcrc32);
obj.parts++; obj.parts++;
list[li]=obj; list[li]=obj;
printf("Part %u/%u added (%u parts in database)\r\n",part,total,obj.parts); printf("Part %u added (%u/%u parts in database)\r\n"
,part,obj.parts,obj.total);
return(true); return(true);
} }
...@@ -418,13 +531,78 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32 ...@@ -418,13 +531,78 @@ function add_part(list,sub_code,hdr,fname,part,total,begin,end,pcrc32,size,crc32
/****************************************************************************/ /****************************************************************************/
/* Combine parts for complete files */ /* Combine parts for complete files */
/****************************************************************************/ /****************************************************************************/
function combine_parts(list) function combine_parts(list,attachment_dir)
{ {
var li;
for(li=0; li<list.length; li++) { for(li=0; li<list.length; li++) {
if(list[li].parts!=list[li].total) if(list[li].parts!=list[li].total)
continue; continue;
printf("File complete: %s (%s parts)\r\n" var obj=list[li];
,list[li].name,list[li].parts.toString()); var sub_code;
printf("File complete: %s (%u parts)\r\n", obj.name, obj.parts);
file = new File(system.temp_dir + "binary.tmp");
if(!file.open("w+b")) {
printf("!ERROR %d opening/creating %s\r\n", file.error, file.name);
continue;
}
file[obj.codec]=true; /* yenc or uue */
var pi;
for(pi=1;pi<=obj.total;pi++) {
printf("Processing part %u of %u\r\n",pi,obj.total);
var prefix=format("part%u.",pi);
sub_code=obj[prefix + "sub"];
msgbase=new MsgBase(sub_code);
if(msgbase.open()==false) {
printf("!ERROR %s opening msgbase: %s\r\n",msgbase.last_error,sub_code);
delete msgbase;
break;
}
ptr=obj[prefix + "msg"];
body = msgbase.get_msg_body(
false /* retrieve by offset */
,ptr /* message number */
,false /* remove ctrl-a codes */
,false /* rfc822 formatted text */
,false /* include tails */
);
if(body == null) {
printf("!FAILED to read message number %ld\r\n",ptr);
break;
}
lines=body.split("\r\n");
first_line=obj[prefix + "first_line"];
last_line=obj[prefix + "last_line"];
for(var l=first_line;l<=last_line;l++)
file.write(lines[l]);
}
if(pi<=obj.total) {
file.remove();
printf("!Combine failure, removing part %u\r\n",pi);
list[li][format("part%u.id",pi)]=undefined;
continue;
}
/* Verify final CRC-32, if available */
if(obj.crc32!=undefined) {
file_crc32=format("%lx",file.crc32);
if(obj.crc32!=file_crc32) {
file.remove();
printf(!"CRC-32 failure, actual: %s, expected: %s\r\n"
,file_crc32, obj.crc32);
continue;
}
}
complete_file(file
,obj.name.toString()
,msg_area.sub[sub_code].attachment_dir);
list[li]=undefined; // Remove file entry from database
} }
} }
...@@ -477,6 +655,6 @@ function complete_file(file, fname, attachment_dir) ...@@ -477,6 +655,6 @@ function complete_file(file, fname, attachment_dir)
} }
printf("Attachment saved as: %s\r\n",fname); printf("Attachment saved as: %s\r\n",fname);
completed_files++;
return(true); return(true);
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment