// ARCCheck.cs // // Copyright (C) 2008,2009 Bartek Jasicki // // This file is part of Grubng. // // Grubng is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // /** * @file ARCCheck.cs * Provide functions for check propriety of .arc file.*/ using System; using System.Text; namespace grubupload { /// /// Provide function for check propriety of .arc file. /// internal static class ARCCheck { /// /// Function check propriety of .arc file. Check sequence of url's, length of each entry in file and type of each url. /// /// /// A object which contains arc file content /// /// /// A Username from .arc filename /// /// /// A Key from .arc filename /// /// /// A Special secret pharase /// /// /// A Array of string, element 0 - 'valid' or 'invalid' values - status of /// .arc file, element 1 - detailed informations about error in .arc file, element 2 - amount /// of links in .arc file. /// public static string[] CheckFile(System.IO.Stream arcfile, string user, string filekey, string hashpass) { byte[] HashValue, PureHash = Encoding.UTF8.GetBytes(hashpass); StringBuilder key = new StringBuilder(); System.Security.Cryptography.SHA1Managed SHhash = new System.Security.Cryptography.SHA1Managed(); HashValue = SHhash.ComputeHash(PureHash); foreach(byte b in HashValue) { key.Append(String.Format("{0:x2}", b)); } StringBuilder arc = new StringBuilder(); string[] arcfields; int tmp; System.Collections.Generic.List tmp2 = new System.Collections.Generic.List(); string[] parts; string path; string [] result = new string[3] {"valid", String.Empty, String.Empty}; int amount = 0; arcfile.Position = 131; long urllength; bool valid; while (arcfile.Position < arcfile.Length) { while (true) { tmp = arcfile.ReadByte(); if ((tmp > Char.MaxValue) || (tmp < Char.MinValue)) { result[0] = "invalid"; break; } if (tmp == 10) { break; } tmp2.Add(Convert.ToByte(tmp)); } //Check for correct data if (result[0] == "invalid") { result[1] = "Invalid data send. Wrong chars in .arc file."; break; } arc.Append(Encoding.UTF8.GetString(tmp2.ToArray(), 0, tmp2.Count)); tmp2.Clear(); tmp2.TrimExcess(); //Check url header if (arc.Length == 0) { result[0] = "invalid"; result[1] = "Empty record in .arc file. Probably wrong count of chars in .arc file."; break; } arcfields = arc.ToString().Split(' '); if (arcfields.Length != 5) { result[0] = "invalid"; result[1] = "Invalid amount of informations in url header in .arc file."; break; } if (String.IsNullOrEmpty(arcfields[3])) { result[0] = "invalid"; result[1] = "No information about content type in url header in .arc file."; break; } valid = arcfields[0].StartsWith("http://"); if (!valid) { result[0] = "invalid"; result[1] = "Wrong url in .arc file. Probably wrong count of chars in .arc file."; break; } //Check protocol information arc.Remove(0, arc.Length); while (true) { tmp = arcfile.ReadByte(); if (tmp == 10) { break; } tmp2.Add(Convert.ToByte(tmp)); } arc.Append(Encoding.UTF8.GetString(tmp2.ToArray(), 0, tmp2.Count)); parts = arc.ToString().Split(' '); if (parts.Length < 2) { result[0] = "invalid"; result[1] = "Invalid amount of informations about HTTP protocol"; break; } valid = parts[0].StartsWith("HTTP"); if (!valid) { result[0] = "invalid"; result[1] = "Invalid information about HTTP protocol version in .arc file"; break; } //TODO: check for HTTP headers //TODO: check for content length //Move to next record valid = long.TryParse(arcfields[4], out urllength); if (valid) { urllength -= Convert.ToInt64(tmp2.Count); } else { result[0] = "invalid"; result[1] = "Wrong record length in .arc file."; break; } tmp2.Clear(); tmp2.TrimExcess(); arcfile.Position += urllength; arc.Remove(0, arc.Length); parts = arcfields[0].Split('/'); path = "/" + String.Join("/", parts, 3, (parts.Length - 3)); PureHash = Encoding.UTF8.GetBytes(key.ToString() + " " + parts[2] + " " + path); key.Remove(0, key.Length); HashValue = SHhash.ComputeHash(PureHash); foreach(byte b in HashValue) { key.Append(String.Format("{0:x2}", b)); } amount ++; GC.Collect(); GC.WaitForPendingFinalizers(); } if (result[0] == "valid") { PureHash = Encoding.UTF8.GetBytes(key.ToString() + " " + user); key.Remove(0, key.Length); HashValue = SHhash.ComputeHash(PureHash); foreach(byte b in HashValue) { key.Append(String.Format("{0:x2}", b)); } if (key.ToString() != filekey) { result[0] = "invalid"; result[1] = "Invalid .arc file key."; } } SHhash = null; HashValue = null; key = null; result[2] = amount.ToString(); return result; } } }