Permission updates working
[pithos-ms-client] / trunk / Pithos.Interfaces / ObjectInfo.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics.Contracts;
4 using System.Dynamic;
5 using System.Globalization;
6 using System.IO;
7 using System.Linq;
8 using System.Text;
9 using System.Text.RegularExpressions;
10 using Newtonsoft.Json;
11
12 namespace Pithos.Interfaces
13 {
14     public class ObjectInfo:DynamicObject 
15     {
16         private readonly List<string> _knownContainers= new List<string>{"trash"};
17         public string Name { get; set; }
18         public string Hash { get; set; }
19         public long Bytes { get; set; }
20         public string Content_Type { get; set; }
21         public DateTime Last_Modified { get; set; }
22
23         private Dictionary<string, string> _tags=new Dictionary<string, string>();
24         public Dictionary<string, string> Tags
25         {
26             get { return _tags; }
27             set { _tags = value; }
28         }
29
30         private Dictionary<string, string> _extensions=new Dictionary<string, string>();
31         public Dictionary<string, string> Extensions
32         {
33             get { return _extensions; }
34             set
35             {
36                 _extensions = value;
37                 ExtractKnownExtensions();
38             }
39         }
40         
41         
42         private Dictionary<string, string> _permissions=new Dictionary<string, string>();
43         [JsonProperty("x_object_sharing")]
44         [JsonConverter(typeof(PermissionConverter))]
45         public Dictionary<string, string> Permissions
46         {
47             get { return _permissions; }
48             set
49             {
50                 _permissions = value;                
51             }
52         }
53
54         /// <summary>
55         /// Version number
56         /// </summary>
57         [JsonProperty("x_object_version")]
58         public long? Version { get; set; }
59
60
61         /// <summary>
62         /// Shared object permissions can be Read or Write
63         /// </summary>
64         [JsonProperty("x_object_allowed_to")]
65         public string AllowedTo { get; set; }
66
67
68         /// <summary>
69         /// Version timestamp
70         /// </summary>
71         [JsonProperty("X_Object_Version_Timestamp"), JsonConverter(typeof(PithosDateTimeConverter))]
72         public DateTime? VersionTimestamp { get; set; }
73
74         [JsonProperty("X_Object_Modified_By")]
75         public string ModifiedBy { get; set; }
76
77
78         public Stream Stream { get; set; }
79
80         public string Account { get; set; }
81
82         public string Container { get; set; }
83
84         public string ContendDisposition { get; set; }
85
86         public string ContentEncoding { get; set; }
87
88         public string Manifest { get; set; }
89
90         private bool _isPublic;
91         public bool IsPublic
92         {
93             get { return !String.IsNullOrWhiteSpace(PublicUrl); }
94             set
95             {
96                 if (!value)
97                     PublicUrl = null;
98                 else if (String.IsNullOrWhiteSpace(PublicUrl))
99                     PublicUrl="true";                
100             }
101         }
102
103         public string PublicUrl { get; set; }
104
105         public ObjectInfo()
106         {}
107
108         public ObjectInfo(string accountPath,string accountName,FileInfo fileInfo)
109         {
110             var relativeUrl = fileInfo.AsRelativeUrlTo(accountPath);
111             //The first part of the URL is the container
112             var slashIndex = relativeUrl.IndexOf('/');
113             var container = relativeUrl.Substring(0, slashIndex);
114             //The second is the file's url relative to the container
115             var fileUrl = relativeUrl.Substring(slashIndex + 1);
116
117             Account = accountName;
118             Container = container;
119             Name = fileUrl; 
120         }
121
122
123         private void ExtractKnownExtensions()
124         {
125             Version=GetLong(KnownExtensions.X_Object_Version);
126             VersionTimestamp = GetTimestamp(KnownExtensions.X_Object_Version_Timestamp);
127             ModifiedBy = GetString(KnownExtensions.X_Object_Modified_By);
128         }
129
130         private string GetString(string name)
131         {            
132             var value=String.Empty;
133             _extensions.TryGetValue(name, out value);
134             return value ;                        
135         }
136
137         private long? GetLong(string name)
138         {
139             string version;
140             long value;
141             return _extensions.TryGetValue(name, out version) && long.TryParse(version, out value)
142                        ? (long?) value
143                        : null;
144         }
145
146         private DateTime? GetTimestamp(string name)
147         {
148             string version;
149             DateTime value;
150             if (_extensions.TryGetValue(name, out version) && 
151                 DateTime.TryParse(version,CultureInfo.InvariantCulture,DateTimeStyles.AdjustToUniversal, out value))
152             {
153                 return value;
154             }
155             return null;
156         }
157
158
159         public static ObjectInfo Empty = new ObjectInfo
160         {
161             Name = String.Empty,
162             Hash = String.Empty,
163             Bytes = 0,
164             Content_Type = String.Empty,
165             Last_Modified = DateTime.MinValue
166         };
167
168         public string RelativeUrlToFilePath(string currentAccount)
169         {
170             if (Name==null)
171                 throw new InvalidOperationException("Name can't be null");
172             if (String.IsNullOrWhiteSpace(currentAccount))
173                 throw new ArgumentNullException("currentAccount");
174             Contract.EndContractBlock();
175
176             if (this == Empty)
177                 return String.Empty;
178
179             var unescaped = Uri.UnescapeDataString(Name);
180             var path = unescaped.Replace("/", "\\");
181             var pathParts=new Stack<string>();
182             pathParts.Push(path);
183             if (!String.IsNullOrWhiteSpace(Container) && !_knownContainers.Contains(Container))
184                 pathParts.Push(Container);
185             if (!currentAccount.Equals(Account, StringComparison.InvariantCultureIgnoreCase))
186             {
187                 if (Account != null)
188                 {
189                     pathParts.Push(Account);
190                     pathParts.Push("others");
191                 }
192             }
193             var finalPath=Path.Combine(pathParts.ToArray());
194             return finalPath;
195         }
196
197         public override bool TrySetMember(SetMemberBinder binder, object value)
198         {
199             if (binder.Name.StartsWith("x_object_meta"))
200             {
201                 Tags[binder.Name] = value.ToString();
202             }
203             return false;
204         }
205
206         public string GetPermissionString()
207         {
208             var permissionBuilder = new StringBuilder();
209             var groupings = Permissions.GroupBy(pair => pair.Value, pair => pair.Key);
210             foreach (var grouping in groupings)
211             {
212                 permissionBuilder.AppendFormat("{0}={1};", grouping.Key, String.Join(",", grouping));
213             }
214             var permissions = permissionBuilder.ToString().Trim(';');
215             return permissions;
216         }
217
218         public void SetPermissions(string permissions)
219         {
220             var permDict=new Dictionary<string, string>();
221             var perms=permissions.Split(';');
222             foreach (var perm in perms)
223             {
224                 var permPairs=perm.Split('=');
225                 var right = permPairs[0];
226                 var users= permPairs[1].Split(new[]{','},StringSplitOptions.RemoveEmptyEntries);
227                 foreach (var user in users)
228                 {
229                     permDict[user] = right;
230                 }
231             }
232             Permissions = permDict;
233         }
234     }
235 }