Added log4net for client profile
authorPanagiotis Kanavos <pkanavos@gmail.com>
Thu, 13 Oct 2011 20:14:47 +0000 (23:14 +0300)
committerPanagiotis Kanavos <pkanavos@gmail.com>
Thu, 13 Oct 2011 20:14:47 +0000 (23:14 +0300)
Refactored to allow retrieval of shared objects

47 files changed:
trunk/Libraries/Json40r2/Source/Src/Newtonsoft.Json/Newtonsoft.Json.csproj
trunk/Libraries/ParallelExtensionsExtras/ParallelExtensionsExtras.csproj
trunk/Libraries/log4net.dll
trunk/NotifyIconWpf/NotifyIconWpf.csproj
trunk/Pithos.Client.Test/Pithos.Client.Test.csproj
trunk/Pithos.Client.WPF/AppBootstrapper.cs
trunk/Pithos.Client.WPF/Caliburn/Micro/Logging/log4netLogger.cs [new file with mode: 0644]
trunk/Pithos.Client.WPF/Pithos.Client.WPF.csproj
trunk/Pithos.Core.Test/NetworkAgentTest.cs
trunk/Pithos.Core.Test/Pithos.Core.Test.csproj
trunk/Pithos.Core/Agents/Agent.cs
trunk/Pithos.Core/Agents/BlockUpdater.cs
trunk/Pithos.Core/Agents/CloudTransferAction.cs [moved from trunk/Pithos.Core/Agents/CloudAction.cs with 75% similarity]
trunk/Pithos.Core/Agents/FileAgent.cs
trunk/Pithos.Core/Agents/FileInfoExtensions.cs
trunk/Pithos.Core/Agents/NetworkAgent.cs
trunk/Pithos.Core/Agents/StatusAgent.cs [moved from trunk/Pithos.Core/StatusKeeper.cs with 76% similarity]
trunk/Pithos.Core/Agents/WorkflowAgent.cs
trunk/Pithos.Core/DbConfig.xml
trunk/Pithos.Core/FileState.cs
trunk/Pithos.Core/IStatusKeeper.cs
trunk/Pithos.Core/NetworkGate.cs
trunk/Pithos.Core/Pithos.Core.csproj
trunk/Pithos.Core/PithosMonitor.cs
trunk/Pithos.Core/PithosWorkflow.cs
trunk/Pithos.Core/TaskExtensions.cs
trunk/Pithos.Interfaces/ObjectInfo.cs
trunk/Pithos.Interfaces/Pithos.Interfaces.csproj
trunk/Pithos.Interfaces/PithosSettingsData.cs
trunk/Pithos.Network.Test/ChecksumTest.cs
trunk/Pithos.Network.Test/CloudFilesClientTest.cs
trunk/Pithos.Network.Test/FolderTests.cs
trunk/Pithos.Network.Test/NetworkOpsTest.cs
trunk/Pithos.Network.Test/ObjectInfoTest.cs [new file with mode: 0644]
trunk/Pithos.Network.Test/Pithos.Network.Test.csproj
trunk/Pithos.Network.Test/SignatureTest.cs
trunk/Pithos.Network/CloudFilesClient.cs
trunk/Pithos.Network/ContainerInfo.cs [new file with mode: 0644]
trunk/Pithos.Network/ICloudClient.cs
trunk/Pithos.Network/Pithos.Network.csproj
trunk/Pithos.Network/RestClient.cs
trunk/Pithos.Network/Signature.cs
trunk/Pithos.Network/TreeHash.cs
trunk/Pithos.Setup.x64/Pithos.Setup.x64.vdproj
trunk/Pithos.ShellExtensions.Test/Pithos.ShellExtensions.Test.csproj
trunk/Pithos.ShellExtensions/Pithos.ShellExtensions.csproj
trunk/Pithos.sln

index 3172fe9..62b2c30 100644 (file)
     <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>CODE_ANALYSIS;DEBUG;TRACE</DefineConstants>
+    <DocumentationFile>bin\Debug\Net\Newtonsoft.Json.xml</DocumentationFile>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisLogFile>bin\Debug\Net\Newtonsoft.Json.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
index 914685a..6c9d902 100644 (file)
   <PropertyGroup>
     <AssemblyOriginatorKeyFile>pithos.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\ParallelExtensionsExtras.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <CodeContractsEnableRuntimeChecking>False</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>False</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>False</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>False</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>False</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>False</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>False</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>False</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>False</CodeContractsCacheAnalysisResults>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core" />
index ffc57e1..cadbcd3 100644 (file)
Binary files a/trunk/Libraries/log4net.dll and b/trunk/Libraries/log4net.dll differ
index 8ec2521..a3596ec 100644 (file)
   <PropertyGroup>
     <AssemblyOriginatorKeyFile>pithos.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Hardcodet.Wpf.TaskbarNotification.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core">
index 6271a8f..001be9e 100644 (file)
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
     <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Client.Test.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+    <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="nunit.framework">
       <HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
index a9167f8..5f53086 100644 (file)
@@ -1,8 +1,14 @@
 using System.Windows;
 using System.Windows.Navigation;
+using Caliburn.Micro;
 using Caliburn.Micro.Logging;
+using Pithos.Client.WPF.Caliburn.Micro.Logging;
 using Pithos.Core;
 using Pithos.Network;
+using log4net.Appender;
+using log4net.Config;
+using log4net.Filter;
+using log4net.Layout;
 
 namespace Pithos.Client.WPF
 {
@@ -20,9 +26,23 @@ namespace Pithos.Client.WPF
 
            public AppBootstrapper()
            {
-            LogManager.GetLog = type => new DebugLogger(type);
+               ConfigureLogging();
+
+            LogManager.GetLog = type => new log4netLogger(type);
            }
 
+        private static void ConfigureLogging()
+        {
+            var patternLayout = new PatternLayout();
+            patternLayout.ConversionPattern = "%logger (%property{myContext}) [%level]- %message%newline";
+            patternLayout.ActivateOptions();
+            var appender = new TraceAppender { Layout = patternLayout };
+            appender.AddFilter(new LevelRangeFilter{LevelMin=log4net.Core.Level.Info,LevelMax=log4net.Core.Level.Fatal});
+            appender.ActivateOptions();
+            
+            BasicConfigurator.Configure(appender);            
+        }
+
                /// <summary>
                /// By default, we are configured to use MEF
                /// </summary>
diff --git a/trunk/Pithos.Client.WPF/Caliburn/Micro/Logging/log4netLogger.cs b/trunk/Pithos.Client.WPF/Caliburn/Micro/Logging/log4netLogger.cs
new file mode 100644 (file)
index 0000000..a08ee29
--- /dev/null
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Caliburn.Micro;
+
+namespace Pithos.Client.WPF.Caliburn.Micro.Logging
+{
+    class log4netLogger : ILog
+    {
+        private log4net.ILog _log = null;
+
+        public log4netLogger(Type type)
+        {
+            _log = log4net.LogManager.GetLogger(type);    
+        }
+        public void Info(string format, params object[] args)
+        {
+            _log.InfoFormat(format,args);
+        }
+
+        public void Warn(string format, params object[] args)
+        {
+            _log.WarnFormat(format, args);
+        }
+
+        public void Error(Exception exception)
+        {
+            _log.Error("",exception);
+        }
+    }
+}
index f6a99b2..32fa97a 100644 (file)
   <PropertyGroup>
     <ApplicationIcon>Images\Tray.ico</ApplicationIcon>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Client.WPF.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Client.WPF.exe.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Caliburn.Micro, Version=1.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
       <HintPath>..\Libraries\Caliburn.Micro.dll</HintPath>
     </Reference>
+    <Reference Include="log4net">
+      <HintPath>..\Libraries\log4net.dll</HintPath>
+    </Reference>
     <Reference Include="System" />
     <Reference Include="System.ComponentModel.Composition" />
     <Reference Include="System.Configuration.Install" />
       <SubType>Designer</SubType>
     </ApplicationDefinition>
     <Compile Include="Caliburn\Micro\Logging\DebugLogger.cs" />
+    <Compile Include="Caliburn\Micro\Logging\log4netLogger.cs" />
     <Compile Include="Configuration\PithosSettings.cs" />
     <Compile Include="FileEntry.cs" />
     <Compile Include="FilePropertiesView.xaml.cs">
index 6094e09..64031dc 100644 (file)
@@ -27,7 +27,8 @@ namespace Pithos.Core.Test
                                 }
             };
 
-            agent.CloudClient.Authenticate("890329@vho.grnet.gr", "24989dce4e0fcb072f8cb60c8922be19");
+            var account = "890329@vho.grnet.gr";
+            agent.CloudClient.Authenticate(account, "24989dce4e0fcb072f8cb60c8922be19");
 
             var fileName = "012345.dump";
             var filePath = Path.Combine(@"e:\pithos\", fileName);
@@ -46,12 +47,12 @@ namespace Pithos.Core.Test
             }
 
 
-            agent.CloudClient.DeleteObject(agent.PithosContainer, fileName);
+            agent.CloudClient.DeleteObject(null, agent.PithosContainer, fileName,agent.TrashContainer);
 
             var task = Signature.CalculateTreeHashAsync(filePath, agent.BlockSize, agent.BlockHash);
-            agent.UploadWithHashMap(new FileInfo(filePath),fileName,task);
+            agent.UploadWithHashMap(account,"pithos",new FileInfo(filePath),fileName,task);
 
-            var newHash = agent.CloudClient.GetHashMap(agent.PithosContainer, fileName).Result;
+            var newHash = agent.CloudClient.GetHashMap(null, agent.PithosContainer, fileName).Result;
 
 
             var treeHash = task.Result;
@@ -79,7 +80,8 @@ namespace Pithos.Core.Test
                 FileAgent=fileAgent
             };
 
-            agent.CloudClient.Authenticate("890329@vho.grnet.gr", "24989dce4e0fcb072f8cb60c8922be19");
+            var account = "890329@vho.grnet.gr";
+            agent.CloudClient.Authenticate(account, "24989dce4e0fcb072f8cb60c8922be19");
 
             var fileName = @"AccessDatabaseEngine_x64.exe";
 
@@ -87,8 +89,8 @@ namespace Pithos.Core.Test
             if (File.Exists(filePath))
                 File.Delete(filePath);            
             
-            var newHash = agent.CloudClient.GetHashMap(agent.PithosContainer, fileName).Result;
-            agent.DownloadWithBlocks(agent.PithosContainer,new Uri(fileName,UriKind.Relative),filePath,newHash)
+            var newHash = agent.CloudClient.GetHashMap(null, agent.PithosContainer, fileName).Result;
+            agent.DownloadWithBlocks(account,agent.PithosContainer,new Uri(fileName,UriKind.Relative),filePath,newHash)
                 .Wait();
 
             Assert.IsTrue(File.Exists(filePath));
index f2a6d26..795eb0a 100644 (file)
     <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Core.Test.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Castle.ActiveRecord, Version=3.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL" />
     <Reference Include="nunit.framework, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
index fc5f0e0..faa5760 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.Linq;
 using System.Text;
 using System.Threading;
@@ -74,6 +75,7 @@ namespace Pithos.Core
 
         public void DoAsync(Action action)
         {
+            Contract.Requires(action!=null);
             Task.Factory.StartNew(action, CancellationToken);
         }
 
@@ -106,6 +108,9 @@ namespace Pithos.Core
 
         public Task LoopAsync(Task process, Action loop,Action<Exception> onError=null)
         {
+            Contract.Requires(process!=null);
+            Contract.Requires(loop!=null);
+
             return process.ContinueWith(t =>
             {   
              
index 6b0d310..ec9f003 100644 (file)
@@ -22,6 +22,20 @@ namespace Pithos.Core.Agents
 
         public string TempPath { get; private set; }
 
+        readonly ConcurrentDictionary<int, string> _blocks = new ConcurrentDictionary<int, string>();
+        readonly ConcurrentDictionary<string, string> _orphanBlocks = new ConcurrentDictionary<string, string>();
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(Path.IsPathRooted(FragmentsPath));
+            Contract.Invariant(Path.IsPathRooted(FilePath));
+            Contract.Invariant(Path.IsPathRooted(TempPath));
+            Contract.Invariant(!Path.IsPathRooted(RelativePath));
+            Contract.Invariant(_blocks!=null);
+            Contract.Invariant(_orphanBlocks!=null);
+            Contract.Invariant(ServerHash!=null);
+        }
 
         public BlockUpdater(string fragmentsPath, string filePath, string relativePath,TreeHash serverHash)
         {   
@@ -50,8 +64,15 @@ namespace Pithos.Core.Agents
             ServerHash = serverHash;
             //The file will be stored in a temporary location while downloading with an extension .download
             TempPath = Path.Combine(FragmentsPath, RelativePath + ".download");
-
-            var directoryPath = Path.GetDirectoryName(TempPath);
+            
+            //Need to calculate the directory path because RelativePath may include folders
+            var directoryPath = Path.GetDirectoryName(TempPath);            
+            //directoryPath CAN be null if TempPath is a root path
+            if (String.IsNullOrWhiteSpace(directoryPath))
+                throw new ArgumentException("TempPath");
+            //FragmentsPath was absolute so directoryPath is absolute too
+            Contract.Assume(Path.IsPathRooted(directoryPath));
+            
             if (!Directory.Exists(directoryPath))
                 Directory.CreateDirectory(directoryPath);
 
@@ -64,6 +85,8 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException("directoryPath");
             if (!Path.IsPathRooted(directoryPath))
                 throw new ArgumentException("The directoryPath must be rooted", "directoryPath");
+            if (ServerHash==null)
+                throw new InvalidOperationException("ServerHash wasn't initialized");
             Contract.EndContractBlock();
 
             var fileNamename = Path.GetFileName(FilePath);
@@ -76,9 +99,13 @@ namespace Pithos.Core.Agents
                     //The server truncates nulls before calculating hashes, have to do the same
                     //Find the last non-null byte, starting from the end
                     var lastByteIndex = Array.FindLastIndex(buffer, buffer.Length-1, aByte => aByte != 0);
-                    var binHash = hasher.ComputeHash(buffer,0,lastByteIndex);
-                    var hash = binHash.ToHashString();
-                    _orphanBlocks[hash] = orphan;
+                    //lastByteIndex may be -1 if the file was empty. We don't want to use that block file
+                    if (lastByteIndex >= 0)
+                    {
+                        var binHash = hasher.ComputeHash(buffer, 0, lastByteIndex);
+                        var hash = binHash.ToHashString();
+                        _orphanBlocks[hash] = orphan;
+                    }
                 }
             }
         }
@@ -98,7 +125,9 @@ namespace Pithos.Core.Agents
                 File.Copy(FilePath, TempPath, true);
 
             //Set the size of the file to the size specified in the treehash
-            //This will also create an empty file if the file doesn't exist            
+            //This will also create an empty file if the file doesn't exist                        
+            
+            
             SetFileSize(TempPath, ServerHash.Bytes);
 
             //Update the temporary file with the data from the blocks
@@ -186,8 +215,6 @@ namespace Pithos.Core.Agents
             return (tempLastWrite < localLastWrite);
         }*/
 
-        ConcurrentDictionary<int,string> _blocks=new ConcurrentDictionary<int, string>();
-        ConcurrentDictionary<string, string> _orphanBlocks = new ConcurrentDictionary<string, string>();
 
         public bool UseOrphan(int blockIndex, string blockHash)
         {
similarity index 75%
rename from trunk/Pithos.Core/Agents/CloudAction.cs
rename to trunk/Pithos.Core/Agents/CloudTransferAction.cs
index 3a594cc..bc4a7fa 100644 (file)
@@ -22,30 +22,25 @@ namespace Pithos.Core.Agents
         public FileInfo LocalFile { get; set; }
         public ObjectInfo CloudFile { get; set; }
         public FileState FileState { get; set; }
+        public string Container { get; set; }
 
-        public Lazy<string> LocalHash { get; private set; }
-        public Lazy<string> TopHash { get; set; }
 
-        public string OldFileName { get; set; }
-        public string OldPath { get; set; }
-        public string NewFileName { get; set; }
-        public string NewPath { get; set; }
+        public Lazy<string> LocalHash { get; protected set; }
+        private Lazy<string> _topHash;
+        public Lazy<string> TopHash
+        {
+            get { return _topHash; }
+            set { _topHash = value; }
+        }
 
 
-        public CloudAction(CloudActionType action, string oldPath, string oldFileName, string newFileName, string newPath)
+        protected CloudAction(CloudActionType action)
         {
             Action = action;
-            OldFileName = oldFileName;
-            OldPath = oldPath;
-            NewFileName = newFileName;
-            NewPath = newPath;
-            //This is a rename operation, a hash will not be used
-            LocalHash = new Lazy<string>(() => String.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
         }
 
-        public CloudAction(CloudActionType action, FileInfo localFile, ObjectInfo cloudFile,FileState state,int blockSize, string algorithm)
+        public CloudAction(CloudActionType action, FileInfo localFile, ObjectInfo cloudFile,FileState state,int blockSize, string algorithm) : this(action)
         {
-            Action = action;
             LocalFile = localFile;
             CloudFile = cloudFile;
             FileState = state;
@@ -56,6 +51,7 @@ namespace Pithos.Core.Agents
             }
         }
 
+
         //Constructor for downloading files
         public CloudAction(CloudActionType action, ObjectInfo cloudFile)
         {
@@ -63,5 +59,27 @@ namespace Pithos.Core.Agents
             CloudFile = cloudFile;
         }
 
+    }    
+
+    public class CloudMoveAction:CloudAction
+    {
+        public string OldFileName { get; set; }
+        public string OldPath { get; set; }
+        public string NewFileName { get; set; }
+        public string NewPath { get; set; }
+
+        public CloudMoveAction(CloudActionType action, string oldPath, string oldFileName, string newFileName, string newPath)
+            :base(action)
+        {
+            OldFileName = oldFileName;
+            OldPath = oldPath;
+            NewFileName = newFileName;
+            NewPath = newPath;
+            //This is a rename operation, a hash will not be used
+            LocalHash = new Lazy<string>(() => String.Empty, LazyThreadSafetyMode.ExecutionAndPublication);
+        }
+
+
     }
+
 }
\ No newline at end of file
index 8b67103..44f032c 100644 (file)
@@ -27,10 +27,18 @@ namespace Pithos.Core.Agents
 
         public string RootPath { get; private set; }
 
+
         public void Start(string rootPath)
         {
+            if (String.IsNullOrWhiteSpace(rootPath))
+                throw new ArgumentNullException("rootPath");
+            if (!Path.IsPathRooted(rootPath))
+                throw new ArgumentException("rootPath must be an absolute path","rootPath");
+            Contract.EndContractBlock();
+
             RootPath = rootPath;
             _watcher = new FileSystemWatcher(rootPath);
+            _watcher.IncludeSubdirectories = true;            
             _watcher.Changed += OnFileEvent;
             _watcher.Created += OnFileEvent;
             _watcher.Deleted += OnFileEvent;
@@ -55,6 +63,10 @@ namespace Pithos.Core.Agents
 
         private Task<object> Process(WorkflowState state)
         {
+            if (state==null)
+                throw new ArgumentNullException("state");
+            Contract.EndContractBlock();
+
             Debug.Assert(!Ignore(state.Path));
 
             var networkState = NetworkGate.GetNetworkState(state.Path);
@@ -116,6 +128,10 @@ namespace Pithos.Core.Agents
 
         public void Post(WorkflowState workflowState)
         {
+            if (workflowState == null)
+                throw new ArgumentNullException("workflowState");
+            Contract.EndContractBlock();
+
             _agent.Post(workflowState);
         }
 
@@ -131,7 +147,8 @@ namespace Pithos.Core.Agents
             }
             _watcher = null;
 
-            _agent.Stop();
+            if (_agent!=null)
+                _agent.Stop();
         }
 
         // Enumerate all files in the Pithos directory except those in the Fragment folder
@@ -217,11 +234,14 @@ namespace Pithos.Core.Agents
 
         private WorkflowState UpdateFileStatus(WorkflowState state)
         {
-            Debug.Assert(!state.Path.Contains("fragments"));
-            Debug.Assert(!state.Path.EndsWith(".ignore", StringComparison.InvariantCultureIgnoreCase));
+            if (state==null)
+                throw new ArgumentNullException("state");
+            if (String.IsNullOrWhiteSpace(state.Path))
+                throw new ArgumentException("The state's Path can't be empty","state");
+            Contract.EndContractBlock();
 
-            string path = state.Path;
-            FileStatus status = _statusDict[state.TriggeringChange];
+            var path = state.Path;
+            var status = _statusDict[state.TriggeringChange];
             var oldStatus = Workflow.StatusKeeper.GetFileStatus(path);
             if (status == oldStatus)
             {
@@ -238,6 +258,10 @@ namespace Pithos.Core.Agents
 
         private WorkflowState UpdateOverlayStatus(WorkflowState state)
         {
+            if (state==null)
+                throw new ArgumentNullException("state");
+            Contract.EndContractBlock();
+
             if (state.Skip)
                 return state;
 
@@ -248,10 +272,10 @@ namespace Pithos.Core.Agents
                     this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified);
                     break;
                 case FileStatus.Deleted:
-                    //this.StatusKeeper.RemoveFileOverlayStatus(state.Path);
+                    //this.StatusAgent.RemoveFileOverlayStatus(state.Path);
                     break;
                 case FileStatus.Renamed:
-                    this.StatusKeeper.RemoveFileOverlayStatus(state.OldPath);
+                    this.StatusKeeper.ClearFileStatus(state.OldPath);
                     this.StatusKeeper.SetFileOverlayStatus(state.Path, FileOverlayStatus.Modified);
                     break;
                 case FileStatus.Unchanged:
@@ -319,7 +343,7 @@ namespace Pithos.Core.Agents
             Contract.EndContractBlock();            
 
             var absolutePath = Path.Combine(RootPath, relativePath);
-            Debug.Assert(File.Exists(absolutePath),String.Format("Path {0} doesn't exist",absolutePath));
+//            Debug.Assert(File.Exists(absolutePath),String.Format("Path {0} doesn't exist",absolutePath));
 
             return new FileInfo(absolutePath);
             
index b8608ad..99895c3 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.Linq;
 using System.Text;
 using System.IO;
@@ -13,6 +14,11 @@ namespace Pithos.Core.Agents
     {
         public static  string AsRelativeTo(this FileInfo fileInfo,string path )
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");            
+            Contract.EndContractBlock();
+            
+
             if (!path.EndsWith("\\"))
                 path=path.ToLower() + "\\";
             int pathLength = path.Length;            
@@ -29,6 +35,9 @@ namespace Pithos.Core.Agents
 
         public static string AsRelativeUrlTo(this FileInfo fileInfo,string path )
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            Contract.EndContractBlock();
 
             var relativePath = fileInfo.AsRelativeTo(path);
             var replacedSlashes = relativePath.Replace("\\","/");
@@ -38,16 +47,12 @@ namespace Pithos.Core.Agents
 
         public static string RelativeUriToFilePath(this Uri uri)
         {
-            return RelativeUrlToFilePath(uri.ToString());
-        }
-
-        public static string RelativeUrlToFilePath(this string url)
-        {
-            var unescaped=Uri.UnescapeDataString(url);
+            var unescaped = Uri.UnescapeDataString(uri.ToString());
             var path = unescaped.Replace("/", "\\");
             return path;
         }
 
+
         public static int Read(this FileInfo fileInfo,byte[] buffer,int offset,int count)
         {            
             //Open the stream only long enough to read a block
@@ -90,6 +95,16 @@ namespace Pithos.Core.Agents
 
         public static string CalculateHash(this FileInfo info,int blockSize,string algorithm)
         {
+            if (info==null)
+                throw new ArgumentNullException("info");
+            if (String.IsNullOrWhiteSpace(info.FullName))
+                throw new ArgumentException("info");
+            if (blockSize<=0)
+                throw new ArgumentOutOfRangeException("blockSize",blockSize,"blockSize must be greater than 0");
+            if (String.IsNullOrWhiteSpace(algorithm))
+                throw new ArgumentNullException("algorithm");
+            Contract.EndContractBlock();
+
             if (info.Length <= blockSize)
                 return Signature.CalculateMD5(info.FullName);
             else
index ff7ca05..7643c45 100644 (file)
@@ -11,6 +11,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using Pithos.Interfaces;
 using Pithos.Network;
+using log4net;
 
 namespace Pithos.Core.Agents
 {
@@ -37,10 +38,13 @@ namespace Pithos.Core.Agents
 
         public string PithosContainer { get; set; }
         public string TrashContainer { get; private set; }
+        public IList<string> Containers { get; private set; }
 
         public int BlockSize { get; set; }
         public string BlockHash { get; set; }
 
+        private static readonly ILog Log = LogManager.GetLogger(typeof(NetworkAgent));
+
 
         public void Start(string pithosContainer, string trashContainer, int blockSize, string blockHash)
         {
@@ -75,85 +79,178 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException("action");
             Contract.EndContractBlock();
 
-            Trace.TraceInformation("[ACTION] Start Processing {0}:{1}->{2}", action.Action, action.LocalFile, action.CloudFile.Name);
+            using (log4net.LogicalThreadContext.Stacks["NETWORK"].Push("PROCESS"))
+            {                
+                Log.InfoFormat("[ACTION] Start Processing {0}:{1}->{2}", action.Action, action.LocalFile,
+                               action.CloudFile.Name);
+
+                var localFile = action.LocalFile;
+                var cloudFile = action.CloudFile;
+                var downloadPath = (cloudFile == null)
+                                       ? String.Empty
+                                       : Path.Combine(FileAgent.RootPath, cloudFile.RelativeUrlToFilePath(CloudClient.UserName));
+
+                try
+                {
+                    var account = action.CloudFile.Account ?? CloudClient.UserName;
+                    var container = action.CloudFile.Container ?? PithosContainer;
+
+                    switch (action.Action)
+                    {
+                        case CloudActionType.UploadUnconditional:
+                            UploadCloudFile(account, container, localFile, action.LocalHash.Value, action.TopHash.Value);
+                            break;
+                        case CloudActionType.DownloadUnconditional:
+
+                            DownloadCloudFile(account, container, new Uri(cloudFile.Name, UriKind.Relative),
+                                              downloadPath);
+                            break;
+                        case CloudActionType.DeleteCloud:
+                            DeleteCloudFile(account, container, cloudFile.Name);
+                            break;
+                        case CloudActionType.RenameCloud:
+                            var moveAction = (CloudMoveAction)action;
+                            RenameCloudFile(account, container, moveAction.OldFileName, moveAction.NewPath,
+                                            moveAction.NewFileName);
+                            break;
+                        case CloudActionType.MustSynch:
+
+                            if (!File.Exists(downloadPath))
+                            {
+                                var cloudUri = new Uri(action.CloudFile.Name, UriKind.Relative);
+                                DownloadCloudFile(account, container, cloudUri, downloadPath);
+                            }
+                            else
+                            {
+                                SyncFiles(action);
+                            }
+                            break;
+                    }
+                    Log.InfoFormat("[ACTION] End Processing {0}:{1}->{2}", action.Action, action.LocalFile,
+                                           action.CloudFile.Name);
+                }
+                catch (OperationCanceledException)
+                {
+                    throw;
+                }
+                catch (System.IO.FileNotFoundException exc)
+                {
+                    Log.ErrorFormat("{0} : {1} -> {2}  failed because the file was not found.\n Rescheduling a delete",
+                        action.Action, action.LocalFile, action.CloudFile, exc);
+                    Post(new CloudAction(CloudActionType.DeleteCloud,action.CloudFile));
+                }
+                catch (Exception exc)
+                {
+                    Log.ErrorFormat("[REQUEUE] {0} : {1} -> {2} due to exception\r\n{3}",
+                                     action.Action, action.LocalFile, action.CloudFile, exc);
+
+                    _agent.Post(action);
+                }
+                return CompletedTask<object>.Default;
+            }
+        }
+
+        private void SyncFiles(CloudAction action)
+        {
+            if (action==null)
+                throw new ArgumentNullException("action");
+            if (action.LocalFile==null)
+                throw new ArgumentException("The action's local file is not specified","action");
+            if (!Path.IsPathRooted(action.LocalFile.FullName))
+                throw new ArgumentException("The action's local file path must be absolute","action");
+            if (action.CloudFile== null)
+                throw new ArgumentException("The action's cloud file is not specified", "action");
+            Contract.EndContractBlock();
+
             var localFile = action.LocalFile;
             var cloudFile = action.CloudFile;
-            var downloadPath = (cloudFile == null) ? String.Empty
-                                    : Path.Combine(FileAgent.RootPath, cloudFile.Name.RelativeUrlToFilePath());
+            var downloadPath=action.LocalFile.FullName.ToLower();
 
-            try
+            var account = cloudFile.Account;
+            //Use "pithos" by default if no container is specified
+            var container = cloudFile.Container ?? PithosContainer;
+
+            var cloudUri = new Uri(cloudFile.Name, UriKind.Relative);
+            var cloudHash = cloudFile.Hash.ToLower();
+            var localHash = action.LocalHash.Value.ToLower();
+            var topHash = action.TopHash.Value.ToLower();
+
+            //Not enough to compare only the local hashes, also have to compare the tophashes
+            
+            //If any of the hashes match, we are done
+            if ((cloudHash == localHash || cloudHash == topHash))
             {
-                switch (action.Action)
+                Log.InfoFormat("Skipping {0}, hashes match",downloadPath);
+                return;
+            }
+
+            //The hashes DON'T match. We need to sync
+            var lastLocalTime = localFile.LastWriteTime;
+            var lastUpTime = cloudFile.Last_Modified;
+            
+            //If the local file is newer upload it
+            if (lastUpTime <= lastLocalTime)
+            {
+                //It probably means it was changed while the app was down                        
+                UploadCloudFile(account, container, localFile, action.LocalHash.Value,
+                                action.TopHash.Value);
+            }
+            else
+            {
+                //It the cloud file has a later date, it was modified by another user or computer.
+                //We need to check the local file's status                
+                var status = StatusKeeper.GetFileStatus(downloadPath);
+                switch (status)
                 {
-                    case CloudActionType.UploadUnconditional:
-                        UploadCloudFile(localFile, action.LocalHash.Value, action.TopHash.Value);
+                    case FileStatus.Unchanged:                        
+                        //If the local file's status is Unchanged, we can go on and download the newer cloud file
+                        DownloadCloudFile(account, container,cloudUri,downloadPath);
                         break;
-                    case CloudActionType.DownloadUnconditional:
-                        DownloadCloudFile(PithosContainer, new Uri(cloudFile.Name, UriKind.Relative), downloadPath);
+                    case FileStatus.Modified:
+                        //If the local file is Modified, we may have a conflict. In this case we should mark the file as Conflict
+                        //We can't ensure that a file modified online since the last time will appear as Modified, unless we 
+                        //index all files before we start listening.                       
+                    case FileStatus.Created:
+                        //If the local file is Created, it means that the local and cloud files aren't related,
+                        // yet they have the same name.
+
+                        //In both cases we must mark the file as in conflict
+                        ReportConflict(downloadPath);
                         break;
-                    case CloudActionType.DeleteCloud:
-                        DeleteCloudFile(cloudFile.Name);
-                        break;
-                    case CloudActionType.RenameCloud:
-                        RenameCloudFile(action.OldFileName, action.NewPath, action.NewFileName);
-                        break;
-                    case CloudActionType.MustSynch:
-                        if (File.Exists(downloadPath))
-                        {
-                            var cloudHash = cloudFile.Hash;
-                            var localHash = action.LocalHash.Value;
-                            var topHash = action.TopHash.Value;
-                            //Not enough to compare only the local hashes, also have to compare the tophashes
-                            if (!cloudHash.Equals(localHash, StringComparison.InvariantCultureIgnoreCase) &&
-                                !cloudHash.Equals(topHash, StringComparison.InvariantCultureIgnoreCase))
-                            {
-                                var lastLocalTime = localFile.LastWriteTime;
-                                var lastUpTime = cloudFile.Last_Modified;
-                                if (lastUpTime <= lastLocalTime)
-                                {
-                                    //Local change while the app was down or Files in conflict
-                                    //Maybe need to store version as well, to check who has the latest version
-
-                                    //StatusKeeper.SetFileOverlayStatus(downloadPath, FileOverlayStatus.Conflict);
-                                    UploadCloudFile(localFile, action.LocalHash.Value, action.TopHash.Value);
-                                }
-                                else
-                                {
-                                    var status = StatusKeeper.GetFileStatus(downloadPath);
-                                    switch (status)
-                                    {
-                                        case FileStatus.Unchanged:
-                                            //It he cloud file has a later date, it was modified by another user or computer.
-                                            //If the local file's status is Unchanged, we should go on and download the cloud file
-                                            DownloadCloudFile(PithosContainer, new Uri(action.CloudFile.Name, UriKind.Relative), downloadPath);
-                                            break;
-                                        case FileStatus.Modified:
-                                            //If the local file is Modified, we may have a conflict. In this case we should mark the file as Conflict
-                                            //We can't ensure that a file modified online since the last time will appear as Modified, unless we 
-                                            //index all files before we start listening.
-                                            StatusKeeper.SetFileOverlayStatus(downloadPath, FileOverlayStatus.Conflict);
-                                            break;
-                                        case FileStatus.Created:
-                                            //If the local file is Created, it means that the local and cloud files aren't related yet have the same name
-                                            //In this case we must mark the file as in conflict
-                                            //Other cases should never occur. Mark them as Conflict as well but log a warning
-                                            StatusKeeper.SetFileOverlayStatus(downloadPath, FileOverlayStatus.Conflict);
-                                            break;
-                                        default:
-                                            //If the local file is Created, it means that the local and cloud files aren't related yet have the same name
-                                            //In this case we must mark the file as in conflict
-                                            //Other cases should never occur. Mark them as Conflict as well but log a warning
-                                            StatusKeeper.SetFileOverlayStatus(downloadPath, FileOverlayStatus.Conflict);
-                                            Trace.TraceWarning("Unexcepted status {0} for file {1}->{2}", status, downloadPath, action.CloudFile.Name);
-                                            break;
-                                    }
-                                }
-                            }
-                        }
-                        else
-                            DownloadCloudFile(PithosContainer, new Uri(action.CloudFile.Name, UriKind.Relative), downloadPath);
+                    default:
+                        //Other cases should never occur. Mark them as Conflict as well but log a warning
+                        ReportConflict(downloadPath);
+                        Log.WarnFormat("Unexcepted status {0} for file {1}->{2}", status,
+                                       downloadPath, action.CloudFile.Name);
                         break;
                 }
+            }
+        }
+
+        private void ReportConflict(string downloadPath)
+        {
+            if (String.IsNullOrWhiteSpace(downloadPath))
+                throw new ArgumentNullException("downloadPath");
+            Contract.EndContractBlock();
+
+            StatusKeeper.SetFileOverlayStatus(downloadPath, FileOverlayStatus.Conflict);
+            var message = String.Format("Conflict detected for file {0}", downloadPath);
+            Log.Warn(message);
+            StatusNotification.NotifyChange(message, TraceLevel.Warning);
+        }
+
+/*
+        private Task<object> Process(CloudMoveAction action)
+        {
+            if (action == null)
+                throw new ArgumentNullException("action");
+            Contract.EndContractBlock();
+
+            Trace.TraceInformation("[ACTION] Start Processing {0}:{1}->{2}", action.Action, action.LocalFile, action.CloudFile.Name);
+
+            try
+            {
+                RenameCloudFile(action.OldFileName, action.NewPath, action.NewFileName);
                 Trace.TraceInformation("[ACTION] End Processing {0}:{1}->{2}", action.Action, action.LocalFile, action.CloudFile.Name);
             }
             catch (OperationCanceledException)
@@ -163,12 +260,13 @@ namespace Pithos.Core.Agents
             catch (Exception exc)
             {
                 Trace.TraceError("[REQUEUE] {0} : {1} -> {2} due to exception\r\n{3}",
-                                action.Action, action.LocalFile, action.CloudFile, exc);
+                                action.Action, action.OldFileName, action.NewFileName, exc);
 
                 _agent.Post(action);
             }
             return CompletedTask<object>.Default;
         }
+*/
 
 
         public void Post(CloudAction cloudAction)
@@ -180,9 +278,15 @@ namespace Pithos.Core.Agents
             //If the action targets a local file, add a treehash calculation
             if (cloudAction.LocalFile != null)
             {
-                cloudAction.TopHash = new Lazy<string>(() => Signature.CalculateTreeHashAsync(cloudAction.LocalFile, 
+
+                if (cloudAction.LocalFile.Length>BlockSize)
+                    cloudAction.TopHash = new Lazy<string>(() => Signature.CalculateTreeHashAsync(cloudAction.LocalFile, 
                                     BlockSize, BlockHash).Result
                                      .TopHash.ToHashString());
+                else
+                {
+                    cloudAction.TopHash=new Lazy<string>(()=> cloudAction.LocalHash.Value);
+                }
 
             }
             _agent.Post(cloudAction);
@@ -208,156 +312,154 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException(accountPath);
             Contract.EndContractBlock();
 
-            Trace.CorrelationManager.StartLogicalOperation();
-            Trace.TraceInformation("[LISTENER] Scheduled");
-            
-            //Get the list of server objects changed since the last check
-            var listObjects = Task<IList<ObjectInfo>>.Factory.StartNewDelayed(10000,()=>
-                            CloudClient.ListObjects(PithosContainer,since));
-            //Get the list of deleted objects since the last check
-            var listTrash= Task<IList<ObjectInfo>>.Factory.StartNewDelayed(10000,()=>
-                            CloudClient.ListObjects(TrashContainer,since));
+            using (log4net.LogicalThreadContext.Stacks["SCHEDULE"].Push("Retrieve Remote"))
+            {
+                Log.Info("[LISTENER] Scheduled");
 
-            var listAll = Task.Factory.TrackedSequence(() => listObjects, () => listTrash);
+                //Get the list of server objects changed since the last check
+                var listObjects = Task<IList<ObjectInfo>>.Factory.StartNewDelayed(10000, () =>
+                                CloudClient.ListObjects(CloudClient.UserName, PithosContainer, since));
+                //Get the list of deleted objects since the last check
+                var listTrash = Task<IList<ObjectInfo>>.Factory.StartNewDelayed(10000, () =>
+                                CloudClient.ListObjects(CloudClient.UserName, TrashContainer, since));                
 
-            //Next time we will check for all changes since the current check minus 1 second
-            //This is done to ensure there are no discrepancies due to clock differences
-            DateTime nextSince = DateTime.Now.AddSeconds(-1);
+                var listShared = Task<IList<ObjectInfo>>.Factory.StartNewDelayed(10000, () =>
+                                CloudClient.ListSharedObjects(since));
 
+                var listAll = Task.Factory.TrackedSequence(
+                    () => listObjects,
+                    () => listTrash,
+                    () => listShared);
 
+                //Next time we will check for all changes since the current check minus 1 second
+                //This is done to ensure there are no discrepancies due to clock differences
+                DateTime nextSince = DateTime.Now.AddSeconds(-1);
 
-            
 
-
-            var enqueueFiles = listAll.ContinueWith(task =>
-            {
-                if (task.IsFaulted)
+                var enqueueFiles = listAll.ContinueWith(task =>
                 {
-                    //ListObjects failed at this point, need to reschedule
-                    Trace.TraceError("[FAIL] ListObjects in ProcessRemoteFiles with {0}", task.Exception);
-                    ProcessRemoteFiles(accountPath, since);
-                    return;
-                }
-                Trace.CorrelationManager.StartLogicalOperation("Listener");
-                Trace.TraceInformation("[LISTENER] Start Processing");
+                    if (task.IsFaulted)
+                    {
+                        //ListObjects failed at this point, need to reschedule
+                        Log.ErrorFormat("[FAIL] ListObjects in ProcessRemoteFiles with {0}", task.Exception);
+                        ProcessRemoteFiles(accountPath, since);
+                        return;
+                    }
+                    using (log4net.LogicalThreadContext.Stacks["SCHEDULE"].Push("Process Results"))
+                    {
+                        var remoteObjects = ((Task<IList<ObjectInfo>>) task.Result[0]).Result;
+                        var trashObjects = ((Task<IList<ObjectInfo>>) task.Result[1]).Result;
+                        var sharedObjects = ((Task<IList<ObjectInfo>>) task.Result[2]).Result;
+
+                        //Items with the same name, hash may be both in the container and the trash
+                        //Don't delete items that exist in the container
+                        var realTrash = from trash in trashObjects
+                                        where !remoteObjects.Any(info => info.Hash == trash.Hash)
+                                        select trash;
+                        ProcessDeletedFiles(realTrash);                        
+
+
+                        var remote = from info in remoteObjects.Union(sharedObjects)
+                                     let name = info.Name
+                                     where !name.EndsWith(".ignore", StringComparison.InvariantCultureIgnoreCase) &&
+                                           !name.StartsWith("fragments/", StringComparison.InvariantCultureIgnoreCase)
+                                     select info;
+
+                        //Create a list of actions from the remote files
+                        var allActions = ObjectsToActions(remote);
+                       
+                        //And remove those that are already being processed by the agent
+                        var distinctActions = allActions
+                            .Except(_agent.GetEnumerable(), new PithosMonitor.LocalFileComparer())
+                            .ToList();
+
+                        //Queue all the actions
+                        foreach (var message in distinctActions)
+                        {
+                            Post(message);
+                        }
 
-                var trashObjects = ((Task<IList<ObjectInfo>>)task.Result[1]).Result;
-                var remoteObjects = ((Task<IList<ObjectInfo>>)task.Result[0]).Result;
+                        //Report the number of new files
+                        var remoteCount = distinctActions.Count(action=>
+                            action.Action==CloudActionType.DownloadUnconditional);
+                        if ( remoteCount > 0)
+                            StatusNotification.NotifyChange(String.Format("Processing {0} new files", remoteCount));
 
-                
-                //Items with the same name, hash may be both in the container and the trash
-                //Don't delete items that exist in the container
-                var realTrash = from trash in trashObjects
-                                where !remoteObjects.Any(info => info.Hash == trash.Hash)
-                                select trash;
-                ProcessDeletedFiles(realTrash);
-
-
-                var remote=from info in remoteObjects
-                                  let name=info.Name
-                                  where !name.EndsWith(".ignore",StringComparison.InvariantCultureIgnoreCase) &&
-                                  !name.StartsWith("fragments/",StringComparison.InvariantCultureIgnoreCase)
-                                select info;
-
-                var commonObjects = new List<Tuple<ObjectInfo, FileInfo,FileState>>();
-                var remoteOnly = new List<ObjectInfo>();
-                
-                //In order to avoid multiple iterations over the files, we iterate only once
-                //over the remote files
-                foreach (var objectInfo in remote)
-                {
-                    var relativePath= objectInfo.Name.RelativeUrlToFilePath();
-                    //and remove any matching objects from the list, adding them to the commonObjects list
-                    if (FileAgent.Exists(relativePath))
+                        Log.Info("[LISTENER] End Processing");                        
+                    }
+                });
+
+                var loop = enqueueFiles.ContinueWith(t =>
+                {                    
+                    if (t.IsFaulted)
                     {
-                        var localFile = FileAgent.GetFileInfo(relativePath);
-                        var state = FileState.FindByFilePath(localFile.FullName);
-                        commonObjects.Add(Tuple.Create(objectInfo, localFile, state));
+                        Log.Error("[LISTENER] Exception", t.Exception);
                     }
                     else
                     {
-                        //If there is no match we add them to the localFiles list
-                        //but only if the file is not marked for deletion
-                        var targetFile = Path.Combine(FileAgent.RootPath, relativePath);
-                        var fileStatus = StatusKeeper.GetFileStatus(targetFile);
-                        if (fileStatus!=FileStatus.Deleted)
-                            remoteOnly.Add(objectInfo);
-                        
-                        
+                        Log.Info("[LISTENER] Finished");
                     }
-                }
-
-                //At the end of the iteration, the *remote* list will contain the files that exist 
-                //only on the server
-
-                //Remote files should be downloaded
-                var actionsForRemote = from upFile in remoteOnly
-                                       select new CloudAction(CloudActionType.DownloadUnconditional,upFile);
-
-                //Common files should be checked on a per-case basis to detect differences, which is newer
-                var actionsForCommon = from pair in commonObjects
-                                       let objectInfo = pair.Item1
-                                       let localFile = pair.Item2
-                                       let state=pair.Item3
-                                       select new CloudAction(CloudActionType.MustSynch, 
-                                           localFile, objectInfo,state,BlockSize,BlockHash);
-                
-                    
-
-
-
-                //Collect all the actions
-                var allActions = actionsForRemote.Union(actionsForCommon);
-
-                //And remove those that are already being processed by the agent
-                var distinctActions =allActions
-                        .Except(_agent.GetEnumerable(), new PithosMonitor.LocalFileComparer())
-                        .ToList();
-
-                //Queue all the actions
-                foreach (var message in distinctActions)
-                {
-                    Post(message);
-                }
-
-
-                if(remoteOnly.Count>0)
-                    StatusNotification.NotifyChange(String.Format("Processing {0} new files", remoteOnly.Count));
+                    ProcessRemoteFiles(accountPath, nextSince);
 
-                Trace.TraceInformation("[LISTENER] End Processing");
-                Trace.CorrelationManager.StopLogicalOperation();
+                });
+                return loop;
+            }
+        }
 
-            });
+        //Creates an appropriate action for each server file
+        private IEnumerable<CloudAction> ObjectsToActions(IEnumerable<ObjectInfo> remote)
+        {
+            if (remote==null)
+                throw new ArgumentNullException();
+            Contract.EndContractBlock();
 
-            var loop = enqueueFiles.ContinueWith(t =>
+            //In order to avoid multiple iterations over the files, we iterate only once
+            //over the remote files
+            foreach (var objectInfo in remote)
             {
-                if (t.IsFaulted)
+                var relativePath = objectInfo.RelativeUrlToFilePath(CloudClient.UserName);
+                //and remove any matching objects from the list, adding them to the commonObjects list
+                if (FileAgent.Exists(relativePath))
                 {
-                    Trace.TraceError("[LISTENER] Exception: {0}", t.Exception);
+                    var localFile = FileAgent.GetFileInfo(relativePath);
+                    var state = FileState.FindByFilePath(localFile.FullName);
+                    //Common files should be checked on a per-case basis to detect differences, which is newer
+
+                    yield return new CloudAction(CloudActionType.MustSynch,
+                                                   localFile, objectInfo, state, BlockSize, BlockHash);
                 }
                 else
                 {
-                    Trace.TraceInformation("[LISTENER] Finished");
+                    //If there is no match we add them to the localFiles list
+                    //but only if the file is not marked for deletion
+                    var targetFile = Path.Combine(FileAgent.RootPath, relativePath);
+                    var fileStatus = StatusKeeper.GetFileStatus(targetFile);
+                    if (fileStatus != FileStatus.Deleted)
+                    {
+                        //Remote files should be downloaded
+                        yield return new CloudAction(CloudActionType.DownloadUnconditional, objectInfo);
+                    }
                 }
-                ProcessRemoteFiles(accountPath, nextSince);
-                
-            });
-            return loop;
+            }            
         }
 
         private void ProcessDeletedFiles(IEnumerable<ObjectInfo> trashObjects)
         {
             foreach (var trashObject in trashObjects)
             {
-                var relativePath = trashObject.Name.RelativeUrlToFilePath();
+                var relativePath = trashObject.RelativeUrlToFilePath(CloudClient.UserName);
                 //and remove any matching objects from the list, adding them to the commonObjects list
                 FileAgent.Delete(relativePath);                                
             }
         }
 
 
-        private void RenameCloudFile(string oldFileName, string newPath, string newFileName)
+        private void RenameCloudFile(string account, string container,string oldFileName, string newPath, string newFileName)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
             if (String.IsNullOrWhiteSpace(oldFileName))
                 throw new ArgumentNullException("oldFileName");
             if (String.IsNullOrWhiteSpace(oldFileName))
@@ -368,31 +470,45 @@ namespace Pithos.Core.Agents
             //The local file is already renamed
             this.StatusKeeper.SetFileOverlayStatus(newPath, FileOverlayStatus.Modified);
 
-            CloudClient.MoveObject(PithosContainer, oldFileName, PithosContainer, newFileName);
+            CloudClient.MoveObject(account, container, oldFileName, container, newFileName);
 
             this.StatusKeeper.SetFileStatus(newPath, FileStatus.Unchanged);
             this.StatusKeeper.SetFileOverlayStatus(newPath, FileOverlayStatus.Normal);
             NativeMethods.RaiseChangeNotification(newPath);
         }
 
-        private void DeleteCloudFile(string fileName)
-        {            
+        private void DeleteCloudFile(string account,string container, string fileName)
+        {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
+
             if (String.IsNullOrWhiteSpace(fileName))
                 throw new ArgumentNullException("fileName");
             if (Path.IsPathRooted(fileName))
                 throw new ArgumentException("The fileName should not be rooted","fileName");
             Contract.EndContractBlock();
 
-            this.StatusKeeper.SetFileOverlayStatus(fileName, FileOverlayStatus.Modified);
-            CloudClient.DeleteObject(PithosContainer, fileName, TrashContainer);
+            using ( log4net.LogicalThreadContext.Stacks["DeleteCloudFile"].Push("Delete"))
+            {
+                var info = FileAgent.GetFileInfo(fileName);
+                var path = info.FullName.ToLower();
+                this.StatusKeeper.SetFileOverlayStatus(path, FileOverlayStatus.Modified);
+
+                CloudClient.DeleteObject(account, container, fileName, TrashContainer);
 
-            this.StatusKeeper.ClearFileStatus(fileName);
-            this.StatusKeeper.RemoveFileOverlayStatus(fileName);
+                this.StatusKeeper.ClearFileStatus(path);
+            }
         }
 
         //Download a file.
-        private void DownloadCloudFile(string container, Uri relativeUrl, string localPath)
+        private void DownloadCloudFile(string account,string container, Uri relativeUrl, string localPath)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
             if (relativeUrl == null)
@@ -403,12 +519,14 @@ namespace Pithos.Core.Agents
                 throw new ArgumentException("The localPath must be rooted", "localPath");
             Contract.EndContractBlock();
             
-            var download=Task.Factory.Iterate(DownloadIterator(container, relativeUrl, localPath));
+            var download=Task.Factory.Iterate(DownloadIterator(account,container, relativeUrl, localPath));
             download.Wait();
         }
 
-        private IEnumerable<Task> DownloadIterator(string container, Uri relativeUrl, string localPath)
+        private IEnumerable<Task> DownloadIterator(string account,string container, Uri relativeUrl, string localPath)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
             if (relativeUrl==null)
@@ -432,22 +550,22 @@ namespace Pithos.Core.Agents
                 //var hashPath = Path.Combine(FileAgent.FragmentsPath, relativePath + ".hashmap");
                 
                 //Retrieve the hashmap from the server
-                var getHashMap = CloudClient.GetHashMap(container,url);
+                var getHashMap = CloudClient.GetHashMap(account, container, url);
                 yield return getHashMap;
                 
                 var serverHash=getHashMap.Result;
                 //If it's a small file
                 var downloadTask=(serverHash.Hashes.Count == 1 )
                     //Download it in one go
-                    ? DownloadEntireFile(container, relativeUrl, localPath) 
+                    ? DownloadEntireFile(account,container, relativeUrl, localPath) 
                     //Otherwise download it block by block
-                    : DownloadWithBlocks(container, relativeUrl, localPath, serverHash);
+                    : DownloadWithBlocks(account,container, relativeUrl, localPath, serverHash);
 
                 yield return downloadTask;
 
 
                 //Retrieve the object's metadata
-                var info=CloudClient.GetObjectInfo(container, url);
+                var info=CloudClient.GetObjectInfo(account, container, url);
                 //And store it
                 StatusKeeper.StoreInfo(localPath, info);
                 
@@ -458,8 +576,10 @@ namespace Pithos.Core.Agents
         }
 
         //Download a small file with a single GET operation
-        private Task DownloadEntireFile(string container, Uri relativeUrl, string localPath)
+        private Task DownloadEntireFile(string account,string container, Uri relativeUrl, string localPath)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
             if (relativeUrl == null)
@@ -480,7 +600,7 @@ namespace Pithos.Core.Agents
                 Directory.CreateDirectory(directoryPath);
 
             //Download the object to the temporary location
-            var getObject = CloudClient.GetObject(container, relativeUrl.ToString(), tempPath).ContinueWith(t =>
+            var getObject = CloudClient.GetObject(account, container, relativeUrl.ToString(), tempPath).ContinueWith(t =>
             {
                 t.PropagateExceptions();
                 //And move it to its actual location once downloading is finished
@@ -493,8 +613,10 @@ namespace Pithos.Core.Agents
         }
 
         //Download a file asynchronously using blocks
-        public Task DownloadWithBlocks(string container, Uri relativeUrl, string localPath, TreeHash serverHash)
+        public Task DownloadWithBlocks(string account,string container, Uri relativeUrl, string localPath, TreeHash serverHash)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
             if (relativeUrl == null)
@@ -507,11 +629,13 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException("serverHash");
             Contract.EndContractBlock();
             
-            return Task.Factory.Iterate(BlockDownloadIterator(container, relativeUrl, localPath, serverHash));
+            return Task.Factory.Iterate(BlockDownloadIterator(account,container, relativeUrl, localPath, serverHash));
         }
         
-        private IEnumerable<Task> BlockDownloadIterator(string container,Uri relativeUrl, string localPath,TreeHash serverHash)
+        private IEnumerable<Task> BlockDownloadIterator(string account,string container,Uri relativeUrl, string localPath,TreeHash serverHash)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
             if (relativeUrl == null)
@@ -547,10 +671,10 @@ namespace Pithos.Core.Agents
                 {
                     if (blockUpdater.UseOrphan(i, upHash))
                     {
-                        Trace.TraceInformation("[BLOCK GET] ORPHAN FOUND for {0} of {1} for {2}", i, upHashes.Length, localPath);
+                        Log.InfoFormat("[BLOCK GET] ORPHAN FOUND for {0} of {1} for {2}", i, upHashes.Length, localPath);
                         continue;
                     }
-                    Trace.TraceInformation("[BLOCK GET] START {0} of {1} for {2}",i,upHashes.Length,localPath);
+                    Log.InfoFormat("[BLOCK GET] START {0} of {1} for {2}", i, upHashes.Length, localPath);
                     var start = i*BlockSize;
                     //To download the last block just pass a null for the end of the range
                     long? end = null;
@@ -558,25 +682,29 @@ namespace Pithos.Core.Agents
                         end= ((i + 1)*BlockSize) ;
                             
                     //Download the missing block
-                    var getBlock = CloudClient.GetBlock(container, relativeUrl, start, end);
+                    var getBlock = CloudClient.GetBlock(account, container, relativeUrl, start, end);
                     yield return getBlock;
                     var block = getBlock.Result;
 
                     //and store it
                     yield return blockUpdater.StoreBlock(i, block);
-                    
 
-                    Trace.TraceInformation("[BLOCK GET] FINISH {0} of {1} for {2}", i, upHashes.Length, localPath);
+
+                    Log.InfoFormat("[BLOCK GET] FINISH {0} of {1} for {2}", i, upHashes.Length, localPath);
                 }
             }
 
             blockUpdater.Commit();
-            Trace.TraceInformation("[BLOCK GET] COMPLETE {0}", localPath);            
+            Log.InfoFormat("[BLOCK GET] COMPLETE {0}", localPath);            
         }
 
 
-        private void UploadCloudFile(FileInfo fileInfo, string hash,string topHash)
+        private void UploadCloudFile(string account,string container,FileInfo fileInfo, string hash,string topHash)
         {
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
             if (fileInfo == null)
                 throw new ArgumentNullException("fileInfo");
             if (String.IsNullOrWhiteSpace(hash))
@@ -585,13 +713,17 @@ namespace Pithos.Core.Agents
                 throw new ArgumentNullException("topHash");
             Contract.EndContractBlock();
 
-            var upload = Task.Factory.Iterate(UploadIterator(fileInfo, hash, topHash));
+            var upload = Task.Factory.Iterate(UploadIterator(account,container,fileInfo, hash, topHash));
             upload.Wait();
         }
 
-        private IEnumerable<Task> UploadIterator(FileInfo fileInfo, string hash,string topHash)
+        private IEnumerable<Task> UploadIterator(string account,string container,FileInfo fileInfo, string hash,string topHash)
         {
-            if (fileInfo==null)
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
+            if (fileInfo == null)
                 throw new ArgumentNullException("fileInfo");
             if (String.IsNullOrWhiteSpace(hash))
                 throw new ArgumentNullException("hash");
@@ -613,7 +745,7 @@ namespace Pithos.Core.Agents
 
 
                 //Even if GetObjectInfo times out, we can proceed with the upload            
-                var info = CloudClient.GetObjectInfo(PithosContainer, url);
+                var info = CloudClient.GetObjectInfo(account, container, url);
 
                 //If the file hashes match, abort the upload
                 if (hash.Equals(info.Hash, StringComparison.InvariantCultureIgnoreCase) ||
@@ -621,7 +753,7 @@ namespace Pithos.Core.Agents
                 {
                     //but store any metadata changes 
                     this.StatusKeeper.StoreInfo(fullFileName, info);
-                    Trace.TraceInformation("Skip upload of {0}, hashes match", fullFileName);
+                    Log.InfoFormat("Skip upload of {0}, hashes match", fullFileName);
                     yield break;
                 }
 
@@ -637,13 +769,13 @@ namespace Pithos.Core.Agents
                     var treeHash = Signature.CalculateTreeHashAsync(fileInfo.FullName, BlockSize, BlockHash);
                     yield return treeHash;
                     
-                    yield return Task.Factory.Iterate(UploadWithHashMap(fileInfo,url,treeHash));
+                    yield return Task.Factory.Iterate(UploadWithHashMap(account,container,fileInfo,url,treeHash));
                                         
                 }
                 else
                 {
                     //Otherwise do a regular PUT
-                    yield return CloudClient.PutObject(PithosContainer,url,fullFileName,hash);                    
+                    yield return CloudClient.PutObject(account, container, url, fullFileName, hash);                    
                 }
                 //If everything succeeds, change the file and overlay status to normal
                 this.StatusKeeper.SetFileState(fullFileName, FileStatus.Unchanged, FileOverlayStatus.Normal);
@@ -653,9 +785,13 @@ namespace Pithos.Core.Agents
             StatusNotification.NotifyChangedFile(fullFileName);
         }
 
-        public IEnumerable<Task> UploadWithHashMap(FileInfo fileInfo,string url,Task<TreeHash> treeHash)
+        public IEnumerable<Task> UploadWithHashMap(string account,string container,FileInfo fileInfo,string url,Task<TreeHash> treeHash)
         {
-            if(fileInfo==null)
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
+            if (fileInfo == null)
                 throw new ArgumentNullException("fileInfo");
             if (String.IsNullOrWhiteSpace(url))
                 throw new ArgumentNullException(url);
@@ -666,7 +802,7 @@ namespace Pithos.Core.Agents
             var fullFileName = fileInfo.FullName;
 
             //Send the hashmap to the server            
-            var hashPut = CloudClient.PutHashMap(PithosContainer, url, treeHash.Result);
+            var hashPut = CloudClient.PutHashMap(account, container, url, treeHash.Result);
             yield return hashPut;
 
             var missingHashes = hashPut.Result;
@@ -684,18 +820,18 @@ namespace Pithos.Core.Agents
                     var read = fileInfo.Read(buffer, offset, BlockSize);
 
                     //And upload the block                
-                    var postBlock = CloudClient.PostBlock(PithosContainer, buffer, 0, read);
+                    var postBlock = CloudClient.PostBlock(account, container, buffer, 0, read);
 
                     //We have to handle possible exceptions in a continuation because
                     //*yield return* can't appear inside a try block
                     yield return postBlock.ContinueWith(t => 
                         t.ReportExceptions(
-                            exc=>Trace.TraceError("[ERROR] uploading block {0} of {1}\n{2}",blockIndex, fullFileName, exc),
-                            ()=>Trace.TraceInformation("[BLOCK] Block {0} of {1} uploaded", blockIndex,fullFileName)));
+                            exc => Log.ErrorFormat("[ERROR] uploading block {0} of {1}\n{2}", blockIndex, fullFileName, exc),
+                            ()=>Log.InfoFormat("[BLOCK] Block {0} of {1} uploaded", blockIndex,fullFileName)));
                 }
 
                 //Repeat until there are no more missing hashes
-                hashPut = CloudClient.PutHashMap(PithosContainer, url, treeHash.Result);
+                hashPut = CloudClient.PutHashMap(account, container, url, treeHash.Result);
                 yield return hashPut;
                 missingHashes = hashPut.Result;
             }
similarity index 76%
rename from trunk/Pithos.Core/StatusKeeper.cs
rename to trunk/Pithos.Core/Agents/StatusAgent.cs
index 52e903a..fc77561 100644 (file)
@@ -1,35 +1,34 @@
 using System;
-using System.Collections;
 using System.Collections.Generic;
 using System.ComponentModel.Composition;
 using System.Diagnostics;
 using System.Diagnostics.Contracts;
 using System.IO;
 using System.Linq;
-using System.Linq.Expressions;
-using System.Security.Cryptography;
-using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
 using Castle.ActiveRecord;
 using Castle.ActiveRecord.Framework.Config;
-using NHibernate.Criterion;
-using NHibernate.Impl;
-using Pithos.Core.Agents;
 using Pithos.Interfaces;
-using Pithos.Network;
+using log4net;
+using log4net.Appender;
+using log4net.Config;
+using log4net.Layout;
 
-namespace Pithos.Core
+namespace Pithos.Core.Agents
 {
     [Export(typeof(IStatusChecker)),Export(typeof(IStatusKeeper))]
-    public class StatusKeeper:IStatusChecker,IStatusKeeper
+    public class StatusAgent:IStatusChecker,IStatusKeeper
     {
         [System.ComponentModel.Composition.Import]
         public IPithosSettings Settings { get; set; }
 
         private Agent<Action> _persistenceAgent;
 
-        public StatusKeeper()
+
+        private static readonly ILog log = LogManager.GetLogger(typeof(StatusAgent));
+
+        public StatusAgent()
         {            
             var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
             _pithosDataPath = Path.Combine(appDataPath , "Pithos");
@@ -38,17 +37,21 @@ namespace Pithos.Core
                 Directory.CreateDirectory(_pithosDataPath);
 
             //File.Delete(Path.Combine(_pithosDataPath, "pithos.db"));
+            
 
             var source = GetConfiguration(_pithosDataPath);
             ActiveRecordStarter.Initialize(source,typeof(FileState),typeof(FileTag));
+            ActiveRecordStarter.UpdateSchema();
 
             ;
             if (!File.Exists(Path.Combine(_pithosDataPath ,"pithos.db")))
                 ActiveRecordStarter.CreateSchema();
             
+            
+
             CleanupStaleStates();
 
-        }
+        }        
 
         private void CleanupStaleStates()
         {
@@ -127,7 +130,6 @@ namespace Pithos.Core
             if(existingFiles  ==null)
                 throw new ArgumentNullException("existingFiles");
             Contract.EndContractBlock();
-            Dictionary<int, int> j;
             
             //Find new or matching files with a left join to the stored states
             var fileStates = FileState.Queryable;
@@ -212,6 +214,8 @@ namespace Pithos.Core
                 throw new ArgumentNullException("path");
             if (!Path.IsPathRooted(path))
                 throw new ArgumentException("path must be a rooted path", "path");
+            if (getter == null)
+                throw new ArgumentNullException("getter");
             Contract.EndContractBlock();
 
 
@@ -236,9 +240,9 @@ namespace Pithos.Core
         {
             if (String.IsNullOrWhiteSpace(path))
                 throw new ArgumentNullException("path", "path can't be empty");
-
             if (setter==null)
                 throw new ArgumentNullException("setter", "setter can't be empty");
+            Contract.EndContractBlock();
 
             _persistenceAgent.Post(() =>
             {
@@ -268,6 +272,14 @@ namespace Pithos.Core
         /// <param name="setter"></param>
         private void UpdateStatus(string path, Action<FileState> setter)
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            if (setter == null)
+                throw new ArgumentNullException("setter");
+            Contract.EndContractBlock();
+
             Debug.Assert(!path.Contains("fragments"));
             Debug.Assert(!path.EndsWith(".ignore"));
 
@@ -303,6 +315,11 @@ namespace Pithos.Core
         /// <param name="setter"></param>
         private void UpdateStatus(Guid stateID, Action<FileState> setter)
         {
+            if (setter == null)
+                throw new ArgumentNullException("setter");
+            Contract.EndContractBlock();
+
+
             _persistenceAgent.Post(() =>
             {
                 using (new SessionScope())
@@ -322,6 +339,12 @@ namespace Pithos.Core
 
         public FileOverlayStatus GetFileOverlayStatus(string path)
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            Contract.EndContractBlock();
+
             try
             {
                 var state = FileState.FindByFilePath(path);
@@ -336,28 +359,66 @@ namespace Pithos.Core
 
         public void SetFileOverlayStatus(string path, FileOverlayStatus overlayStatus)
         {
-            SetStatus(path,s=>s.OverlayStatus=overlayStatus);
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted","path");
+            Contract.EndContractBlock();
+
+            SetStatus(path.ToLower(),s=>s.OverlayStatus=overlayStatus);
         }
 
-        public void RemoveFileOverlayStatus(string path)
+        /*public void RemoveFileOverlayStatus(string path)
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            Contract.EndContractBlock();
+
             _persistenceAgent.Post(() =>
                 InnerRemoveFileOverlayStatus(path));
         }
 
         private static void InnerRemoveFileOverlayStatus(string path)
         {
-            FileState.DeleteAll(String.Format("FilePath = '{0}'",path));
-        }
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            Contract.EndContractBlock();
+
+            FileState.DeleteByFilePath(path);            
+        }*/
 
         public void RenameFileOverlayStatus(string oldPath, string newPath)
         {
+            if (String.IsNullOrWhiteSpace(oldPath))
+                throw new ArgumentNullException("oldPath");
+            if (!Path.IsPathRooted(oldPath))
+                throw new ArgumentException("The oldPath must be rooted", "oldPath");
+            if (String.IsNullOrWhiteSpace(newPath))
+                throw new ArgumentNullException("newPath");
+            if (!Path.IsPathRooted(newPath))
+                throw new ArgumentException("The newPath must be rooted", "newPath");
+            Contract.EndContractBlock();
+
             _persistenceAgent.Post(() =>
                 InnerRenameFileOverlayStatus(oldPath, newPath));
         }
 
         private static void InnerRenameFileOverlayStatus(string oldPath, string newPath)
         {
+            if (String.IsNullOrWhiteSpace(oldPath))
+                throw new ArgumentNullException("oldPath");
+            if (!Path.IsPathRooted(oldPath))
+                throw new ArgumentException("The oldPath must be rooted", "oldPath");
+            if (String.IsNullOrWhiteSpace(newPath))
+                throw new ArgumentNullException("newPath");
+            if (!Path.IsPathRooted(newPath))
+                throw new ArgumentException("The newPath must be rooted", "newPath");
+            Contract.EndContractBlock();
+
             var state = FileState.FindByFilePath(oldPath);
 
             if (state == null)
@@ -373,10 +434,12 @@ namespace Pithos.Core
         public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus)
         {
             if (String.IsNullOrWhiteSpace(path))
-                throw new ArgumentNullException("path", "path can't be empty");
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
             Contract.EndContractBlock();
 
-            UpdateStatus(path,state=>
+            UpdateStatus(path.ToLower(),state=>
                                   {
                                       state.FileStatus = fileStatus;
                                       state.OverlayStatus = overlayStatus;
@@ -386,8 +449,10 @@ namespace Pithos.Core
         public void StoreInfo(string path,ObjectInfo objectInfo)
         {
             if (String.IsNullOrWhiteSpace(path))
-                throw new ArgumentNullException("path", "path can't be empty");
-            if (objectInfo==null)
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");            
+            if (objectInfo == null)
                 throw new ArgumentNullException("objectInfo", "objectInfo can't be empty");
             Contract.EndContractBlock();
 
@@ -433,24 +498,48 @@ namespace Pithos.Core
         
         public void SetFileStatus(string path, FileStatus status)
         {            
-            UpdateStatus(path, state=>state.FileStatus = status);
+            UpdateStatus(path.ToLower(), state=>state.FileStatus = status);
         }
 
         public FileStatus GetFileStatus(string path)
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            Contract.EndContractBlock();
+
             var state = FileState.FindByFilePath(path);
             return (state==null)?FileStatus.Missing:state.FileStatus ;
         }
 
         public void ClearFileStatus(string path)
         {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");
+            Contract.EndContractBlock();
+
             //TODO:SHOULDN'T need both clear file status and remove overlay status
-            _persistenceAgent.Post(()=> FileState.DeleteByFilePath(path));   
+            _persistenceAgent.Post(() =>
+            {
+                using (new SessionScope())
+                {
+                    FileState.DeleteByFilePath(path);
+                }
+            });   
         }
 
         public void UpdateFileChecksum(string path, string checksum)
-        {         
-            _persistenceAgent.Post(()=>
+        {
+            if (String.IsNullOrWhiteSpace(path))
+                throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("The path must be rooted", "path");            
+            Contract.EndContractBlock();
+
+            _persistenceAgent.Post(() =>
             {
                 using (new SessionScope())
                 {
index 6553636..2d630c1 100644 (file)
@@ -47,32 +47,32 @@ namespace Pithos.Core.Agents
         {
             if (state.Skip)
                 return CompletedTask<object>.Default;
-            string path = state.Path.ToLower();
-            string fileName = Path.GetFileName(path);
+            string path = state.Path.ToLower();            
 
             //Bypass deleted files, unless the status is Deleted
             if (!File.Exists(path) && state.Status != FileStatus.Deleted)
             {
                 state.Skip = true;
-                this.StatusKeeper.RemoveFileOverlayStatus(path);
+                this.StatusKeeper.ClearFileStatus(path);
                 return CompletedTask<object>.Default;
             }
             var fileState = FileState.FindByFilePath(path);
             var blockHash = NetworkAgent.BlockHash;
             var blockSize = NetworkAgent.BlockSize;
+            var info = new FileInfo(path);
 
             switch (state.Status)
             {
                 case FileStatus.Created:
                 case FileStatus.Modified:
-                    var info = new FileInfo(path);
                     NetworkAgent.Post(new CloudAction(CloudActionType.UploadUnconditional, info, ObjectInfo.Empty, fileState,blockSize,blockHash));
                     break;
                 case FileStatus.Deleted:
+                    string fileName = info.AsRelativeUrlTo(NetworkAgent.FileAgent.RootPath);                    
                     NetworkAgent.Post(new CloudAction(CloudActionType.DeleteCloud, null, new ObjectInfo { Name = fileName }, fileState, blockSize, blockHash));
                     break;
                 case FileStatus.Renamed:
-                    NetworkAgent.Post(new CloudAction(CloudActionType.RenameCloud, state.OldFileName, state.OldPath, state.FileName, state.Path));
+                    NetworkAgent.Post(new CloudMoveAction(CloudActionType.RenameCloud, state.OldFileName, state.OldPath, state.FileName, state.Path));
                     break;
             }
 
index 1fdf273..586b9e7 100644 (file)
@@ -1,6 +1,5 @@
 <?xml version="1.0" encoding="utf-8" ?>
 <activerecord>
-
   <config>
     <add key="connection.driver_class"  value="NHibernate.Driver.SQLite20Driver" />
     <add key="dialect"                  value="NHibernate.Dialect.SQLiteDialect" />
index 8d04ba3..bb0c481 100644 (file)
@@ -9,6 +9,7 @@ using System.IO;
 using System.Threading.Tasks;
 using Castle.ActiveRecord;
 using Castle.ActiveRecord.Framework;
+using Castle.ActiveRecord.Queries;
 using NHibernate.Engine;
 using Pithos.Core.Agents;
 using Pithos.Interfaces;
@@ -59,7 +60,17 @@ namespace Pithos.Core
 
         [Property]
         public DateTime? VersionTimeStamp { get; set; }
-        
+
+
+        [Property]
+        public bool IsShared { get; set; }
+
+        [Property]
+        public string SharedBy { get; set; }
+
+        [Property]
+        public bool ShareWrite { get; set; }
+
 
        [HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Lazy = true,Inverse=true)]
         public IList<FileTag> Tags
@@ -88,10 +99,15 @@ namespace Pithos.Core
                 throw new ArgumentNullException("absolutePath");
             Contract.EndContractBlock();
             
-            var stateKeys = from state in FileState.Queryable
-                            where state.FilePath == absolutePath.ToLower()
-                            select state.Id;
-            DeleteAll(stateKeys);                                           
+            FileState.Execute((session, instance) =>
+                             {
+                                 const string hqlDelete = "delete FileState where FilePath = :path";                                 
+                                 var deletedEntities = session.CreateQuery(hqlDelete)
+                                         .SetString("path", absolutePath.ToLower())
+                                         .ExecuteUpdate();
+                                 return null;
+                             },null);
+            
         }
 
         public static Task<FileState> CreateForAsync(string filePath,int blockSize,string algorithm)
index 080d898..ded754f 100644 (file)
@@ -13,7 +13,6 @@ namespace Pithos.Core
     {
         void SetFileOverlayStatus(string path,FileOverlayStatus status);
         void UpdateFileChecksum(string path, string checksum);
-        void RemoveFileOverlayStatus(string path);
         void SetFileStatus(string path, FileStatus status);
         FileStatus GetFileStatus(string path);
         void ClearFileStatus(string path);
@@ -38,34 +37,41 @@ namespace Pithos.Core
         public void SetFileOverlayStatus(string path, FileOverlayStatus status)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public void UpdateFileChecksum(string path, string checksum)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
             Contract.Requires(checksum!=null);
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
-        public void RemoveFileOverlayStatus(string path)
+     /*   public void RemoveFileOverlayStatus(string path)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
-        }
+            Contract.Requires(Path.IsPathRooted(path));
+        }*/
 
         public void RenameFileOverlayStatus(string oldPath, string newPath)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(oldPath));
+            Contract.Requires(Path.IsPathRooted(oldPath));
             Contract.Requires(!String.IsNullOrWhiteSpace(newPath));
+            Contract.Requires(Path.IsPathRooted(newPath));
 
         }
 
         public void SetFileStatus(string path, FileStatus status)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public FileStatus GetFileStatus(string path)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
 
             return default(FileStatus);
         }
@@ -73,6 +79,7 @@ namespace Pithos.Core
         public FileOverlayStatus GetFileOverlayStatus(string path)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
 
             return default(FileOverlayStatus);
         }
@@ -80,7 +87,6 @@ namespace Pithos.Core
         public void ProcessExistingFiles(IEnumerable<FileInfo> paths)
         {
             Contract.Requires(paths!=null);
-
         }
 
         public void Stop()
@@ -91,18 +97,21 @@ namespace Pithos.Core
         public void SetFileState(string path, FileStatus fileStatus, FileOverlayStatus overlayStatus)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public void StoreInfo(string path, ObjectInfo objectInfo)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
-            Contract.Requires(objectInfo!=null);            
+            Contract.Requires(objectInfo!=null);
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public T GetStatus<T>(string path, Func<FileState, T> getter, T defaultValue)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
             Contract.Requires(getter!=null);
+            Contract.Requires(Path.IsPathRooted(path));
 
             return default(T);
         }
@@ -111,17 +120,20 @@ namespace Pithos.Core
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
             Contract.Requires(setter != null);
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public void SetNetworkState(string path, NetworkOperation operation)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
-            Contract.Requires(Path.IsPathRooted(path));            
+            Contract.Requires(Path.IsPathRooted(path));
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public NetworkOperation GetNetworkState(string path)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
 
             return default(NetworkOperation);
         }
@@ -129,6 +141,7 @@ namespace Pithos.Core
         public void ClearFileStatus(string path)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(path));
+            Contract.Requires(Path.IsPathRooted(path));
         }
 
         public void SetPithosStatus(PithosStatus status)
index 906ce5d..5fd4c18 100644 (file)
@@ -17,6 +17,16 @@ namespace Pithos.Core
     //uploading.   
     public class NetworkGate:IDisposable
     {
+        public string FilePath { get; private set; }
+        public NetworkOperation Operation { get; private set; }
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(!String.IsNullOrWhiteSpace(FilePath));
+            Contract.Invariant(Path.IsPathRooted(FilePath));
+        }
+
         //The state of each file is stored in a thread-safe dictionary
         static readonly ConcurrentDictionary<string, NetworkOperation> NetworkState = new ConcurrentDictionary<string, NetworkOperation>();
 
@@ -74,17 +84,19 @@ namespace Pithos.Core
 
 
 
-        public string FilePath { get; private set; }
-        public NetworkOperation Operation { get; private set; }
+
+
 
         private NetworkGate(string path,NetworkOperation operation)
         {
             if (String.IsNullOrWhiteSpace(path))
                 throw new ArgumentNullException("path");
+            if (!Path.IsPathRooted(path))
+                throw new ArgumentException("path must be rooted","path");
             Contract.EndContractBlock();
 
             Operation = operation;
-            FilePath = path.ToLower();
+            FilePath = path.ToLower();            
 
             //Skip dummy operations (those with Operation == None)
             if (Operation != NetworkOperation.None)
index 0c607f2..b00f449 100644 (file)
@@ -12,7 +12,7 @@
     <AssemblyName>Pithos.Core</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+    <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
     <TargetFrameworkProfile>Client</TargetFrameworkProfile>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <PropertyGroup>
     <AssemblyOriginatorKeyFile>pithos.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Core.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>0</CodeContractsAnalysisWarningLevel>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Caliburn.Micro, Version=1.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
       <HintPath>..\Libraries\Caliburn.Micro.dll</HintPath>
   <ItemGroup>
     <Compile Include="Agents\Agent.cs" />
     <Compile Include="Agents\BlockUpdater.cs" />
-    <Compile Include="Agents\CloudAction.cs" />
+    <Compile Include="Agents\CloudTransferAction.cs" />
     <Compile Include="Agents\FileAgent.cs" />
     <Compile Include="Agents\FileInfoExtensions.cs" />
     <Compile Include="Agents\NetworkAgent.cs" />
     <Compile Include="IStatusService.cs" />
     <Compile Include="JobQueue.cs" />
     <Compile Include="NetworkGate.cs" />
-    <Compile Include="StatusKeeper.cs" />
+    <Compile Include="Agents\StatusAgent.cs" />
     <Compile Include="IPithosWorkflow.cs" />
     <Compile Include="IStatusKeeper.cs" />
     <Compile Include="NativeMethods.cs" />
index 9e93fdf..e097cf0 100644 (file)
@@ -44,9 +44,6 @@ namespace Pithos.Core
         [Import]
         public ICloudClient CloudClient { get; set; }
 
-        [Import]
-        public ICloudClient CloudListeningClient { get; set; }
-
         public IStatusNotification StatusNotification { get; set; }
 
         [Import]
@@ -126,23 +123,36 @@ namespace Pithos.Core
             CloudClient.AuthenticationUrl = this.AuthenticationUrl;
             CloudClient.Authenticate(UserName, ApiKey);
 
-            var pithosContainers = new[] { TrashContainer,PithosContainer};
+            //Create the two default containers if they are missing
+            var pithosContainers = new List<string>{ TrashContainer,PithosContainer};
             foreach (var container in pithosContainers)
-            {
-                var info=CloudClient.GetContainerInfo(container);
+            {                
+                var info=CloudClient.GetContainerInfo(this.UserName, container);
                 if (info == ContainerInfo.Empty)
                 {
-                    CloudClient.CreateContainer(container);
-                    info = CloudClient.GetContainerInfo(container);
+                    CloudClient.CreateContainer(this.UserName, container);
+                    info = CloudClient.GetContainerInfo(this.UserName, container);
                 }
                 _blockSize = info.BlockSize;
                 _blockHash = info.BlockHash;
             }
 
-            var allContainers= CloudClient.ListContainers();
+/*
+            //Create folders for any other containers
+            var allContainers = CloudClient.ListContainers();            
+            pithosContainers.AddRange(new[]{"shared","others"});
+
             var extraContainers = from container in allContainers
                                   where !pithosContainers.Contains(container.Name.ToLower())
-                                      select container;
+                                  select container;
+            
+            foreach (var container in extraContainers)
+            {
+                var containerPath = Path.Combine(this.RootPath, container.Name);
+                if (!Directory.Exists(containerPath))
+                    Directory.CreateDirectory(containerPath);
+            }
+*/
 
 
 
@@ -297,7 +307,7 @@ namespace Pithos.Core
             public override int GetHashCode(CloudAction obj)
             {
                 var hash1 = (obj.LocalFile == null) ? int.MaxValue : obj.LocalFile.FullName.GetHashCode();
-                var hash2 = (obj.CloudFile == null) ? int.MaxValue : (obj.CloudFile.Hash ?? obj.CloudFile.Name).GetHashCode();
+                var hash2 = (obj.CloudFile == null) ? int.MaxValue : (obj.CloudFile.Hash ?? obj.CloudFile.Name??"").GetHashCode();
                 var hash3 = obj.Action.GetHashCode();
                 return hash1 ^ hash2 & hash3;
             }
index 845632f..1badcc1 100644 (file)
@@ -59,7 +59,7 @@ namespace Pithos.Core
             if (String.IsNullOrWhiteSpace(path))
                 throw new ArgumentNullException("path", "The path parameter must not be emtpy");
 
-            StatusKeeper.ClearFileStatus(path);
+            StatusKeeper.ClearFileStatus(path.ToLower());
         }
        
 
index b94dafb..59c5c07 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.Linq;
 using System.Text;
 using System.Threading;
@@ -11,18 +12,32 @@ namespace Pithos.Core
     {
         public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next)
         {
+            if (first == null)
+                throw new ArgumentNullException("first");
+            if (next == null)
+                throw new ArgumentNullException("next");
+            Contract.EndContractBlock();
             return Then(first, next, CancellationToken.None);
         }
 
         public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next)
         {
+            if (first == null)
+                throw new ArgumentNullException("first");
+            if (next == null)
+                throw new ArgumentNullException("next");
+            Contract.EndContractBlock();
             return Then(first, next, CancellationToken.None);
         }
 
         public static Task<T2> Then<T1, T2>(this Task<T1> first, Func<T1, Task<T2>> next, CancellationToken cancellationToken)
         {
-            if (first == null) throw new ArgumentNullException("first");
-            if (next == null) throw new ArgumentNullException("next");
+            if (first == null) 
+                throw new ArgumentNullException("first");
+            if (next == null) 
+                throw new ArgumentNullException("next");
+            Contract.EndContractBlock();
+            Contract.Assume(TaskScheduler.Current!=null);
 
             var tcs = new TaskCompletionSource<T2>();
             first.ContinueWith(delegate
@@ -50,8 +65,12 @@ namespace Pithos.Core
 
         public static Task Then<T1>(this Task<T1> first, Func<T1, Task> next, CancellationToken cancellationToken)
         {
-            if (first == null) throw new ArgumentNullException("first");
-            if (next == null) throw new ArgumentNullException("next");
+            if (first == null)
+                throw new ArgumentNullException("first");
+            if (next == null)
+                throw new ArgumentNullException("next");
+            Contract.EndContractBlock();
+            Contract.Assume(TaskScheduler.Current != null);
 
             var tcs = new TaskCompletionSource<object>();
             first.ContinueWith(delegate
index 6be3253..0d04a0a 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.Globalization;
 using System.IO;
 
@@ -7,6 +8,7 @@ namespace Pithos.Interfaces
 {
     public class ObjectInfo
     {
+        private List<string> _knownContainers= new List<string>{"pithos","trash"};
         public string Name { get; set; }
         public string Hash { get; set; }
         public long Bytes { get; set; }
@@ -44,10 +46,31 @@ namespace Pithos.Interfaces
             get { return _version; }
             set { _version = value; }
         }
+
+        private string _allowedTo;
+        public string AllowedTo
+        {
+            get { return _allowedTo; }
+            set { _allowedTo = value; }
+        }
+
+        //Object permissions for Json deserialization, can be Read or Write
         
+        public string x_object_allowed_to
+        {
+            get { return _allowedTo; }
+            set { _allowedTo = value; }
+        }
+
+        //Object permissions for HEAD deserialization, can be Read or Write        
+        public string X_Object_Allowed_To
+        {
+            get { return _allowedTo; }
+            set { _allowedTo = value; }
+        }
+
         //Alias for VersionTimestamp, for Json deserialization purposes
-        //The x_object_version_timestamp returned by GET on a container is
-        //a float, probably due to a bug.
+        //The x_object_version_timestamp is a unix timestamp.
         public double? X_Object_Version_Timestamp
         {
             get
@@ -91,6 +114,10 @@ namespace Pithos.Interfaces
 
         public Stream Stream { get; set; }
 
+        public string Account { get; set; }
+
+        public string Container { get; set; }
+
 
         private void ExtractKnownExtensions()
         {
@@ -139,5 +166,37 @@ namespace Pithos.Interfaces
 
         private string _modifiedBy;
         private DateTime _epoch = new DateTime(1970, 1, 1);
+
+
+
+        public string RelativeUrlToFilePath(string currentAccount)
+        {
+            if (this.Name==null)
+                throw new InvalidOperationException("Name can't be null");
+            if (String.IsNullOrWhiteSpace(currentAccount))
+                throw new ArgumentNullException("currentAccount");
+            Contract.EndContractBlock();
+
+            if (this == Empty)
+                return String.Empty;
+
+            var unescaped = Uri.UnescapeDataString(this.Name);
+            var path = unescaped.Replace("/", "\\");
+            var pathParts=new Stack<string>();
+            pathParts.Push(path);
+            if (!String.IsNullOrWhiteSpace(Container) && !_knownContainers.Contains(Container))
+                pathParts.Push(Container);
+            if (!currentAccount.Equals(Account, StringComparison.InvariantCultureIgnoreCase))
+            {
+                if (Account != null)
+                {
+                    pathParts.Push(Account);
+                    pathParts.Push("others");
+                }
+            }
+            var finalPath=Path.Combine(pathParts.ToArray());
+            return finalPath;
+        }
+
     }
 }
\ No newline at end of file
index ea0bd49..9e964a0 100644 (file)
@@ -12,7 +12,7 @@
     <AssemblyName>Pithos.Interfaces</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+    <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
     <TargetFrameworkProfile>Client</TargetFrameworkProfile>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
     <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Interfaces.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+    <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>2</CodeContractsAnalysisWarningLevel>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Core" />
index 97e7e71..a361762 100644 (file)
@@ -4,6 +4,8 @@
 // </copyright>
 // -----------------------------------------------------------------------
 
+using System.Diagnostics.Contracts;
+
 namespace Pithos.Interfaces
 {
     using System;
@@ -38,6 +40,10 @@ namespace Pithos.Interfaces
         }
         public PithosSettingsData(IPithosSettings other)
         {
+            if (other == null)
+                throw new ArgumentNullException("other");
+            Contract.EndContractBlock();
+
             PithosPath = other.PithosPath;
             PithosSite = other.PithosSite;
             IconsPath = other.IconsPath;
index 3c15c58..089e1e2 100644 (file)
@@ -39,10 +39,10 @@ namespace Pithos.Network.Test
                
                     var hash = CalculateHash(filePath);
                     
-                    client.PutObject("Shares", info.Name, filePath);
+                    client.PutObject(null, "Shares", info.Name, filePath);
 
 
-                    var meta = client.GetObjectInfo("Shares", "DeveloperGuide.pdf");
+                    var meta = client.GetObjectInfo(null, "Shares", "DeveloperGuide.pdf");
                     Assert.IsNotEmpty(meta.Hash);
                     
 
index a1fb3c2..d356b08 100644 (file)
@@ -18,10 +18,11 @@ namespace Pithos.Network.Test
                                  AuthenticationUrl = @"https://pithos.dev.grnet.gr", 
                                  UsePithos = true
                              };
-            client.Authenticate("890329@vho.grnet.gr", "24989dce4e0fcb072f8cb60c8922be19");
+            var account = "890329@vho.grnet.gr";
+            client.Authenticate(account, "24989dce4e0fcb072f8cb60c8922be19");
             var fileName = @"vlc-1.1.11-win32.exe";
             var treeHash=Signature.CalculateTreeHashAsync(Path.Combine(@"e:\pithos\" ,fileName), 4*1024*1024 , "sha256").Result;
-            var result=client.PutHashMap("pithos", fileName, treeHash).Result;
+            var result = client.PutHashMap(account, "pithos", fileName, treeHash).Result;
 
             Assert.AreEqual(0,result.Count);
         }
index 79312f2..b4cb484 100644 (file)
@@ -43,12 +43,12 @@ namespace Pithos.Network.Test
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
 
-            client.CreateContainer("Pithos");
+            client.CreateContainer(null, "Pithos");
 
-            client.CreateFolder("Pithos", "RootFolder");
+            client.CreateFolder(null, "Pithos", "RootFolder");
 
-            Assert.IsTrue(client.ObjectExists("Pithos","RootFolder"));
-            var info = client.GetObjectInfo("Pithos", "RootFolder");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos","RootFolder"));
+            var info = client.GetObjectInfo(null, "Pithos", "RootFolder");
             Assert.AreEqual(@"application/directory",info.Content_Type);
             
         } 
@@ -59,20 +59,20 @@ namespace Pithos.Network.Test
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
 
-            client.CreateContainer("Pithos");
+            client.CreateContainer(null, "Pithos");
 
-            client.CreateFolder("Pithos", "RootFolder");
-            client.CreateFolder("Pithos", "RootFolder/Folder1");            
-            client.PutObject("Pithos","RootFolder/Folder1/test.txt","test.txt");
+            client.CreateFolder(null, "Pithos", "RootFolder");
+            client.CreateFolder(null, "Pithos", "RootFolder/Folder1");            
+            client.PutObject(null, "Pithos","RootFolder/Folder1/test.txt","test.txt");
 
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder/Folder1"));
-            var folderInfo = client.GetObjectInfo("Pithos", "RootFolder/Folder1");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder/Folder1"));
+            var folderInfo = client.GetObjectInfo(null, "Pithos", "RootFolder/Folder1");
             Assert.AreEqual(@"application/directory",folderInfo.Content_Type);
 
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder/Folder1/test.txt"));
-            var fileInfo = client.GetObjectInfo("Pithos", "RootFolder/Folder1/test.txt");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder/Folder1/test.txt"));
+            var fileInfo = client.GetObjectInfo(null, "Pithos", "RootFolder/Folder1/test.txt");
             Assert.AreEqual(@"application/octet-stream", fileInfo.Content_Type);
             
         }
@@ -80,26 +80,25 @@ namespace Pithos.Network.Test
         [Test]
         public void TestDeleteSubFolders([Values(true, false)]bool usePithos)
         {
-            throw new NotImplementedException();
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
 
-            client.CreateContainer("Pithos");
+            client.CreateContainer(null, "Pithos");
 
-            client.CreateFolder("Pithos", "RootFolder");
-            client.CreateFolder("Pithos", "RootFolder/Folder1");
+            client.CreateFolder(null, "Pithos", "RootFolder");
+            client.CreateFolder(null, "Pithos", "RootFolder/Folder1");
             var localInfo = new FileInfo("test.txt");
-            client.PutObject("Pithos","RootFolder/Folder1/test.txt","test.txt");
+            client.PutObject(null, "Pithos","RootFolder/Folder1/test.txt","test.txt");
 
-            client.DeleteObject("Pithos", "RootFolder/Folder1");
+            client.DeleteObject(null, "pithos", "RootFolder/Folder1","trash");
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder/Folder1"));
-            var folderInfo = client.GetObjectInfo("Pithos", "RootFolder/Folder1");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder/Folder1"));
+            var folderInfo = client.GetObjectInfo(null, "Pithos", "RootFolder/Folder1");
             Assert.AreEqual(@"application/directory",folderInfo.Content_Type);
 
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder/Folder1/test.txt"));
-            var fileInfo = client.GetObjectInfo("Pithos", "RootFolder/Folder1/test.txt");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder/Folder1/test.txt"));
+            var fileInfo = client.GetObjectInfo(null, "Pithos", "RootFolder/Folder1/test.txt");
             Assert.AreEqual(@"application/octet-stream", fileInfo.Content_Type);
             
         } 
@@ -110,14 +109,14 @@ namespace Pithos.Network.Test
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
 
-            client.CreateContainer("Pithos");
-            client.CreateFolder("Pithos", "RootFolder3");
-            client.CreateFolder("Pithos", "RootFolder3/Folder1");
+            client.CreateContainer(null, "Pithos");
+            client.CreateFolder(null, "Pithos", "RootFolder3");
+            client.CreateFolder(null, "Pithos", "RootFolder3/Folder1");
 
             
-            client.PutObject("Pithos", "RootFolder3/test1.txt", "test.txt");
-            client.PutObject("Pithos", "RootFolder3/test2.txt", "test.txt");
-            client.PutObject("Pithos", "RootFolder3/Folder1/test2.txt", "test.txt");
+            client.PutObject(null, "Pithos", "RootFolder3/test1.txt", "test.txt");
+            client.PutObject(null, "Pithos", "RootFolder3/test2.txt", "test.txt");
+            client.PutObject(null, "Pithos", "RootFolder3/Folder1/test2.txt", "test.txt");
 
             var files=client.ListObjects("Pithos", "RootFolder3");
             Assert.AreEqual(3,files.Count,"Unexpected number of root items");
@@ -135,21 +134,21 @@ namespace Pithos.Network.Test
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
 
-            client.CreateContainer("Pithos");
+            client.CreateContainer(null, "Pithos");
             
-            client.CreateFolder("Pithos", "RootFolder2/Folder1");
+            client.CreateFolder(null, "Pithos", "RootFolder2/Folder1");
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder2/Folder1"));
-            var folderInfo = client.GetObjectInfo("Pithos", "RootFolder2/Folder1");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder2/Folder1"));
+            var folderInfo = client.GetObjectInfo(null, "Pithos", "RootFolder2/Folder1");
             Assert.AreEqual(@"application/directory",folderInfo.Content_Type);
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder2"));
-            folderInfo = client.GetObjectInfo("Pithos", "RootFolder2");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder2"));
+            folderInfo = client.GetObjectInfo(null, "Pithos", "RootFolder2");
             Assert.AreEqual(@"application/directory", folderInfo.Content_Type);
 
 
-            Assert.IsTrue(client.ObjectExists("Pithos", "RootFolder2/Folder1/test.txt"));
-            var fileInfo = client.GetObjectInfo("Pithos", "RootFolder2/Folder1/test.txt");
+            Assert.IsTrue(client.ObjectExists(null, "Pithos", "RootFolder2/Folder1/test.txt"));
+            var fileInfo = client.GetObjectInfo(null, "Pithos", "RootFolder2/Folder1/test.txt");
             Assert.AreEqual(@"application/octet-stream", fileInfo.Content_Type);
             
         }
index 56bdc95..9ccd37d 100644 (file)
@@ -35,7 +35,7 @@ namespace Pithos.Network.Test
         {
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
-            client.CreateContainer("PITHOS");
+            client.CreateContainer(null, "PITHOS");
 
             IList<ContainerInfo> containers=client.ListContainers();
             Assert.IsTrue(containers.Count()>1);
@@ -46,10 +46,10 @@ namespace Pithos.Network.Test
         {
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
-            client.CreateContainer("PITHOS");            
-            client.PutObject("PITHOS","devguide.pdf","devguide.pdf");
+            client.CreateContainer(null, "PITHOS");            
+            client.PutObject(null, "PITHOS","devguide.pdf","devguide.pdf");
 
-            IList<ObjectInfo> objects=client.ListObjects("PITHOS");
+            IList<ObjectInfo> objects=client.ListObjects(null, "PITHOS");
             Assert.IsTrue(objects.Count()>=1);
         }
 
@@ -58,10 +58,10 @@ namespace Pithos.Network.Test
         {
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
-            client.CreateContainer("TestContainer");
-            bool dnzExists=client.ContainerExists("TestContainer");
+            client.CreateContainer(null, "TestContainer");
+            bool dnzExists=client.ContainerExists(null, "TestContainer");
             
-            bool mooExists = client.ContainerExists("Moo");
+            bool mooExists = client.ContainerExists(null, "Moo");
             Assert.IsTrue(dnzExists);
             
             Assert.IsFalse(mooExists);
@@ -73,16 +73,16 @@ namespace Pithos.Network.Test
             ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
             client.Authenticate(_userName, _apiKey);
 
-            client.CreateContainer("PITHOS");
-            client.CreateContainer("DotNetZone");
+            client.CreateContainer(null, "PITHOS");
+            client.CreateContainer(null, "DotNetZone");
 
-            var dnzInfo =client.GetContainerInfo("DotNetZone");
+            var dnzInfo =client.GetContainerInfo(null, "DotNetZone");
             Assert.AreNotEqual(ContainerInfo.Empty, dnzInfo,"Expected DotNetZone container not found");
 
-            var pithosInfo = client.GetContainerInfo("PITHOS");
+            var pithosInfo = client.GetContainerInfo(null, "PITHOS");
             Assert.AreNotEqual(ContainerInfo.Empty, pithosInfo,"Expected PITHOS container not found");
 
-            var mooInfo = client.GetContainerInfo("moo");
+            var mooInfo = client.GetContainerInfo(null, "moo");
             Assert.AreEqual(ContainerInfo.Empty, mooInfo);
         }
 
@@ -94,14 +94,14 @@ namespace Pithos.Network.Test
                                         ICloudClient client = new CloudFilesClient{UsePithos=usePithos};
                                         client.Authenticate(_userName, _apiKey);
 
-                                        client.CreateContainer("Shares2");
-                                        Assert.IsTrue(client.ContainerExists("Shares2"));
-                                        client.DeleteContainer("Shares2");
+                                        client.CreateContainer(null, "Shares2");
+                                        Assert.IsTrue(client.ContainerExists(null, "Shares2"));
+                                        client.DeleteContainer(null, "Shares2");
 
-                                        client.CreateContainer("Shares");
-                                        Assert.IsTrue(client.ContainerExists("Shares"));
-                                        client.CreateContainer("DotNetZone");
-                                        Assert.IsTrue(client.ContainerExists("DotNetZone"));
+                                        client.CreateContainer(null, "Shares");
+                                        Assert.IsTrue(client.ContainerExists(null, "Shares"));
+                                        client.CreateContainer(null, "DotNetZone");
+                                        Assert.IsTrue(client.ContainerExists(null, "DotNetZone"));
                                     });
         }
 
@@ -113,14 +113,14 @@ namespace Pithos.Network.Test
                 ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
                 client.Authenticate(_userName, _apiKey);
                 //Prepare test file
-                client.CreateContainer("Shares");                
+                client.CreateContainer(null, "Shares");                
                 string testFileName = "test.txt";                
                 var info = new FileInfo(testFileName);
-                client.PutObject("Shares",testFileName,testFileName);
+                client.PutObject(null, "Shares",testFileName,testFileName);
                 
 
                 string downloadFile = "test2.txt";
-                client.GetObject("Shares", testFileName, downloadFile)
+                client.GetObject(null, "Shares", testFileName, downloadFile)
                     .Wait();
 
                 Assert.IsTrue(File.Exists(downloadFile));
@@ -137,14 +137,14 @@ namespace Pithos.Network.Test
                                         ICloudClient client = new CloudFilesClient {UsePithos = usePithos};
                                         client.Authenticate(_userName, _apiKey);
 
-                                        client.CreateContainer("Shares");
-                                        Assert.IsTrue(client.ContainerExists("Shares"));
+                                        client.CreateContainer(null, "Shares");
+                                        Assert.IsTrue(client.ContainerExists(null, "Shares"));
 
                                         var filePath = "devguide.pdf";
                                         FileInfo info = new FileInfo(filePath);
 
 
-                                        client.PutObject("Shares", info.Name, filePath);
+                                        client.PutObject(null, "Shares", info.Name, filePath);
 
 
                                     });
@@ -159,19 +159,19 @@ namespace Pithos.Network.Test
                 ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
                 client.Authenticate(_userName, _apiKey);
 
-                client.CreateContainer("Shares");
-                Assert.IsTrue(client.ContainerExists("Shares"));
+                client.CreateContainer(null, "Shares");
+                Assert.IsTrue(client.ContainerExists(null, "Shares"));
 
                 var filePath = "devguide.pdf";
                 FileInfo info = new FileInfo(filePath);
 
                
-                    client.PutObject("Shares", info.Name, filePath);
+                    client.PutObject(null, "Shares", info.Name, filePath);
                 
 
 
                 
-                var meta=client.GetObjectInfo("Shares", filePath);
+                var meta=client.GetObjectInfo(null, "Shares", filePath);
                 Assert.IsNotEmpty(meta.Hash);
                 Assert.AreEqual(meta.Name,filePath);
 
@@ -187,19 +187,19 @@ namespace Pithos.Network.Test
                 ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
                 client.Authenticate(_userName, _apiKey);
 
-                client.CreateContainer("Shares");
-                Assert.IsTrue(client.ContainerExists("Shares"),"Container Exists");                
+                client.CreateContainer(null, "Shares");
+                Assert.IsTrue(client.ContainerExists(null, "Shares"),"Container Exists");                
 
                 var filePath = "devguide.pdf";
                 FileInfo info=new FileInfo(filePath);
                 
                
-                    client.PutObject("Shares",info.Name, filePath);
+                    client.PutObject(null, "Shares",info.Name, filePath);
                 
 
-                Assert.IsTrue(client.ObjectExists("Shares",info.Name),"File Created");
+                Assert.IsTrue(client.ObjectExists(null, "Shares",info.Name),"File Created");
 
-                client.DeleteObject("Shares/devguide.pdf",info.Name);
+                client.DeleteObject(null, "Shares/devguide.pdf",info.Name,"trash");
                 
             });
 
@@ -213,23 +213,23 @@ namespace Pithos.Network.Test
                 ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
                 client.Authenticate(_userName, _apiKey);
 
-                client.CreateContainer("Shares");
-                Assert.IsTrue(client.ContainerExists("Shares"),"Container Exists");                
+                client.CreateContainer(null, "Shares");
+                Assert.IsTrue(client.ContainerExists(null, "Shares"),"Container Exists");                
 
                 var filePath = "devguide.pdf";
                 FileInfo info=new FileInfo(filePath);
                 
                
-                    client.PutObject("Shares",info.Name, filePath );
+                    client.PutObject(null, "Shares",info.Name, filePath );
                 
 
-                Assert.IsTrue(client.ObjectExists("Shares",info.Name),"File Created");
+                Assert.IsTrue(client.ObjectExists(null, "Shares",info.Name),"File Created");
 
-                client.DeleteObject("Shares",info.Name);
-                Assert.IsFalse(client.ObjectExists("Shares", info.Name),"Container Deleted");
+                client.DeleteObject(null, "Shares",info.Name,"trash");
+                Assert.IsFalse(client.ObjectExists(null, "Shares", info.Name),"Container Deleted");
                 
-                client.DeleteObject("Moo",info.Name);
-                Assert.IsFalse(client.ObjectExists("Moo", info.Name),"Container Deleted");
+                client.DeleteObject(null, "Moo",info.Name,"trash");
+                Assert.IsFalse(client.ObjectExists(null, "Moo", info.Name),"Container Deleted");
                 
             });
 
@@ -272,21 +272,21 @@ namespace Pithos.Network.Test
                 ICloudClient client = new CloudFilesClient { UsePithos = usePithos };
                 client.Authenticate(_userName, _apiKey);
 
-                client.CreateContainer("Shares");
-                Assert.IsTrue(client.ContainerExists("Shares"),"Container Exists");                
+                client.CreateContainer(null, "Shares");
+                Assert.IsTrue(client.ContainerExists(null, "Shares"),"Container Exists");                
 
                 var filePath = "devguide.pdf";
                 FileInfo info=new FileInfo(filePath);
                 
                
-                    client.PutObject("Shares",info.Name, filePath);
+                    client.PutObject(null, "Shares",info.Name, filePath);
                 
 
-                Assert.IsTrue(client.ObjectExists("Shares",info.Name),"File Created");
+                Assert.IsTrue(client.ObjectExists(null, "Shares",info.Name),"File Created");
 
-                client.MoveObject("Shares",info.Name,"Shares","smoo.pdf");
-                Assert.IsFalse(client.ObjectExists("Shares", info.Name),"Original File Deleted");
-                Assert.IsTrue(client.ObjectExists("Shares", "smoo.pdf"), "Target File Created");
+                client.MoveObject(null, "Shares",info.Name,"Shares","smoo.pdf");
+                Assert.IsFalse(client.ObjectExists(null, "Shares", info.Name),"Original File Deleted");
+                Assert.IsTrue(client.ObjectExists(null, "Shares", "smoo.pdf"), "Target File Created");
 
             });
 
diff --git a/trunk/Pithos.Network.Test/ObjectInfoTest.cs b/trunk/Pithos.Network.Test/ObjectInfoTest.cs
new file mode 100644 (file)
index 0000000..4926ff4
--- /dev/null
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using NUnit.Framework;
+using Pithos.Interfaces;
+
+namespace Pithos.Network.Test
+{
+    [TestFixture]
+    class ObjectInfoTest
+    {
+        [Test]
+        public void RelativeUrlToFilePath()
+        {
+
+            var info1 = new ObjectInfo {Account = "pkanavos", Container = "pithos", Name = "somefolder/file1.txt"};
+            var path1=info1.RelativeUrlToFilePath("PKANAVOS");
+            Assert.AreEqual(@"somefolder\file1.txt",path1);
+            var path2 = info1.RelativeUrlToFilePath("user1");
+            Assert.AreEqual(@"others\pkanavos\somefolder\file1.txt", path2);
+            var info3 = new ObjectInfo { Account = "pkanavos", Name = "somefolder/file1.txt" };
+            var path3 = info1.RelativeUrlToFilePath("PKANAVOS");
+            Assert.AreEqual(@"somefolder\file1.txt", path1);
+
+        }
+    }
+}
index 8d5df7b..2ab1543 100644 (file)
     <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Network.Test.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="Newtonsoft.Json, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
@@ -71,6 +87,7 @@
     <Compile Include="CloudFilesClientTest.cs" />
     <Compile Include="FolderTests.cs" />
     <Compile Include="NetworkOpsTest.cs" />
+    <Compile Include="ObjectInfoTest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="SignatureTest.cs" />
   </ItemGroup>
index 141d33a..fe5ede3 100644 (file)
@@ -103,10 +103,11 @@ namespace Pithos.Core.Test
             CloudFilesClient client = new CloudFilesClient();
             client.AuthenticationUrl = @"https://pithos.dev.grnet.gr";
             client.UsePithos = true;
-            client.Authenticate("890329@vho.grnet.gr", "24989dce4e0fcb072f8cb60c8922be19");
+            var account = "890329@vho.grnet.gr";
+            client.Authenticate(account, "24989dce4e0fcb072f8cb60c8922be19");
             var fileName = @"vlc-1.1.11-win32.exe";
             var localHash= Signature.CalculateTreeHashAsync(Path.Combine(@"e:\pithos\", fileName), 4 * 1024 * 1024, "sha256").Result;
-            var upHash= client.GetHashMap("pithos", fileName).Result;
+            var upHash= client.GetHashMap(fileName, account, "pithos").Result;
 
             Assert.AreEqual(upHash.TopHash, localHash.TopHash);
 
index b01c7a3..f542831 100644 (file)
@@ -29,12 +29,6 @@ namespace Pithos.Network
         //RestClient provides a REST-friendly interface over the standard WebClient.
         private RestClient _baseClient;
         
-        //Some operations can specify a Timeout. The default value of all timeouts is 10 seconds
-        private readonly TimeSpan _shortTimeout = TimeSpan.FromSeconds(10);
-        
-        //Some operations can be retried before failing. The default number of retries is 5
-        private readonly int _retries = 5;        
-        
         //During authentication the client provides a UserName 
         public string UserName { get; set; }
         
@@ -48,7 +42,9 @@ namespace Pithos.Network
         //The client also receives a StorageUrl after authentication. All subsequent operations must
         //use this url
         public Uri StorageUrl { get; set; }
-        
+
+        protected Uri RootAddressUri { get; set; }
+
         public Uri Proxy { get; set; }
 
         public double DownloadPercentLimit { get; set; }
@@ -69,11 +65,14 @@ namespace Pithos.Network
         //
         public void Authenticate(string userName,string apiKey)
         {
-            Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName);
             if (String.IsNullOrWhiteSpace(userName))
                 throw new ArgumentNullException("userName", "The userName property can't be empty");
             if (String.IsNullOrWhiteSpace(apiKey))
                 throw new ArgumentNullException("apiKey", "The apiKey property can't be empty");
+            Contract.Ensures(_baseClient != null);
+            Contract.EndContractBlock();
+
+            Trace.TraceInformation("[AUTHENTICATE] Start for {0}", userName);
 
             if (_authenticated)
                 return;
@@ -87,6 +86,8 @@ namespace Pithos.Network
                 if (Proxy != null)
                     authClient.Proxy = new WebProxy(Proxy);
 
+                Contract.Assume(authClient.Headers!=null);
+
                 authClient.Headers.Add("X-Auth-User", UserName);
                 authClient.Headers.Add("X-Auth-Key", ApiKey);
 
@@ -99,6 +100,11 @@ namespace Pithos.Network
                     throw new InvalidOperationException("Failed to obtain storage url");
                 StorageUrl = new Uri(storageUrl);
                 
+                //Get the root address (StorageUrl without the account)
+                var usernameIndex=storageUrl.LastIndexOf(UserName);
+                var rootUrl = storageUrl.Substring(0, usernameIndex);
+                RootAddressUri = new Uri(rootUrl);
+                
                 var token = authClient.GetHeaderValue("X-Auth-Token");
                 if (String.IsNullOrWhiteSpace(token))
                     throw new InvalidOperationException("Failed to obtain token url");
@@ -112,16 +118,24 @@ namespace Pithos.Network
             if (Proxy!=null)
                 _baseClient.Proxy = new WebProxy(Proxy);
 
+            
+            
+            Contract.Assume(_baseClient.Headers!=null);
             _baseClient.Headers.Add("X-Auth-Token", Token);
 
             Trace.TraceInformation("[AUTHENTICATE] End for {0}", userName);
         }
 
 
-        public IList<ContainerInfo> ListContainers()
+
+        public IList<ContainerInfo> ListContainers(string account)
         {
+
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+                
                 client.Parameters.Clear();
                 client.Parameters.Add("format", "json");
                 var content = client.DownloadStringWithRetry("", 3);
@@ -135,9 +149,109 @@ namespace Pithos.Network
 
         }
 
+        private string GetAccountUrl(string account)
+        {
+            return new Uri(this.RootAddressUri, new Uri(account,UriKind.Relative)).AbsoluteUri;
+        }
+
+        public IList<ShareAccountInfo> ListSharingAccounts(DateTime? since=null)
+        {
+            Trace.TraceInformation("[START] ListSharingAccounts");
+
+            using (var client = new RestClient(_baseClient))
+            {
+                client.Parameters.Clear();
+                client.Parameters.Add("format", "json");
+                client.IfModifiedSince = since;
+
+                //Extract the username from the base address
+                client.BaseAddress = RootAddressUri.AbsoluteUri;
+                
+                var content = client.DownloadStringWithRetry(@"", 3);
+
+                client.AssertStatusOK("ListSharingAccounts failed");
+
+                //If the result is empty, return an empty list,
+                var infos = String.IsNullOrWhiteSpace(content)
+                    ? new List<ShareAccountInfo>()
+                    //Otherwise deserialize the account list into a list of ShareAccountInfos
+                    : JsonConvert.DeserializeObject<IList<ShareAccountInfo>>(content);
+
+                Trace.TraceInformation("[END] ListSharingAccounts");
+                return infos;
+            }
+        }
+
         //Request listing of all objects in a container modified since a specific time.
         //If the *since* value is missing, return all objects
-        public IList<ObjectInfo> ListObjects(string container, DateTime? since = null)
+        public IList<ObjectInfo> ListSharedObjects(DateTime? since = null)
+        {
+
+            Trace.TraceInformation("[START] ListSharedObjects");
+
+            var objects=new List<ObjectInfo>();
+            var accounts=ListSharingAccounts(since);
+            foreach (var account in accounts)
+            {
+                var containers=ListContainers(account.name);
+                foreach (var container in containers)
+                {
+                    var containerObjects=ListObjects(account.name, container.Name, account.last_modified);
+                    objects.AddRange(containerObjects);
+                }
+            }
+            return objects;
+        }
+
+        public void ShareObject(string account, string container, string objectName, string shareTo, bool read, bool write)
+        {
+            if (String.IsNullOrWhiteSpace(Token))
+                throw new InvalidOperationException("The Token is not set");
+            if (StorageUrl==null)
+                throw new InvalidOperationException("The StorageUrl is not set");
+            if (String.IsNullOrWhiteSpace(container))
+                throw new ArgumentNullException("container");
+            if (String.IsNullOrWhiteSpace(objectName))
+                throw new ArgumentNullException("objectName");
+            if (String.IsNullOrWhiteSpace(account))
+                throw new ArgumentNullException("account");
+            if (String.IsNullOrWhiteSpace(shareTo))
+                throw new ArgumentNullException("shareTo");
+            Contract.EndContractBlock();
+
+            using (var client = new RestClient(_baseClient))
+            {
+            
+                client.BaseAddress = GetAccountUrl(account);
+
+                client.Parameters.Clear();
+                client.Parameters.Add("format", "json");
+
+                string permission = "";
+                if (write)
+                    permission = String.Format("write={0}", shareTo); 
+                else if (read)
+                    permission=String.Format("read={0}", shareTo);                
+                client.Headers.Add("X-Object-Sharing",permission);
+                
+                var content = client.DownloadStringWithRetry(container, 3);
+
+                client.AssertStatusOK("ShareObject failed");
+
+                //If the result is empty, return an empty list,
+                var infos = String.IsNullOrWhiteSpace(content)
+                    ? new List<ObjectInfo>()
+                    //Otherwise deserialize the object list into a list of ObjectInfos
+                    : JsonConvert.DeserializeObject<IList<ObjectInfo>>(content);
+
+                Trace.TraceInformation("[END] ListObjects");                
+            }
+
+            
+        }
+
+
+        public IList<ObjectInfo> ListObjects(string account, string container, DateTime? since = null)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
@@ -147,6 +261,9 @@ namespace Pithos.Network
 
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Parameters.Clear();
                 client.Parameters.Add("format", "json");
                 client.IfModifiedSince = since;
@@ -160,6 +277,11 @@ namespace Pithos.Network
                     //Otherwise deserialize the object list into a list of ObjectInfos
                     : JsonConvert.DeserializeObject<IList<ObjectInfo>>(content);
 
+                foreach (var info in infos)
+                {
+                    info.Container = container;
+                    info.Account = account;
+                }
                 Trace.TraceInformation("[END] ListObjects");
                 return infos;
             }
@@ -167,7 +289,7 @@ namespace Pithos.Network
 
 
 
-        public IList<ObjectInfo> ListObjects(string container, string folder, DateTime? since = null)
+        public IList<ObjectInfo> ListObjects(string account, string container, string folder, DateTime? since = null)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
@@ -179,6 +301,9 @@ namespace Pithos.Network
 
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Parameters.Clear();
                 client.Parameters.Add("format", "json");
                 client.Parameters.Add("path", folder);
@@ -194,12 +319,17 @@ namespace Pithos.Network
         }
 
  
-        public bool ContainerExists(string container)
+        public bool ContainerExists(string account, string container)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
+            Contract.EndContractBlock();
+
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Parameters.Clear();
                 client.Head(container, 3);
 
@@ -216,14 +346,19 @@ namespace Pithos.Network
             }
         }
 
-        public bool ObjectExists(string container,string objectName)
+        public bool ObjectExists(string account, string container, string objectName)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
             if (String.IsNullOrWhiteSpace(objectName))
                 throw new ArgumentNullException("objectName", "The objectName property can't be empty");
+            Contract.EndContractBlock();
+
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Parameters.Clear();
                 client.Head(container + "/" + objectName, 3);
 
@@ -241,15 +376,18 @@ namespace Pithos.Network
 
         }
 
-        public ObjectInfo GetObjectInfo(string container, string objectName)
+        public ObjectInfo GetObjectInfo(string account, string container, string objectName)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
             if (String.IsNullOrWhiteSpace(objectName))
                 throw new ArgumentNullException("objectName", "The objectName property can't be empty");
+            Contract.EndContractBlock();
 
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);                    
                 try
                 {
                     client.Parameters.Clear();
@@ -308,16 +446,20 @@ namespace Pithos.Network
 
         }
 
-        public void CreateFolder(string container, string folder)
+        public void CreateFolder(string account, string container, string folder)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
             if (String.IsNullOrWhiteSpace(folder))
                 throw new ArgumentNullException("folder", "The folder property can't be empty");
+            Contract.EndContractBlock();
 
             var folderUrl=String.Format("{0}/{1}",container,folder);
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Parameters.Clear();
                 client.Headers.Add("Content-Type", @"application/directory");
                 client.Headers.Add("Content-Length", "0");
@@ -328,12 +470,17 @@ namespace Pithos.Network
             }
         }
 
-        public ContainerInfo GetContainerInfo(string container)
+        public ContainerInfo GetContainerInfo(string account, string container)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
+            Contract.EndContractBlock();
+
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);                
+
                 client.Head(container);
                 switch (client.StatusCode)
                 {
@@ -357,12 +504,17 @@ namespace Pithos.Network
             }
         }
 
-        public void CreateContainer(string container)
-        {
+        public void CreateContainer(string account, string container)
+        {            
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
+            Contract.EndContractBlock();
+
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.PutWithRetry(container, 3);
                 var expectedCodes = new[] {HttpStatusCode.Created, HttpStatusCode.Accepted, HttpStatusCode.OK};
                 if (!expectedCodes.Contains(client.StatusCode))
@@ -370,12 +522,17 @@ namespace Pithos.Network
             }
         }
 
-        public void DeleteContainer(string container)
+        public void DeleteContainer(string account, string container)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
+            Contract.EndContractBlock();
+
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.DeleteWithRetry(container, 3);
                 var expectedCodes = new[] {HttpStatusCode.NotFound, HttpStatusCode.NoContent};
                 if (!expectedCodes.Contains(client.StatusCode))
@@ -387,6 +544,7 @@ namespace Pithos.Network
         /// <summary>
         /// 
         /// </summary>
+        /// <param name="account"></param>
         /// <param name="container"></param>
         /// <param name="objectName"></param>
         /// <param name="fileName"></param>
@@ -394,7 +552,7 @@ namespace Pithos.Network
         /// <remarks>This method should have no timeout or a very long one</remarks>
         //Asynchronously download the object specified by *objectName* in a specific *container* to 
         // a local file
-        public Task GetObject(string container, string objectName, string fileName)
+        public Task GetObject(string account, string container, string objectName, string fileName)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
@@ -404,16 +562,19 @@ namespace Pithos.Network
 
             try
             {
-                //The container and objectName are relative names. They are joined with the client's
-                //BaseAddress to create the object's absolute address
-                var builder = GetAddressBuilder(container, objectName);
-                var uri = builder.Uri;
                 //WebClient, and by extension RestClient, are not thread-safe. Create a new RestClient
                 //object to avoid concurrency errors.
                 //
                 //Download operations take a long time therefore they have no timeout.
                 var client = new RestClient(_baseClient) { Timeout = 0 };
-               
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
+                //The container and objectName are relative names. They are joined with the client's
+                //BaseAddress to create the object's absolute address
+                var builder = client.GetAddressBuilder(container, objectName);
+                var uri = builder.Uri;
+
                 //Download progress is reported to the Trace log
                 Trace.TraceInformation("[GET] START {0}", objectName);
                 client.DownloadProgressChanged += (sender, args) => 
@@ -453,7 +614,7 @@ namespace Pithos.Network
 
         }
 
-        public Task<IList<string>> PutHashMap(string container, string objectName, TreeHash hash)
+        public Task<IList<string>> PutHashMap(string account, string container, string objectName, TreeHash hash)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
@@ -466,14 +627,19 @@ namespace Pithos.Network
             if (StorageUrl == null)
                 throw new InvalidOperationException("Invalid Storage Url");
             Contract.EndContractBlock();
+
+
+            //Don't use a timeout because putting the hashmap may be a long process
+            var client = new RestClient(_baseClient) { Timeout = 0 };
+            if (!String.IsNullOrWhiteSpace(account))
+                client.BaseAddress = GetAccountUrl(account);
+
             //The container and objectName are relative names. They are joined with the client's
             //BaseAddress to create the object's absolute address
-            var builder = GetAddressBuilder(container, objectName);
+            var builder = client.GetAddressBuilder(container, objectName);
             builder.Query = "format=json&hashmap";
             var uri = builder.Uri;
 
-            //Don't use a timeout because putting the hashmap may be a long process
-            var client = new RestClient(_baseClient) { Timeout = 0 };
 
             //Send the tree hash as Json to the server            
             client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
@@ -533,7 +699,7 @@ namespace Pithos.Network
 
         }
 
-        public Task<byte[]> GetBlock(string container, Uri relativeUrl, long start, long? end=null)
+        public Task<byte[]> GetBlock(string account, string container, Uri relativeUrl, long start, long? end)
         {
             if (String.IsNullOrWhiteSpace(Token))
                 throw new InvalidOperationException("Invalid Token");
@@ -549,12 +715,15 @@ namespace Pithos.Network
                 throw new ArgumentOutOfRangeException("start");
             Contract.EndContractBlock();
 
-            var builder = GetAddressBuilder(container, relativeUrl.ToString());
-
-            var uri = builder.Uri;
 
             //Don't use a timeout because putting the hashmap may be a long process
             var client = new RestClient(_baseClient) {Timeout = 0, RangeFrom = start, RangeTo = end};
+            if (!String.IsNullOrWhiteSpace(account))
+                client.BaseAddress = GetAccountUrl(account);
+
+            var builder = client.GetAddressBuilder(container, relativeUrl.ToString());
+            var uri = builder.Uri;
+
             return client.DownloadDataTask(uri)
                 .ContinueWith(t=>
                                   {
@@ -564,7 +733,7 @@ namespace Pithos.Network
         }
 
 
-        public Task PostBlock(string container,byte[] block,int offset,int count)
+        public Task PostBlock(string account, string container, byte[] block, int offset, int count)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
@@ -580,13 +749,17 @@ namespace Pithos.Network
                 throw new InvalidOperationException("Invalid Storage Url");                        
             Contract.EndContractBlock();
 
-            var builder = GetAddressBuilder(container, "");
+                        
+            //Don't use a timeout because putting the hashmap may be a long process
+            var client = new RestClient(_baseClient) { Timeout = 0 };
+            if (!String.IsNullOrWhiteSpace(account))
+                client.BaseAddress = GetAccountUrl(account);
+
+            var builder = client.GetAddressBuilder(container, "");
             //We are doing an update
             builder.Query = "update";
             var uri = builder.Uri;
-                        
-            //Don't use a timeout because putting the hashmap may be a long process
-            var client = new RestClient(_baseClient) { Timeout = 0 };                                   
+
             client.Headers[HttpRequestHeader.ContentType] = "application/octet-stream";
 
             Trace.TraceInformation("[BLOCK POST] START");
@@ -618,7 +791,7 @@ namespace Pithos.Network
         }
 
 
-        public Task<TreeHash> GetHashMap(string container, string objectName)
+        public Task<TreeHash> GetHashMap(string account, string container, string objectName)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container");
@@ -632,19 +805,22 @@ namespace Pithos.Network
 
             try
             {
-                //The container and objectName are relative names. They are joined with the client's
-                //BaseAddress to create the object's absolute address
-                var builder = GetAddressBuilder(container, objectName);
-                builder.Query="format=json&hashmap";
-                var uri = builder.Uri;                
                 //WebClient, and by extension RestClient, are not thread-safe. Create a new RestClient
                 //object to avoid concurrency errors.
                 //
                 //Download operations take a long time therefore they have no timeout.
                 //TODO: Do we really? this is a hashmap operation, not a download
                 var client = new RestClient(_baseClient) { Timeout = 0 };
-               
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
 
+                //The container and objectName are relative names. They are joined with the client's
+                //BaseAddress to create the object's absolute address
+                var builder = client.GetAddressBuilder(container, objectName);
+                builder.Query = "format=json&hashmap";
+                var uri = builder.Uri;
+                
                 //Start downloading the object asynchronously
                 var downloadTask = client.DownloadStringTask(uri);
                 
@@ -678,22 +854,17 @@ namespace Pithos.Network
 
         }
 
-        private UriBuilder GetAddressBuilder(string container, string objectName)
-        {
-            var builder = new UriBuilder(String.Join("/", _baseClient.BaseAddress, container, objectName));
-            return builder;
-        }
-
 
         /// <summary>
         /// 
         /// </summary>
+        /// <param name="account"></param>
         /// <param name="container"></param>
         /// <param name="objectName"></param>
         /// <param name="fileName"></param>
         /// <param name="hash">Optional hash value for the file. If no hash is provided, the method calculates a new hash</param>
         /// <remarks>>This method should have no timeout or a very long one</remarks>
-        public Task PutObject(string container, string objectName, string fileName, string hash = null)
+        public Task PutObject(string account, string container, string objectName, string fileName, string hash = null)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
@@ -703,14 +874,18 @@ namespace Pithos.Network
                 throw new ArgumentNullException("fileName", "The fileName property can't be empty");
             if (!File.Exists(fileName))
                 throw new FileNotFoundException("The file does not exist",fileName);
-
+            Contract.EndContractBlock();
             
             try
             {
-                var builder= GetAddressBuilder(container,objectName);
+
+                var client = new RestClient(_baseClient){Timeout=0};
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
+                var builder = client.GetAddressBuilder(container, objectName);
                 var uri = builder.Uri;
 
-                var client = new RestClient(_baseClient){Timeout=0};           
                 string etag = hash ?? CalculateHash(fileName);
 
                 client.Headers.Add("Content-Type", "application/octet-stream");
@@ -765,15 +940,19 @@ namespace Pithos.Network
             return hash;
         }
 
-        public void DeleteObject(string container, string objectName)
+       /* public void DeleteObject(string container, string objectName,string account)
         {
             if (String.IsNullOrWhiteSpace(container))
                 throw new ArgumentNullException("container", "The container property can't be empty");
             if (String.IsNullOrWhiteSpace(objectName))
                 throw new ArgumentNullException("objectName", "The objectName property can't be empty");
+            Contract.EndContractBlock();
+
             using (var client = new RestClient(_baseClient))
             {
-
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+                );
                 client.DeleteWithRetry(container + "/" + objectName, 3);
 
                 var expectedCodes = new[] {HttpStatusCode.NotFound, HttpStatusCode.NoContent};
@@ -781,9 +960,9 @@ namespace Pithos.Network
                     throw CreateWebException("DeleteObject", client.StatusCode);
             }
 
-        }
+        }*/
 
-        public void MoveObject(string sourceContainer, string oldObjectName, string targetContainer,string newObjectName)
+        public void MoveObject(string account, string sourceContainer, string oldObjectName, string targetContainer, string newObjectName)
         {
             if (String.IsNullOrWhiteSpace(sourceContainer))
                 throw new ArgumentNullException("sourceContainer", "The container property can't be empty");
@@ -793,12 +972,16 @@ namespace Pithos.Network
                 throw new ArgumentNullException("targetContainer", "The container property can't be empty");
             if (String.IsNullOrWhiteSpace(newObjectName))
                 throw new ArgumentNullException("newObjectName", "The newObjectName property can't be empty");
+            Contract.EndContractBlock();
 
             var targetUrl = targetContainer + "/" + newObjectName;
             var sourceUrl = String.Format("/{0}/{1}", sourceContainer, oldObjectName);
 
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Headers.Add("X-Move-From", sourceUrl);
                 client.PutWithRetry(targetUrl, 3);
 
@@ -808,7 +991,7 @@ namespace Pithos.Network
             }
         }
 
-        public void DeleteObject(string sourceContainer, string objectName, string targetContainer)
+        public void DeleteObject(string account, string sourceContainer, string objectName, string targetContainer)
         {            
             if (String.IsNullOrWhiteSpace(sourceContainer))
                 throw new ArgumentNullException("sourceContainer", "The container property can't be empty");
@@ -816,12 +999,16 @@ namespace Pithos.Network
                 throw new ArgumentNullException("objectName", "The oldObjectName property can't be empty");
             if (String.IsNullOrWhiteSpace(targetContainer))
                 throw new ArgumentNullException("targetContainer", "The container property can't be empty");
+            Contract.EndContractBlock();
 
             var targetUrl = targetContainer + "/" + objectName;
             var sourceUrl = String.Format("/{0}/{1}", sourceContainer, objectName);
 
             using (var client = new RestClient(_baseClient))
             {
+                if (!String.IsNullOrWhiteSpace(account))
+                    client.BaseAddress = GetAccountUrl(account);
+
                 client.Headers.Add("X-Move-From", sourceUrl);
                 client.PutWithRetry(targetUrl, 3);
 
@@ -839,4 +1026,10 @@ namespace Pithos.Network
 
         
     }
+
+    public class ShareAccountInfo
+    {
+        public DateTime? last_modified { get; set; }
+        public string name { get; set; }
+    }
 }
diff --git a/trunk/Pithos.Network/ContainerInfo.cs b/trunk/Pithos.Network/ContainerInfo.cs
new file mode 100644 (file)
index 0000000..29907d7
--- /dev/null
@@ -0,0 +1,13 @@
+namespace Pithos.Network
+{
+    public class ContainerInfo
+    {
+        public string Name { get; set; }
+        public long Count { get; set; }
+        public long Bytes { get; set; }
+        public string BlockHash { get; set; }
+        public int BlockSize { get; set; }
+
+        public static ContainerInfo Empty=new ContainerInfo();
+    }
+}
\ No newline at end of file
index fde14dd..6643ab8 100644 (file)
@@ -20,29 +20,40 @@ namespace Pithos.Network
         double UploadPercentLimit { get; set; }
         string AuthenticationUrl { get; set; }
 
-
-        IList<ContainerInfo> ListContainers();
-        IList<ObjectInfo> ListObjects(string container,DateTime? since=null);
-        IList<ObjectInfo> ListObjects(string container, string folder, DateTime? since = null); 
-        bool ContainerExists(string container);
-        ContainerInfo GetContainerInfo(string container);
-        void CreateContainer(string container);
-        void DeleteContainer(string container);
+        #region Container operations
         
-        Task GetObject(string container, string objectName, string fileName);
-        Task PutObject(string container, string objectName, string fileName, string hash = null);
-        void DeleteObject(string container, string objectName, string trashContainer);
-        void DeleteObject(string container, string objectName);
-        void MoveObject(string sourceContainer, string oldObjectName, string targetContainer,string newObjectName);
-        bool ObjectExists(string container,string objectName);
-        ObjectInfo GetObjectInfo(string container, string objectName);
-        void CreateFolder(string container, string folder);
-
-
-        Task<TreeHash> GetHashMap(string container, string objectName);
-        Task<IList<string>> PutHashMap(string container, string objectName, TreeHash hash);
-        Task PostBlock(string container,byte[] block,int offset,int count);
-        Task<byte[]> GetBlock(string container, Uri relativeUrl, long start, long? end);
+        IList<ContainerInfo> ListContainers(string account=null);
+        IList<ObjectInfo> ListObjects(string account, string container, DateTime? since = null);
+        IList<ObjectInfo> ListObjects(string account, string container, string folder, DateTime? since = null);
+        bool ContainerExists(string account, string container);
+        ContainerInfo GetContainerInfo(string account, string container);
+        void CreateContainer(string account, string container);
+        void DeleteContainer(string account, string container);
+        #endregion
+
+        #region Object operations        
+        Task GetObject(string account, string container, string objectName, string fileName);
+        Task PutObject(string account, string container, string objectName, string fileName, string hash = null);
+        void DeleteObject(string account, string container, string objectName, string trashContainer);
+        //void DeleteObject(string container, string objectName, string account = null);
+        void MoveObject(string account, string sourceContainer, string oldObjectName, string targetContainer, string newObjectName);
+        bool ObjectExists(string account, string container, string objectName);
+        ObjectInfo GetObjectInfo(string account, string container, string objectName);
+        void CreateFolder(string account, string container, string folder);
+        #endregion
+
+        #region Hashmap operations        
+        Task<TreeHash> GetHashMap(string account, string container, string objectName);
+        Task<IList<string>> PutHashMap(string account, string container, string objectName, TreeHash hash);
+        Task PostBlock(string account, string container, byte[] block, int offset, int count);
+        Task<byte[]> GetBlock(string account, string container, Uri relativeUrl, long start, long? end);
+        #endregion
+
+        #region Sharing operations        
+        IList<ObjectInfo> ListSharedObjects(DateTime? since);
+        void ShareObject(string account, string container, string objectName, string shareTo, bool read, bool write);
+
+        #endregion
     }
 
 
@@ -74,7 +85,7 @@ namespace Pithos.Network
             
         }
 
-        public IList<ContainerInfo> ListContainers()
+        public IList<ContainerInfo> ListContainers(string account=null)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);            
@@ -82,7 +93,27 @@ namespace Pithos.Network
             return default(IList<ContainerInfo>);
         }
 
-        public IList<ObjectInfo> ListObjects(string container, DateTime? since = null)
+        public IList<ObjectInfo> ListSharedObjects(DateTime? since)
+        {
+            Contract.Requires(!String.IsNullOrWhiteSpace(Token));
+            Contract.Requires(StorageUrl != null);
+
+            return default(IList<ObjectInfo>);
+        }
+
+        public void ShareObject(string account, string container, string objectName, string shareTo, bool read, bool write)
+        {
+            Contract.Requires(!String.IsNullOrWhiteSpace(Token));
+            Contract.Requires(StorageUrl != null);
+            Contract.Requires(!String.IsNullOrWhiteSpace(container));
+            Contract.Requires(!String.IsNullOrWhiteSpace(objectName));
+            Contract.Requires(!String.IsNullOrWhiteSpace(account));
+            Contract.Requires(!String.IsNullOrWhiteSpace(shareTo));
+   
+        }
+
+
+        public IList<ObjectInfo> ListObjects(string account, string container, DateTime? since = null)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -91,7 +122,7 @@ namespace Pithos.Network
             return default(IList<ObjectInfo>);
         }
 
-        public IList<ObjectInfo> ListObjects(string container, string folder, DateTime? since = null)
+        public IList<ObjectInfo> ListObjects(string account, string container, string folder, DateTime? since = null)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -101,7 +132,7 @@ namespace Pithos.Network
             return default(IList<ObjectInfo>);
         }
 
-        public bool ContainerExists(string container)
+        public bool ContainerExists(string account, string container)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -110,7 +141,7 @@ namespace Pithos.Network
             return default(bool);
         }
 
-        public ContainerInfo GetContainerInfo(string container)
+        public ContainerInfo GetContainerInfo(string account, string container)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -119,21 +150,21 @@ namespace Pithos.Network
             return default(ContainerInfo);
         }
 
-        public void CreateContainer(string container)
+        public void CreateContainer(string account, string container)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
             Contract.Requires(!String.IsNullOrWhiteSpace(container));
         }
 
-        public void DeleteContainer(string container)
+        public void DeleteContainer(string account, string container)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
             Contract.Requires(!String.IsNullOrWhiteSpace(container));
         }
 
-        public Task GetObject(string container, string objectName, string fileName)
+        public Task GetObject(string account, string container, string objectName, string fileName)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -143,7 +174,7 @@ namespace Pithos.Network
             return default(Task);
         }
 
-        public Task PutObject(string container, string objectName, string fileName, string hash = null)
+        public Task PutObject(string account, string container, string objectName, string fileName, string hash = null)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -154,7 +185,7 @@ namespace Pithos.Network
             return default(Task);
         }
 
-        public void DeleteObject(string container, string objectName, string trashContainer)
+        public void DeleteObject(string account, string container, string objectName, string trashContainer)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -163,7 +194,7 @@ namespace Pithos.Network
             Contract.Requires(!String.IsNullOrWhiteSpace(trashContainer));
         }
 
-        public void DeleteObject(string container, string objectName)
+        public void DeleteObject(string container, string objectName, string account = null)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -171,7 +202,7 @@ namespace Pithos.Network
             Contract.Requires(!String.IsNullOrWhiteSpace(objectName));            
         }
 
-        public void MoveObject(string sourceContainer, string oldObjectName, string targetContainer,string newObjectName)
+        public void MoveObject(string account, string sourceContainer, string oldObjectName, string targetContainer, string newObjectName)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -181,7 +212,7 @@ namespace Pithos.Network
             Contract.Requires(!String.IsNullOrWhiteSpace(newObjectName));
         }
 
-        public bool ObjectExists(string container,string objectName)
+        public bool ObjectExists(string account, string container, string objectName)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -191,7 +222,7 @@ namespace Pithos.Network
             return default(bool);
         }
 
-        public ObjectInfo GetObjectInfo(string container,string objectName)
+        public ObjectInfo GetObjectInfo(string account, string container, string objectName)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl!=null);
@@ -201,7 +232,7 @@ namespace Pithos.Network
             return default(ObjectInfo);
         }
 
-        public void CreateFolder(string container, string folder)
+        public void CreateFolder(string account, string container, string folder)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -209,7 +240,7 @@ namespace Pithos.Network
             Contract.Requires(!String.IsNullOrWhiteSpace(folder));            
         }
 
-        public Task<TreeHash> GetHashMap(string container, string objectName)
+        public Task<TreeHash> GetHashMap(string account, string container, string objectName)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -219,7 +250,7 @@ namespace Pithos.Network
             return default(Task<TreeHash>);
         }
 
-        public Task<IList<string>> PutHashMap(string container, string objectName, TreeHash hash)
+        public Task<IList<string>> PutHashMap(string account, string container, string objectName, TreeHash hash)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -230,7 +261,7 @@ namespace Pithos.Network
             return default(Task<IList<string>>);
         }
 
-        public Task PostBlock(string container,byte[] block,int offset,int count)
+        public Task PostBlock(string account, string container, byte[] block, int offset, int count)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -244,7 +275,7 @@ namespace Pithos.Network
             return default(Task);
         }
 
-        public Task<byte[]> GetBlock(string container, Uri relativeUrl, long start, long? end)
+        public Task<byte[]> GetBlock(string account, string container, Uri relativeUrl, long start, long? end)
         {
             Contract.Requires(!String.IsNullOrWhiteSpace(Token));
             Contract.Requires(StorageUrl != null);
@@ -255,16 +286,6 @@ namespace Pithos.Network
 
             return default(Task<byte[]>);
         }
-    }
-
-    public class ContainerInfo
-    {
-        public string Name { get; set; }
-        public long Count { get; set; }
-        public long Bytes { get; set; }
-        public string BlockHash { get; set; }
-        public int BlockSize { get; set; }
 
-        public static ContainerInfo Empty=new ContainerInfo();
     }
 }
index 7c5b7ed..20defa9 100644 (file)
@@ -12,7 +12,7 @@
     <AssemblyName>Pithos.Network</AssemblyName>
     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
-    <CodeContractsAssemblyMode>1</CodeContractsAssemblyMode>
+    <CodeContractsAssemblyMode>0</CodeContractsAssemblyMode>
     <TargetFrameworkProfile>Client</TargetFrameworkProfile>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
   <PropertyGroup>
     <AssemblyOriginatorKeyFile>pithos.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.Network.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+    <CodeContractsEnableRuntimeChecking>True</CodeContractsEnableRuntimeChecking>
+    <CodeContractsRuntimeOnlyPublicSurface>False</CodeContractsRuntimeOnlyPublicSurface>
+    <CodeContractsRuntimeThrowOnFailure>True</CodeContractsRuntimeThrowOnFailure>
+    <CodeContractsRuntimeCallSiteRequires>False</CodeContractsRuntimeCallSiteRequires>
+    <CodeContractsRuntimeSkipQuantifiers>False</CodeContractsRuntimeSkipQuantifiers>
+    <CodeContractsRunCodeAnalysis>True</CodeContractsRunCodeAnalysis>
+    <CodeContractsNonNullObligations>True</CodeContractsNonNullObligations>
+    <CodeContractsBoundsObligations>True</CodeContractsBoundsObligations>
+    <CodeContractsArithmeticObligations>True</CodeContractsArithmeticObligations>
+    <CodeContractsEnumObligations>True</CodeContractsEnumObligations>
+    <CodeContractsRedundantAssumptions>False</CodeContractsRedundantAssumptions>
+    <CodeContractsRunInBackground>True</CodeContractsRunInBackground>
+    <CodeContractsShowSquigglies>True</CodeContractsShowSquigglies>
+    <CodeContractsUseBaseLine>False</CodeContractsUseBaseLine>
+    <CodeContractsEmitXMLDocs>True</CodeContractsEmitXMLDocs>
+    <CodeContractsCustomRewriterAssembly />
+    <CodeContractsCustomRewriterClass />
+    <CodeContractsLibPaths />
+    <CodeContractsExtraRewriteOptions />
+    <CodeContractsExtraAnalysisOptions />
+    <CodeContractsBaseLineFile />
+    <CodeContractsCacheAnalysisResults>True</CodeContractsCacheAnalysisResults>
+    <CodeContractsRuntimeCheckingLevel>Full</CodeContractsRuntimeCheckingLevel>
+    <CodeContractsReferenceAssembly>Build</CodeContractsReferenceAssembly>
+    <CodeContractsAnalysisWarningLevel>2</CodeContractsAnalysisWarningLevel>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.ComponentModel.Composition" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="CloudFilesClient.cs" />
+    <Compile Include="ContainerInfo.cs" />
     <Compile Include="ICloudClient.cs" />
     <Compile Include="RestClient.cs">
       <SubType>Component</SubType>
index c58d469..8a0b984 100644 (file)
@@ -40,7 +40,17 @@ namespace Pithos.Network
         private readonly Dictionary<string, string> _parameters=new Dictionary<string, string>();
         public Dictionary<string, string> Parameters
         {
-            get { return _parameters; }            
+            get
+            {
+                Contract.Ensures(_parameters!=null);
+                return _parameters;
+            }            
+        }
+
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(Headers!=null);    
         }
 
         public RestClient():base()
@@ -52,6 +62,10 @@ namespace Pithos.Network
         public RestClient(RestClient other)
             : base()
         {
+            if (other==null)
+                throw new ArgumentNullException("other");
+            Contract.EndContractBlock();
+
             CopyHeaders(other);
             Timeout = other.Timeout;
             Retries = other.Retries;
@@ -69,7 +83,7 @@ namespace Pithos.Network
         {
             TimedOut = false;
             var webRequest = base.GetWebRequest(address);
-            var request = webRequest as HttpWebRequest;
+            var request = (HttpWebRequest)webRequest;
             if (IfModifiedSince.HasValue)
                 request.IfModifiedSince = IfModifiedSince.Value;
             request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
@@ -96,7 +110,14 @@ namespace Pithos.Network
             return response;
         }
 
-
+        private readonly List<HttpStatusCode> _allowedStatusCodes=new List<HttpStatusCode>{HttpStatusCode.NotModified};
+        public List<HttpStatusCode> AllowedStatusCodes
+        {
+            get
+            {
+                return _allowedStatusCodes;
+            }            
+        }
 
         protected override WebResponse GetWebResponse(WebRequest request)
         {
@@ -113,8 +134,14 @@ namespace Pithos.Network
                 if (exc.Response!=null)
                 {
                     var response = (exc.Response as HttpWebResponse);
-                    if (response.StatusCode == HttpStatusCode.NotModified)
+                    if (AllowedStatusCodes.Contains(response.StatusCode))
+                    {
+                        StatusCode = response.StatusCode;
+                        LastModified = response.LastModified;
+                        StatusDescription = response.StatusDescription;
+
                         return response;
+                    }
                     if (exc.Response.ContentLength > 0)
                     {
                         string content = GetContent(exc.Response);
@@ -129,6 +156,10 @@ namespace Pithos.Network
 
         private static string GetContent(WebResponse webResponse)
         {
+            if (webResponse == null)
+                throw new ArgumentNullException("webResponse");
+            Contract.EndContractBlock();
+
             string content;
             using (var stream = webResponse.GetResponseStream())
             using (var reader = new StreamReader(stream))
@@ -168,6 +199,7 @@ namespace Pithos.Network
 
         public void Head(string address,int retries=0)
         {
+            AllowedStatusCodes.Add(HttpStatusCode.NotFound);
             RetryWithoutContent(address, retries, "HEAD");
         }
 
@@ -183,6 +215,10 @@ namespace Pithos.Network
 
         public string GetHeaderValue(string headerName)
         {
+            if (this.ResponseHeaders==null)
+                throw new InvalidOperationException("ResponseHeaders are null");
+            Contract.EndContractBlock();
+
             var values=this.ResponseHeaders.GetValues(headerName);
             if (values == null)
                 throw new WebException(String.Format("The {0}  header is missing", headerName));
@@ -293,9 +329,12 @@ namespace Pithos.Network
         /// <param name="source">The RestClient from which the headers are copied</param>
         public void CopyHeaders(RestClient source)
         {
-            Contract.Requires(source != null, "source can't be null");
             if (source == null)
                 throw new ArgumentNullException("source", "source can't be null");
+            Contract.EndContractBlock();
+            //The Headers getter initializes the property, it is never null
+            Contract.Assume(Headers!=null);
+                
             CopyHeaders(source.Headers,Headers);
         }
         
@@ -306,12 +345,12 @@ namespace Pithos.Network
         /// <param name="target">The target collection to which the headers are copied</param>
         public static void CopyHeaders(WebHeaderCollection source,WebHeaderCollection target)
         {
-            Contract.Requires(source != null, "source can't be null");
-            Contract.Requires(target != null, "target can't be null");
             if (source == null)
                 throw new ArgumentNullException("source", "source can't be null");
             if (target == null)
                 throw new ArgumentNullException("target", "target can't be null");
+            Contract.EndContractBlock();
+
             for (int i = 0; i < source.Count; i++)
             {
                 target.Add(source.GetKey(i), source[i]);
@@ -327,6 +366,10 @@ namespace Pithos.Network
 
         private Task<T> Retry<T>(Func<T> original, int retryCount, TaskCompletionSource<T> tcs = null)
         {
+            if (original==null)
+                throw new ArgumentNullException("original");
+            Contract.EndContractBlock();
+
             if (tcs == null)
                 tcs = new TaskCompletionSource<T>();
             Task.Factory.StartNew(original).ContinueWith(_original =>
@@ -374,6 +417,8 @@ namespace Pithos.Network
 
         private HttpStatusCode GetStatusCode(WebException we)
         {
+            if (we==null)
+                throw new ArgumentNullException("we");
             var statusCode = HttpStatusCode.RequestTimeout;
             if (we.Response != null)
             {
@@ -382,6 +427,12 @@ namespace Pithos.Network
             }
             return statusCode;
         }
+
+        public UriBuilder GetAddressBuilder(string container, string objectName)
+        {
+            var builder = new UriBuilder(String.Join("/", BaseAddress, container, objectName));
+            return builder;
+        }
     }
 
     public class RetryException:Exception
index df1fb91..ff481bf 100644 (file)
@@ -17,6 +17,8 @@ namespace Pithos.Network
         {
             if (info==null)
                 throw new ArgumentNullException("info");
+            if (String.IsNullOrWhiteSpace(info.FullName))
+                throw new ArgumentException("info.FullName is empty","info");
             Contract.EndContractBlock();
 
             return CalculateMD5(info.FullName);
@@ -74,6 +76,8 @@ namespace Pithos.Network
         {
             if (fileInfo==null)
                 throw new ArgumentNullException("fileInfo");
+            if (String.IsNullOrWhiteSpace(fileInfo.FullName))
+                throw new ArgumentException("fileInfo.FullName is empty","fileInfo");
             if (blockSize <= 0)
                 throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero ");
             if (String.IsNullOrWhiteSpace(algorithm))
@@ -108,6 +112,8 @@ namespace Pithos.Network
         {
             if (fileInfo == null)
                 throw new ArgumentNullException("fileInfo");
+            if (String.IsNullOrWhiteSpace(fileInfo.FullName))
+                throw new ArgumentNullException("fileInfo.FullName is empty","fileInfo");
             if (blockSize <= 0)
                 throw new ArgumentOutOfRangeException("blockSize", "blockSize must be a value greater than zero ");
             if (String.IsNullOrWhiteSpace(algorithm))
index 2f036b1..6a6dfdd 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Diagnostics.Contracts;
 using System.IO;
 using System.Text;
 using System.Threading.Tasks;
@@ -16,7 +17,27 @@ namespace Pithos.Network
         private const int DEFAULT_BLOCK_SIZE = 4*1024*1024;
         public string BlockHash { get; set; }
         public int BlockSize { get; set; }
-        public long Bytes { get; set; }
+        
+        private long _bytes;
+        public long Bytes
+        {
+            get
+            {
+                Contract.Ensures(Contract.Result<long>() >= 0);
+                return _bytes;
+            }
+            set
+            {
+                if (value<0)
+                    throw new ArgumentOutOfRangeException("Bytes");
+                Contract.Requires(value >= 0);
+                Contract.EndContractBlock();
+                
+                _bytes = value;
+            }
+        }
+        
+
 
         public Guid FileId { get; set; }
 
@@ -27,17 +48,25 @@ namespace Pithos.Network
         }
 
         private IList<byte[]> _hashes;
+
         public IList<byte[]> Hashes
         {
             get { return _hashes; }
             set
             {
                 _hashes = value;
-                _topHash.Force();                
+                _topHash.Force();
             }
         }
 
-        public TreeHash(string algorithm)
+        [ContractInvariantMethod]
+        private void Invariants()
+        {
+            Contract.Invariant(_bytes>=0);
+        }
+        
+
+       public TreeHash(string algorithm)
         {
             BlockHash = algorithm;            
             _topHash = new Lazy<byte[]>(() =>
@@ -104,6 +133,10 @@ namespace Pithos.Network
         //Saves the Json representation to a file
         public Task Save(string filePath)
         {
+            if (String.IsNullOrWhiteSpace(filePath))
+                throw new ArgumentNullException("filePath");
+            Contract.EndContractBlock();
+
             var fileName = FileId.ToString("N");
             var path = Path.Combine(filePath, fileName);
             if (!Directory.Exists(filePath))
@@ -139,9 +172,12 @@ namespace Pithos.Network
         public static TreeHash Parse(string json)
         {
             if (String.IsNullOrWhiteSpace(json))
-                return Empty;
+                return Empty;            
 
             var value = JsonConvert.DeserializeObject<JObject>(json);
+            if (value==null)
+                throw new ArgumentException("The json parameter doesn't contain any json data","json");
+            Contract.Assume(value!=null);
 
             var blockHash = (string) value["block_hash"];
             var size = value.Value<int>("block_size");
index 7af9a6a..5c8ddc8 100644 (file)
     {
         "Entry"
         {
-        "MsmKey" = "8:_04BA020DDB8E799F1B05E41389C33CDB"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
-        "MsmSig" = "8:_UNDEFINED"
-        }
-        "Entry"
-        {
-        "MsmKey" = "8:_04BA020DDB8E799F1B05E41389C33CDB"
+        "MsmKey" = "8:_0E4F95BDB07F23F411C53FB6C2E602F7"
         "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_04BA020DDB8E799F1B05E41389C33CDB"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_19A1385E2CA0B02EAB082C45FB563106"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_08C5DBFDA002573955C5E1E5397AA883"
+        "MsmKey" = "8:_19A1385E2CA0B02EAB082C45FB563106"
         "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
+        "MsmKey" = "8:_19A1385E2CA0B02EAB082C45FB563106"
         "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
-        "OwnerKey" = "8:_DEDA5BD2F233F0A42AFD96D4F704B4DF"
+        "MsmKey" = "8:_2837CB1EABE794B2B8C0028FDCFEA1C0"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
-        "OwnerKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
+        "MsmKey" = "8:_379682952A41C4DD701D113A41CD0ACC"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
-        "OwnerKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
+        "MsmKey" = "8:_379682952A41C4DD701D113A41CD0ACC"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
-        "OwnerKey" = "8:_BAA515E0FCDE402CBF2A6FF3D94A0B83"
+        "MsmKey" = "8:_379682952A41C4DD701D113A41CD0ACC"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
-        "OwnerKey" = "8:_B032B8B884C0A6A2E9CA650FCAC16970"
+        "MsmKey" = "8:_412610FA5B854CE1B90857177A4DF634"
+        "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_311197E10704448D93A69A8EC39C3C80"
-        "OwnerKey" = "8:_UNDEFINED"
+        "MsmKey" = "8:_413A3C9A9C848F0F0E34C29B1C919557"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_412610FA5B854CE1B90857177A4DF634"
-        "OwnerKey" = "8:_UNDEFINED"
+        "MsmKey" = "8:_413A3C9A9C848F0F0E34C29B1C919557"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_52E458D5C0305865B4E25CD0FDD3644B"
+        "MsmKey" = "8:_413A3C9A9C848F0F0E34C29B1C919557"
         "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_52E458D5C0305865B4E25CD0FDD3644B"
-        "OwnerKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
+        "MsmKey" = "8:_413A3C9A9C848F0F0E34C29B1C919557"
+        "OwnerKey" = "8:_476D990A74530772679162FBBFE0FCF4"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_52E458D5C0305865B4E25CD0FDD3644B"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_413A3C9A9C848F0F0E34C29B1C919557"
+        "OwnerKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_52E458D5C0305865B4E25CD0FDD3644B"
-        "OwnerKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
+        "MsmKey" = "8:_4414524BD941C2AB1F7C50E315B4C9EF"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_52E458D5C0305865B4E25CD0FDD3644B"
-        "OwnerKey" = "8:_B032B8B884C0A6A2E9CA650FCAC16970"
+        "MsmKey" = "8:_4414524BD941C2AB1F7C50E315B4C9EF"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_53268E13E9741B866CCEC4CAAB6F7CC0"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_4414524BD941C2AB1F7C50E315B4C9EF"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_53268E13E9741B866CCEC4CAAB6F7CC0"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_4414524BD941C2AB1F7C50E315B4C9EF"
+        "OwnerKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_53268E13E9741B866CCEC4CAAB6F7CC0"
-        "OwnerKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
+        "MsmKey" = "8:_4414524BD941C2AB1F7C50E315B4C9EF"
+        "OwnerKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_53268E13E9741B866CCEC4CAAB6F7CC0"
-        "OwnerKey" = "8:_B032B8B884C0A6A2E9CA650FCAC16970"
+        "MsmKey" = "8:_476D990A74530772679162FBBFE0FCF4"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_54F1D51175D73ACE29F26142CAE00C3A"
-        "OwnerKey" = "8:_DEDA5BD2F233F0A42AFD96D4F704B4DF"
+        "MsmKey" = "8:_476D990A74530772679162FBBFE0FCF4"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_5550CCC7F6A61F45C1B9E5259AD0933E"
+        "MsmKey" = "8:_476D990A74530772679162FBBFE0FCF4"
         "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_5999946716C03EF42A7E7AB943915D64"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
+        "OwnerKey" = "8:_379682952A41C4DD701D113A41CD0ACC"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_5999946716C03EF42A7E7AB943915D64"
-        "OwnerKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
+        "MsmKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_5999946716C03EF42A7E7AB943915D64"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_5999946716C03EF42A7E7AB943915D64"
-        "OwnerKey" = "8:_5550CCC7F6A61F45C1B9E5259AD0933E"
+        "MsmKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
+        "OwnerKey" = "8:_476D990A74530772679162FBBFE0FCF4"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_74535AE0FDD2421E81F24E0DB0554D26"
-        "OwnerKey" = "8:_UNDEFINED"
+        "MsmKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_77F82E591A29D6C19B7A7CDE824B968C"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
+        "MsmKey" = "8:_71AB7BB89699C43F04EFBBD41DFF976E"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_77F82E591A29D6C19B7A7CDE824B968C"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_71AB7BB89699C43F04EFBBD41DFF976E"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_77F82E591A29D6C19B7A7CDE824B968C"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_71AB7BB89699C43F04EFBBD41DFF976E"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_77F82E591A29D6C19B7A7CDE824B968C"
-        "OwnerKey" = "8:_04BA020DDB8E799F1B05E41389C33CDB"
+        "MsmKey" = "8:_71AB7BB89699C43F04EFBBD41DFF976E"
+        "OwnerKey" = "8:_2837CB1EABE794B2B8C0028FDCFEA1C0"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_77F82E591A29D6C19B7A7CDE824B968C"
-        "OwnerKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
+        "MsmKey" = "8:_74535AE0FDD2421E81F24E0DB0554D26"
+        "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_7F0D4FC20A3B3B6E7819390C3E74A983"
+        "MsmKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_8201861880C6B87DFDD8A70B2B580914"
-        "OwnerKey" = "8:_8C512BF6FF06B9F7518CBE310877E479"
+        "OwnerKey" = "8:_C9615BA8AC66AC373BB153F8A95E9DA8"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_856286C42763F5D5F644D3E450795653"
+        "MsmKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_856286C42763F5D5F644D3E450795653"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_8C512BF6FF06B9F7518CBE310877E479"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_8C512BF6FF06B9F7518CBE310877E479"
-        "OwnerKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
+        "MsmKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_8C512BF6FF06B9F7518CBE310877E479"
+        "MsmKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
         "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
-        "OwnerKey" = "8:_A68ECCEBE87AD544F44B6E7734EBD621"
+        "MsmKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
-        "MsmSig" = "8:_UNDEFINED"
-        }
-        "Entry"
-        {
-        "MsmKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_9419C61DF5F3441099A56E07565699F0"
+        "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
-        "OwnerKey" = "8:_04BA020DDB8E799F1B05E41389C33CDB"
+        "MsmKey" = "8:_9F55CE39394926A083741C3E2824DE59"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
+        "MsmKey" = "8:_BAA515E0FCDE402CBF2A6FF3D94A0B83"
+        "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_9419C61DF5F3441099A56E07565699F0"
+        "MsmKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
         "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_A68ECCEBE87AD544F44B6E7734EBD621"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
+        "MsmKey" = "8:_C017F2E6E691B9F1814D8EDA1C80C44E"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_A68ECCEBE87AD544F44B6E7734EBD621"
+        "MsmKey" = "8:_C017F2E6E691B9F1814D8EDA1C80C44E"
         "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_A68ECCEBE87AD544F44B6E7734EBD621"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_C017F2E6E691B9F1814D8EDA1C80C44E"
+        "OwnerKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_B032B8B884C0A6A2E9CA650FCAC16970"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_C017F2E6E691B9F1814D8EDA1C80C44E"
+        "OwnerKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_B032B8B884C0A6A2E9CA650FCAC16970"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_B03A075A5CDF3E0434B54DAB685A5E8D"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
+        "MsmKey" = "8:_C7FAC6DF0866992BDABC6B70456C92F1"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_B03A075A5CDF3E0434B54DAB685A5E8D"
+        "MsmKey" = "8:_C7FAC6DF0866992BDABC6B70456C92F1"
         "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_B03A075A5CDF3E0434B54DAB685A5E8D"
+        "MsmKey" = "8:_C9615BA8AC66AC373BB153F8A95E9DA8"
         "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_B03A075A5CDF3E0434B54DAB685A5E8D"
-        "OwnerKey" = "8:_A68ECCEBE87AD544F44B6E7734EBD621"
+        "MsmKey" = "8:_C9615BA8AC66AC373BB153F8A95E9DA8"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_BAA515E0FCDE402CBF2A6FF3D94A0B83"
-        "OwnerKey" = "8:_UNDEFINED"
+        "MsmKey" = "8:_C9615BA8AC66AC373BB153F8A95E9DA8"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
+        "MsmKey" = "8:_CE1C7673CEC14F70AFCF2B48FF8B3D37"
         "OwnerKey" = "8:_UNDEFINED"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_C4EB6477683944848E47C160C41EA94A"
-        "OwnerKey" = "8:_UNDEFINED"
+        "MsmKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_CE1C7673CEC14F70AFCF2B48FF8B3D37"
-        "OwnerKey" = "8:_UNDEFINED"
+        "MsmKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_DEDA5BD2F233F0A42AFD96D4F704B4DF"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
+        "OwnerKey" = "8:_BBBEFA365EAA4B09B277CBDBED99E839"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_E800F1D1BBBD8589A3E9175B06D71A0F"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
+        "MsmKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
+        "OwnerKey" = "8:_BAA515E0FCDE402CBF2A6FF3D94A0B83"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_E800F1D1BBBD8589A3E9175B06D71A0F"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
+        "OwnerKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_E800F1D1BBBD8589A3E9175B06D71A0F"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_E5247C57FCF8FDC4526119494C9CA91D"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
-        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
+        "MsmKey" = "8:_E5247C57FCF8FDC4526119494C9CA91D"
+        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
-        "OwnerKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
+        "MsmKey" = "8:_E5247C57FCF8FDC4526119494C9CA91D"
+        "OwnerKey" = "8:_311197E10704448D93A69A8EC39C3C80"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
-        "MsmKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
-        "OwnerKey" = "8:_C4EB6477683944848E47C160C41EA94A"
+        "MsmKey" = "8:_E5247C57FCF8FDC4526119494C9CA91D"
+        "OwnerKey" = "8:_379682952A41C4DD701D113A41CD0ACC"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_DEDA5BD2F233F0A42AFD96D4F704B4DF"
-        "MsmSig" = "8:_UNDEFINED"
-        }
-        "Entry"
-        {
-        "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_D1664994F2882FF26943EB0063AB1E2D"
+        "OwnerKey" = "8:_8046A0650A0FDBD7044C0059B48CB6EA"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_7F0D4FC20A3B3B6E7819390C3E74A983"
+        "OwnerKey" = "8:_0E4F95BDB07F23F411C53FB6C2E602F7"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_08C5DBFDA002573955C5E1E5397AA883"
+        "OwnerKey" = "8:_9F55CE39394926A083741C3E2824DE59"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_B032B8B884C0A6A2E9CA650FCAC16970"
+        "OwnerKey" = "8:_8B189FCC1135DE71AFEBE665EBC98E1E"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_53268E13E9741B866CCEC4CAAB6F7CC0"
+        "OwnerKey" = "8:_D27724C0B9E9EA480E1B445116EB2A8B"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_290CB87DCCB9F0FC2F8645677EA05D8F"
+        "OwnerKey" = "8:_C7FAC6DF0866992BDABC6B70456C92F1"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_856286C42763F5D5F644D3E450795653"
+        "OwnerKey" = "8:_4414524BD941C2AB1F7C50E315B4C9EF"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_52E458D5C0305865B4E25CD0FDD3644B"
+        "OwnerKey" = "8:_2837CB1EABE794B2B8C0028FDCFEA1C0"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_5550CCC7F6A61F45C1B9E5259AD0933E"
+        "OwnerKey" = "8:_71AB7BB89699C43F04EFBBD41DFF976E"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_5999946716C03EF42A7E7AB943915D64"
+        "OwnerKey" = "8:_C017F2E6E691B9F1814D8EDA1C80C44E"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_EDB900CFF8D60A69C698930CF318E12F"
+        "OwnerKey" = "8:_8202743C43C25F5033105429DB6BB9A3"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_04BA020DDB8E799F1B05E41389C33CDB"
+        "OwnerKey" = "8:_476D990A74530772679162FBBFE0FCF4"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_A68ECCEBE87AD544F44B6E7734EBD621"
+        "OwnerKey" = "8:_379682952A41C4DD701D113A41CD0ACC"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_91362F1FE448D304981DEE4A2E25926E"
+        "OwnerKey" = "8:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_77F82E591A29D6C19B7A7CDE824B968C"
+        "OwnerKey" = "8:_413A3C9A9C848F0F0E34C29B1C919557"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_B03A075A5CDF3E0434B54DAB685A5E8D"
+        "OwnerKey" = "8:_E5247C57FCF8FDC4526119494C9CA91D"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_E800F1D1BBBD8589A3E9175B06D71A0F"
+        "OwnerKey" = "8:_19A1385E2CA0B02EAB082C45FB563106"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
         {
         "MsmKey" = "8:_UNDEFINED"
-        "OwnerKey" = "8:_8C512BF6FF06B9F7518CBE310877E479"
+        "OwnerKey" = "8:_C9615BA8AC66AC373BB153F8A95E9DA8"
         "MsmSig" = "8:_UNDEFINED"
         }
         "Entry"
                 }
             }
         }
+        "Premium Debug"
+        {
+        "DisplayName" = "8:Premium Debug"
+        "IsDebugOnly" = "11:FALSE"
+        "IsReleaseOnly" = "11:FALSE"
+        "OutputFilename" = "8:Premium Debug\\Pithos.Setup.x64.msi"
+        "PackageFilesAs" = "3:2"
+        "PackageFileSize" = "3:-2147483648"
+        "CabType" = "3:1"
+        "Compression" = "3:2"
+        "SignOutput" = "11:FALSE"
+        "CertificateFile" = "8:"
+        "PrivateKeyFile" = "8:"
+        "TimeStampServer" = "8:"
+        "InstallerBootstrapper" = "3:2"
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
+            {
+            "Enabled" = "11:TRUE"
+            "PromptEnabled" = "11:TRUE"
+            "PrerequisitesLocation" = "2:1"
+            "Url" = "8:"
+            "ComponentsUrl" = "8:"
+                "Items"
+                {
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.0,Profile=Client"
+                    {
+                    "Name" = "8:Microsoft .NET Framework 4 Client Profile (x86 and x64)"
+                    "ProductCode" = "8:.NETFramework,Version=v4.0,Profile=Client"
+                    }
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1"
+                    {
+                    "Name" = "8:Windows Installer 3.1"
+                    "ProductCode" = "8:Microsoft.Windows.Installer.3.1"
+                    }
+                }
+            }
+        }
         "Release"
         {
         "DisplayName" = "8:Release"
         }
         "File"
         {
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_04BA020DDB8E799F1B05E41389C33CDB"
-            {
-            "AssemblyRegister" = "3:1"
-            "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:NHibernate.Search, Version=0.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
-                "ScatterAssemblies"
-                {
-                    "_04BA020DDB8E799F1B05E41389C33CDB"
-                    {
-                    "Name" = "8:NHibernate.Search.dll"
-                    "Attributes" = "3:512"
-                    }
-                }
-            "SourcePath" = "8:NHibernate.Search.dll"
-            "TargetName" = "8:"
-            "Tag" = "8:"
-            "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
-            "Condition" = "8:"
-            "Transitive" = "11:FALSE"
-            "Vital" = "11:TRUE"
-            "ReadOnly" = "11:FALSE"
-            "Hidden" = "11:FALSE"
-            "System" = "11:FALSE"
-            "Permanent" = "11:FALSE"
-            "SharedLegacy" = "11:FALSE"
-            "PackageAs" = "3:1"
-            "Register" = "3:1"
-            "Exclude" = "11:FALSE"
-            "IsDependency" = "11:TRUE"
-            "IsolateTo" = "8:"
-            }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_08C5DBFDA002573955C5E1E5397AA883"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_0E4F95BDB07F23F411C53FB6C2E602F7"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Hardcodet.Wpf.TaskbarNotification, Version=1.0.4.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:WPF.Themes, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_08C5DBFDA002573955C5E1E5397AA883"
+                    "_0E4F95BDB07F23F411C53FB6C2E602F7"
                     {
-                    "Name" = "8:Hardcodet.Wpf.TaskbarNotification.dll"
+                    "Name" = "8:WPF.Themes.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Hardcodet.Wpf.TaskbarNotification.dll"
+            "SourcePath" = "8:WPF.Themes.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_290CB87DCCB9F0FC2F8645677EA05D8F"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_19A1385E2CA0B02EAB082C45FB563106"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Pithos.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Castle.Components.Validator, Version=2.5.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_290CB87DCCB9F0FC2F8645677EA05D8F"
+                    "_19A1385E2CA0B02EAB082C45FB563106"
                     {
-                    "Name" = "8:Pithos.Interfaces.dll"
+                    "Name" = "8:Castle.Components.Validator.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Pithos.Interfaces.dll"
+            "SourcePath" = "8:Castle.Components.Validator.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_52E458D5C0305865B4E25CD0FDD3644B"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_2837CB1EABE794B2B8C0028FDCFEA1C0"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:ParallelExtensionsExtras, Version=1.2.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_52E458D5C0305865B4E25CD0FDD3644B"
+                    "_2837CB1EABE794B2B8C0028FDCFEA1C0"
                     {
-                    "Name" = "8:ParallelExtensionsExtras.dll"
+                    "Name" = "8:Microsoft.WindowsAPICodePack.Shell.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:ParallelExtensionsExtras.dll"
+            "SourcePath" = "8:Microsoft.WindowsAPICodePack.Shell.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_53268E13E9741B866CCEC4CAAB6F7CC0"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_379682952A41C4DD701D113A41CD0ACC"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Newtonsoft.Json, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:NHibernate.ByteCode.Castle, Version=3.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_53268E13E9741B866CCEC4CAAB6F7CC0"
+                    "_379682952A41C4DD701D113A41CD0ACC"
                     {
-                    "Name" = "8:Newtonsoft.Json.dll"
+                    "Name" = "8:NHibernate.ByteCode.Castle.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Newtonsoft.Json.dll"
+            "SourcePath" = "8:NHibernate.ByteCode.Castle.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_54F1D51175D73ACE29F26142CAE00C3A"
-            {
-            "SourcePath" = "8:Pithos.ShellExtensions.tlb"
-            "TargetName" = "8:Pithos.ShellExtensions.tlb"
-            "Tag" = "8:"
-            "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
-            "Condition" = "8:"
-            "Transitive" = "11:FALSE"
-            "Vital" = "11:TRUE"
-            "ReadOnly" = "11:FALSE"
-            "Hidden" = "11:FALSE"
-            "System" = "11:FALSE"
-            "Permanent" = "11:FALSE"
-            "SharedLegacy" = "11:FALSE"
-            "PackageAs" = "3:1"
-            "Register" = "3:2"
-            "Exclude" = "11:FALSE"
-            "IsDependency" = "11:TRUE"
-            "IsolateTo" = "8:"
-            }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_5550CCC7F6A61F45C1B9E5259AD0933E"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_413A3C9A9C848F0F0E34C29B1C919557"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Iesi.Collections, Version=1.0.1.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_5550CCC7F6A61F45C1B9E5259AD0933E"
+                    "_413A3C9A9C848F0F0E34C29B1C919557"
                     {
-                    "Name" = "8:Microsoft.WindowsAPICodePack.Shell.dll"
+                    "Name" = "8:Iesi.Collections.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Microsoft.WindowsAPICodePack.Shell.dll"
+            "SourcePath" = "8:Iesi.Collections.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_5999946716C03EF42A7E7AB943915D64"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_4414524BD941C2AB1F7C50E315B4C9EF"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:ParallelExtensionsExtras, Version=1.2.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_5999946716C03EF42A7E7AB943915D64"
+                    "_4414524BD941C2AB1F7C50E315B4C9EF"
                     {
-                    "Name" = "8:Microsoft.WindowsAPICodePack.dll"
+                    "Name" = "8:ParallelExtensionsExtras.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Microsoft.WindowsAPICodePack.dll"
+            "SourcePath" = "8:ParallelExtensionsExtras.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_77F82E591A29D6C19B7A7CDE824B968C"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_476D990A74530772679162FBBFE0FCF4"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Iesi.Collections, Version=1.0.1.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:NHibernate.Search, Version=0.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_77F82E591A29D6C19B7A7CDE824B968C"
+                    "_476D990A74530772679162FBBFE0FCF4"
                     {
-                    "Name" = "8:Iesi.Collections.dll"
+                    "Name" = "8:NHibernate.Search.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Iesi.Collections.dll"
+            "SourcePath" = "8:NHibernate.Search.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_7F0D4FC20A3B3B6E7819390C3E74A983"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:WPF.Themes, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:NHibernate, Version=3.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_7F0D4FC20A3B3B6E7819390C3E74A983"
+                    "_4CFFEFA8D3F3865F15FEA354C6BF4ECC"
                     {
-                    "Name" = "8:WPF.Themes.dll"
+                    "Name" = "8:NHibernate.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:WPF.Themes.dll"
+            "SourcePath" = "8:NHibernate.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_8201861880C6B87DFDD8A70B2B580914"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_71AB7BB89699C43F04EFBBD41DFF976E"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_8201861880C6B87DFDD8A70B2B580914"
+                    "_71AB7BB89699C43F04EFBBD41DFF976E"
                     {
-                    "Name" = "8:System.Windows.Interactivity.dll"
+                    "Name" = "8:Microsoft.WindowsAPICodePack.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:System.Windows.Interactivity.dll"
+            "SourcePath" = "8:Microsoft.WindowsAPICodePack.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_856286C42763F5D5F644D3E450795653"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_8046A0650A0FDBD7044C0059B48CB6EA"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:System.Data.SQLite, Version=1.0.74.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Pithos.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_856286C42763F5D5F644D3E450795653"
+                    "_8046A0650A0FDBD7044C0059B48CB6EA"
                     {
-                    "Name" = "8:System.Data.SQLite.dll"
+                    "Name" = "8:Pithos.Core.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:System.Data.SQLite.dll"
+            "SourcePath" = "8:Pithos.Core.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_8C512BF6FF06B9F7518CBE310877E479"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_8201861880C6B87DFDD8A70B2B580914"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Caliburn.Micro, Version=1.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_8C512BF6FF06B9F7518CBE310877E479"
+                    "_8201861880C6B87DFDD8A70B2B580914"
                     {
-                    "Name" = "8:Caliburn.Micro.dll"
+                    "Name" = "8:System.Windows.Interactivity.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Caliburn.Micro.dll"
+            "SourcePath" = "8:System.Windows.Interactivity.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_91362F1FE448D304981DEE4A2E25926E"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_8202743C43C25F5033105429DB6BB9A3"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:NHibernate, Version=3.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Castle.ActiveRecord, Version=3.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_91362F1FE448D304981DEE4A2E25926E"
+                    "_8202743C43C25F5033105429DB6BB9A3"
                     {
-                    "Name" = "8:NHibernate.dll"
+                    "Name" = "8:Castle.ActiveRecord.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:NHibernate.dll"
+            "SourcePath" = "8:Castle.ActiveRecord.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_A68ECCEBE87AD544F44B6E7734EBD621"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_8B189FCC1135DE71AFEBE665EBC98E1E"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:NHibernate.ByteCode.Castle, Version=3.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Pithos.Network, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_A68ECCEBE87AD544F44B6E7734EBD621"
+                    "_8B189FCC1135DE71AFEBE665EBC98E1E"
                     {
-                    "Name" = "8:NHibernate.ByteCode.Castle.dll"
+                    "Name" = "8:Pithos.Network.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:NHibernate.ByteCode.Castle.dll"
+            "SourcePath" = "8:Pithos.Network.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_B032B8B884C0A6A2E9CA650FCAC16970"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_9F55CE39394926A083741C3E2824DE59"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Pithos.Network, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Hardcodet.Wpf.TaskbarNotification, Version=1.0.4.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_B032B8B884C0A6A2E9CA650FCAC16970"
+                    "_9F55CE39394926A083741C3E2824DE59"
                     {
-                    "Name" = "8:Pithos.Network.dll"
+                    "Name" = "8:Hardcodet.Wpf.TaskbarNotification.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Pithos.Network.dll"
+            "SourcePath" = "8:Hardcodet.Wpf.TaskbarNotification.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_B03A075A5CDF3E0434B54DAB685A5E8D"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_C017F2E6E691B9F1814D8EDA1C80C44E"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Castle.Core, Version=2.5.1.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Newtonsoft.Json, Version=4.0.2.0, Culture=neutral, PublicKeyToken=b9a188c8922137c6, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_B03A075A5CDF3E0434B54DAB685A5E8D"
+                    "_C017F2E6E691B9F1814D8EDA1C80C44E"
                     {
-                    "Name" = "8:Castle.Core.dll"
+                    "Name" = "8:Newtonsoft.Json.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Castle.Core.dll"
+            "SourcePath" = "8:Newtonsoft.Json.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_D1664994F2882FF26943EB0063AB1E2D"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_C7FAC6DF0866992BDABC6B70456C92F1"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Pithos.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:System.Data.SQLite, Version=1.0.74.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_D1664994F2882FF26943EB0063AB1E2D"
+                    "_C7FAC6DF0866992BDABC6B70456C92F1"
                     {
-                    "Name" = "8:Pithos.Core.dll"
+                    "Name" = "8:System.Data.SQLite.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Pithos.Core.dll"
+            "SourcePath" = "8:System.Data.SQLite.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_DEDA5BD2F233F0A42AFD96D4F704B4DF"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_C9615BA8AC66AC373BB153F8A95E9DA8"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Pithos.ShellExtensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Caliburn.Micro, Version=1.2.0.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_DEDA5BD2F233F0A42AFD96D4F704B4DF"
+                    "_C9615BA8AC66AC373BB153F8A95E9DA8"
                     {
-                    "Name" = "8:Pithos.ShellExtensions.dll"
+                    "Name" = "8:Caliburn.Micro.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Pithos.ShellExtensions.dll"
+            "SourcePath" = "8:Caliburn.Micro.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_E800F1D1BBBD8589A3E9175B06D71A0F"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_D27724C0B9E9EA480E1B445116EB2A8B"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Castle.Components.Validator, Version=2.5.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Pithos.Interfaces, Version=1.0.0.0, Culture=neutral, PublicKeyToken=2cc55badaa91f4de, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_E800F1D1BBBD8589A3E9175B06D71A0F"
+                    "_D27724C0B9E9EA480E1B445116EB2A8B"
                     {
-                    "Name" = "8:Castle.Components.Validator.dll"
+                    "Name" = "8:Pithos.Interfaces.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Castle.Components.Validator.dll"
+            "SourcePath" = "8:Pithos.Interfaces.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             "IsDependency" = "11:TRUE"
             "IsolateTo" = "8:"
             }
-            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_EDB900CFF8D60A69C698930CF318E12F"
+            "{9F6F8455-1EF1-4B85-886A-4223BCC8E7F7}:_E5247C57FCF8FDC4526119494C9CA91D"
             {
             "AssemblyRegister" = "3:1"
             "AssemblyIsInGAC" = "11:FALSE"
-            "AssemblyAsmDisplayName" = "8:Castle.ActiveRecord, Version=3.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
+            "AssemblyAsmDisplayName" = "8:Castle.Core, Version=2.5.1.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL"
                 "ScatterAssemblies"
                 {
-                    "_EDB900CFF8D60A69C698930CF318E12F"
+                    "_E5247C57FCF8FDC4526119494C9CA91D"
                     {
-                    "Name" = "8:Castle.ActiveRecord.dll"
+                    "Name" = "8:Castle.Core.dll"
                     "Attributes" = "3:512"
                     }
                 }
-            "SourcePath" = "8:Castle.ActiveRecord.dll"
+            "SourcePath" = "8:Castle.Core.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_311197E10704448D93A69A8EC39C3C80"
             {
-            "SourcePath" = "8:..\\Pithos.Core\\obj\\Debug\\Pithos.Core.dll"
+            "SourcePath" = "8:..\\Pithos.Core\\obj\\Premium Debug\\Pithos.Core.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_74535AE0FDD2421E81F24E0DB0554D26"
             {
-            "SourcePath" = "8:..\\Libraries\\Json40r2\\Source\\Src\\Newtonsoft.Json\\obj\\Debug\\Newtonsoft.Json.dll"
+            "SourcePath" = "8:..\\Libraries\\Json40r2\\Source\\Src\\Newtonsoft.Json\\obj\\Premium Debug\\Newtonsoft.Json.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_9419C61DF5F3441099A56E07565699F0"
             {
-            "SourcePath" = "8:..\\Libraries\\ParallelExtensionsExtras\\obj\\Debug\\ParallelExtensionsExtras.dll"
+            "SourcePath" = "8:..\\Libraries\\ParallelExtensionsExtras\\obj\\Premium Debug\\ParallelExtensionsExtras.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_BAA515E0FCDE402CBF2A6FF3D94A0B83"
             {
-            "SourcePath" = "8:..\\Pithos.ShellExtensions\\obj\\Debug\\Pithos.ShellExtensions.dll"
+            "SourcePath" = "8:..\\Pithos.ShellExtensions\\obj\\Premium Debug\\Pithos.ShellExtensions.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_BBBEFA365EAA4B09B277CBDBED99E839"
             {
-            "SourcePath" = "8:..\\Pithos.Network\\obj\\Debug\\Pithos.Network.dll"
+            "SourcePath" = "8:..\\Pithos.Network\\obj\\Premium Debug\\Pithos.Network.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_C4EB6477683944848E47C160C41EA94A"
             {
-            "SourcePath" = "8:..\\Pithos.Client.WPF\\obj\\Debug\\Pithos.Client.WPF.exe"
+            "SourcePath" = "8:..\\Pithos.Client.WPF\\obj\\Premium Debug\\Pithos.Client.WPF.exe"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_CE1C7673CEC14F70AFCF2B48FF8B3D37"
             {
-            "SourcePath" = "8:..\\Pithos.Interfaces\\obj\\Debug\\Pithos.Interfaces.dll"
+            "SourcePath" = "8:..\\Pithos.Interfaces\\obj\\Premium Debug\\Pithos.Interfaces.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
             }
             "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_F65AE860659D453AAFD4D6F068DAC541"
             {
-            "SourcePath" = "8:..\\NotifyIconWpf\\obj\\Debug\\Hardcodet.Wpf.TaskbarNotification.dll"
+            "SourcePath" = "8:..\\NotifyIconWpf\\obj\\Premium Debug\\Hardcodet.Wpf.TaskbarNotification.dll"
             "TargetName" = "8:"
             "Tag" = "8:"
             "Folder" = "8:_2E4412A903CE41838ECE5DCF9470F71C"
index b9cfe7f..26ef99f 100644 (file)
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
     <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.ShellExtensions.Test.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="nunit.framework, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
       <HintPath>..\packages\NUnit.2.5.10.11092\lib\nunit.framework.dll</HintPath>
index 1620007..c10c59f 100644 (file)
     <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
     <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Premium Debug|AnyCPU'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\Premium Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <RegisterForComInterop>true</RegisterForComInterop>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <CodeAnalysisLogFile>bin\Debug\Pithos.ShellExtensions.dll.CodeAnalysisLog.xml</CodeAnalysisLogFile>
+    <CodeAnalysisUseTypeNameInSuppression>true</CodeAnalysisUseTypeNameInSuppression>
+    <CodeAnalysisModuleSuppressionsFile>GlobalSuppressions.cs</CodeAnalysisModuleSuppressionsFile>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSetDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets</CodeAnalysisRuleSetDirectories>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
+    <CodeAnalysisIgnoreBuiltInRules>false</CodeAnalysisIgnoreBuiltInRules>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.ComponentModel.Composition" />
index 64a326c..0d9148d 100644 (file)
@@ -39,6 +39,9 @@ Global
                Debug|Any CPU = Debug|Any CPU
                Debug|Mixed Platforms = Debug|Mixed Platforms
                Debug|x86 = Debug|x86
+               Premium Debug|Any CPU = Premium Debug|Any CPU
+               Premium Debug|Mixed Platforms = Premium Debug|Mixed Platforms
+               Premium Debug|x86 = Premium Debug|x86
                Release|Any CPU = Release|Any CPU
                Release|Mixed Platforms = Release|Mixed Platforms
                Release|x86 = Release|x86
@@ -50,6 +53,10 @@ Global
                {240B432F-1030-4623-BCC3-FF351D6C1B63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {240B432F-1030-4623-BCC3-FF351D6C1B63}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {240B432F-1030-4623-BCC3-FF351D6C1B63}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {240B432F-1030-4623-BCC3-FF351D6C1B63}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {240B432F-1030-4623-BCC3-FF351D6C1B63}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {240B432F-1030-4623-BCC3-FF351D6C1B63}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {240B432F-1030-4623-BCC3-FF351D6C1B63}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {240B432F-1030-4623-BCC3-FF351D6C1B63}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {240B432F-1030-4623-BCC3-FF351D6C1B63}.Release|Any CPU.Build.0 = Release|Any CPU
                {240B432F-1030-4623-BCC3-FF351D6C1B63}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -64,6 +71,10 @@ Global
                {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Release|Any CPU.Build.0 = Release|Any CPU
                {2CFE2DF1-20AE-47E2-B1BB-36B974600BE1}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -78,6 +89,11 @@ Global
                {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Release|Any CPU.Build.0 = Release|Any CPU
                {7EEFF32F-CCF8-436A-9E0B-F40434C09AF4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -93,6 +109,11 @@ Global
                {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Release|Any CPU.Build.0 = Release|Any CPU
                {822F885B-83E8-4A9A-B02E-0FEAE444D960}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -108,6 +129,11 @@ Global
                {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Release|Any CPU.Build.0 = Release|Any CPU
                {C45218F8-09E7-4F57-85BC-5D8D2AC736A3}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -123,6 +149,11 @@ Global
                {142AF135-DF30-4563-B0AC-B604235AE874}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {142AF135-DF30-4563-B0AC-B604235AE874}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {142AF135-DF30-4563-B0AC-B604235AE874}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {142AF135-DF30-4563-B0AC-B604235AE874}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {142AF135-DF30-4563-B0AC-B604235AE874}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {142AF135-DF30-4563-B0AC-B604235AE874}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {142AF135-DF30-4563-B0AC-B604235AE874}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {142AF135-DF30-4563-B0AC-B604235AE874}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {142AF135-DF30-4563-B0AC-B604235AE874}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {142AF135-DF30-4563-B0AC-B604235AE874}.Release|Any CPU.Build.0 = Release|Any CPU
                {142AF135-DF30-4563-B0AC-B604235AE874}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -138,6 +169,11 @@ Global
                {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Release|Any CPU.Build.0 = Release|Any CPU
                {E027200B-C26A-4877-BFD9-1A18CF5DF2F4}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -153,6 +189,11 @@ Global
                {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Release|Any CPU.Build.0 = Release|Any CPU
                {C8E2BC8B-C7F1-4222-855C-4B04A57FFDFD}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -168,6 +209,11 @@ Global
                {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Release|Any CPU.Build.0 = Release|Any CPU
                {F9AF3E97-BCB7-46B7-8014-7FC858AEE9BA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -183,6 +229,11 @@ Global
                {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Release|Any CPU.Build.0 = Release|Any CPU
                {A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -199,6 +250,12 @@ Global
                {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Debug|x86.ActiveCfg = Debug|Any CPU
                {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Debug|x86.Build.0 = Debug|Any CPU
+               {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Premium Debug|x86.ActiveCfg = Premium Debug|x86
+               {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Premium Debug|x86.Build.0 = Premium Debug|x86
                {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Release|Any CPU.ActiveCfg = Release|x86
                {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Release|Mixed Platforms.ActiveCfg = Release|x86
                {4D9406A3-50ED-4672-BB97-A0B3EA4946FE}.Release|Mixed Platforms.Build.0 = Release|x86
@@ -214,6 +271,11 @@ Global
                {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
                {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
                {7AC63864-7638-41C4-969C-D3197EF2BED9}.Debug|x86.ActiveCfg = Debug|Any CPU
+               {7AC63864-7638-41C4-969C-D3197EF2BED9}.Premium Debug|Any CPU.ActiveCfg = Premium Debug|Any CPU
+               {7AC63864-7638-41C4-969C-D3197EF2BED9}.Premium Debug|Any CPU.Build.0 = Premium Debug|Any CPU
+               {7AC63864-7638-41C4-969C-D3197EF2BED9}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug|Any CPU
+               {7AC63864-7638-41C4-969C-D3197EF2BED9}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug|Any CPU
+               {7AC63864-7638-41C4-969C-D3197EF2BED9}.Premium Debug|x86.ActiveCfg = Premium Debug|Any CPU
                {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Any CPU.Build.0 = Release|Any CPU
                {7AC63864-7638-41C4-969C-D3197EF2BED9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
@@ -227,6 +289,11 @@ Global
                {C6251981-3C49-404B-BB5B-9732887388D2}.Debug|Any CPU.ActiveCfg = Debug
                {C6251981-3C49-404B-BB5B-9732887388D2}.Debug|Mixed Platforms.ActiveCfg = Debug
                {C6251981-3C49-404B-BB5B-9732887388D2}.Debug|x86.ActiveCfg = Debug
+               {C6251981-3C49-404B-BB5B-9732887388D2}.Premium Debug|Any CPU.ActiveCfg = Premium Debug
+               {C6251981-3C49-404B-BB5B-9732887388D2}.Premium Debug|Mixed Platforms.ActiveCfg = Premium Debug
+               {C6251981-3C49-404B-BB5B-9732887388D2}.Premium Debug|Mixed Platforms.Build.0 = Premium Debug
+               {C6251981-3C49-404B-BB5B-9732887388D2}.Premium Debug|x86.ActiveCfg = Premium Debug
+               {C6251981-3C49-404B-BB5B-9732887388D2}.Premium Debug|x86.Build.0 = Premium Debug
                {C6251981-3C49-404B-BB5B-9732887388D2}.Release|Any CPU.ActiveCfg = Release
                {C6251981-3C49-404B-BB5B-9732887388D2}.Release|Mixed Platforms.ActiveCfg = Release
                {C6251981-3C49-404B-BB5B-9732887388D2}.Release|x86.ActiveCfg = Release