// 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;
}
}
}