Support for CreateFolder in FTP and WEBDAV backends.
git-svn-id: https://duplicati.googlecode.com/svn/trunk@338 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
@@ -144,18 +144,28 @@ namespace Duplicati.Library.Backend
|
||||
req.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails;
|
||||
req.UseBinary = false;
|
||||
|
||||
List<FileEntry> lst = new List<FileEntry>();
|
||||
using (System.Net.WebResponse resp = req.GetResponse())
|
||||
using (System.IO.Stream rs = resp.GetResponseStream())
|
||||
using (System.IO.StreamReader sr = new System.IO.StreamReader(rs))
|
||||
while(sr.Peek() >= 0)
|
||||
{
|
||||
FileEntry f = ParseLine(sr.ReadLine());
|
||||
if (f != null)
|
||||
lst.Add(f);
|
||||
}
|
||||
try
|
||||
{
|
||||
List<FileEntry> lst = new List<FileEntry>();
|
||||
using (System.Net.WebResponse resp = req.GetResponse())
|
||||
using (System.IO.Stream rs = resp.GetResponseStream())
|
||||
using (System.IO.StreamReader sr = new System.IO.StreamReader(rs))
|
||||
while (sr.Peek() >= 0)
|
||||
{
|
||||
FileEntry f = ParseLine(sr.ReadLine());
|
||||
if (f != null)
|
||||
lst.Add(f);
|
||||
}
|
||||
|
||||
return lst;
|
||||
return lst;
|
||||
}
|
||||
catch (System.Net.WebException wex)
|
||||
{
|
||||
if (wex.Response as System.Net.FtpWebResponse != null && (wex.Response as System.Net.FtpWebResponse).StatusCode == System.Net.FtpStatusCode.ActionNotTakenFileUnavailable)
|
||||
throw new Backend.FolderMissingException(string.Format(Strings.FTPBackend.MissingFolderError, req.RequestUri.PathAndQuery, wex.Message), wex);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void Put(string remotename, System.IO.Stream input)
|
||||
@@ -251,7 +261,14 @@ namespace Duplicati.Library.Backend
|
||||
return req;
|
||||
}
|
||||
|
||||
|
||||
public void CreateFolder()
|
||||
{
|
||||
System.Net.FtpWebRequest req = CreateRequest("");
|
||||
req.Method = System.Net.WebRequestMethods.Ftp.MakeDirectory;
|
||||
req.KeepAlive = false;
|
||||
using (req.GetResponse())
|
||||
{ }
|
||||
}
|
||||
|
||||
|
||||
#region IBackendGUI Members
|
||||
|
||||
@@ -201,11 +201,26 @@ namespace Duplicati.Library.Backend
|
||||
MessageBox.Show(this, Backend.CommonStrings.ConnectionSuccess, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
m_hasTested = true;
|
||||
}
|
||||
catch (Backend.FolderMissingException)
|
||||
{
|
||||
switch (MessageBox.Show(this, Strings.FTPUI.CreateMissingFolderQuestion, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
|
||||
{
|
||||
case DialogResult.Yes:
|
||||
CreateFolderButton.PerformClick();
|
||||
TestConnection.PerformClick();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(this, string.Format(Backend.CommonStrings.ConnectionFailure, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
this.Cursor = c;
|
||||
finally
|
||||
{
|
||||
this.Cursor = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,23 +261,28 @@ namespace Duplicati.Library.Backend
|
||||
{
|
||||
if (ValidateForm())
|
||||
{
|
||||
Cursor c = this.Cursor;
|
||||
try
|
||||
{
|
||||
string url = "ftp://" + Servername.Text + ":" + Port.Value.ToString() + "/" + Path.Text;
|
||||
System.Net.FtpWebRequest req = (System.Net.FtpWebRequest)System.Net.FtpWebRequest.Create(url);
|
||||
req.Credentials = new System.Net.NetworkCredential(Username.Text, Password.Text);
|
||||
req.Method = System.Net.WebRequestMethods.Ftp.MakeDirectory;
|
||||
req.KeepAlive = false;
|
||||
using (req.GetResponse())
|
||||
{ }
|
||||
this.Cursor = Cursors.WaitCursor;
|
||||
SaveSettings();
|
||||
|
||||
Dictionary<string, string> options = new Dictionary<string, string>();
|
||||
string hostname = GetConfiguration(m_options, options);
|
||||
FTP f = new FTP(hostname, options);
|
||||
f.CreateFolder();
|
||||
|
||||
MessageBox.Show(this, Backend.CommonStrings.FolderCreated, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
}
|
||||
catch(Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(this, string.Format(Backend.CommonStrings.ConnectionFailure, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.Cursor = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+10
-1
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3053
|
||||
// Runtime Version:2.0.50727.4927
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -167,5 +167,14 @@ namespace Duplicati.Library.Backend.Strings {
|
||||
return ResourceManager.GetString("DisplayName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The folder {0} was not found, message: {1}.
|
||||
/// </summary>
|
||||
internal static string MissingFolderError {
|
||||
get {
|
||||
return ResourceManager.GetString("MissingFolderError", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,4 +153,7 @@
|
||||
<data name="DisplayName" xml:space="preserve">
|
||||
<value>FTP based</value>
|
||||
</data>
|
||||
<data name="MissingFolderError" xml:space="preserve">
|
||||
<value>The folder {0} was not found, message: {1}</value>
|
||||
</data>
|
||||
</root>
|
||||
+10
-1
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3053
|
||||
// Runtime Version:2.0.50727.4927
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -60,6 +60,15 @@ namespace Duplicati.Library.Backend.Strings {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The folder does not exist, do you want to create it?.
|
||||
/// </summary>
|
||||
internal static string CreateMissingFolderQuestion {
|
||||
get {
|
||||
return ResourceManager.GetString("CreateMissingFolderQuestion", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to On this page you can select where to store the backup data..
|
||||
/// </summary>
|
||||
|
||||
@@ -117,6 +117,9 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CreateMissingFolderQuestion" xml:space="preserve">
|
||||
<value>The folder does not exist, do you want to create it?</value>
|
||||
</data>
|
||||
<data name="PageDescription" xml:space="preserve">
|
||||
<value>On this page you can select where to store the backup data.</value>
|
||||
</data>
|
||||
|
||||
+10
-1
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3082
|
||||
// Runtime Version:2.0.50727.4927
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -149,5 +149,14 @@ namespace Duplicati.Library.Backend.Strings {
|
||||
return ResourceManager.GetString("DisplayName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The folder {0} was not found, message: {1}.
|
||||
/// </summary>
|
||||
internal static string MissingFolderError {
|
||||
get {
|
||||
return ResourceManager.GetString("MissingFolderError", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,4 +147,7 @@
|
||||
<data name="DisplayName" xml:space="preserve">
|
||||
<value>WEBDAV based</value>
|
||||
</data>
|
||||
<data name="MissingFolderError" xml:space="preserve">
|
||||
<value>The folder {0} was not found, message: {1}</value>
|
||||
</data>
|
||||
</root>
|
||||
+10
-1
@@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3053
|
||||
// Runtime Version:2.0.50727.4927
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -60,6 +60,15 @@ namespace Duplicati.Library.Backend.Strings {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The folder does not exist, do you want to create it?.
|
||||
/// </summary>
|
||||
internal static string CreateMissingFolderQuestion {
|
||||
get {
|
||||
return ResourceManager.GetString("CreateMissingFolderQuestion", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to On this page you can select where to store the backup data..
|
||||
/// </summary>
|
||||
|
||||
@@ -117,6 +117,9 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="CreateMissingFolderQuestion" xml:space="preserve">
|
||||
<value>The folder does not exist, do you want to create it?</value>
|
||||
</data>
|
||||
<data name="PageDescription" xml:space="preserve">
|
||||
<value>On this page you can select where to store the backup data.</value>
|
||||
</data>
|
||||
|
||||
@@ -108,74 +108,85 @@ namespace Duplicati.Library.Backend
|
||||
using (System.IO.Stream s = req.GetRequestStream())
|
||||
s.Write(PROPFIND, 0, PROPFIND.Length);
|
||||
|
||||
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
|
||||
using (System.Net.HttpWebResponse resp = (System.Net.HttpWebResponse)req.GetResponse())
|
||||
{
|
||||
int code = (int)resp.StatusCode;
|
||||
if (code < 200 || code >= 300) //For some reason Mono does not throw this automatically
|
||||
throw new System.Net.WebException(resp.StatusDescription, null, System.Net.WebExceptionStatus.ProtocolError, resp);
|
||||
|
||||
doc.Load(resp.GetResponseStream());
|
||||
}
|
||||
|
||||
System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(doc.NameTable);
|
||||
nm.AddNamespace("D", "DAV:");
|
||||
|
||||
List<FileEntry> files = new List<FileEntry>();
|
||||
|
||||
foreach (System.Xml.XmlNode n in doc.SelectNodes("D:multistatus/D:response/D:href", nm))
|
||||
try
|
||||
{
|
||||
string name = System.Web.HttpUtility.UrlDecode(n.InnerText);
|
||||
|
||||
string cmp_path;
|
||||
|
||||
if (name.StartsWith(m_url))
|
||||
cmp_path = m_url;
|
||||
else if (name.StartsWith(m_rawurl))
|
||||
cmp_path = m_rawurl;
|
||||
else if (name.StartsWith(m_path))
|
||||
cmp_path = m_path;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (name.Length <= cmp_path.Length)
|
||||
continue;
|
||||
|
||||
name = name.Substring(cmp_path.Length);
|
||||
|
||||
long size = 0;
|
||||
DateTime lastAccess = new DateTime();
|
||||
DateTime lastModified = new DateTime();
|
||||
bool isCollection = false;
|
||||
|
||||
System.Xml.XmlNode stat = n.ParentNode.SelectSingleNode("D:propstat/D:prop", nm);
|
||||
if (stat != null)
|
||||
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
|
||||
using (System.Net.HttpWebResponse resp = (System.Net.HttpWebResponse)req.GetResponse())
|
||||
{
|
||||
System.Xml.XmlNode s = stat.SelectSingleNode("D:getcontentlength", nm);
|
||||
if (s != null)
|
||||
size = long.Parse(s.InnerText);
|
||||
s = stat.SelectSingleNode("D:getlastmodified", nm);
|
||||
if (s != null)
|
||||
try
|
||||
{
|
||||
//Not important if this succeeds
|
||||
lastAccess = lastModified = DateTime.Parse(s.InnerText, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch { }
|
||||
int code = (int)resp.StatusCode;
|
||||
if (code < 200 || code >= 300) //For some reason Mono does not throw this automatically
|
||||
throw new System.Net.WebException(resp.StatusDescription, null, System.Net.WebExceptionStatus.ProtocolError, resp);
|
||||
|
||||
s = stat.SelectSingleNode("D:iscollection", nm);
|
||||
if (s != null)
|
||||
isCollection = s.InnerText.Trim() == "1";
|
||||
else
|
||||
isCollection = (stat.SelectSingleNode("D:resourcetype/D:collection", nm) != null);
|
||||
doc.Load(resp.GetResponseStream());
|
||||
}
|
||||
|
||||
FileEntry fe = new FileEntry(name, size, lastAccess, lastModified);
|
||||
fe.IsFolder = isCollection;
|
||||
files.Add(fe);
|
||||
System.Xml.XmlNamespaceManager nm = new System.Xml.XmlNamespaceManager(doc.NameTable);
|
||||
nm.AddNamespace("D", "DAV:");
|
||||
|
||||
List<FileEntry> files = new List<FileEntry>();
|
||||
|
||||
foreach (System.Xml.XmlNode n in doc.SelectNodes("D:multistatus/D:response/D:href", nm))
|
||||
{
|
||||
string name = System.Web.HttpUtility.UrlDecode(n.InnerText);
|
||||
|
||||
string cmp_path;
|
||||
|
||||
if (name.StartsWith(m_url))
|
||||
cmp_path = m_url;
|
||||
else if (name.StartsWith(m_rawurl))
|
||||
cmp_path = m_rawurl;
|
||||
else if (name.StartsWith(m_path))
|
||||
cmp_path = m_path;
|
||||
else
|
||||
continue;
|
||||
|
||||
if (name.Length <= cmp_path.Length)
|
||||
continue;
|
||||
|
||||
name = name.Substring(cmp_path.Length);
|
||||
|
||||
long size = 0;
|
||||
DateTime lastAccess = new DateTime();
|
||||
DateTime lastModified = new DateTime();
|
||||
bool isCollection = false;
|
||||
|
||||
System.Xml.XmlNode stat = n.ParentNode.SelectSingleNode("D:propstat/D:prop", nm);
|
||||
if (stat != null)
|
||||
{
|
||||
System.Xml.XmlNode s = stat.SelectSingleNode("D:getcontentlength", nm);
|
||||
if (s != null)
|
||||
size = long.Parse(s.InnerText);
|
||||
s = stat.SelectSingleNode("D:getlastmodified", nm);
|
||||
if (s != null)
|
||||
try
|
||||
{
|
||||
//Not important if this succeeds
|
||||
lastAccess = lastModified = DateTime.Parse(s.InnerText, System.Globalization.CultureInfo.InvariantCulture);
|
||||
}
|
||||
catch { }
|
||||
|
||||
s = stat.SelectSingleNode("D:iscollection", nm);
|
||||
if (s != null)
|
||||
isCollection = s.InnerText.Trim() == "1";
|
||||
else
|
||||
isCollection = (stat.SelectSingleNode("D:resourcetype/D:collection", nm) != null);
|
||||
}
|
||||
|
||||
FileEntry fe = new FileEntry(name, size, lastAccess, lastModified);
|
||||
fe.IsFolder = isCollection;
|
||||
files.Add(fe);
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
catch (System.Net.WebException wex)
|
||||
{
|
||||
if (wex.Response as System.Net.HttpWebResponse != null && (wex.Response as System.Net.HttpWebResponse).StatusCode == System.Net.HttpStatusCode.NotFound)
|
||||
throw new Backend.FolderMissingException(string.Format(Strings.WEBDAV.MissingFolderError, m_path, wex.Message), wex);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
public void Put(string remotename, string filename)
|
||||
|
||||
@@ -215,6 +215,18 @@ namespace Duplicati.Library.Backend
|
||||
MessageBox.Show(this, Backend.CommonStrings.ConnectionSuccess, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
m_hasTested = true;
|
||||
}
|
||||
catch (Backend.FolderMissingException)
|
||||
{
|
||||
switch (MessageBox.Show(this, Strings.WebDAVUI.CreateMissingFolderQuestion, Application.ProductName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question))
|
||||
{
|
||||
case DialogResult.Yes:
|
||||
CreateFolderButton.PerformClick();
|
||||
TestConnection.PerformClick();
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show(this, string.Format(Backend.CommonStrings.ConnectionFailure, ex.Message), Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
|
||||
Reference in New Issue
Block a user