private void StartDecode() { var file = _list.GetRange(0, 1).First(); //Get the nzbImport at the index found above _list.RemoveAt(0); file.Status = NzbFileStatus.Decoding; FileStream output = null; StreamReader input = null; string line; string decoder = ""; string sdecoder = ""; string outputfile = ""; long outputsize = -1; bool crcfailed = false; Crc32Helper crc = new Crc32Helper(); int decodedsegments = 0; foreach (NzbSegmentModel segment in file.Segments) { if (segment.Storage == null) //Make sure Storage isn't null... Null Exception Avoidance { continue; } // Check if the storage is 0 (It will be empty then) if (segment.Storage.Length == 0) { continue; } input = new StreamReader(segment.Storage, Encoding.GetEncoding("iso-8859-1")); // If uudecode is used, each file is automaticly a new segment if (decoder == "uudecode" || (decoder == "mime" && sdecoder == "base64")) { decodedsegments++; } line = input.ReadLine(); while (line != null) { if (decoder == "mime") { if (line.StartsWith("Content-Transfer-Encoding:")) { sdecoder = line.Remove(0, 27); } if (line.StartsWith("--=") || line.StartsWith("Content-Type:")) { decoder = ""; sdecoder = ""; outputfile = ""; output.Close(); output = null; } // Perhaps get filename out of this, but its also in the content type if (line.StartsWith("Content-Disposition:")) { line = ""; } if (sdecoder == "base64") { if (line.Length % 4 > 0) { line = ""; } if (line != "") { byte[] buffer; buffer = Convert.FromBase64String(line); output.Write(buffer, 0, buffer.Length); } } } if (decoder == "uudecode") { if (line != "" && line != "end") { char[] buffer = line.ToCharArray(); if (uudecode_checkline(buffer)) { int p = 0; int n = 0; byte ch; n = uudecode_dec(buffer[p]); for (++p; n > 0; p += 4, n -= 3) { if (n >= 3) { // Error ? if (!(uudecode_is_dec(buffer[p]) && uudecode_is_dec(buffer[p + 1]) && uudecode_is_dec(buffer[p + 2]) && uudecode_is_dec(buffer[p + 3]))) { throw new Exception("33"); } ch = (byte)(uudecode_dec(buffer[p + 0]) << 2 | uudecode_dec(buffer[p + 1]) >> 4); output.WriteByte(ch); ch = (byte)(uudecode_dec(buffer[p + 1]) << 4 | uudecode_dec(buffer[p + 2]) >> 2); output.WriteByte(ch); ch = (byte)(uudecode_dec(buffer[p + 2]) << 6 | uudecode_dec(buffer[p + 3])); output.WriteByte(ch); } else { if (n >= 1) { if (!(uudecode_is_dec(buffer[p]) && uudecode_is_dec(buffer[p + 1]))) { throw new Exception("34"); } ch = (byte)(uudecode_dec(buffer[p + 0]) << 2 | uudecode_dec(buffer[p + 1]) >> 4); output.WriteByte(ch); } if (n >= 2) { if (!(uudecode_is_dec(buffer[p + 1]) && uudecode_is_dec(buffer[p + 2]))) { throw new Exception("35"); } ch = (byte)(uudecode_dec(buffer[p + 1]) << 4 | uudecode_dec(buffer[p + 2]) >> 2); output.WriteByte(ch); } if (n >= 3) { if (!(uudecode_is_dec(buffer[p + 2]) && uudecode_is_dec(buffer[p + 3]))) { throw new Exception("36"); } ch = (byte)(uudecode_dec(buffer[p + 2]) << 6 | uudecode_dec(buffer[p + 3])); output.WriteByte(ch); } } } } } if (line == "end") { decoder = ""; outputfile = ""; output.Close(); output = null; } } if (decoder == "yenc") { if (line.StartsWith("=ypart ")) { // Part description string[] ypart = line.Split(" ".ToCharArray()); foreach (string s in ypart) { if (s.StartsWith("begin")) { output.Seek(long.Parse(s.Remove(0, 6)) - 1, SeekOrigin.Begin); } } } else { if (line.StartsWith("=yend ")) { // End of the Yenc part, do CRC check decoder = ""; string[] yend = line.Split(" ".ToCharArray()); foreach (string s in yend) { if (s.StartsWith("pcrc32")) { long opcrc = Convert.ToInt64(s.Remove(0, 7), 16); long cpcrc = crc.EndByteCRC(); if (opcrc != cpcrc) { crcfailed = true; } } } decodedsegments++; if (outputsize == output.Length) { outputsize = -1; } if (outputsize == -1) { output.Close(); output = null; outputfile = ""; } } else { // Yenc Encoded part bool escape = false; if (line.StartsWith("..")) { line = line.Remove(0, 1); } foreach (char c in line.ToCharArray()) { if (c == '=' && !escape) { escape = true; } else { byte nc = (byte)c; if (escape) { nc = (byte)(nc - 64); escape = false; } nc = (byte)(nc - 42); output.WriteByte(nc); crc.AddByteCRC(nc); } } } } } if (decoder == "") { if (line.StartsWith("=ybegin ")) { decoder = "yenc"; crc.StartByteCRC(); // Check if its a valid ybegin line, as per 1.2 line, size and name have to be present if (line.IndexOf("line=") != -1 && line.IndexOf("size=") != -1 && line.IndexOf("name=") != -1) { int b, e; b = line.IndexOf("size="); e = line.IndexOf(" ", b); outputsize = long.Parse(line.Substring(b + 5, e - b - 5)); b = line.IndexOf("name="); if (outputfile != line.Substring(b + 5)) { outputfile = line.Substring(b + 5); if (file.Filename == "") { file.Filename = outputfile; } //why add second filename? //article.Filename = article.Filename + outputfile; //string path = GetDirectory(article); try { if (!_disk.FolderExists(Path.GetFullPath(file.Path))) { _disk.CreateDirectory(Path.GetFullPath(file.Path)); } } catch (Exception ex) { Logger.ErrorException("Unable to create directory [" + file.Path + "]", ex); } if (output != null) { output.Close(); output = null; } output = new FileStream(Path.GetFullPath(file.Path) + "\\" + outputfile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 1024 * 1024); } } } if (line.StartsWith("begin 644 ")) { decodedsegments++; decoder = "uudecode"; outputfile = line.Remove(0, 10); if (file.Filename == "") { file.Filename = outputfile; } //why add second file name? //article.Filename = article.Filename + outputfile; //string path = GetDirectory(article); try { if (!_disk.FolderExists(Path.GetFullPath(file.Path))) { _disk.CreateDirectory(Path.GetFullPath(file.Path)); } } catch (Exception ex) { throw (ex); } if (output != null) { output.Close(); output = null; } output = new FileStream(Path.GetFullPath(file.Path) + "\\" + outputfile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 1024 * 1024); } if (line.StartsWith("Content-Type: application/octet-stream;")) { decodedsegments++; decoder = "mime"; sdecoder = ""; outputfile = line.Substring(line.IndexOf("name=") + 5); if (outputfile[0] == '\"' && outputfile[outputfile.Length - 1] == '\"') { outputfile = outputfile.Substring(1, outputfile.Length - 2); } if (outputfile[0] == '\'' && outputfile[outputfile.Length - 1] == '\'') { outputfile = outputfile.Substring(1, outputfile.Length - 2); } if (file.Filename == "") { file.Filename = outputfile; } //why add second file name? //article.Filename = article.Filename + outputfile; //string path = GetDirectory(article); try { if (!_disk.FolderExists(Path.GetFullPath(file.Path))) { _disk.CreateDirectory(Path.GetFullPath(file.Path)); } } catch (Exception ex) { //frmMain.LogWriteError("Unable to create directory [" + path + "]"); throw (ex); } if (output != null) { output.Close(); output = null; } output = new FileStream(Path.GetFullPath(file.Path) + "\\" + outputfile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None, 1024 * 1024); } } line = input.ReadLine(); } input.Close(); input = null; if (output != null) { output.Flush(); } segment.Status = NzbSegmentStatus.Decoded; segment.Storage.Close(); segment.Storage = null; //Clear out the MemoryStream so we get our RAM back } if (output != null) { output.Close(); output = null; } if (crcfailed || decodedsegments == 0) { file.Status = NzbFileStatus.DecodeFailed; return; } file.Status = NzbFileStatus.Decoded; //File Decoded Properly return; }