Files
Work/yproxy/pdecode.cpp
2024-08-07 09:16:27 -04:00

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());
}