webdav protal office 365 fix

This commit is contained in:
vfedosevich 2015-01-15 04:03:02 -08:00
parent 92befdea38
commit f2c54df2b0
27 changed files with 466 additions and 80 deletions

View file

@ -5,21 +5,21 @@ using WebsitePanel.WebDavPortal.WebConfigSections;
namespace WebsitePanel.WebDav.Core.Config.Entities
{
public class OfficeOnlineCollection : AbstractConfigCollection, IReadOnlyCollection<string>
public class OfficeOnlineCollection : AbstractConfigCollection, IReadOnlyCollection<OfficeOnlineElement>
{
private readonly IList<string> _officeExtensions;
private readonly IList<OfficeOnlineElement> _officeExtensions;
public OfficeOnlineCollection()
{
IsEnabled = ConfigSection.OfficeOnline.IsEnabled;
Url = ConfigSection.OfficeOnline.Url;
_officeExtensions = ConfigSection.OfficeOnline.Cast<OfficeOnlineElement>().Select(x => x.Extension).ToList();
_officeExtensions = ConfigSection.OfficeOnline.Cast<OfficeOnlineElement>().ToList();
}
public bool IsEnabled { get; private set; }
public string Url { get; private set; }
public IEnumerator<string> GetEnumerator()
public IEnumerator<OfficeOnlineElement> GetEnumerator()
{
return _officeExtensions.GetEnumerator();
}
@ -36,7 +36,7 @@ namespace WebsitePanel.WebDav.Core.Config.Entities
public bool Contains(string extension)
{
return _officeExtensions.Contains(extension);
return _officeExtensions.Any(x=>x.Extension == extension);
}
}
}

View file

@ -5,6 +5,7 @@ namespace WebsitePanel.WebDavPortal.WebConfigSections
public class OfficeOnlineElement : ConfigurationElement
{
private const string ExtensionKey = "extension";
private const string OwaOpenerKey = "owaOpener";
[ConfigurationProperty(ExtensionKey, IsKey = true, IsRequired = true)]
public string Extension
@ -12,5 +13,12 @@ namespace WebsitePanel.WebDavPortal.WebConfigSections
get { return this[ExtensionKey].ToString(); }
set { this[ExtensionKey] = value; }
}
[ConfigurationProperty(OwaOpenerKey, IsKey = true, IsRequired = true)]
public string OwaOpener
{
get { return this[OwaOpenerKey].ToString(); }
set { this[OwaOpenerKey] = value; }
}
}
}

View file

@ -0,0 +1,124 @@
using System.Runtime.Serialization;
namespace WebsitePanel.WebDav.Core.Entities.Owa
{
[DataContract]
public class CheckFileInfo
{
[DataMember]
public string BaseFileName { get; set; }
[DataMember]
public string OwnerId { get; set; }
[DataMember]
public long Size { get; set; }
[DataMember]
public string Version { get; set; }
//[DataMember]
//public string SHA256 { get; set; }
//[DataMember]
//public bool AllowExternalMarketplace { get; set; }
//[DataMember]
//public string BreadcrumbBrandName { get; set; }
//[DataMember]
//public string BreadcrumbBrandUrl { get; set; }
//[DataMember]
//public string BreadcrumbDocName { get; set; }
//[DataMember]
//public string BreadcrumbDocUrl { get; set; }
//[DataMember]
//public string BreadcrumbFolderName { get; set; }
//[DataMember]
//public string BreadcrumbFolderUrl { get; set; }
//[DataMember]
//public string ClientUrl { get; set; }
//[DataMember]
//public bool CloseButtonClosesWindow { get; set; }
//[DataMember]
//public string CloseUrl { get; set; }
//[DataMember]
//public bool DisableBrowserCachingOfUserContent { get; set; }
//[DataMember]
//public bool DisablePrint { get; set; }
//[DataMember]
//public bool DisableTranslation { get; set; }
//[DataMember]
//public string DownloadUrl { get; set; }
//[DataMember]
//public string FileSharingUrl { get; set; }
//[DataMember]
//public string FileUrl { get; set; }
//[DataMember]
//public string HostAuthenticationId { get; set; }
//[DataMember]
//public string HostEditUrl { get; set; }
//[DataMember]
//public string HostEmbeddedEditUrl { get; set; }
//[DataMember]
//public string HostEmbeddedViewUrl { get; set; }
//[DataMember]
//public string HostName { get; set; }
//[DataMember]
//public string HostNotes { get; set; }
//[DataMember]
//public string HostRestUrl { get; set; }
//[DataMember]
//public string HostViewUrl { get; set; }
//[DataMember]
//public string IrmPolicyDescription { get; set; }
//[DataMember]
//public string IrmPolicyTitle { get; set; }
//[DataMember]
//public string PresenceProvider { get; set; }
//[DataMember]
//public string PresenceUserId { get; set; }
//[DataMember]
//public string PrivacyUrl { get; set; }
//[DataMember]
//public bool ProtectInClient { get; set; }
//[DataMember]
//public bool ReadOnly { get; set; }
//[DataMember]
//public bool RestrictedWebViewOnly { get; set; }
//[DataMember]
//public string SignoutUrl { get; set; }
//[DataMember]
//public bool SupportsCoauth { get; set; }
//[DataMember]
//public bool SupportsCobalt { get; set; }
//[DataMember]
//public bool SupportsFolders { get; set; }
//[DataMember]
//public bool SupportsLocks { get; set; }
//[DataMember]
//public bool SupportsScenarioLinks { get; set; }
//[DataMember]
//public bool SupportsSecureStore { get; set; }
//[DataMember]
//public bool SupportsUpdate { get; set; }
//[DataMember]
//public string TenantId { get; set; }
//[DataMember]
//public string TermsOfUseUrl { get; set; }
//[DataMember]
//public string TimeZone { get; set; }
//[DataMember]
//public bool UserCanAttend { get; set; }
//[DataMember]
//public bool UserCanNotWriteRelative { get; set; }
//[DataMember]
//public bool UserCanPresent { get; set; }
//[DataMember]
//public bool UserCanWrite { get; set; }
//[DataMember]
//public string UserFriendlyName { get; set; }
//[DataMember]
//public string UserId { get; set; }
//[DataMember]
//public bool WebEditingDisabled { get; set; }
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Runtime.Serialization;
namespace WebsitePanel.WebDav.Core.Exceptions
{
[Serializable]
public class ConnectToWebDavServerException : Exception
{
public ConnectToWebDavServerException()
{
}
public ConnectToWebDavServerException(string message) : base(message)
{
}
public ConnectToWebDavServerException(string message, Exception inner) : base(message, inner)
{
}
protected ConnectToWebDavServerException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}

View file

@ -0,0 +1,25 @@
using System;
using System.Runtime.Serialization;
namespace WebsitePanel.WebDav.Core.Exceptions
{
[Serializable]
public class ResourceNotFoundException : Exception
{
public ResourceNotFoundException()
{
}
public ResourceNotFoundException(string message) : base(message)
{
}
public ResourceNotFoundException(string message, Exception inner) : base(message, inner)
{
}
protected ResourceNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Linq;
using System.Net;
@ -6,6 +7,7 @@ using System.Net.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using WebsitePanel.WebDav.Core.Config;
using WebsitePanel.WebDav.Core.Exceptions;
namespace WebsitePanel.WebDav.Core
@ -18,6 +20,7 @@ namespace WebsitePanel.WebDav.Core
IFolder CreateFolder(string name);
IHierarchyItem[] GetChildren();
IResource GetResource(string name);
Uri Path { get; }
}
public class WebDavFolder : WebDavHierarchyItem, IFolder
@ -25,6 +28,8 @@ namespace WebsitePanel.WebDav.Core
private IHierarchyItem[] _children = new IHierarchyItem[0];
private Uri _path;
public Uri Path { get { return _path; } }
/// <summary>
/// The constructor
/// </summary>
@ -155,7 +160,7 @@ namespace WebsitePanel.WebDav.Core
/// </summary>
public void Open()
{
var request = (HttpWebRequest) WebRequest.Create(_path);
var request = (HttpWebRequest)WebRequest.Create(_path);
request.PreAuthenticate = true;
request.Method = "PROPFIND";
request.ContentType = "application/xml";
@ -163,10 +168,10 @@ namespace WebsitePanel.WebDav.Core
//TODO Disable SSL
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
var credentials = (NetworkCredential) _credentials;
var credentials = (NetworkCredential)_credentials;
if (credentials != null && credentials.UserName != null)
{
request.Credentials = credentials;
//request.Credentials = credentials;
string auth = "Basic " +
Convert.ToBase64String(
Encoding.Default.GetBytes(credentials.UserName + ":" + credentials.Password));

View file

@ -0,0 +1,19 @@
using System.Collections.Generic;
using WebsitePanel.WebDav.Core.Client;
namespace WebsitePanel.WebDav.Core.Interfaces.Managers
{
public interface IWebDavManager
{
string RootPath { get; }
void OpenFolder(string pathPart);
IEnumerable<IHierarchyItem> GetChildren();
bool IsFile(string fileName);
byte[] GetFileBytes(string fileName);
IResource GetResource( string fileName);
string GetFileUrl(string fileName);
string CreateFileId(string path);
string FilePathFromId(string id);
}
}

View file

@ -0,0 +1,12 @@
using System.Web.Mvc;
using WebsitePanel.WebDav.Core.Client;
using WebsitePanel.WebDav.Core.Entities.Owa;
namespace WebsitePanel.WebDav.Core.Interfaces.Owa
{
public interface IWopiServer
{
CheckFileInfo GetCheckFileInfo(string path);
FileResult GetFile(string path);
}
}

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Security;
using WebsitePanel.WebDav.Core.Security.Authentication.Principals;
namespace WebsitePanel.WebDav.Core.Interfaces.Security
@ -10,7 +11,9 @@ namespace WebsitePanel.WebDav.Core.Interfaces.Security
public interface IAuthenticationService
{
WspPrincipal LogIn(string login, string password);
WspPrincipal LogIn(string accessToken);
void CreateAuthenticationTicket(WspPrincipal principal);
string CreateAccessToken(WspPrincipal principal);
void LogOut();
}
}

View file

@ -0,0 +1,197 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using log4net;
using WebsitePanel.Providers.OS;
using WebsitePanel.WebDav.Core.Client;
using WebsitePanel.WebDav.Core.Config;
using WebsitePanel.WebDav.Core.Exceptions;
using WebsitePanel.WebDav.Core.Interfaces.Managers;
using WebsitePanel.WebDav.Core.Security.Cryptography;
using WebsitePanel.WebDav.Core.Wsp.Framework;
namespace WebsitePanel.WebDav.Core.Managers
{
public class WebDavManager : IWebDavManager
{
private readonly ICryptography _cryptography;
private readonly WebDavSession _webDavSession;
private readonly ILog Log;
private IFolder _currentFolder;
private bool _isRoot = true;
private Lazy<IList<SystemFile>> _rootFolders;
private Lazy<string> _webDavRootPath;
public string RootPath
{
get { return _webDavRootPath.Value; }
}
public WebDavManager(ICryptography cryptography)
{
_cryptography = cryptography;
Log = LogManager.GetLogger(this.GetType());
_webDavSession = new WebDavSession();
_rootFolders = new Lazy<IList<SystemFile>>(ConnectToWebDavServer);
_webDavRootPath = new Lazy<string>(() =>
{
if (_rootFolders.Value.Any())
{
var folder = _rootFolders.Value.First();
var uri = new Uri(folder.Url);
return uri.Scheme + "://" + uri.Host + uri.Segments[0] + uri.Segments[1];
}
return string.Empty;
});
}
public void OpenFolder(string pathPart)
{
if (string.IsNullOrWhiteSpace(pathPart))
{
_isRoot = true;
return;
}
_isRoot = false;
_webDavSession.Credentials = new NetworkCredential(WspContext.User.Login, _cryptography.Decrypt(WspContext.User.EncryptedPassword), WebDavAppConfigManager.Instance.UserDomain);
_currentFolder = _webDavSession.OpenFolder(_webDavRootPath.Value + pathPart);
}
public IEnumerable<IHierarchyItem> GetChildren()
{
IHierarchyItem[] children;
if (_isRoot)
{
children = _rootFolders.Value.Select(x => new WebDavHierarchyItem {Href = new Uri(x.Url), ItemType = ItemType.Folder}).ToArray();
}
else
{
children = _currentFolder.GetChildren();
}
List<IHierarchyItem> sortedChildren = children.Where(x => x.ItemType == ItemType.Folder).OrderBy(x => x.DisplayName).ToList();
sortedChildren.AddRange(children.Where(x => x.ItemType != ItemType.Folder).OrderBy(x => x.DisplayName));
return sortedChildren;
}
public bool IsFile(string fileName)
{
if (string.IsNullOrWhiteSpace(fileName) | _currentFolder == null)
return false;
try
{
IResource resource = _currentFolder.GetResource(fileName);
//Stream stream = resource.GetReadStream();
return true;
}
catch (InvalidOperationException)
{
}
return false;
}
public byte[] GetFileBytes(string fileName)
{
try
{
IResource resource = _currentFolder.GetResource(fileName);
Stream stream = resource.GetReadStream();
byte[] fileBytes = ReadFully(stream);
return fileBytes;
}
catch (InvalidOperationException exception)
{
throw new ResourceNotFoundException("Resource not found", exception);
}
}
public IResource GetResource(string fileName)
{
try
{
IResource resource = _currentFolder.GetResource(fileName);
return resource;
}
catch (InvalidOperationException exception)
{
throw new ResourceNotFoundException("Resource not found", exception);
}
}
public string GetFileUrl(string fileName)
{
try
{
IResource resource = _currentFolder.GetResource(fileName);
return resource.Href.ToString();
}
catch (InvalidOperationException exception)
{
throw new ResourceNotFoundException("Resource not found", exception);
}
}
private IList<SystemFile> ConnectToWebDavServer()
{
var rootFolders = new List<SystemFile>();
var user = WspContext.User;
var userGroups = WSP.Services.Organizations.GetSecurityGroupsByMember(user.ItemId, user.AccountId);
foreach (var folder in WSP.Services.EnterpriseStorage.GetEnterpriseFolders(WspContext.User.ItemId))
{
var permissions = WSP.Services.EnterpriseStorage.GetEnterpriseFolderPermissions(WspContext.User.ItemId, folder.Name);
foreach (var permission in permissions)
{
if ((!permission.IsGroup
&& (permission.DisplayName == user.UserName || permission.DisplayName == user.DisplayName))
|| (permission.IsGroup && userGroups.Any(x => x.DisplayName == permission.DisplayName)))
{
rootFolders.Add(folder);
break;
}
}
}
return rootFolders;
}
private byte[] ReadFully(Stream input)
{
var buffer = new byte[16*1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
ms.Write(buffer, 0, read);
return ms.ToArray();
}
}
public string CreateFileId(string path)
{
return _cryptography.Encrypt(path).Replace("/", "AAAAA");
}
public string FilePathFromId(string id)
{
return _cryptography.Decrypt(id.Replace("AAAAA", "/"));
}
}
}

View file

@ -0,0 +1,58 @@
using System;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Web.Mvc;
using WebsitePanel.WebDav.Core.Client;
using WebsitePanel.WebDav.Core.Entities.Owa;
using WebsitePanel.WebDav.Core.Interfaces.Managers;
using WebsitePanel.WebDav.Core.Interfaces.Owa;
namespace WebsitePanel.WebDav.Core.Owa
{
public class WopiServer : IWopiServer
{
private readonly IWebDavManager _webDavManager;
public WopiServer(IWebDavManager webDavManager)
{
_webDavManager = webDavManager;
}
public CheckFileInfo GetCheckFileInfo(string path)
{
string fileName = path.Split('/').Last();
int index = path.LastIndexOf(fileName, StringComparison.InvariantCultureIgnoreCase);
string folder = path.Remove(index - 1, fileName.Length + 1);
_webDavManager.OpenFolder(folder);
var resource = _webDavManager.GetResource(fileName);
var cFileInfo = new CheckFileInfo
{
BaseFileName = resource.DisplayName,
OwnerId = @"4257508bfe174aa28b461536d8b6b648",
Size = resource.ContentLength,
Version = @"%22%7B59CCD75F%2D0687%2D4F86%2DBBCF%2D059126640640%7D%2C1%22"
};
return cFileInfo;
}
public FileResult GetFile(string path)
{
string fileName = path.Split('/').Last();
int index = path.LastIndexOf(fileName, StringComparison.InvariantCultureIgnoreCase);
string folder = path.Remove(index - 1, fileName.Length + 1);
_webDavManager.OpenFolder(folder);
var fileBytes = _webDavManager.GetFileBytes(fileName);
return new FileContentResult(fileBytes, MediaTypeNames.Application.Octet);
}
}
}

View file

@ -1,5 +1,6 @@
using System;
using System.DirectoryServices.AccountManagement;
using System.Threading;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.Security;
@ -29,8 +30,10 @@ namespace WebsitePanel.WebDav.Core.Security.Authentication
return null;
}
var principal = new WspPrincipal(login);
//var user = UserPrincipal.FindByIdentity(_principalContext, IdentityType.UserPrincipalName, login);
var principal = new WspPrincipal(login);
var exchangeAccount = WSP.Services.ExchangeServer.GetAccountByAccountNameWithoutItemId(login);
var organization = WSP.Services.Organizations.GetOrganization(exchangeAccount.ItemId);
@ -40,13 +43,34 @@ namespace WebsitePanel.WebDav.Core.Security.Authentication
principal.DisplayName = exchangeAccount.DisplayName;
principal.EncryptedPassword = _cryptography.Encrypt(password);
CreateAuthenticationTicket(principal);
if (HttpContext.Current != null)
{
HttpContext.Current.User = principal;
}
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = principal;
return principal;
}
public WspPrincipal LogIn(string accessToken)
{
var token = _cryptography.Decrypt(accessToken.Replace("AAAAA", "/"));
var splitResult = token.Split(':');
var login = splitResult[0];
var password = _cryptography.Decrypt(splitResult[1]);
var expiration = DateTime.Parse(splitResult[2]);
if (expiration < DateTime.Today)
{
return null;
}
return LogIn(login, password);
}
public void CreateAuthenticationTicket(WspPrincipal principal)
{
var serializer = new JavaScriptSerializer();
@ -67,6 +91,13 @@ namespace WebsitePanel.WebDav.Core.Security.Authentication
HttpContext.Current.Response.Cookies.Add(cookie);
}
public string CreateAccessToken(WspPrincipal principal)
{
var token = string.Format("{0}:{1}:{2}", principal.Login, principal.EncryptedPassword, DateTime.Now.ToShortDateString());
return _cryptography.Encrypt(token).Replace("/", "AAAAA");
}
public void LogOut()
{
FormsAuthentication.SignOut();

View file

@ -28,8 +28,8 @@ namespace WebsitePanel.WebDav.Core.Security.Authentication.Principals
public IIdentity Identity { get; private set; }
public WspPrincipal(string username)
{
Identity = new GenericIdentity(username);
{
Identity = new GenericIdentity(username);//new WindowsIdentity(username, "WindowsAuthentication");
Login = username;
}

View file

@ -32,6 +32,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="log4net">
<HintPath>..\packages\log4net.2.0.0\lib\net40-full\log4net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
@ -45,6 +48,7 @@
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.DirectoryServices.AccountManagement" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Web">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.Web.dll</HintPath>
</Reference>
@ -79,6 +83,10 @@
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WebsitePanel.EnterpriseServer.Base, Version=2.1.0.1, Culture=neutral, PublicKeyToken=da8782a6fc4d0081, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Scheduler Domains\WebsitePanel\Bin\WebsitePanel.EnterpriseServer.Base.dll</HintPath>
</Reference>
<Reference Include="WebsitePanel.EnterpriseServer.Client">
<HintPath>..\WebsitePanel.WebPortal\Bin\WebsitePanel.EnterpriseServer.Client.dll</HintPath>
</Reference>
@ -108,6 +116,9 @@
<Compile Include="Config\WebConfigSections\WebDavExplorerConfigurationSettingsSection.cs" />
<Compile Include="Config\WebConfigSections\WebsitePanelConstantUserElement.cs" />
<Compile Include="Config\WebDavAppConfigManager.cs" />
<Compile Include="Entities\Owa\CheckFileInfo.cs" />
<Compile Include="Exceptions\ConnectToWebDavServerException.cs" />
<Compile Include="Exceptions\ResourceNotFoundException.cs" />
<Compile Include="Exceptions\UnauthorizedException.cs" />
<Compile Include="Exceptions\WebDavException.cs" />
<Compile Include="Exceptions\WebDavHttpException.cs" />
@ -115,11 +126,14 @@
<Compile Include="IFolder.cs" />
<Compile Include="IHierarchyItem.cs" />
<Compile Include="IItemContent.cs" />
<Compile Include="Interfaces\Managers\IWebDavManager.cs" />
<Compile Include="Interfaces\Owa\IWopiServer.cs" />
<Compile Include="Interfaces\Security\IAuthenticationService.cs" />
<Compile Include="IResource.cs" />
<Compile Include="IResumableUpload.cs" />
<Compile Include="ItemType.cs" />
<Compile Include="LockUriTokenPair.cs" />
<Compile Include="Managers\WebDavManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Property.cs" />
<Compile Include="PropertyName.cs" />
@ -132,6 +146,7 @@
<Compile Include="Security\Cryptography\ICryptography.cs" />
<Compile Include="Security\Authentication\FormsAuthenticationService.cs" />
<Compile Include="Security\Authentication\Principals\WspPrincipal.cs" />
<Compile Include="Owa\WopiServer.cs" />
<Compile Include="WebDavSession.cs" />
<Compile Include="WspContext.cs" />
<Compile Include="Wsp\Framework\WSP.cs" />

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.0" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.2" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.2.2" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.2.2" targetFramework="net45" />