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