2
* This file is part of nzbget
4
* Copyright (C) 2004 Sven Henkel <sidddy@users.sourceforge.net>
5
* Copyright (C) 2007 Andrei Prygounkov <hugbug@users.sourceforge.net>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
* $Date: 2009-01-26 23:14:50 +0100 (Mo, 26 Jan 2009) $
47
const char* Decoder::FormatNames[] = { "Unknown", "yEnc", "UU" };
48
unsigned int YDecoder::crc_tab[256];
52
debug("Creating Decoder");
54
m_szSrcFilename = NULL;
55
m_szDestFilename = NULL;
56
m_szArticleFilename = NULL;
61
debug("Destroying Decoder");
63
if (m_szArticleFilename)
65
free(m_szArticleFilename);
71
if (m_szArticleFilename)
73
free(m_szArticleFilename);
75
m_szArticleFilename = NULL;
78
Decoder::EFormat Decoder::DetectFormat(const char* buffer, int len)
80
if (!strncmp(buffer, "=ybegin ", 8))
85
if ((len == 62 || len == 63) && (buffer[62] == '\n' || buffer[62] == '\r') && *buffer == 'M')
90
if (!strncmp(buffer, "begin ", 6))
93
buffer += 6; //strlen("begin ")
94
while (*buffer && *buffer != ' ')
97
if (ch < '0' || ch > '7')
113
* YDecoder: fast implementation of yEnc-Decoder
116
void YDecoder::Init()
118
debug("Initializing global decoder");
122
void YDecoder::Final()
124
debug("Finalizing global Decoder");
132
void YDecoder::Clear()
142
m_lCalculatedCRC = 0xFFFFFFFF;
148
m_bNeedSetPos = false;
152
/* from crc32.c (http://www.koders.com/c/fid699AFE0A656F0022C9D6B9D1743E697B69CE5815.aspx)
154
* (c) 1999,2000 Krzysztof Dabrowski
155
* (c) 1999,2000 ElysiuM deeZine
156
* Released under GPL (thanks)
158
* chksum_crc32gentab() -- to a global crc_tab[256], this one will
159
* calculate the crcTable for crc32-checksums.
160
* it is generated to the polynom [..]
162
void YDecoder::crc32gentab()
164
unsigned long crc, poly;
168
for (i = 0; i < 256; i++)
171
for (j = 8; j > 0; j--)
175
crc = (crc >> 1) ^ poly;
186
/* This is modified version of chksum_crc() from
187
* crc32.c (http://www.koders.com/c/fid699AFE0A656F0022C9D6B9D1743E697B69CE5815.aspx)
188
* (c) 1999,2000 Krzysztof Dabrowski
189
* (c) 1999,2000 ElysiuM deeZine
191
* chksum_crc() -- to a given block, this one calculates the
192
* crc32-checksum until the length is
193
* reached. the crc32-checksum will be
196
unsigned long YDecoder::crc32m(unsigned long startCrc, unsigned char *block, unsigned int length)
198
register unsigned long crc = startCrc;
199
for (unsigned long i = 0; i < length; i++)
201
crc = ((crc >> 8) & 0x00FFFFFF) ^ crc_tab[(crc ^ *block++) & 0xFF];
206
unsigned int YDecoder::DecodeBuffer(char* buffer)
208
if (m_bBody && !m_bEnd)
210
if (!strncmp(buffer, "=yend ", 6))
213
char* pb = strstr(buffer, m_bPart ? " pcrc32=" : " crc32=");
217
pb += 7 + (int)m_bPart; //=strlen(" crc32=") or strlen(" pcrc32=")
218
m_lExpectedCRC = strtoul(pb, NULL, 16);
220
pb = strstr(buffer, " size=");
223
pb += 6; //=strlen(" size=")
224
m_iEndSize = (int)atoi(pb);
235
case '=': //escape-sequence
237
*optr = *iptr - 64 - 42;
240
case '\n': // ignored char
241
case '\r': // ignored char
245
default: // normal char
256
m_lCalculatedCRC = crc32m(m_lCalculatedCRC, (unsigned char *)buffer, (unsigned int)(optr - buffer));
258
return (unsigned int)(optr - buffer);
262
if (!m_bPart && !strncmp(buffer, "=ybegin ", 8))
265
char* pb = strstr(buffer, " name=");
268
pb += 6; //=strlen(" name=")
270
for (pe = pb; *pe != '\0' && *pe != '\n' && *pe != '\r'; pe++) ;
271
if (m_szArticleFilename)
273
free(m_szArticleFilename);
275
m_szArticleFilename = (char*)malloc(pe - pb + 1);
276
strncpy(m_szArticleFilename, pb, pe - pb);
277
m_szArticleFilename[pe - pb] = '\0';
279
pb = strstr(buffer, " size=");
282
pb += 6; //=strlen(" size=")
283
m_iSize = (int)atoi(pb);
285
m_bPart = strstr(buffer, " part=");
293
else if (m_bPart && !strncmp(buffer, "=ypart ", 7))
297
char* pb = strstr(buffer, " begin=");
300
pb += 7; //=strlen(" begin=")
301
m_iBegin = (int)atoi(pb);
303
pb = strstr(buffer, " end=");
306
pb += 5; //=strlen(" end=")
307
m_iEnd = (int)atoi(pb);
315
bool YDecoder::Write(char* buffer, int len, FILE* outfile)
317
unsigned int wcnt = DecodeBuffer(buffer);
322
if (m_iBegin == 0 || m_iEnd == 0xFFFFFFFF || !outfile)
326
if (fseek(outfile, m_iBegin - 1, SEEK_SET))
330
m_bNeedSetPos = false;
332
fwrite(buffer, 1, wcnt, outfile);
337
Decoder::EStatus YDecoder::Check()
339
m_lCalculatedCRC ^= 0xFFFFFFFF;
341
debug("Expected crc32=%x", m_lExpectedCRC);
342
debug("Calculated crc32=%x", m_lCalculatedCRC);
346
return eNoBinaryData;
350
return eArticleIncomplete;
352
else if (!m_bPart && m_iSize != m_iEndSize)
356
else if (m_bCrcCheck && m_bCrc && (m_lExpectedCRC != m_lCalculatedCRC))
366
* UDecoder: supports UU encoding formats
374
void UDecoder::Clear()
382
/* DecodeBuffer-function uses portions of code from tool UUDECODE by Clem Dye
383
* UUDECODE.c (http://www.bastet.com/uue.zip)
384
* Copyright (C) 1998 Clem Dye
386
* Released under GPL (thanks)
389
#define UU_DECODE_CHAR(c) (c == '`' ? 0 : (((c) - ' ') & 077))
391
unsigned int UDecoder::DecodeBuffer(char* buffer, int len)
395
if (!strncmp(buffer, "begin ", 6))
398
pb += 6; //strlen("begin ")
400
// skip file-permissions
401
for (; *pb != ' ' && *pb != '\0' && *pb != '\n' && *pb != '\r'; pb++) ;
404
// extracting filename
406
for (pe = pb; *pe != '\0' && *pe != '\n' && *pe != '\r'; pe++) ;
407
if (m_szArticleFilename)
409
free(m_szArticleFilename);
411
m_szArticleFilename = (char*)malloc(pe - pb + 1);
412
strncpy(m_szArticleFilename, pb, pe - pb);
413
m_szArticleFilename[pe - pb] = '\0';
418
else if ((len == 62 || len == 63) && (buffer[62] == '\n' || buffer[62] == '\r') && *buffer == 'M')
424
if (m_bBody && (!strncmp(buffer, "end ", 4) || *buffer == '`'))
429
if (m_bBody && !m_bEnd)
431
int iEffLen = UU_DECODE_CHAR(buffer[0]);
440
for (++iptr; iEffLen > 0; iptr += 4, iEffLen -= 3)
444
*optr++ = UU_DECODE_CHAR (iptr[0]) << 2 | UU_DECODE_CHAR (iptr[1]) >> 4;
445
*optr++ = UU_DECODE_CHAR (iptr[1]) << 4 | UU_DECODE_CHAR (iptr[2]) >> 2;
446
*optr++ = UU_DECODE_CHAR (iptr[2]) << 6 | UU_DECODE_CHAR (iptr[3]);
452
*optr++ = UU_DECODE_CHAR (iptr[0]) << 2 | UU_DECODE_CHAR (iptr[1]) >> 4;
456
*optr++ = UU_DECODE_CHAR (iptr[1]) << 4 | UU_DECODE_CHAR (iptr[2]) >> 2;
461
return (unsigned int)(optr - buffer);
467
bool UDecoder::Write(char* buffer, int len, FILE* outfile)
469
unsigned int wcnt = DecodeBuffer(buffer, len);
472
fwrite(buffer, 1, wcnt, outfile);
477
Decoder::EStatus UDecoder::Check()
481
return eNoBinaryData;