#region /* ----------------------------------------------------------------------- * * * Copyright 2011-2012 GRNET S.A. All rights reserved. * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and * documentation are those of the authors and should not be * interpreted as representing official policies, either expressed * or implied, of GRNET S.A. * * ----------------------------------------------------------------------- */ #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Contracts; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using Newtonsoft.Json; namespace Pithos.Interfaces { [DebuggerDisplay("Name {Name}")] public class ObjectInfo//:DynamicObject { private readonly List _knownContainers= new List{"trash"}; public string Name { get; set; } public string Hash { get; set; } public string X_Object_Hash { get { return Hash; } set { Hash = value; } } [JsonProperty("x_object_uuid")] public string UUID { get; set; } public long Bytes { get; set; } public string Content_Type { get; set; } public DateTime Last_Modified { get; set; } private Dictionary _tags=new Dictionary(); public Dictionary Tags { get { return _tags; } set { _tags = value; } } private Dictionary _extensions=new Dictionary(); public Dictionary Extensions { get { return _extensions; } set { _extensions = value; ExtractKnownExtensions(); } } private Dictionary _permissions=new Dictionary(); [JsonProperty("x_object_sharing")] [JsonConverter(typeof(PermissionConverter))] public Dictionary Permissions { get { return _permissions; } set { _permissions = value; } } /// /// Version number /// [JsonProperty("x_object_version")] public long? Version { get; set; } /// /// Shared object permissions can be Read or Write /// [JsonProperty("x_object_allowed_to")] public string AllowedTo { get; set; } /// /// Version timestamp /// [JsonProperty("X_Object_Version_Timestamp"), JsonConverter(typeof(PithosDateTimeConverter))] public DateTime? VersionTimestamp { get; set; } [JsonProperty("X_Object_Modified_By")] public string ModifiedBy { get; set; } public Stream Stream { get; set; } public Uri StorageUri { get; set; } public string Account { get; set; } public string Container { get; set; } public Uri Uri { get { var relativeUrl=String.Format("{0}/{1}/{2}",Account, Container,Name); return StorageUri==null ? new Uri(relativeUrl,UriKind.Relative) : new Uri(StorageUri, relativeUrl); } } public string ContendDisposition { get; set; } public string ContentEncoding { get; set; } public string Manifest { get; set; } public bool IsPublic { get { return !String.IsNullOrWhiteSpace(PublicUrl); } set { if (!value) PublicUrl = null; else if (String.IsNullOrWhiteSpace(PublicUrl)) PublicUrl="true"; } } [JsonProperty("X_Object_Public")] public string PublicUrl { get; set; } public string PreviousHash { get; set; } public ObjectInfo() {} public ObjectInfo(string accountPath,string accountName,FileSystemInfo fileInfo) { if (String.IsNullOrWhiteSpace(accountPath)) throw new ArgumentNullException("accountPath"); if (string.IsNullOrWhiteSpace(accountName)) throw new ArgumentNullException("accountName"); if (fileInfo == null) throw new ArgumentNullException("fileInfo"); Contract.EndContractBlock(); var relativeUrl = fileInfo.WithProperCapitalization().AsRelativeUrlTo(accountPath); //The first part of the URL is the container var slashIndex = relativeUrl.IndexOf('/'); var container = relativeUrl.Substring(0, slashIndex); //The second is the file's url relative to the container var fileUrl = relativeUrl.Substring(slashIndex + 1); Account = accountName; Container = container; Name = fileUrl; } private void ExtractKnownExtensions() { Version=GetLong(KnownExtensions.X_Object_Version); VersionTimestamp = GetTimestamp(KnownExtensions.X_Object_Version_Timestamp); ModifiedBy = GetString(KnownExtensions.X_Object_Modified_By); } private string GetString(string name) { string value; _extensions.TryGetValue(name, out value); return value ; } private long? GetLong(string name) { string version; long value; return _extensions.TryGetValue(name, out version) && long.TryParse(version, out value) ? (long?) value : null; } private DateTime? GetTimestamp(string name) { string version; DateTime value; if (_extensions.TryGetValue(name, out version) && DateTime.TryParse(version,CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal, out value)) { return value; } return null; } public static ObjectInfo Empty = new ObjectInfo { Name = String.Empty, Hash = String.Empty, Bytes = 0, Content_Type = String.Empty, Last_Modified = DateTime.MinValue, Exists=false }; private bool _exists=true; public bool Exists { get { return _exists; } set { _exists = value; } } public string RelativeUrlToFilePath(string currentAccount) { if (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(Name); var path = unescaped.Replace("/", "\\"); var pathParts=new Stack(); 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(FolderConstants.OthersFolder); } } var finalPath=Path.Combine(pathParts.ToArray()); return finalPath; } /* public override bool TrySetMember(SetMemberBinder binder, object value) { if (binder.Name.StartsWith("x_object_meta")) { Tags[binder.Name] = value.ToString(); } return false; } */ public string GetPermissionString() { if (Permissions==null) throw new InvalidOperationException(); Contract.EndContractBlock(); var permissionBuilder = new StringBuilder(); var groupings = Permissions.GroupBy(pair => pair.Value, pair => pair.Key); foreach (var grouping in groupings) { permissionBuilder.AppendFormat("{0}={1};", grouping.Key, String.Join(",", grouping)); } var permissions = permissionBuilder.ToString().Trim(';'); return permissions; } public void SetPermissions(string permissions) { if (String.IsNullOrWhiteSpace(permissions)) return; var permDict=new Dictionary(); var perms=permissions.Split(';'); foreach (var perm in perms) { var permPairs=perm.Split('='); var right = permPairs[0]; var users= permPairs[1].Split(new[]{','},StringSplitOptions.RemoveEmptyEntries); foreach (var user in users) { permDict[user] = right; } } Permissions = permDict; } //The previous values that correspond to a NoModification object //have the same account, container and possibly the same folder public bool CorrespondsTo(ObjectInfo other) { return other.Account == this.Account && other.Container == this.Container && (this.Name == null || other.Name.StartsWith(this.Name)); } public ObjectInfo Previous { get; private set; } public bool IsDirectory { get { return String.Equals(Content_Type, @"application/directory",StringComparison.InvariantCultureIgnoreCase); } } public ObjectInfo SetPrevious(ObjectInfo previous) { Previous = previous; PreviousHash = previous.Hash; return this; } } }