Added object sharing functionality.
authorMiltiadis Vasilakis <mvasilak@gmail.com>
Wed, 9 Nov 2011 20:03:30 +0000 (22:03 +0200)
committerMiltiadis Vasilakis <mvasilak@gmail.com>
Wed, 9 Nov 2011 20:03:30 +0000 (22:03 +0200)
Classes/EditMetadataViewController.h
Classes/EditPermissionsViewController.h [new file with mode: 0644]
Classes/EditPermissionsViewController.m [new file with mode: 0644]
Classes/EditPermissionsViewController.xib [new file with mode: 0644]
Classes/OpenStackRequest.m
Classes/StorageObject.h
Classes/StorageObject.m
Classes/StorageObjectViewController.h
Classes/StorageObjectViewController.m
OpenStack.xcodeproj/project.pbxproj

index b9960c3..d553fb7 100644 (file)
 // or implied, of GRNET S.A.
 
 #import <UIKit/UIKit.h>
-#import "OpenStackViewController.h"
 #import "OpenStackAccount.h"
 #import "Container.h"
-#import "Folder.h"
 #import "StorageObject.h"
 #import "ActivityIndicatorView.h"
 
diff --git a/Classes/EditPermissionsViewController.h b/Classes/EditPermissionsViewController.h
new file mode 100644 (file)
index 0000000..a3b13a5
--- /dev/null
@@ -0,0 +1,80 @@
+//
+//  EditPermissionsViewController.h
+//  pithos-ios
+//
+// Copyright 2011 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.
+
+#import <UIKit/UIKit.h>
+#import "OpenStackAccount.h"
+#import "Container.h"
+#import "StorageObject.h"
+#import "ActivityIndicatorView.h"
+
+
+@interface EditPermissionsViewController : UITableViewController <UITextFieldDelegate> {
+    NSString *user;
+    BOOL readPermissionSelected;
+    BOOL writePermissionSelected;
+    NSMutableDictionary *permissions;
+    
+    OpenStackAccount *account;
+    Container *container;
+    StorageObject *object;
+    
+    ActivityIndicatorView *activityIndicatorView;
+    
+    id successObserver;
+    id failureObserver;
+    
+    NSString *oldPermissionsString;
+    BOOL newPermissionsEntry;
+    
+    BOOL permissionsChanged;
+    
+}
+
+@property (nonatomic, retain) OpenStackAccount *account;
+@property (nonatomic, retain) Container *container;
+@property (nonatomic, retain) StorageObject *object;
+
+@property (nonatomic, retain) NSString *user;
+@property (nonatomic) BOOL readPermissionSelected;
+@property (nonatomic) BOOL writePermissionSelected;
+@property (nonatomic) BOOL newPermissionsEntry;
+@property (nonatomic, retain) NSMutableDictionary *permissions;
+@property (nonatomic, retain) NSString *oldPermissionsString;
+
+- (NSString *)buildPermissionsString;
+
+@end
diff --git a/Classes/EditPermissionsViewController.m b/Classes/EditPermissionsViewController.m
new file mode 100644 (file)
index 0000000..2cc1dd0
--- /dev/null
@@ -0,0 +1,366 @@
+//
+//  EditPermissionsViewController.m
+//  pithos-ios
+//
+// Copyright 2011 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.
+
+#import "EditPermissionsViewController.h"
+#import "AccountManager.h"
+#import "UIViewController+Conveniences.h"
+
+#define kUser 0
+#define kPermissions 1
+#define kRemovePermissions 2
+
+@implementation EditPermissionsViewController
+
+@synthesize account, container, object;
+@synthesize user, readPermissionSelected, writePermissionSelected, permissions;
+@synthesize oldPermissionsString;
+@synthesize newPermissionsEntry;
+
+
+- (void)dealloc
+{
+    [super dealloc];
+}
+
+- (void)didReceiveMemoryWarning
+{
+    // Releases the view if it doesn't have a superview.
+    [super didReceiveMemoryWarning];
+    
+    // Release any cached data, images, etc that aren't in use.
+}
+
+#pragma mark - View lifecycle
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+
+}
+
+- (void)viewDidUnload
+{
+    [super viewDidUnload];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+    [super viewWillAppear:animated];
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+    [super viewDidAppear:animated];
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+    [super viewWillDisappear:animated];
+}
+
+- (void)viewDidDisappear:(BOOL)animated
+{
+    [super viewDidDisappear:animated];
+}
+
+- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
+    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
+}
+
+#pragma mark - Table view data source
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
+{
+    if (newPermissionsEntry)
+        return 2;
+    else 
+        return 3;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    if (section == kPermissions)
+        return 2;
+    else
+        return 1;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    static NSString *CellIdentifier = @"Cell";
+    
+    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+    if (cell == nil) {
+        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
+    }
+
+    if (indexPath.section == kUser) {
+        if (newPermissionsEntry) {
+            CGRect bounds = [cell.contentView bounds];
+            CGRect rect = CGRectInset(bounds, 20.0, 10.0);                        
+            UITextField *textField = [[UITextField alloc] initWithFrame:rect];
+            [textField setFrame:rect];
+            [textField setClearButtonMode:UITextFieldViewModeWhileEditing];
+            [textField setBackgroundColor:[UIColor whiteColor]];
+            [textField setOpaque:YES];
+            [textField setAutocorrectionType:UITextAutocorrectionTypeNo];
+            [textField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
+            [textField setDelegate:self];
+            textField.placeholder = @"User";
+            
+            cell.selectionStyle = UITableViewCellSelectionStyleNone;
+            [cell.contentView addSubview:textField];
+        }
+        else {
+            for (id subView in cell.contentView.subviews) {
+                if ([subView isKindOfClass:[UITextField class]]) {
+                    NSLog(@"textfield found at index: %d", [cell.contentView.subviews indexOfObject:subView]);
+                    [subView removeFromSuperview];
+                }
+            }
+            
+            cell.accessoryType = UITableViewCellAccessoryNone;
+            cell.selectionStyle = UITableViewCellSelectionStyleNone;
+        }
+        cell.textLabel.text = self.user;
+    }
+    else if (indexPath.section == kPermissions) {
+        cell.selectionStyle = UITableViewCellSelectionStyleNone;
+        if (indexPath.row == 0) {
+            cell.textLabel.text = @"Read";
+            if (readPermissionSelected)
+                cell.accessoryType = UITableViewCellAccessoryCheckmark;
+            else
+                cell.accessoryType = UITableViewCellAccessoryNone;
+        }
+        else {
+            cell.textLabel.text = @"Write";
+            if (writePermissionSelected)
+                cell.accessoryType = UITableViewCellAccessoryCheckmark;
+            else
+                cell.accessoryType = UITableViewCellAccessoryNone;
+        }
+    } 
+    else if (indexPath.section == kRemovePermissions) {
+        cell.textLabel.text = @"Remove";
+        cell.accessoryType = UITableViewCellAccessoryNone;
+    }
+    
+    return cell;
+}
+
+#pragma mark - Table view delegate
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{    
+
+    if (indexPath.section != kUser && newPermissionsEntry) {
+        if ([self.user length] == 0
+            || [[self.user stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
+            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+            [self alert:@"Invalid input" message:@"User name field cannot be empty"];
+            return;
+        }
+    }
+    
+    if (indexPath.section == kPermissions) {
+        if (indexPath.row == 0) {
+            if (!readPermissionSelected) {
+                readPermissionSelected = YES;
+                [self.permissions setObject:@"read" forKey:user];
+                if (writePermissionSelected)
+                    writePermissionSelected = FALSE;
+                permissionsChanged = YES;
+            }
+            else 
+                permissionsChanged = NO;
+        }
+        else if (indexPath.row == 1) {
+            if (!writePermissionSelected) {
+                writePermissionSelected = YES;
+                [self.permissions setObject:@"write" forKey:user];
+                if (readPermissionSelected)
+                    readPermissionSelected = FALSE;
+                permissionsChanged = YES;
+            }
+            else
+                permissionsChanged = NO;
+        }
+        
+        if (permissionsChanged) {
+            [self.tableView reloadData];
+            NSString *activityMessage = @"Applying permissions...";
+            activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
+            [activityIndicatorView addToView:self.view];
+            self.oldPermissionsString = object.sharing;
+            object.sharing = [self buildPermissionsString];
+            [self.account.manager writeObjectMetadata:container object:object];
+            successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded"
+                                                                                object:object
+                                                                                 queue:[NSOperationQueue mainQueue]
+                                                                            usingBlock:^(NSNotification *notification)
+                               {
+                                   if (newPermissionsEntry) {
+                                       newPermissionsEntry = FALSE;
+                                       [self.tableView reloadData];
+                                   }
+                                   [activityIndicatorView removeFromSuperviewAndRelease];
+                                   [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+                                   [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
+                               }];
+            failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed" 
+                                                                                object:object 
+                                                                                 queue:[NSOperationQueue mainQueue] 
+                                                                            usingBlock:^(NSNotification *notification)
+                               {
+                                   object.sharing = self.oldPermissionsString;
+                                   if (!newPermissionsEntry) {
+                                       readPermissionSelected = !readPermissionSelected;
+                                       writePermissionSelected = !writePermissionSelected;
+                                   }
+                                   else {
+                                       self.user = @"";
+                                       readPermissionSelected = FALSE;
+                                       writePermissionSelected = FALSE;
+                                   }
+                                   if (readPermissionSelected)
+                                       [self.permissions setObject:@"read" forKey:user];
+                                   else if (writePermissionSelected) 
+                                       [self.permissions setObject:@"write" forKey:user];
+                               
+                                   [activityIndicatorView removeFromSuperviewAndRelease];
+                                   [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+                                   [self.tableView reloadData];
+                                   [self alert:@"There was a problem applying the permissions." request:[notification.userInfo objectForKey:@"request"]];
+                                   [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
+                               }];
+        }
+    } 
+    else if (indexPath.section == kRemovePermissions) {
+        NSString *activityMessage = @"Removing permissions...";            
+        activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
+        [activityIndicatorView addToView:self.view];
+        
+        [permissions removeObjectForKey:user];
+        self.oldPermissionsString = object.sharing;
+        object.sharing = [self buildPermissionsString];
+        [self.account.manager writeObjectMetadata:container object:object];
+        successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded"
+                                                                            object:object
+                                                                             queue:[NSOperationQueue mainQueue]
+                                                                        usingBlock:^(NSNotification *notification)
+                           {
+                               self.user = @"";
+                               self.readPermissionSelected = FALSE;
+                               self.writePermissionSelected = FALSE;
+                               [self.tableView reloadData];
+                               [activityIndicatorView removeFromSuperviewAndRelease];
+                               [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+                               [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
+                           }];
+
+        
+        failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed" 
+                                                                            object:object 
+                                                                             queue:[NSOperationQueue mainQueue] 
+                                                                        usingBlock:^(NSNotification *notification)
+                           {
+                               object.sharing = self.oldPermissionsString;
+                               if (readPermissionSelected)
+                                   [self.permissions setObject:@"read" forKey:user];
+                               else if (writePermissionSelected) 
+                                   [self.permissions setObject:@"write" forKey:user];
+
+                               [activityIndicatorView removeFromSuperviewAndRelease];
+                               [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+                               [self.tableView reloadData];
+                               [self alert:@"There was a problem removing the permissions." request:[notification.userInfo objectForKey:@"request"]];
+                               [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
+                           }];
+    }
+}
+
+#pragma mark - Textfield delegate
+
+- (void)textFieldDidEndEditing:(UITextField *)textField
+{
+    if ([textField.text length] == 0
+        || [[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
+        [self alert:@"Invalid input" message:@"User name field cannot be empty"];
+    }
+    else {
+        self.user = textField.text;
+    }
+}
+
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField
+{
+    [textField resignFirstResponder];
+    return YES;
+}
+
+#pragma mark - helper methods
+
+- (NSString *)buildPermissionsString
+{
+    NSString *readPermissionsString = @"";
+    NSString *writePermissionsString = @"";
+    for (NSString *aUser in [permissions allKeys]) {
+        if ([[permissions objectForKey:aUser] isEqual:@"read"]) {
+            if ([readPermissionsString length] == 0)
+                readPermissionsString = [NSString stringWithFormat:@"read=%@", aUser];
+            else
+                readPermissionsString = [NSString stringWithFormat:@"%@,%@", readPermissionsString ,aUser];
+        }
+        else if ([[permissions objectForKey:aUser] isEqual:@"write"]) {
+            if ([writePermissionsString length] == 0)
+                writePermissionsString = [NSString stringWithFormat:@"write=%@", aUser];
+            else
+                writePermissionsString = [NSString stringWithFormat:@"%@,%@", writePermissionsString, aUser];
+        }
+    }
+    
+    if ([writePermissionsString length] == 0)
+        return readPermissionsString;
+    else if ([readPermissionsString length] == 0)
+        return writePermissionsString;
+    else return [NSString stringWithFormat:@"%@;%@", readPermissionsString, writePermissionsString];
+}
+
+
+@end
diff --git a/Classes/EditPermissionsViewController.xib b/Classes/EditPermissionsViewController.xib
new file mode 100644 (file)
index 0000000..33cf7bc
--- /dev/null
@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+       <data>
+               <int key="IBDocument.SystemTarget">1056</int>
+               <string key="IBDocument.SystemVersion">10K549</string>
+               <string key="IBDocument.InterfaceBuilderVersion">1306</string>
+               <string key="IBDocument.AppKitVersion">1038.36</string>
+               <string key="IBDocument.HIToolboxVersion">461.00</string>
+               <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+                       <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+                       <string key="NS.object.0">301</string>
+               </object>
+               <object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+                       <bool key="EncodedWithXMLCoder">YES</bool>
+                       <string>IBProxyObject</string>
+                       <string>IBUITableView</string>
+               </object>
+               <object class="NSArray" key="IBDocument.PluginDependencies">
+                       <bool key="EncodedWithXMLCoder">YES</bool>
+                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+               </object>
+               <object class="NSMutableDictionary" key="IBDocument.Metadata">
+                       <bool key="EncodedWithXMLCoder">YES</bool>
+                       <object class="NSArray" key="dict.sortedKeys" id="0">
+                               <bool key="EncodedWithXMLCoder">YES</bool>
+                       </object>
+                       <reference key="dict.values" ref="0"/>
+               </object>
+               <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+                       <bool key="EncodedWithXMLCoder">YES</bool>
+                       <object class="IBProxyObject" id="372490531">
+                               <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+                       </object>
+                       <object class="IBProxyObject" id="975951072">
+                               <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+                       </object>
+                       <object class="IBUITableView" id="873029372">
+                               <reference key="NSNextResponder"/>
+                               <int key="NSvFlags">274</int>
+                               <string key="NSFrame">{{0, 20}, {320, 460}}</string>
+                               <reference key="NSSuperview"/>
+                               <reference key="NSWindow"/>
+                               <reference key="NSNextKeyView"/>
+                               <object class="NSColor" key="IBUIBackgroundColor">
+                                       <int key="NSColorSpace">10</int>
+                                       <object class="NSImage" key="NSImage">
+                                               <int key="NSImageFlags">549453824</int>
+                                               <string key="NSSize">{84, 1}</string>
+                                               <object class="NSMutableArray" key="NSReps">
+                                                       <bool key="EncodedWithXMLCoder">YES</bool>
+                                                       <object class="NSArray">
+                                                               <bool key="EncodedWithXMLCoder">YES</bool>
+                                                               <integer value="0"/>
+                                                               <object class="NSBitmapImageRep">
+                                                                       <object class="NSData" key="NSTIFFRepresentation">
+                                                                               <bytes key="NS.bytes">TU0AKgAAAVjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/
+y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/
+xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/
+xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/
+xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/
+xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P8ADQEAAAMAAAABAFQAAAEB
+AAMAAAABAAEAAAECAAMAAAAEAAAB+gEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABAAEAAAEXAAQAAAABAAABUAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAACAgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+                                                                       </object>
+                                                               </object>
+                                                       </object>
+                                               </object>
+                                               <object class="NSColor" key="NSColor">
+                                                       <int key="NSColorSpace">3</int>
+                                                       <bytes key="NSWhite">MCAwAA</bytes>
+                                               </object>
+                                       </object>
+                                       <string key="IBUIColorCocoaTouchKeyPath">groupTableViewBackgroundColor</string>
+                               </object>
+                               <bool key="IBUIOpaque">NO</bool>
+                               <bool key="IBUIClipsSubviews">YES</bool>
+                               <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+                               <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+                               <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+                               <bool key="IBUIBouncesZoom">NO</bool>
+                               <int key="IBUIStyle">1</int>
+                               <int key="IBUISeparatorStyle">2</int>
+                               <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+                               <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+                               <float key="IBUIRowHeight">44</float>
+                               <float key="IBUISectionHeaderHeight">10</float>
+                               <float key="IBUISectionFooterHeight">10</float>
+                       </object>
+               </object>
+               <object class="IBObjectContainer" key="IBDocument.Objects">
+                       <object class="NSMutableArray" key="connectionRecords">
+                               <bool key="EncodedWithXMLCoder">YES</bool>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBCocoaTouchOutletConnection" key="connection">
+                                               <string key="label">view</string>
+                                               <reference key="source" ref="372490531"/>
+                                               <reference key="destination" ref="873029372"/>
+                                       </object>
+                                       <int key="connectionID">5</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBCocoaTouchOutletConnection" key="connection">
+                                               <string key="label">dataSource</string>
+                                               <reference key="source" ref="873029372"/>
+                                               <reference key="destination" ref="372490531"/>
+                                       </object>
+                                       <int key="connectionID">6</int>
+                               </object>
+                               <object class="IBConnectionRecord">
+                                       <object class="IBCocoaTouchOutletConnection" key="connection">
+                                               <string key="label">delegate</string>
+                                               <reference key="source" ref="873029372"/>
+                                               <reference key="destination" ref="372490531"/>
+                                       </object>
+                                       <int key="connectionID">7</int>
+                               </object>
+                       </object>
+                       <object class="IBMutableOrderedSet" key="objectRecords">
+                               <object class="NSArray" key="orderedObjects">
+                                       <bool key="EncodedWithXMLCoder">YES</bool>
+                                       <object class="IBObjectRecord">
+                                               <int key="objectID">0</int>
+                                               <reference key="object" ref="0"/>
+                                               <reference key="children" ref="1000"/>
+                                               <nil key="parent"/>
+                                       </object>
+                                       <object class="IBObjectRecord">
+                                               <int key="objectID">-1</int>
+                                               <reference key="object" ref="372490531"/>
+                                               <reference key="parent" ref="0"/>
+                                               <string key="objectName">File's Owner</string>
+                                       </object>
+                                       <object class="IBObjectRecord">
+                                               <int key="objectID">-2</int>
+                                               <reference key="object" ref="975951072"/>
+                                               <reference key="parent" ref="0"/>
+                                       </object>
+                                       <object class="IBObjectRecord">
+                                               <int key="objectID">4</int>
+                                               <reference key="object" ref="873029372"/>
+                                               <reference key="parent" ref="0"/>
+                                       </object>
+                               </object>
+                       </object>
+                       <object class="NSMutableDictionary" key="flattenedProperties">
+                               <bool key="EncodedWithXMLCoder">YES</bool>
+                               <object class="NSArray" key="dict.sortedKeys">
+                                       <bool key="EncodedWithXMLCoder">YES</bool>
+                                       <string>-1.CustomClassName</string>
+                                       <string>-2.CustomClassName</string>
+                                       <string>4.IBEditorWindowLastContentRect</string>
+                                       <string>4.IBPluginDependency</string>
+                               </object>
+                               <object class="NSMutableArray" key="dict.values">
+                                       <bool key="EncodedWithXMLCoder">YES</bool>
+                                       <string>EditPermissionsViewController</string>
+                                       <string>UIResponder</string>
+                                       <string>{{329, 504}, {320, 480}}</string>
+                                       <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+                               </object>
+                       </object>
+                       <object class="NSMutableDictionary" key="unlocalizedProperties">
+                               <bool key="EncodedWithXMLCoder">YES</bool>
+                               <reference key="dict.sortedKeys" ref="0"/>
+                               <reference key="dict.values" ref="0"/>
+                       </object>
+                       <nil key="activeLocalization"/>
+                       <object class="NSMutableDictionary" key="localizations">
+                               <bool key="EncodedWithXMLCoder">YES</bool>
+                               <reference key="dict.sortedKeys" ref="0"/>
+                               <reference key="dict.values" ref="0"/>
+                       </object>
+                       <nil key="sourceID"/>
+                       <int key="maxID">7</int>
+               </object>
+               <object class="IBClassDescriber" key="IBDocument.Classes">
+                       <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+                               <bool key="EncodedWithXMLCoder">YES</bool>
+                               <object class="IBPartialClassDescription">
+                                       <string key="className">EditPermissionsViewController</string>
+                                       <string key="superclassName">UITableViewController</string>
+                                       <object class="IBClassDescriptionSource" key="sourceIdentifier">
+                                               <string key="majorKey">IBProjectSource</string>
+                                               <string key="minorKey">./Classes/EditPermissionsViewController.h</string>
+                                       </object>
+                               </object>
+                       </object>
+               </object>
+               <int key="IBDocument.localizationMode">0</int>
+               <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+               <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+                       <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+                       <integer value="3000" key="NS.object.0"/>
+               </object>
+               <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+               <int key="IBDocument.defaultPropertyAccessControl">3</int>
+               <string key="IBCocoaTouchPluginVersion">301</string>
+       </data>
+</archive>
index fa447eb..24ea7ea 100755 (executable)
@@ -672,6 +672,10 @@ static NSRecursiveLock *accessDetailsLock = nil;
     
     NSString *objectIsPublic = ([object.publicURI length]) ? @"true" : @"false";
     [request.requestHeaders setObject:objectIsPublic forKey:@"X-Object-Public"];
+    
+    if (object.sharing)
+        [request.requestHeaders setObject:object.sharing forKey:@"X-Object-Sharing"];
+    
     return request;
 }
 
index c9046f8..0855847 100755 (executable)
@@ -18,6 +18,7 @@
        NSDate *lastModified;
        NSData *data;
     NSString *publicURI;
+    NSString *sharing;
        NSMutableDictionary *metadata;
 }
 
@@ -29,6 +30,7 @@
 @property (nonatomic, retain) NSDate *lastModified;
 @property (nonatomic, retain) NSData *data;    
 @property (nonatomic, retain) NSString *publicURI;
+@property (nonatomic, retain) NSString *sharing;
 @property (nonatomic, retain) NSMutableDictionary *metadata;
 
 - (NSString *)humanizedBytes;
index 2b3cc80..6094f81 100755 (executable)
@@ -13,7 +13,7 @@
 
 @implementation StorageObject
 
-@synthesize name, fullPath, hash, bytes, contentType, lastModified, data, publicURI, metadata;
+@synthesize name, fullPath, hash, bytes, contentType, lastModified, data, publicURI, sharing, metadata;
 
 #pragma mark -
 #pragma mark Serialization
@@ -64,6 +64,7 @@
     object.contentType = [dict objectForKey:@"content_type"];
     object.lastModified = [ComputeModel dateFromString:[dict objectForKey:@"last_modified"]];
     object.publicURI = [dict objectForKey:@"x_object_public"];
+    object.sharing = [dict objectForKey:@"x_object_sharing"];
         
     object.metadata = [NSMutableDictionary dictionary];
     for (NSString *key in dict) {
index e57de17..3ad782c 100755 (executable)
@@ -44,6 +44,7 @@
     NSInteger deleteSection;
     
     NSString *oldPublicURI;
+    NSMutableDictionary *permissions;
 }
 
 @property (nonatomic, retain) OpenStackAccount *account;
index 0cccb5b..c410583 100755 (executable)
 #import "OpenStackAppDelegate.h"
 #import "EditMetadataViewController.h"
 #import "Provider.h"
+#import "EditPermissionsViewController.h"
 
 #define kDetails 0
 #define kMetadata 1
 #define kPublic 2
+#define kPermissions 3
 
 #define maxMetadataViewableLength 12
 
     [objectIsPublicSwitch addTarget:self action:@selector(objectIsPublicSwitchChanged:) forControlEvents:UIControlEventValueChanged];
     
     deleteActionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure you want to delete this file?  This operation cannot be undone." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete File" otherButtonTitles:nil];
+    
+    permissions = [[NSMutableDictionary alloc] init];
+    NSArray *sharingArray = [object.sharing componentsSeparatedByString:@";"];
+    for (NSString *typeSpecificPermissions in sharingArray) { 
+        NSArray *array=[typeSpecificPermissions componentsSeparatedByString:@"="];
+        NSString *permissionsType = [array objectAtIndex:0];
+        if ([permissionsType hasPrefix:@" "])
+            permissionsType = [permissionsType substringFromIndex:1];
+                            
+        NSArray *users = [[array objectAtIndex:1] componentsSeparatedByString:@","];
+        for (NSString *user in users) {
+            [permissions setObject:permissionsType forKey:user];
+        }
+    }    
 }
 
 - (void)viewWillAppear:(BOOL)animated {
     
     [self setBackgroundView];
     if (self.container.cdnEnabled) {
-        cdnURLSection = 3;
-        actionsSection = 4;
-        deleteSection = 5;
+        cdnURLSection = 4;
+        actionsSection = 5;
+        deleteSection = 6;
     } else {
         cdnURLSection = -1;
-        actionsSection = 3;
-        deleteSection = 4;
+        actionsSection = 4;
+        deleteSection = 5;
     }
     
     // let's see if we can tweet
 #pragma mark Table view data source
 
 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
-    return self.container.cdnEnabled ? 6 : 5;
+    return self.container.cdnEnabled ? 7 : 6;
 }
 
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
         return fileDownloaded ? 2 : 1;
     } else if (section == kPublic) {
         return objectIsPublic ? 2 : 1;
+    } else if (section == kPermissions) {
+        return 1 + [permissions count];
     } else {
         return 1;
     }
     }
     
     cell.detailTextLabel.textAlignment = UITextAlignmentRight;
+    cell.accessoryView = nil;
+    cell.textLabel.font = [UIFont boldSystemFontOfSize:17.0];
     
     // Configure the cell...
     if (indexPath.section == kDetails) {
             cell.textLabel.font = [UIFont systemFontOfSize:15.0];
             cell.selectionStyle = UITableViewCellSelectionStyleNone;
         }
+    } else if (indexPath.section == kPermissions) {
+        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
+        cell.accessoryView = nil;
+        if (indexPath.row == [permissions count]) {
+            cell.textLabel.text = @"Add Permissions";
+            cell.detailTextLabel.text = @""; 
+        }
+        else {
+            NSString *user = [[permissions allKeys] objectAtIndex:indexPath.row];
+            cell.textLabel.text = user;
+            cell.detailTextLabel.text = [permissions objectForKey:user];
+        }
     } else if (indexPath.section == cdnURLSection) {
         cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
         vc.object = object;
         [self.navigationController pushViewController:vc animated:YES];
         [vc release];
+    } else if (indexPath.section == kPermissions) {
+        EditPermissionsViewController *vc = [[EditPermissionsViewController alloc] initWithNibName:@"EditPermissionsViewController" bundle:nil];
+        NSString *user;
+        
+        if (indexPath.row == [permissions count]) {
+            user = @"";
+            vc.newPermissionsEntry = TRUE;
+            vc.navigationItem.title = @"Add Permissions";
+        }
+        else {
+            user = [[permissions allKeys] objectAtIndex:indexPath.row];
+            NSString *userPermissions = [permissions objectForKey:user];
+            if ([userPermissions rangeOfString:@"read"].location != NSNotFound)
+                vc.readPermissionSelected = YES;
+            else
+                vc.readPermissionSelected = NO;
+            
+            if ([userPermissions rangeOfString:@"write"].location != NSNotFound)
+                vc.writePermissionSelected = YES;
+            else
+                vc.writePermissionSelected = NO;
+            
+            vc.newPermissionsEntry = FALSE;
+            vc.navigationItem.title = @"Edit Permissions";
+        }
+        
+        vc.user = user;
+        vc.permissions = permissions;
+        vc.account = account;
+        vc.container = container;
+        vc.object = object;
+        [self.navigationController pushViewController:vc animated:YES];
+        [vc release];
     } else if (indexPath.section == cdnURLSection) {
         [cdnURLActionSheet showInView:self.view];
     } else if (indexPath.section == actionsSection) {
     [tableView release];
     [folderViewController release];
     [objectIsPublicSwitch release];
+    [permissions release];
     [super dealloc];
 }
 
index 43d6486..10a4954 100755 (executable)
@@ -9,6 +9,8 @@
 /* Begin PBXBuildFile section */
                1D3623260D0F684500981E51 /* OpenStackAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* OpenStackAppDelegate.m */; };
                1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+               2485477B1446D36800E48921 /* EditPermissionsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 248547791446D36800E48921 /* EditPermissionsViewController.m */; };
+               2485477C1446D36800E48921 /* EditPermissionsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2485477A1446D36800E48921 /* EditPermissionsViewController.xib */; };
                24A18E22143DB870003232F1 /* EditMetadataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 24A18E20143DB870003232F1 /* EditMetadataViewController.m */; };
                24A18E23143DB870003232F1 /* EditMetadataViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24A18E21143DB870003232F1 /* EditMetadataViewController.xib */; };
                24A18E56143F0429003232F1 /* FolderDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 24A18E54143F0428003232F1 /* FolderDetailViewController.m */; };
                1D3623240D0F684500981E51 /* OpenStackAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenStackAppDelegate.h; sourceTree = "<group>"; };
                1D3623250D0F684500981E51 /* OpenStackAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenStackAppDelegate.m; sourceTree = "<group>"; };
                1D6058910D05DD3D006BFB54 /* OpenStack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenStack.app; sourceTree = BUILT_PRODUCTS_DIR; };
+               248547781446D36700E48921 /* EditPermissionsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditPermissionsViewController.h; sourceTree = "<group>"; };
+               248547791446D36800E48921 /* EditPermissionsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditPermissionsViewController.m; sourceTree = "<group>"; };
+               2485477A1446D36800E48921 /* EditPermissionsViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EditPermissionsViewController.xib; sourceTree = "<group>"; };
                24A18E1F143DB86F003232F1 /* EditMetadataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditMetadataViewController.h; sourceTree = "<group>"; };
                24A18E20143DB870003232F1 /* EditMetadataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditMetadataViewController.m; sourceTree = "<group>"; };
                24A18E21143DB870003232F1 /* EditMetadataViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EditMetadataViewController.xib; sourceTree = "<group>"; };
                                278906DB12BEDAB5007112B6 /* StorageObjectViewController.h */,
                                278907A112BEF72C007112B6 /* StorageObjectViewController.m */,
                                278906DD12BEDAB5007112B6 /* StorageObjectViewController.xib */,
+                               248547781446D36700E48921 /* EditPermissionsViewController.h */,
+                               248547791446D36800E48921 /* EditPermissionsViewController.m */,
+                               2485477A1446D36800E48921 /* EditPermissionsViewController.xib */,
                                24A18E1F143DB86F003232F1 /* EditMetadataViewController.h */,
                                24A18E20143DB870003232F1 /* EditMetadataViewController.m */,
                                24A18E21143DB870003232F1 /* EditMetadataViewController.xib */,
                                27C38BC213D0D48500CC7222 /* red-delete-button.png in Resources */,
                                24A18E23143DB870003232F1 /* EditMetadataViewController.xib in Resources */,
                                24A18E57143F0429003232F1 /* FolderDetailViewController.xib in Resources */,
+                               2485477C1446D36800E48921 /* EditPermissionsViewController.xib in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                27DC5DD813CB8F0F00091902 /* LoadBalancerConnectionThrottle.m in Sources */,
                                24A18E22143DB870003232F1 /* EditMetadataViewController.m in Sources */,
                                24A18E56143F0429003232F1 /* FolderDetailViewController.m in Sources */,
+                               2485477B1446D36800E48921 /* EditPermissionsViewController.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };