git-svn-id: https://duplicati.googlecode.com/svn/trunk@85 59da171f-624f-0410-aa54-27559c288bec
136 lines
5.7 KiB
C#
136 lines
5.7 KiB
C#
#region Disclaimer / License
|
|
// Copyright (C) 2009, 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;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Duplicati.Library.Main
|
|
{
|
|
/// <summary>
|
|
/// This class is responsible for naming remote files,
|
|
/// and parsing remote filenames
|
|
/// </summary>
|
|
internal class FilenameStrategy
|
|
{
|
|
private bool m_useShortFilenames;
|
|
private string m_timeSeperator;
|
|
private string m_prefix;
|
|
|
|
private Regex m_filenameRegExp;
|
|
private Regex m_shortRegExp;
|
|
|
|
public FilenameStrategy(Dictionary<string, string> options)
|
|
{
|
|
m_useShortFilenames = options.ContainsKey("short-filenames");
|
|
if (options.ContainsKey("time-separator"))
|
|
m_timeSeperator = options["time-separator"];
|
|
else
|
|
m_timeSeperator = ":";
|
|
|
|
if (!options.ContainsKey("backup-prefix"))
|
|
m_prefix = m_useShortFilenames ? "dpl" : "duplicati";
|
|
else
|
|
m_prefix = options["backup-prefix"];
|
|
|
|
m_shortRegExp = new Regex(@"(?<prefix>" + m_prefix + @")\-(?<type>(C|S|M))(?<inc>(F|I))(?<time>([A-F]|[a-f]|[0-9])+)\.(?<extension>.+)");
|
|
m_filenameRegExp = new Regex(@"(?<prefix>" + m_prefix + @")\-(?<inc>(full|inc))\-(?<type>(content|signature|manifest))\.(?<time>\d{4}\-\d{2}\-\d{2}.\d{2}\" + m_timeSeperator + @"\d{2}\" + m_timeSeperator + @"\d{2}(?<timezone>([\+\-]\d{2}" + m_timeSeperator + @"\d{2})|Z)?)\.(?<extension>.+)");
|
|
}
|
|
|
|
public string GenerateFilename(BackupEntry.EntryType type, bool full, DateTime time, int volume)
|
|
{
|
|
return GenerateFilename(type, full, time) + ".vol" + volume.ToString();
|
|
}
|
|
|
|
public string GenerateFilename(BackupEntry.EntryType type, bool full, DateTime time)
|
|
{
|
|
return GenerateFilename(type, full, m_useShortFilenames, time);
|
|
}
|
|
|
|
public string GenerateFilename(BackupEntry.EntryType type, bool full, bool shortName, DateTime time)
|
|
{
|
|
string t;
|
|
if (type == BackupEntry.EntryType.Manifest)
|
|
t = shortName ? "M" : "manifest";
|
|
else if (type == BackupEntry.EntryType.Content)
|
|
t = shortName ? "C" : "content";
|
|
else if (type == BackupEntry.EntryType.Signature)
|
|
t = shortName ? "S" : "signature";
|
|
else
|
|
throw new Exception("Invalid entry type specified");
|
|
|
|
if (!shortName)
|
|
{
|
|
|
|
string datetime = time.ToString("yyyy-MM-ddTHH:mm:ssK").Replace(":", m_timeSeperator);
|
|
return m_prefix + "-" + (full ? "full" : "inc") + "-" + t + "." + datetime;
|
|
}
|
|
else
|
|
{
|
|
return m_prefix + "-" + t + (full ? "F" : "I") + (time.ToUniversalTime().Ticks / TimeSpan.TicksPerSecond).ToString("X");
|
|
}
|
|
}
|
|
|
|
public BackupEntry DecodeFilename(Duplicati.Library.Backend.FileEntry fe)
|
|
{
|
|
Match m = m_filenameRegExp.Match(fe.Name);
|
|
if (!m.Success)
|
|
m = m_shortRegExp.Match(fe.Name);
|
|
if (!m.Success)
|
|
return null;
|
|
|
|
BackupEntry.EntryType type;
|
|
if (m.Groups["type"].Value == "manifest" || m.Groups["type"].Value == "M")
|
|
type = BackupEntry.EntryType.Manifest;
|
|
else if (m.Groups["type"].Value == "content" || m.Groups["type"].Value == "C")
|
|
type = BackupEntry.EntryType.Content;
|
|
else if (m.Groups["type"].Value == "signature" || m.Groups["type"].Value == "S")
|
|
type = BackupEntry.EntryType.Signature;
|
|
else
|
|
return null;
|
|
|
|
bool isFull = m.Groups["inc"].Value == "full" || m.Groups["inc"].Value == "F";
|
|
bool isShortName = m.Groups["inc"].Value.Length == 1;
|
|
DateTime time;
|
|
if (isShortName)
|
|
time = new DateTime(long.Parse(m.Groups["time"].Value, System.Globalization.NumberStyles.HexNumber) * TimeSpan.TicksPerSecond, DateTimeKind.Utc).ToLocalTime();
|
|
else
|
|
time = DateTime.Parse(m.Groups["time"].Value.Replace(m_timeSeperator, ":"));
|
|
|
|
string extension = m.Groups["extension"].Value;
|
|
if (extension.StartsWith("vol"))
|
|
extension = extension.Substring(extension.IndexOf(".") + 1);
|
|
|
|
string compression = extension;
|
|
string encryption = null;
|
|
|
|
int dotIndex = compression.IndexOf(".");
|
|
if (dotIndex > 0)
|
|
{
|
|
encryption = compression.Substring(dotIndex + 1);
|
|
compression = compression.Substring(0, dotIndex);
|
|
}
|
|
|
|
return new BackupEntry(fe, time, type, isFull, isShortName, compression, encryption);
|
|
}
|
|
|
|
}
|
|
}
|