Files
duplicati/Duplicati/Library/Main/VerificationFile.cs
T
2011-05-09 19:52:28 +00:00

147 lines
7.5 KiB
C#

#region Disclaimer / License
// Copyright (C) 2011, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace Duplicati.Library.Main
{
/// <summary>
/// A class that contains all logic for generating the verification files
/// </summary>
public class VerificationFile
{
private System.Xml.XmlDocument m_doc;
private System.Xml.XmlNode m_node;
private System.Xml.XmlNode m_manifestEntry;
internal VerificationFile(IEnumerable<ManifestEntry> parentChain, FilenameStrategy str)
{
m_doc = new System.Xml.XmlDocument();
System.Xml.XmlNode root = m_doc.AppendChild(m_doc.CreateElement("Verify"));
root.Attributes.Append(m_doc.CreateAttribute("hash-algorithm")).Value = Utility.Utility.HashAlgorithm;
root.Attributes.Append(m_doc.CreateAttribute("version")).Value = "1";
m_node = root.AppendChild(m_doc.CreateElement("Files"));
foreach (ManifestEntry mfe in parentChain)
{
System.Xml.XmlNode f = m_node.AppendChild(m_doc.CreateElement("File"));
f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "manifest";
f.Attributes.Append(m_doc.CreateAttribute("name")).Value = mfe.Filename;
f.Attributes.Append(m_doc.CreateAttribute("size")).Value = mfe.Filesize.ToString();
f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(mfe.RemoteHash));
for (int i = 0; i < mfe.ParsedManifest.SignatureHashes.Count; i++)
{
string sigfilename = mfe.ParsedManifest.SignatureHashes[i].Name;
string contentfilename = mfe.ParsedManifest.ContentHashes[i].Name;
bool missing = i >= mfe.Volumes.Count;
if (string.IsNullOrEmpty(sigfilename) || string.IsNullOrEmpty(contentfilename))
{
if (missing)
{
sigfilename = str.GenerateFilename(new SignatureEntry(mfe.Time, mfe.IsFull, i + 1));
contentfilename = str.GenerateFilename(new ContentEntry(mfe.Time, mfe.IsFull, i + 1));
//Since these files are missing, we have to guess what their real names were
string compressionGuess;
if (mfe.Volumes.Count <= 0)
compressionGuess = ".zip"; //Default if we have no knowledge
else
compressionGuess = "." + mfe.Volumes[0].Key.Compression; //Most likely the same as all the others
//Encryption will likely be the same as the one the manifest uses
string encryptionGuess = string.IsNullOrEmpty(mfe.EncryptionMode) ? "" : "." + mfe.EncryptionMode;
sigfilename += compressionGuess + encryptionGuess;
contentfilename += compressionGuess + encryptionGuess;
}
else
{
sigfilename = mfe.Volumes[i].Key.Filename;
contentfilename = mfe.Volumes[i].Value.Filename;
}
}
f = m_node.AppendChild(m_doc.CreateElement("File"));
f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "signature";
f.Attributes.Append(m_doc.CreateAttribute("name")).Value = sigfilename;
f.Attributes.Append(m_doc.CreateAttribute("size")).Value = mfe.ParsedManifest.SignatureHashes[i].Size.ToString();
if (missing) f.Attributes.Append(m_doc.CreateAttribute("missing")).Value = "true";
f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(mfe.ParsedManifest.SignatureHashes[i].Hash));
f = m_node.AppendChild(m_doc.CreateElement("File"));
f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "content";
f.Attributes.Append(m_doc.CreateAttribute("name")).Value = contentfilename;
f.Attributes.Append(m_doc.CreateAttribute("size")).Value = mfe.ParsedManifest.ContentHashes[i].Size.ToString();
if (missing) f.Attributes.Append(m_doc.CreateAttribute("missing")).Value = "true";
f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(mfe.ParsedManifest.ContentHashes[i].Hash));
}
}
}
public void UpdateManifest(ManifestEntry manifest)
{
if (m_manifestEntry == null)
{
m_manifestEntry = m_node.AppendChild(m_doc.CreateElement("File"));
m_manifestEntry.Attributes.Append(m_doc.CreateAttribute("type")).Value = "manifest";
m_manifestEntry.Attributes.Append(m_doc.CreateAttribute("name")).Value = manifest.Filename;
m_manifestEntry.Attributes.Append(m_doc.CreateAttribute("size")).Value = manifest.Filesize.ToString();
}
else
{
m_manifestEntry.Attributes["type"].Value = "manifest";
m_manifestEntry.Attributes["name"].Value = manifest.Filename;
m_manifestEntry.Attributes["size"].Value = manifest.Filesize.ToString();
}
m_manifestEntry.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(manifest.RemoteHash));
}
public void AddFile(BackupEntryBase file)
{
System.Xml.XmlNode f = m_node.AppendChild(m_doc.CreateElement("File"));
if (file is ManifestEntry)
f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "manifest";
else if (file is SignatureEntry)
f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "signature";
else if (file is ContentEntry)
f.Attributes.Append(m_doc.CreateAttribute("type")).Value = "content";
f.Attributes.Append(m_doc.CreateAttribute("name")).Value = file.Filename;
f.Attributes.Append(m_doc.CreateAttribute("size")).Value = file.Filesize.ToString();
f.InnerText = Utility.Utility.ByteArrayAsHexString(Convert.FromBase64String(file.RemoteHash));
}
public void Save(System.IO.Stream stream)
{
m_doc.Save(stream);
}
public void Save(string filename)
{
m_doc.Save(filename);
}
}
}