582 lines
12 KiB
C++
582 lines
12 KiB
C++
#include <common/windows.hpp>
|
|
#include <common/stdio.hpp>
|
|
#include <common/stdlib.hpp>
|
|
#include <common/finddata.hpp>
|
|
#include <yproxy/pdecode.hpp>
|
|
#include <yproxy/crc.hpp>
|
|
#include <io.h>
|
|
|
|
PureDecoder::PureDecoder()
|
|
: mErrors(0), mErrParts(0), mErrFiles(0), mDisplay(true), myBegin(0), myEnd(0), mAdResCrc(0), mAdResLen(0)
|
|
{
|
|
::memset(mAttName,0,sizeof(mAttName));
|
|
::memset(mAtText,0,sizeof(mAtText));
|
|
}
|
|
|
|
char *PureDecoder::ad_fgetscr(char * buffer, int maxlen, FILE * fp)
|
|
{
|
|
char * cp;
|
|
char * dp;
|
|
|
|
cp=fgets(buffer,maxlen,fp);
|
|
if(cp==NULL)return(NULL);
|
|
dp=strrchr(buffer,'\n'); // Eliminate CRLF
|
|
if (dp) *dp=0;
|
|
dp=strrchr(buffer,'\r');
|
|
if (dp) *dp=0;
|
|
return(cp);
|
|
}
|
|
|
|
unsigned long PureDecoder::hex_to_ulong(char * text)
|
|
{
|
|
unsigned long res;
|
|
unsigned char c;
|
|
|
|
if (text==NULL) return(-1);
|
|
res=0;
|
|
|
|
while(true)
|
|
{
|
|
c=*text; text++;
|
|
if ((c>='0')&(c<='9'))
|
|
{
|
|
res=(res<<4)+((long)(c-48) & 0x0F);
|
|
continue;
|
|
}
|
|
if ((c>='A')&(c<='F'))
|
|
{
|
|
res=(res<<4)+((long)(c-55) & 0x0F);
|
|
continue;
|
|
}
|
|
if ((c>='a')&(c<='f'))
|
|
{
|
|
res=(res<<4)+((long)(c-87) & 0x0F);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
return(res);
|
|
}
|
|
|
|
int PureDecoder::yDecode(FILE * fOut, FILE * fIn, long y_line, long y_size,int y_part)
|
|
{
|
|
unsigned char srcbuf[4100];
|
|
unsigned char desbuf[4100];
|
|
unsigned char * srcp;
|
|
unsigned char * desp;
|
|
int deslen;
|
|
int srclen;
|
|
unsigned char c;
|
|
int id;
|
|
char * cp;
|
|
long decolen;
|
|
unsigned long crc32;
|
|
char name[260];
|
|
int esize;
|
|
unsigned char * partbuf;
|
|
unsigned char * partptr;
|
|
long partsize;
|
|
long partfree;
|
|
long wlen;
|
|
long flen;
|
|
|
|
if(mDisplay)
|
|
{
|
|
display("yDecoder started...\r\n");
|
|
}
|
|
CRC crc;
|
|
|
|
decolen=0;
|
|
deslen=0;
|
|
desp=desbuf;
|
|
|
|
if(y_part) // This is a multipart message !
|
|
{
|
|
cp=ad_fgetscr((char*) srcbuf,4097,fIn); // fgets especially with ad_length
|
|
if (cp==NULL)
|
|
{
|
|
error("Unexpected eof in yEncoded file\r\n");
|
|
mErrors++;
|
|
return(1);
|
|
}
|
|
if(mDisplay)
|
|
{
|
|
String str;
|
|
::sprintf(str,"=ypart-line: %s\r\n",srcbuf);
|
|
display(str);
|
|
}
|
|
if (strncmp((char*) srcbuf,"=ypart ",7))
|
|
{
|
|
error("Missing =ypart line in yEncoded multipart message\r\n");
|
|
mErrors++;
|
|
return(2);
|
|
}
|
|
cp=strstr((char*)srcbuf,"end=");
|
|
if (cp==NULL)
|
|
{
|
|
error("Missing end= in yEncoded multipart message\r\n");
|
|
mErrors++;
|
|
return(2);
|
|
}
|
|
myEnd=atol(cp+4);
|
|
cp=strstr((char*)srcbuf,"begin=");
|
|
if (cp==NULL)
|
|
{
|
|
error("Missing begin= in yEncoded multipart message\r\n");
|
|
mErrors++;
|
|
return(2);
|
|
}
|
|
myBegin=atol(cp+6);
|
|
if(mDisplay)
|
|
{
|
|
String str;
|
|
::sprintf(str,"part-begin: %ld\r\n",myBegin);
|
|
display(str);
|
|
sprintf(str,"part-end : %ld\r\n",myEnd);
|
|
display(str);
|
|
}
|
|
partbuf=(unsigned char*)malloc(myEnd-myBegin+10); // Allocate a buffer for the part
|
|
partptr=partbuf;
|
|
partsize=myEnd-myBegin+1;
|
|
partfree=partsize;
|
|
}
|
|
|
|
loop:
|
|
|
|
cp=ad_fgetscr((char*) srcbuf,4097,fIn); // fgets especially with ad_length
|
|
if(cp==NULL)
|
|
{
|
|
error("Unexpected eof in yEncoded file\r\n");
|
|
mErrors++;
|
|
return(1);
|
|
}
|
|
if (strncmp((char*) srcbuf,"=yend ",6)==0)
|
|
{
|
|
if(mDisplay)
|
|
{
|
|
String str;
|
|
sprintf(str,"Endline (%d bytes): %s\r\n",decolen,srcbuf);
|
|
display(str);
|
|
}
|
|
goto end_of_file;
|
|
}
|
|
if (strncmp((char*) srcbuf,"=ybegin ",8)==0)
|
|
{
|
|
error("Unexpected =ybegin in yEncoded file\r\n");
|
|
mErrors++;
|
|
return(1);
|
|
}
|
|
srclen=strlen((char*)srcbuf);
|
|
if (srclen<y_line)
|
|
{
|
|
if(mDisplay)display("Last line.\r\n");
|
|
}
|
|
srcp=srcbuf;
|
|
|
|
loop2:
|
|
c=*srcp; srcp++;
|
|
if(c==0)
|
|
{
|
|
goto loop; // End of line reached
|
|
}
|
|
if(c=='=') // The escape character comes in
|
|
{
|
|
c=*srcp; srcp++;
|
|
if(c==0)return(2); // Last char cannot be escape char !
|
|
c=(unsigned char)(c-64);
|
|
}
|
|
c=(unsigned char)(c-42); // Subtract the secret number
|
|
*desp=c;
|
|
desp++;
|
|
deslen++;
|
|
decolen++;
|
|
|
|
// crc.crcAdd(c);
|
|
crc.crcAdd(c);
|
|
|
|
if (deslen>=4096)
|
|
{
|
|
if (y_part) // MultiPart --> to the partbuffer !
|
|
{
|
|
if (deslen>partfree)
|
|
{
|
|
error("Partial message corrupt: longer than (end-begin)!\r\n");
|
|
mErrors++;
|
|
return(11);
|
|
}
|
|
memcpy(partptr,desbuf,deslen);
|
|
partptr=partptr+deslen;
|
|
partfree=partfree-deslen;
|
|
}
|
|
else // Single part --> directly to target file
|
|
{
|
|
id=fwrite(desbuf,deslen,1,fOut);
|
|
if (id != 1)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"Error in writing decoded file (code=%d)\r\n",errno);
|
|
error(strError);
|
|
mErrors++;
|
|
return(3);
|
|
}
|
|
}
|
|
deslen=0;
|
|
desp=desbuf;
|
|
}
|
|
goto loop2;
|
|
|
|
end_of_file:
|
|
|
|
if (deslen>0) // Empty the last buffer
|
|
{
|
|
if (y_part)
|
|
{
|
|
if (deslen>partfree)
|
|
{
|
|
error("Partial message corrupt: longer than (end-begin)!\r\n");
|
|
mErrors++;
|
|
return(11);
|
|
}
|
|
memcpy(partptr,desbuf,deslen);
|
|
//partptr=partptr+deslen;
|
|
//partfree=partfree-deslen;
|
|
}
|
|
else // Single part --> directly to target file
|
|
{
|
|
id=fwrite(desbuf,deslen,1,fOut);
|
|
if (id != 1)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"Error in writing decoded file (code=%d)\r\n",errno);
|
|
error(strError);
|
|
mErrors++;
|
|
return(3);
|
|
}
|
|
}
|
|
}
|
|
cp=strstr((char*) srcbuf,"size="); // Compare the decoded size to the =yend size
|
|
if (cp)
|
|
{
|
|
esize=atoi(cp+5);
|
|
if (esize != decolen)
|
|
{
|
|
sprintf(name,"%s(size=%ld)",mAttName,decolen);
|
|
strcpy(mAttName,name);
|
|
String strError;
|
|
::sprintf(strError,"Corrupt yEnc binary - endsize mismatch (%s%s)\r\n",mAttName,mAtText);
|
|
error(strError);
|
|
mErrors++;
|
|
mErrFiles++;
|
|
return(0);
|
|
}
|
|
}
|
|
// Check the srcbuf for the CRC
|
|
if (y_part==0)
|
|
{
|
|
cp=strstr((char*)srcbuf,"crc32=");
|
|
if (cp)
|
|
{
|
|
crc32=hex_to_ulong((char*)(cp+6));
|
|
mAdResCrc=crc.getVal() ^ 0xFFFFFFFFl;
|
|
|
|
if (mDisplay)
|
|
{
|
|
String str;
|
|
sprintf(str,"Included CRC: $%08lx - calculated CRC: $%08lx\r\n",crc32,mAdResCrc);
|
|
display(str);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cp=strstr((char*)srcbuf,"pcrc32=");
|
|
if (cp)
|
|
{
|
|
crc32=hex_to_ulong((char*)(cp+7));
|
|
mAdResCrc=crc.getVal() ^ 0xFFFFFFFFl;
|
|
|
|
if (mDisplay)
|
|
{
|
|
String str;
|
|
sprintf(str,"Included CRC: $%08lx - calculated CRC: $%08lx\r\n",crc32,mAdResCrc);
|
|
display(str);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cp!=NULL)
|
|
{
|
|
if (crc32 != mAdResCrc)
|
|
{
|
|
sprintf(name,"%s(crc=%08lx)",mAttName,mAdResCrc);
|
|
strcpy(mAttName,name);
|
|
String strError;
|
|
::sprintf(strError,"Corrupt yEnc binary - CRC mismatch (%s%s)\r\n",mAttName,mAtText);
|
|
error(strError);
|
|
mErrors++;
|
|
mErrFiles++;
|
|
return(0);
|
|
}
|
|
}
|
|
|
|
if (y_part==0) // Single message
|
|
{
|
|
if ((y_part==0) & (decolen != y_size))
|
|
{
|
|
// eprint("Y-Decoder: Size mismatch - file corrupt.\r\n");
|
|
|
|
sprintf(name,"%s(len=%ld)",mAttName,decolen);
|
|
strcpy(mAttName,name);
|
|
|
|
String strError;
|
|
::sprintf(strError,"Corrupt yEnc binary - size mismatch (%s%s)\r\n",mAttName,mAtText);
|
|
error(strError);
|
|
mErrors++;
|
|
mErrFiles++;
|
|
return(0);
|
|
}
|
|
mAdResLen=decolen;
|
|
mAdResCrc=crc.getVal() ^ 0xFFFFFFFFl;
|
|
if(mDisplay)
|
|
{
|
|
String str;
|
|
sprintf(str,"yDecoder: Job done. %ld bytes written. CRC: $%08lx \r\n",decolen,mAdResCrc);
|
|
display(str);
|
|
}
|
|
return(0);
|
|
}
|
|
if ((y_part>0) & (decolen != (myEnd-myBegin+1)))
|
|
{
|
|
error("yDecoder: Part size mismatch - file corrupt.\r\n");
|
|
mErrors++;
|
|
mErrParts++;
|
|
return(6);
|
|
}
|
|
id=fseek(fOut,myBegin-1,0);
|
|
if(id)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"Cannot write a part (fseek failed) [reason:%d]\r\n",errno);
|
|
error(strError);
|
|
mErrors++;
|
|
return(12);
|
|
}
|
|
flen=decolen;
|
|
partptr=partbuf;
|
|
if (mDisplay)
|
|
{
|
|
String str;
|
|
sprintf(str,"Write part to target file (start: %ld, size: %ld)\r\n",myBegin-1,flen);
|
|
display(str);
|
|
}
|
|
while (flen>0)
|
|
{
|
|
wlen=flen;
|
|
if (wlen>8192) wlen=8192;
|
|
id=fwrite(partptr,wlen,1,fOut);
|
|
if (id != 1)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"Cannot write a part (fwrite failed) [reason:%d]\r\n",errno);
|
|
error(strError);
|
|
mErrors++;
|
|
return(12);
|
|
}
|
|
partptr=partptr+wlen;
|
|
flen=flen-wlen;
|
|
}
|
|
free(partbuf);
|
|
return(0);
|
|
}
|
|
|
|
int PureDecoder::AddPart(char * srcname,long y_begin, long y_end)
|
|
{
|
|
FILE * fSrc;
|
|
FILE * fDes;
|
|
char desname[260];
|
|
char line[1024];
|
|
long a,e;
|
|
int copyrest;
|
|
char * cp;
|
|
int resparts;
|
|
long flen;
|
|
|
|
if (mDisplay)
|
|
{
|
|
String str;
|
|
sprintf("AddPart (%s) [%ld - %ld]\r\n",srcname,y_begin,y_end);
|
|
display(str);
|
|
}
|
|
copyrest=0;
|
|
resparts=0;
|
|
sprintf(desname,"%s.des",srcname);
|
|
fSrc=fopen(srcname,"rb");
|
|
if (fSrc==NULL)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"AddPart: Part Info File not found (%s)\r\n",srcname);
|
|
error(strError);
|
|
mErrors++;
|
|
return(-1);
|
|
}
|
|
flen=filelength(fileno(fSrc));
|
|
if (flen==0) // Already complete
|
|
{
|
|
return(-9);
|
|
}
|
|
fDes=fopen(desname,"wb");
|
|
if(fDes==NULL)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"AddPart: Cannot create temporary part file (%s) [reason: %d]\r\n",desname,errno);
|
|
error(strError);
|
|
fclose(fSrc);
|
|
mErrors++;
|
|
return(-2);
|
|
}
|
|
loop:
|
|
cp=fgets(line,1000,fSrc);
|
|
if (cp==NULL) goto eof1;
|
|
cp=strrchr(line,'\n');
|
|
if (cp) *cp=0;
|
|
cp=strrchr(line,'\r');
|
|
if (cp) *cp=0;
|
|
|
|
// print("%s\r\n",line);
|
|
|
|
if (copyrest) // Analysis done - copy rest & done.
|
|
{
|
|
fprintf(fDes,"%s\r\n",line);
|
|
resparts++;
|
|
goto loop;
|
|
}
|
|
|
|
a=atol(line);
|
|
if (a==0)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"Corrupt part-info file (%s)\r\n",line);
|
|
error(strError);
|
|
mErrors++;
|
|
fclose(fSrc); fclose(fDes); return(-3);
|
|
}
|
|
cp=strchr(line,',');
|
|
if (cp==NULL)
|
|
{
|
|
String strError;
|
|
::sprintf(strError,"Corrupt part-info file (%s)\r\n",line);
|
|
error(strError);
|
|
mErrors++;
|
|
fclose(fSrc); fclose(fDes); return(-4);
|
|
}
|
|
e=atol(cp+1);
|
|
// print("a:%6d, e:%6d\r\n",a,e);
|
|
|
|
// ----- Case Analysis -----
|
|
// .............[yb--------ye] (The new, incoming block)
|
|
// 1...a****e (The old, missing block)
|
|
// 2...a********-----e (***) Newly written missing block
|
|
// 3...a********--------------****e
|
|
// .............[yb--------ye]
|
|
// 4............a-----e
|
|
// 5............a------------e
|
|
// 6............a-------------****e
|
|
// .............[yb--------ye]
|
|
// 7............................a***e
|
|
// .............[yb--------ye]
|
|
// 8................a----e
|
|
// 9................a---------****e
|
|
|
|
|
|
|
|
|
|
if (a<y_begin) // A previous section was missed
|
|
{
|
|
if (e<y_begin) // A previous section was missed entirely
|
|
{
|
|
// Case-1
|
|
fprintf(fDes,"%ld,%ld\r\n",a,e); // --> Keep that entry
|
|
resparts++;
|
|
goto loop;
|
|
}
|
|
if (e<=y_end) // Rduce the old section
|
|
{
|
|
// Case-2
|
|
fprintf(fDes,"%ld,%ld\r\n",a,y_begin-1); // --> Reduce that entry
|
|
resparts++;
|
|
goto loop;
|
|
}
|
|
// The new section is splitting the old missing section
|
|
// Case-3
|
|
fprintf(fDes,"%ld,%ld\r\n",a,y_begin-1); // --> First part
|
|
fprintf(fDes,"%ld,%ld\r\n",y_end+1,e); // --> First part
|
|
resparts++; resparts++;
|
|
goto loop;
|
|
}
|
|
|
|
if (a==y_begin) // New part matches this segment
|
|
{
|
|
if (e<y_end) // Just a smaller section was missed
|
|
{
|
|
// case 4
|
|
goto loop; // Skip this and analyse next
|
|
}
|
|
if (e==y_end) // This missing section was exactly -> remove it & done.
|
|
{
|
|
// case 5
|
|
copyrest=1; goto loop;
|
|
}
|
|
if (e>y_end) // The first part was found
|
|
{
|
|
// case-6
|
|
fprintf(fDes,"%ld,%ld\r\n",y_end+1,e); // Write the rest
|
|
resparts++;
|
|
copyrest=1; goto loop;
|
|
}
|
|
}
|
|
|
|
if (a>y_begin)
|
|
{
|
|
if (a>y_end) // the found section completely in front of this one.
|
|
{
|
|
// Case-7
|
|
fprintf(fDes,"%ld,%ld\r\n",a,e); // Rewrite it & copy the rest
|
|
resparts++;
|
|
copyrest=1; goto loop;
|
|
}
|
|
if (e<=y_end) // The section was completely found
|
|
{
|
|
// Case-8
|
|
goto loop; // Analyse the rest
|
|
}
|
|
// The first part of the missing section was found
|
|
// case-9
|
|
fprintf(fDes,"%ld,%ld\r\n",y_end+1,e); // Reduce it & copy the rest
|
|
resparts++;
|
|
copyrest=1; goto loop;
|
|
}
|
|
|
|
eof1:
|
|
fclose(fSrc); fclose(fDes);
|
|
remove(srcname);
|
|
|
|
rename(desname,srcname);
|
|
|
|
return(resparts);
|
|
}
|
|
|
|
// virtuals
|
|
|
|
void PureDecoder::error(const String &error)
|
|
{
|
|
::OutputDebugString(error.str());
|
|
}
|
|
|
|
void PureDecoder::display(const String &string)
|
|
{
|
|
::OutputDebugString(string.str());
|
|
}
|
|
|
|
|
|
|