Revision 8f918cb0

b/trunk/Pithos.Core/Agents/StatusAgent.cs
350 350
                        {
351 351
                            var createdState = FileState.CreateFor(FileInfoExtensions.FromPath(path));
352 352
                            createdState.FileStatus = status;
353
                            _persistenceAgent.Post(createdState.Create);
353
                            createdState.Create();
354 354
                        }
355 355
                        return affected;
356 356
                    }
......
390 390
                            var createdState=FileState.CreateFor(FileInfoExtensions.FromPath(absolutePath));
391 391
                            createdState.FileStatus = fileStatus;
392 392
                            createdState.OverlayStatus = overlayStatus;
393
                            _persistenceAgent.Post(createdState.Create);  
393
                            createdState.Create();  
394 394
                        }
395 395
                        return affected;
396 396
                    }
b/trunk/Pithos.Core/Agents/Uploader.cs
83 83
                        {
84 84

  
85 85
                            var client = new CloudFilesClient(accountInfo);
86

  
86 87
                            //Even if GetObjectInfo times out, we can proceed with the upload            
87 88
                            var cloudInfo = client.GetObjectInfo(account, cloudFile.Container, cloudFile.Name);
88 89

  
89
                            //If this is a read-only file, do not upload changes
90
                            if (!cloudInfo.IsWritable(action.AccountInfo.UserName))
91
                                return;
90
                            //If this a shared file
91
                            if (!cloudFile.Account.Equals(action.AccountInfo.UserName,StringComparison.InvariantCultureIgnoreCase))
92
                            {
93
                                //If this is a read-only file, do not upload changes
94
                                if (!cloudInfo.IsWritable(action.AccountInfo.UserName))
95
                                {
96
                                    MakeFileReadOnly(fullFileName);
97
                                    return;
98
                                }
92 99

  
93
                                //TODO: If the object does not exist, check that we can upload to the folder
100
                                //If the file is new, can we upload it?
101
                                if ( !cloudInfo.Exists && !client.CanUpload(account, cloudFile))
102
                                {
103
                                    MakeFileReadOnly(fullFileName);
104
                                    return;
105
                                }
106

  
107
                            }
94 108

  
95 109
                            if (fileInfo is DirectoryInfo)
96 110
                            {
......
143 157
                            if (response.StatusCode == HttpStatusCode.Forbidden)
144 158
                            {
145 159
                                StatusKeeper.SetFileState(fileInfo.FullName, FileStatus.Forbidden, FileOverlayStatus.Conflict, "Forbidden");
146
                                
160
                                MakeFileReadOnly(fullFileName);
147 161
                            }
148 162
                            else
149 163
                                //In any other case, propagate the error
......
177 191
            }
178 192
        }
179 193

  
194
        private static void MakeFileReadOnly(string fullFileName)
195
        {
196
            var attributes = File.GetAttributes(fullFileName);
197
            //Do not make any modifications if not necessary
198
            if (attributes.HasFlag(FileAttributes.ReadOnly))
199
                return;
200
            File.SetAttributes(fullFileName, attributes | FileAttributes.ReadOnly);
201
        }
202

  
180 203
        private static AccountInfo GetSharerAccount(string relativePath, AccountInfo accountInfo)
181 204
        {
182 205
            var parts = relativePath.Split('\\');
b/trunk/Pithos.Network.Test/ObjectInfoTest.cs
18 18

  
19 19
            var info1 = new ObjectInfo {Account = "pkanavos", Container = "pithos", Name = "somefolder/file1.txt"};
20 20
            var path1=info1.RelativeUrlToFilePath("PKANAVOS");
21
            Assert.AreEqual(@"somefolder\file1.txt",path1);
21
            Assert.AreEqual(@"pithos\somefolder\file1.txt",path1);
22 22
            var path2 = info1.RelativeUrlToFilePath("user1");
23
            Assert.AreEqual(@"others\pkanavos\somefolder\file1.txt", path2);
23
            Assert.AreEqual(@"others-shared\pkanavos\pithos\somefolder\file1.txt", path2);
24 24
            var info3 = new ObjectInfo { Account = "pkanavos", Name = "somefolder/file1.txt" };
25 25
            var path3 = info1.RelativeUrlToFilePath("PKANAVOS");
26
            Assert.AreEqual(@"somefolder\file1.txt", path1);
26
            Assert.AreEqual(@"pithos\somefolder\file1.txt", path1);
27 27

  
28 28
        }
29 29

  
......
75 75
            var permissionString = objectInfo.GetPermissionString();
76 76

  
77 77
            Assert.IsNotNullOrEmpty(permissionString);
78
            Assert.AreEqual("read=user1;write=user2",permissionString);
78
            Assert.AreEqual("read=user1;write=user2",Uri.UnescapeDataString(permissionString));
79 79
        }
80 80

  
81 81
        [Test]
......
96 96
            Assert.IsTrue(objectInfo.Permissions["user3@somehost.gr"]=="write");
97 97

  
98 98
        }
99

  
100
        [Test]
101
        public void empty_should_be_writable()
102
        {
103
            Assert.That(ObjectInfo.Empty.IsWritable("somAccount"),Is.True);
104
        }
105

  
106
        [Test]
107
        public void should_be_writeable_for_write_permission()
108
        {
109
            var objectInfo = new ObjectInfo();
110
            var permissionString = "read=user1;write=user2,user3@somehost.gr";
111
            objectInfo.SetPermissions(permissionString);
112

  
113
            Assert.That(objectInfo.IsWritable("user3@somehost.gr"),Is.True);
114

  
115
        }
116

  
117
        [Test]
118
        public void should_not_be_writeable_for_read_permission()
119
        {
120
            var objectInfo = new ObjectInfo();
121
            var permissionString = "read=user1;write=user2,user3@somehost.gr";
122
            objectInfo.SetPermissions(permissionString);
123

  
124
            Assert.That(objectInfo.IsWritable("user1"),Is.False);
125

  
126
        }
127

  
128
        [Test]
129
        public void should_not_be_writeable_for_allowed()
130
        {
131
            var objectInfo = new ObjectInfo{AllowedTo="write"};
132
            var permissionString = "read=user1;write=user2,user3@somehost.gr";
133
            objectInfo.SetPermissions(permissionString);
134

  
135
            Assert.That(objectInfo.IsWritable("user4"),Is.True);
136

  
137
        }
99 138
    }
100 139
}
b/trunk/Pithos.Network/CloudFilesClient.cs
1393 1393
            var directories=this.ListObjects(container.Account, container.Name, "/");
1394 1394
        }
1395 1395
*/
1396

  
1397
        public bool CanUpload(string account, ObjectInfo cloudFile)
1398
        {
1399
            Contract.Requires(!String.IsNullOrWhiteSpace(account));
1400
            Contract.Requires(cloudFile!=null);
1401

  
1402
            using (var client = new RestClient(_baseClient))
1403
            {
1404
                if (!String.IsNullOrWhiteSpace(account))
1405
                    client.BaseAddress = GetAccountUrl(account);
1406

  
1407

  
1408
                var parts = cloudFile.Name.Split('/');
1409
                var folder = String.Join("/", parts,0,parts.Length-1);
1410

  
1411
                var fileUrl=String.Format("{0}/{1}/{2}.pithos.ignore",cloudFile.Container,folder,Guid.NewGuid());
1412

  
1413
                client.Parameters.Clear();
1414
                try
1415
                {
1416
                    client.PutWithRetry(fileUrl, 3, @"application/octet-stream");
1417

  
1418
                    var expectedCodes = new[] { HttpStatusCode.OK, HttpStatusCode.NoContent, HttpStatusCode.Created};
1419
                    return (expectedCodes.Contains(client.StatusCode));
1420
                }
1421
                catch
1422
                {
1423
                    return false;
1424
                }
1425
                finally
1426
                {
1427
                    DeleteObject(account,cloudFile.Container,fileUrl);                    
1428
                }                
1429
            }
1430
        }
1396 1431
    }
1397 1432

  
1398 1433
    public class ShareAccountInfo
b/trunk/Pithos.Network/RestClient.cs
307 307
            RetryWithoutContent(address, retries, "HEAD");
308 308
        }
309 309

  
310
        public void PutWithRetry(string address, int retries = 0)
310
        public void PutWithRetry(string address, int retries = 0, string contentType=null)
311 311
        {
312
            RetryWithoutContent(address, retries, "PUT");
312
            RetryWithoutContent(address, retries, "PUT",contentType);
313 313
        }
314 314

  
315 315
        public void PostWithRetry(string address,string contentType)

Also available in: Unified diff