// 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"
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
--- /dev/null
+<?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>
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;
}
NSDate *lastModified;
NSData *data;
NSString *publicURI;
+ NSString *sharing;
NSMutableDictionary *metadata;
}
@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;
@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
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) {
NSInteger deleteSection;
NSString *oldPublicURI;
+ NSMutableDictionary *permissions;
}
@property (nonatomic, retain) OpenStackAccount *account;
#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];
}
/* 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;
};