Commits

Valdis Iljuconoks committed 157da52 Merge
  • Participants
  • Parent commits e8d05b3, 3d247ff

Comments (0)

Files changed (59)

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3.sln

+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geta.Commerce.AmazonS3", "Geta.Commerce.AmazonS3\Geta.Commerce.AmazonS3.csproj", "{AD928387-573C-47B8-877E-DC0ECB55C449}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{AD928387-573C-47B8-877E-DC0ECB55C449}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AD928387-573C-47B8-877E-DC0ECB55C449}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AD928387-573C-47B8-877E-DC0ECB55C449}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AD928387-573C-47B8-877E-DC0ECB55C449}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Extensions/AmazonS3Extensions.cs

+using System;
+using Amazon.S3.Model;
+using Geta.Commerce.AmazonS3.Model;
+
+namespace Geta.Commerce.AmazonS3.Extensions
+{
+    public static class AmazonS3Extensions
+    {
+        public static AmazonS3Object ToAmazonS3Object(this GetObjectResponse response)
+        {
+            var amazonS3Object = new AmazonS3Object();
+            amazonS3Object.Name = response.Key;
+            amazonS3Object.Id = response.AmazonId2;
+            amazonS3Object.Length = response.ContentLength;
+            return amazonS3Object;
+        }
+
+        public static AmazonS3Object ToAmazonS3Object(this S3Object response)
+        {
+            var amazonS3Object = new AmazonS3Object();
+            amazonS3Object.Name = response.Key;
+            amazonS3Object.Modified = Convert.ToDateTime(response.LastModified);
+            amazonS3Object.Length = response.Size;
+            return amazonS3Object;
+        }
+
+        public static string RemovePath(this string path, string removePath)
+        {
+            return EPiServer.Url.Decode(path).Replace(removePath, string.Empty);
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3.csproj

+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{AD928387-573C-47B8-877E-DC0ECB55C449}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Geta.Commerce.AmazonS3</RootNamespace>
+    <AssemblyName>Geta.Commerce.AmazonS3</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="AWSSDK, Version=1.3.13.1, Culture=neutral, PublicKeyToken=cd2d24cd2bace800, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\AWSSDK.1.3.13.1\lib\AWSSDK.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.ApplicationModules, Version=6.2.267.1, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.Framework.6.2.267.1\lib\EPiServer.ApplicationModules.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.BaseLibrary, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.BaseLibrary.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Blog, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Blog.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Business.Commerce">
+      <HintPath>..\packages\EPiServer.Commerce.1.1.1\lib\EPiServer.Business.Commerce.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Configuration, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Configuration.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Data, Version=6.2.267.1, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.Framework.6.2.267.1\lib\EPiServer.Data.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Enterprise, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Enterprise.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Events, Version=6.2.267.1, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.Framework.6.2.267.1\lib\EPiServer.Events.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Framework, Version=6.2.267.1, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.Framework.6.2.267.1\lib\EPiServer.Framework.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.ImageLibrary, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.ImageLibrary.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Implementation, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Implementation.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Legacy4, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Legacy4.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.LinkAnalyzer, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.LinkAnalyzer.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Log.Analyzers, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Log.Analyzers.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Log.Core, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Log.Core.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Lucene, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Lucene.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Scheduler, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Scheduler.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Scheduler.WKTL, Version=5.1.422.4, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Scheduler.WKTL.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Shell, Version=6.2.267.1, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.Framework.6.2.267.1\lib\EPiServer.Shell.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.Web.WebControls, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.Web.WebControls.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.WebDav, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.WebDav.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.WebParts, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.WebParts.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.WorkflowFoundation, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.WorkflowFoundation.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.XForms, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.XForms.dll</HintPath>
+    </Reference>
+    <Reference Include="EPiServer.XmlRpc, Version=6.1.379.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.CMS.Core.6.1.379.0\lib\EPiServer.XmlRpc.dll</HintPath>
+    </Reference>
+    <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\log4net.1.2.10\lib\2.0\log4net.dll</HintPath>
+    </Reference>
+    <Reference Include="Mediachase.BusinessFoundation">
+      <HintPath>..\packages\EPiServer.Commerce.1.1.1\lib\Mediachase.BusinessFoundation.dll</HintPath>
+    </Reference>
+    <Reference Include="Mediachase.BusinessFoundation.Data">
+      <HintPath>..\packages\EPiServer.Commerce.1.1.1\lib\Mediachase.BusinessFoundation.Data.dll</HintPath>
+    </Reference>
+    <Reference Include="Mediachase.Commerce">
+      <HintPath>..\packages\EPiServer.Commerce.1.1.1\lib\Mediachase.Commerce.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.ComponentModel.Composition, Version=2009.22.10.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7, processorArchitecture=MSIL">
+      <Private>True</Private>
+      <HintPath>..\packages\EPiServer.Framework.6.2.267.1\lib\System.ComponentModel.Composition.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Web" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Extensions\AmazonS3Extensions.cs" />
+    <Compile Include="Helpers\AmazonS3VirtualPathHelper.cs" />
+    <Compile Include="Hosting\AmazonS3Directory.cs" />
+    <Compile Include="Hosting\AmazonS3File.cs" />
+    <Compile Include="Hosting\AmazonS3Summary.cs" />
+    <Compile Include="Hosting\AmazonS3VirtualPathProvider.cs" />
+    <Compile Include="Model\AmazonS3Object.cs" />
+    <Compile Include="Modules\AmazonS3Module.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Repository\AmazonS3Repository.cs" />
+    <Compile Include="Repository\IAmazonS3Repository.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Helpers/AmazonS3VirtualPathHelper.cs

+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Web;
+using EPiServer.Web.Hosting;
+using Geta.Commerce.AmazonS3.Hosting;
+
+namespace Geta.Commerce.AmazonS3.Helpers
+{
+    public static class AmazonS3VirtualPathHelper
+    {
+        private static readonly object CacheLockObject = new object();
+
+         public static IEnumerable<ProviderSettings> GetAllSettings()
+         {
+             string cacheKey = "CommerceAmazonS3Providers";
+
+             var allAmazonS3ProviderSettings = HttpRuntime.Cache[cacheKey] as List<ProviderSettings>;
+
+             if (allAmazonS3ProviderSettings == null)
+             {
+                 lock (CacheLockObject)
+                 {
+                     allAmazonS3ProviderSettings = HttpRuntime.Cache[cacheKey] as List<ProviderSettings>;
+
+                     if (allAmazonS3ProviderSettings == null)
+                     {
+                         allAmazonS3ProviderSettings = VirtualPathHandler.Instance.VirtualPathProviders.Where(p => p.Key.GetType() == typeof (AmazonS3VirtualPathProvider)).Select(p => p.Value).ToList();
+
+                         HttpRuntime.Cache.Insert(cacheKey, allAmazonS3ProviderSettings, null, DateTime.MaxValue, TimeSpan.Zero);
+                     }
+                 }
+             }
+
+             return allAmazonS3ProviderSettings;
+         }
+
+        public static string GetVirtualPath(ProviderSettings providerSettings)
+        {
+            string virtualPath = providerSettings.Parameters["virtualPath"];
+
+            virtualPath = VirtualPathUtility.ToAbsolute(virtualPath);
+
+            return virtualPath;
+        }
+
+        public static string GetHostName(ProviderSettings providerSettings)
+        {
+            return providerSettings.Parameters["hostName"];
+        }
+
+        public static string GetScheme(ProviderSettings providerSettings)
+        {
+            return providerSettings.Parameters["scheme"] ?? "http://";
+        }
+
+        public static string GetBaseUrl(ProviderSettings providerSettings)
+        {
+            string hostName = GetHostName(providerSettings);
+
+            string scheme = GetScheme(providerSettings);
+
+            return VirtualPathUtility.AppendTrailingSlash(scheme + hostName);
+        }
+
+        public static void SetFileToPublic(ProviderSettings providerSettings, string file)
+        {
+            new Repository.AmazonS3Repository(providerSettings.Parameters["awsAccessKey"],
+                                              providerSettings.Parameters["awsSecretKey"],
+                                              providerSettings.Parameters["bucketName"]).SetFileToPublic(file);
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Hosting/AmazonS3Directory.cs

+using System;
+using System.Collections;
+using System.Linq;
+using System.Web;
+using System.Web.Hosting;
+using EPiServer.Security;
+using EPiServer.Web.Hosting;
+using Geta.Commerce.AmazonS3.Extensions;
+using Geta.Commerce.AmazonS3.Repository;
+
+namespace Geta.Commerce.AmazonS3.Hosting
+{
+    public class AmazonS3Directory : UnifiedDirectory
+    {
+        private readonly AmazonS3Repository _amazon;
+
+        public AmazonS3Directory(VirtualPathUnifiedProvider provider, string virtualPath) : base(provider, virtualPath, null, true)
+        {
+            this._amazon = new AmazonS3Repository(((AmazonS3VirtualPathProvider)this.Provider).AwsAccessKey, ((AmazonS3VirtualPathProvider)this.Provider).AwsSecretKey, ((AmazonS3VirtualPathProvider)this.Provider).BucketName);
+        }
+
+        public override IEnumerable Files
+        {
+            get 
+            {
+                return this._amazon.GetFiles(EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty)).Select(amazonFile => new AmazonS3File(this, this.Provider, this.Provider.VirtualPathRoot + amazonFile.Key, this.Provider.BypassAccessCheck, amazonFile.ToAmazonS3Object()));
+            }
+        }
+
+        public override AccessControlList ACL
+        {
+            get
+            {
+                var accessControlList = new AccessControlList();
+
+                if (this.Provider.BypassAccessCheck)
+                {
+                    accessControlList.Add(new AccessControlEntry("Everyone", AccessLevel.FullAccess, SecurityEntityType.Role));
+                }
+
+                return accessControlList;
+            }
+        }
+
+        public override IEnumerable Directories
+        {
+            get
+            {
+                return this._amazon.GetFolder(EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty)).Select(amazonFolder => new AmazonS3Directory(this.Provider, this.Provider.VirtualPathRoot + amazonFolder));
+            }
+        }
+
+        public override IEnumerable Children
+        {
+            get
+            {
+                yield return this.Files;
+                yield return this.Directories;
+            }
+        }
+
+        public override bool IsFirstLevel
+        {
+            get
+            {
+                return this.Parent == null;
+            }
+        }
+
+        public override UnifiedDirectory Parent
+        {
+            get
+            {
+                return HostingEnvironment.VirtualPathProvider.GetDirectory(VirtualPathUtility.GetDirectory(VirtualPath)) as AmazonS3Directory;
+            }
+        }
+
+        public override UnifiedDirectory[] GetDirectories()
+        {
+            return this.Directories.Cast<AmazonS3Directory>().ToArray();
+        }
+
+        public override UnifiedFile[] GetFiles()
+        {
+            return this.Files.Cast<AmazonS3File>().ToArray();
+        }
+
+        public override UnifiedDirectory CreateSubdirectory(string path)
+        {
+            this._amazon.CreateFolder(((AmazonS3VirtualPathProvider)this.Provider).BucketName, EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty) + path);
+            return new AmazonS3Directory(this.Provider, this.VirtualPath + path);
+        }
+
+        public override void Delete()
+        {
+            this._amazon.Delete(EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty));
+        }
+
+        public override UnifiedFile CreateFile(string name)
+        {
+            return CreateFile(name, Guid.NewGuid());
+        }
+
+        public override UnifiedFile CreateFile(string name, Guid id)
+        {
+            var virtualPath = Provider.CombineVirtualPaths(VirtualPath, name);
+            return new AmazonS3File(this, this.Provider, virtualPath, this.Provider.BypassAccessCheck, null);
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Hosting/AmazonS3File.cs

+using System;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Web;
+using System.Web.Hosting;
+using EPiServer.Security;
+using EPiServer.Web.Hosting;
+using Geta.Commerce.AmazonS3.Extensions;
+using Geta.Commerce.AmazonS3.Model;
+using Geta.Commerce.AmazonS3.Repository;
+using log4net;
+
+namespace Geta.Commerce.AmazonS3.Hosting
+{
+    public class AmazonS3File : UnifiedFile
+    {
+        private readonly AmazonS3Summary _summary;
+        private readonly AmazonS3Repository _amazon;
+        private readonly AmazonS3Object _file;
+        private readonly string _virtualPath;
+
+        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        public AmazonS3File(UnifiedDirectory directory, VirtualPathUnifiedProvider provider, string virtualPath, bool bypassAccessCheck, AmazonS3Object file) : base(directory, provider, virtualPath, bypassAccessCheck)
+        {
+            this._amazon = new AmazonS3Repository(((AmazonS3VirtualPathProvider)this.Provider).AwsAccessKey, ((AmazonS3VirtualPathProvider)this.Provider).AwsSecretKey, ((AmazonS3VirtualPathProvider)this.Provider).BucketName);
+            this._summary = new AmazonS3Summary();
+            this._virtualPath = virtualPath;
+
+            if (file != null)
+            {
+                this._file = file;
+            }
+        }
+
+        public override string Name
+        {
+            get
+            {
+                return VirtualPathUtility.GetFileName(_virtualPath);
+            }
+        }
+
+        public string AmazonKey
+        {
+            get { return EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty); }
+        }
+
+        public override UnifiedDirectory Parent
+        {
+            get
+            {
+                return HostingEnvironment.VirtualPathProvider.GetDirectory(VirtualPathUtility.GetDirectory(VirtualPath)) as AmazonS3Directory;
+            }
+        }
+
+        public override string LocalPath
+        {
+            get
+            {
+                var provider = (AmazonS3VirtualPathProvider)this.Provider;
+
+                string baseUrl = VirtualPathUtility.AppendTrailingSlash(provider.Scheme + provider.HostName);
+
+                return string.Format("{0}{1}", baseUrl, this.Name);
+            }
+        }
+
+        public override bool IsDirectory
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        public override long Length
+        {
+            get { return this._file.Length; }
+        }
+
+        public override DateTime Changed
+        {
+            get { return Convert.ToDateTime(this._file.Modified); }
+        }
+
+        public override DateTime Created
+        {
+            get { return Convert.ToDateTime(this._file.Created); }
+        }
+
+
+        public override string PermanentLinkVirtualPath
+        {
+            get
+            {
+                return this.LocalPath;
+            }
+        }
+
+        public string Url
+        {
+            get { return this.LocalPath; }
+        }
+
+        public override AccessLevel QueryAccess()
+        {
+            return AccessLevel.Read;
+        }
+
+        public override Stream Open()
+        {
+            return Open(FileMode.Open, FileAccess.Read, FileShare.Read);
+        }
+
+        public override Stream Open(FileMode mode)
+        {
+            return this.Open(mode, (mode == FileMode.Append) ? FileAccess.Write : FileAccess.ReadWrite);
+        }
+
+        public override Stream Open(FileMode mode, FileAccess access)
+        {
+            return Open(mode, access, FileShare.Read);
+        }
+
+        public override Stream Open(FileMode mode, FileAccess access, FileShare share)
+        {
+            if (mode == FileMode.CreateNew || mode == FileMode.Create || mode == FileMode.OpenOrCreate)
+            {
+                const string amazons3Tempfilename = "AmazonS3TempFileName";
+                const string tempExtension = ".TMP";
+
+                var sessionAmazonS3TempFileName = HttpContext.Current.Session[amazons3Tempfilename];
+                if (sessionAmazonS3TempFileName != null && !string.IsNullOrEmpty(sessionAmazonS3TempFileName.ToString()))
+                {
+                    this._amazon.Move(sessionAmazonS3TempFileName.ToString(), VirtualPath.RemovePath(this.Provider.VirtualPathRoot));
+                    HttpContext.Current.Session.Remove(amazons3Tempfilename);
+                }
+                else
+                {
+                    _amazon.Upload(EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty), HttpContext.Current.Request.Files[0].InputStream);
+                }
+                if (VirtualPathUtility.GetExtension(VirtualPath).ToLower() == tempExtension.ToLower())
+                {
+                    HttpContext.Current.Session.Add(amazons3Tempfilename, EPiServer.Url.Decode(this.VirtualPath).Replace(this.Provider.VirtualPathRoot, string.Empty));
+                }
+            }
+            return OpenRead();
+        }
+
+        public Stream OpenRead()
+        {
+            try
+            {
+                var client = new WebClient();
+                var fileByte = client.DownloadData(this.LocalPath);
+                return new MemoryStream(fileByte);
+            }
+            catch (Exception ex)
+            {
+                Log.Error("File {0} not exists");
+                return new MemoryStream();
+            }
+        }
+
+        public override void Delete()
+        {
+            this._amazon.Delete(this.AmazonKey);
+        }
+
+        public override void MoveTo(string newVirtualPath)
+        {
+            var e = new UnifiedVirtualPathEventArgs(newVirtualPath, this.VirtualPath);
+            
+            if (e.Cancel)
+            {
+                Log.Error(e.Reason);
+                throw new OperationAbortedException(e.Reason);
+            }
+
+            this._amazon.Move(this.VirtualPath.RemovePath(this.Provider.VirtualPathRoot), newVirtualPath.RemovePath(this.Provider.VirtualPathRoot));
+        }
+        
+        public override void CopyTo(string newVirtualPath)
+        {
+            CopyTo(newVirtualPath, new Guid());
+        }
+
+        public override void CopyTo(string newVirtualPath, Guid fileId)
+        {
+            this._amazon.Copy(this.VirtualPath.RemovePath(this.Provider.VirtualPathRoot), newVirtualPath.RemovePath(this.Provider.VirtualPathRoot));
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Hosting/AmazonS3Summary.cs

+using EPiServer.Web.Hosting;
+
+namespace Geta.Commerce.AmazonS3.Hosting
+{
+    public class AmazonS3Summary : UnifiedSummary
+    {
+        public override bool CanPersist
+        {
+            get { return true; }
+        }
+
+        public override void SaveChanges()
+        {
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Hosting/AmazonS3VirtualPathProvider.cs

+using System.Collections.Specialized;
+using System.Configuration;
+using System.Reflection;
+using System.Web;
+using System.Web.Hosting;
+using Geta.Commerce.AmazonS3.Repository;
+using log4net;
+
+namespace Geta.Commerce.AmazonS3.Hosting
+{
+    public class AmazonS3VirtualPathProvider : EPiServer.Business.Commerce.VirtualPathProviders.AssetVirtualPathProvider
+    {
+        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        public AmazonS3VirtualPathProvider(string name, NameValueCollection configParameters) : base(name, configParameters)
+        {
+            this.BucketName = configParameters["bucketName"];
+            const string logMessage = "AmazonS3VirtualPathProvider configuration missing or empty attribute '{0}'";
+            if (string.IsNullOrEmpty(this.BucketName))
+            {
+                Log.Error(string.Format(logMessage, "bucketName"));
+                throw new ConfigurationErrorsException(string.Format(logMessage, "bucketName"));
+            }
+
+            this.HostName = configParameters["hostName"];
+            if (string.IsNullOrEmpty(this.HostName))
+            {
+                Log.Error(string.Format(logMessage, "hostName"));
+                throw new ConfigurationErrorsException(string.Format(logMessage, "hostName"));
+            }
+
+            this.AwsAccessKey = configParameters["awsAccessKey"];
+            if (string.IsNullOrEmpty(this.AwsAccessKey))
+            {
+                Log.Error(string.Format(logMessage, "awsAccessKey"));
+                throw new ConfigurationErrorsException(string.Format(logMessage, "awsAccessKey"));
+            }
+
+            this.AwsSecretKey = configParameters["awsSecretKey"];
+            if (string.IsNullOrEmpty(this.AwsSecretKey))
+            {
+                Log.Error(string.Format(logMessage, "awsSecretKey"));
+                throw new ConfigurationErrorsException(string.Format(logMessage, "awsSecretKey"));
+            }
+
+            this.Scheme = configParameters["scheme"] ?? "http://";
+
+            this.VirtualPathRoot = VirtualPathUtility.AppendTrailingSlash(VirtualPathUtility.ToAbsolute(configParameters["virtualPath"]));
+
+            this.ValidateAndSetupConfigParams();
+        }
+
+        public string BucketName { get; set; }
+
+        public string AwsAccessKey { get; set; }
+
+        public string AwsSecretKey { get; set; }
+
+        public string HostName { get; set; }
+
+        public string Scheme { get; set; }
+       
+        public override VirtualDirectory GetDirectory(string virtualDir)
+        {
+            if (virtualDir.StartsWith(VirtualPathRoot))
+            {
+                var directory = new AmazonS3Directory(this, virtualDir);
+                return directory;
+            }
+
+            return Previous.GetDirectory(virtualDir);
+        }
+
+        public override VirtualFile GetFile(string virtualPath)
+        {
+            if (virtualPath.StartsWith(this.VirtualPathRoot))
+            {
+                var amazonFile = new AmazonS3Repository(this.AwsAccessKey, this.AwsSecretKey, this.BucketName).GetFile(EPiServer.Url.Decode(virtualPath).Replace(VirtualPathRoot, string.Empty));
+                var parent = new AmazonS3Directory(this, VirtualPathUtility.GetDirectory(virtualPath));
+                
+                if (amazonFile == null)
+                {
+                    return null;
+                }
+
+                return new AmazonS3File(parent, this, virtualPath, true, amazonFile);
+            }
+
+            if (string.IsNullOrEmpty(virtualPath))
+            {
+                return null;
+            }
+
+            return this.Previous.GetFile(virtualPath);
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Model/AmazonS3Object.cs

+using System;
+
+namespace Geta.Commerce.AmazonS3.Model
+{
+    public class AmazonS3Object
+    {
+        public string Id { get; set; }
+
+        public string Name { get; set; }
+
+        public long Length { get; set; }
+
+        public string Url { get; set; }
+
+        public string PermanentLinkUrl { get; set; }
+
+        public DateTime Created { get; set; }
+
+        public DateTime Modified { get; set; }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Modules/AmazonS3Module.cs

+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Globalization;
+using System.Net;
+using System.Reflection;
+using System.Web;
+using EPiServer;
+using EPiServer.Framework;
+using EPiServer.Framework.Initialization;
+using EPiServer.Web;
+using System.Linq;
+using log4net;
+using Mediachase.Commerce.Assets;
+using InitializationModule = EPiServer.Web.InitializationModule;
+
+namespace Geta.Commerce.AmazonS3.Modules
+{
+    [InitializableModule]
+    [ModuleDependency((typeof(InitializationModule)))]
+    public class AmazonS3Module : IInitializableModule
+    {
+        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+        public void Initialize(InitializationEngine context)
+        {
+            UrlRewriteModuleBase.HttpRewriteInit += HttpRewriteInit;
+        }
+
+        public void Preload(string[] parameters)
+        {
+        }
+
+        public void Uninitialize(InitializationEngine context)
+        {
+            UrlRewriteModuleBase.HttpRewriteInit -= HttpRewriteInit;
+        }
+
+        private static void HttpRewriteInit(object sender, UrlRewriteEventArgs e)
+        {
+            var urlRewriteModule = (UrlRewriteModule)sender;
+            urlRewriteModule.HttpRewritingToInternal += UrlRewriteModuleHttpRewritingToInternal;
+        }
+
+        private static void UrlRewriteModuleHttpRewritingToInternal(object sender, UrlRewriteEventArgs e)
+        {
+            IEnumerable<ProviderSettings> providerSettings = Helpers.AmazonS3VirtualPathHelper.GetAllSettings();
+
+            if (!providerSettings.Any())
+            {
+                return;
+            }
+
+            foreach (ProviderSettings providerSetting in providerSettings)
+            {
+                string virtualPath = Helpers.AmazonS3VirtualPathHelper.GetVirtualPath(providerSetting);
+
+                if (e.Url.Path.StartsWith(virtualPath))
+                {
+                    var url = Helpers.AmazonS3VirtualPathHelper.GetBaseUrl(providerSetting);
+                    var path = e.Url.Path.Replace(virtualPath, string.Empty);
+
+                    var pathSplit = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries);
+
+                    var folders = path.Split(new[] {'/'}, StringSplitOptions.RemoveEmptyEntries).ToList();
+                    folders.Remove(pathSplit.Last());
+
+
+
+                    var currentFolder = FolderEntity.GetChildFolders(1).First(n => n.Name == folders.First().ToString(CultureInfo.InvariantCulture));
+                    foreach (var folder in folders)
+                    {
+                        if (currentFolder.PrimaryKeyId.HasValue)
+                        {
+                            foreach (var child in FolderEntity.GetChildFolders(currentFolder.PrimaryKeyId.Value))
+                            {
+                                if (child.Name == folder)
+                                {
+                                    currentFolder = child;
+                                }
+
+                            }
+                        }
+                    }
+                    if (currentFolder.PrimaryKeyId != null)
+                    {
+                        var folderElementEntities = FolderEntity.GetChildElements(currentFolder.PrimaryKeyId.Value);
+                        var imagename = folderElementEntities.First(a => a.Name == pathSplit.Last().ToString(CultureInfo.InvariantCulture));
+                        Helpers.AmazonS3VirtualPathHelper.SetFileToPublic(providerSetting, imagename.BlobUid.ToString());
+
+                        url = UriSupport.Combine(url, imagename.BlobUid.ToString());
+                    }
+
+                    try
+                    {
+                        // Assuming url is the  url to the S3 object.
+                        var buffer = new byte[1024 * 8]; // 8k buffer. 
+                        var request = (HttpWebRequest)WebRequest.Create(url);
+                        var response = request.GetResponse();
+                        int bytesRead = 0;
+                        HttpContext.Current.Response.ContentType = request.ContentType;
+
+                        using (var responseStream = response.GetResponseStream())
+                        {
+                            while (responseStream != null && (bytesRead = responseStream.Read(buffer, 0, buffer.Length)) != 0)
+                            {
+                                HttpContext.Current.Response.OutputStream.Write(buffer, 0, bytesRead);
+                            }
+                        }
+                    }
+                    catch(WebException exception)
+                    {
+                        if (exception.Status == WebExceptionStatus.ProtocolError)
+                        {
+                            HttpContext.Current.Response.StatusCode = 403;
+                        }
+                    }
+
+                    HttpContext.Current.Response.End();
+                }
+            }
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Properties/AssemblyInfo.cs

+using System.Reflection;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Geta.AmazonS3")]
+[assembly: AssemblyDescription("Virtual Path Provider for Amazon S3 and Cloudfront")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Geta AS")]
+[assembly: AssemblyProduct("Geta.AmazonS3")]
+[assembly: AssemblyCopyright("Copyright © Geta AS 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a4736d9b-75b8-4d2b-a8a8-8d039e84ed50")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.0.3")]
+[assembly: AssemblyFileVersion("0.0.3")]

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Repository/AmazonS3Repository.cs

+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Amazon;
+using Amazon.S3.Model;
+using Geta.Commerce.AmazonS3.Extensions;
+using Geta.Commerce.AmazonS3.Model;
+using log4net;
+
+namespace Geta.Commerce.AmazonS3.Repository
+{
+    public class AmazonS3Repository : IAmazonS3Repository
+    {
+        private readonly string _bucketName;
+        private readonly Amazon.S3.AmazonS3 _client;
+
+        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+
+        public AmazonS3Repository(string accessKey, string secretKey, string bucketName)
+        {
+            this._client = AWSClientFactory.CreateAmazonS3Client(accessKey, secretKey);
+            this._bucketName = bucketName;
+        }
+
+        public IEnumerable<S3Object> GetFiles(string folder)
+        {
+            var request = new ListObjectsRequest().WithBucketName(this._bucketName).WithPrefix(folder).WithDelimiter("/");
+
+            using (var response = this._client.ListObjects(request))
+            {
+                return response.S3Objects.Where(o => o.Key.Last() != '/');
+            }
+        }
+
+        public IEnumerable<string> GetFolder(string folder)
+        {
+            var request = new ListObjectsRequest().WithBucketName(this._bucketName).WithPrefix(folder);
+            using (var response = this._client.ListObjects(request))
+            {
+                if (folder == string.Empty || folder == "/")
+                {
+                    // get the objects at the TOP LEVEL, i.e. not inside any folders
+                    var objects = response.S3Objects.Where(o => !o.Key.Contains(@"/"));
+
+                    // get the folders at the TOP LEVEL only
+                    return response.S3Objects.Except(objects).Where(o => o.Key.Last() == '/' && o.Key.IndexOf(@"/") == o.Key.LastIndexOf(@"/")).Select(n => n.Key);
+                }
+
+
+                var directories = new List<string>();
+
+                foreach (var split in response.S3Objects.Select(s3Object => s3Object.Key.Replace(folder, string.Empty).Split('/')).Where(splits => splits.Count() > 1 && !directories.Contains(splits.First())))
+                {
+                    directories.Add(split.First());
+                }
+
+                return directories;
+            }
+        }
+
+        public void CreateFolder(string bucket, string folder)
+        {
+            var key = string.Format(@"{0}/", folder);
+
+            if (this._client.ListObjects(new ListObjectsRequest().WithBucketName(this._bucketName).WithPrefix(folder)).S3Objects.Count > 0)
+            {
+                return;
+            }
+
+            var request = new PutObjectRequest().WithBucketName(bucket).WithKey(key).WithCannedACL(S3CannedACL.PublicRead);
+            request.InputStream = new MemoryStream();
+            this._client.PutObject(request);
+        }
+
+        public AmazonS3Object GetFile(string key)
+        {
+            var request = new GetObjectRequest();
+            request.WithBucketName(this._bucketName).WithKey(key);
+
+            try
+            {
+                var response = this._client.GetObject(request);
+                return response.ToAmazonS3Object();
+            }
+            catch (Exception ex)
+            {
+                Log.Error(string.Format("Cannot find the file with key {0}. Debug message: {1}", key, ex.Message));
+                return null;
+            }
+        }
+
+        public void SetFileToPublic(string key)
+        {
+            try
+            {
+                var request = new SetACLRequest();
+                request.WithBucketName(this._bucketName).WithKey(key);
+                request.CannedACL = S3CannedACL.PublicRead;
+                this._client.SetACL(request);
+            }
+            catch
+            {
+                // File not found
+            }
+        }
+
+        public void Delete(string key)
+        {
+            var deleteObject = new DeleteObjectRequest();
+            deleteObject.WithBucketName(this._bucketName).WithKey(key);
+            this._client.DeleteObject(deleteObject);
+        }
+
+        public void Upload(string fileName, Stream stream)
+        {
+            var request = new PutObjectRequest();
+            request.WithBucketName(this._bucketName).WithKey(fileName).WithInputStream(stream);
+            request.CannedACL = S3CannedACL.PublicRead;
+            request.StorageClass = S3StorageClass.ReducedRedundancy;
+            S3Response response = this._client.PutObject(request);
+            response.Dispose();
+        }
+
+        public void Copy(string copyFrom, string copyTo)
+        {
+            try
+            {
+                var copyRequest = new CopyObjectRequest().WithSourceBucket(this._bucketName).WithDestinationBucket(this._bucketName).WithSourceKey(copyFrom).WithDestinationKey(copyTo).WithCannedACL(S3CannedACL.PublicReadWrite);
+                this._client.CopyObject(copyRequest);               
+            }
+            catch (Exception ex)
+            {
+                Log.Error(string.Format("Cannot copy file from {0} to {1}. Debug message: {2}", copyFrom, copyTo, ex.Message));
+                return;
+            }
+        }
+
+        public void Move(string moveFrom, string moveTo)
+        {
+            try
+            {
+                var copyRequest = new CopyObjectRequest().WithSourceBucket(this._bucketName).WithDestinationBucket(this._bucketName).WithSourceKey(moveFrom).WithDestinationKey(moveTo).WithCannedACL(S3CannedACL.PublicReadWrite);
+                this._client.CopyObject(copyRequest);
+                this.Delete(moveFrom);
+            }
+            catch (Exception ex)
+            {
+                Log.Error(string.Format("Cannot move file from {0} to {1}. Debug message: {2}", moveFrom, moveTo, ex.Message));
+                return;
+            }
+        }
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/Repository/IAmazonS3Repository.cs

+using System.Collections.Generic;
+using System.IO;
+using Amazon.S3.Model;
+using Geta.Commerce.AmazonS3.Model;
+
+namespace Geta.Commerce.AmazonS3.Repository
+{
+    public interface IAmazonS3Repository
+    {
+        IEnumerable<S3Object> GetFiles(string folder);
+
+        IEnumerable<string> GetFolder(string folder);
+
+        void CreateFolder(string bucket, string folder);
+
+        AmazonS3Object GetFile(string key);
+
+        void Delete(string key);
+
+        void Upload(string fileName, Stream stream);
+
+        void Copy(string copyFrom, string copyTo);
+
+        void Move(string moveFrom, string moveTo);
+
+        void SetFileToPublic(string key);
+    }
+}

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/episerver.config.transform

+<episerver xmlns="http://EPiServer.Configuration.EPiServerSection">
+    <virtualPath>
+        <providers>
+            <add showInFileManager="true"
+               virtualName="Amazon"
+               virtualPath="~/AmazonS3/"
+               bucketName="company-bucket-name"
+               bypassAccessCheck="true"
+               hostName="static.example.com"
+               maxVersions="5"
+               name="SiteAmazonS3"
+               type="Geta.AmazonS3.Hosting.AmazonS3VirtualPathProvider,Geta.AmazonS3"
+               awsAccessKey="accessKey"
+               awsSecretKey="secretKey" />
+        </providers>
+    </virtualPath>
+</episerver>

Geta.Commerce.AmazonS3/Geta.Commerce.AmazonS3/packages.config

+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="AWSSDK" version="1.3.13.1" />
+  <package id="EPiServer.CMS.Core" version="6.1.379.0" />
+  <package id="EPiServer.Framework" version="6.2.267.1" />
+  <package id="log4net" version="1.2.10" />
+</packages>