Skip to content

Commit

Permalink
- OCItemVersionSeed: new value to allow quick detection of changes in…
Browse files Browse the repository at this point in the history
… items

	- OCItem: add new versionSeed property and associated methods to update the seed
	- OCCore: add support for updating versionSeed when changes occur
- OCItem+OCDataItem: make OCItem comply to OCDataItem and OCDataItemVersion (the latter using the new version seed)
- OCHTTPResponse: extend support for encoding-sensitive conversion of body data to NSStrings, with explicit fallback encoding
- OCResourceSourceDriveItems: make text resource encoding sensitive
- OCResourceText: make compliant to OCDataItem and OCDataItemVersion
- OCDrive: include readme and image in significant update detection, add support for subtitles/descriptions
- GAGraphData+Decoder: add support for unescaped URLs (owncloud/ocis#3538)
- OCLocation: add .lastPathComponent utility property
- OCViewProviderContext: add initializer and context key for content mode
- OCQuery: add .queryResultsDataSource property providing an OCDataSource tracking the query's results (leaving room for future performance improvements)
  • Loading branch information
felix-schwarz committed Apr 21, 2022
1 parent 43dd85c commit 8dfb50e
Show file tree
Hide file tree
Showing 26 changed files with 303 additions and 22 deletions.
8 changes: 8 additions & 0 deletions ownCloudSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@
DC39DC4E2041B53000189B9A /* AuthenticationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DC39DC4D2041B53000189B9A /* AuthenticationTests.m */; };
DC39DC59204215A800189B9A /* NSProgress+OCEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = DC39DC57204215A800189B9A /* NSProgress+OCEvent.h */; settings = {ATTRIBUTES = (Public, ); }; };
DC39DC5A204215A800189B9A /* NSProgress+OCEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = DC39DC58204215A800189B9A /* NSProgress+OCEvent.m */; };
DC3AB1912808B3C400789435 /* OCItem+OCDataItem.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3AB18F2808B3C400789435 /* OCItem+OCDataItem.h */; settings = {ATTRIBUTES = (Public, ); }; };
DC3AB1922808B3C400789435 /* OCItem+OCDataItem.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3AB1902808B3C400789435 /* OCItem+OCDataItem.m */; };
DC3C7FE121A6EDE00064D193 /* NSError+OCHTTPStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = DC3C7FDF21A6EDE00064D193 /* NSError+OCHTTPStatus.h */; settings = {ATTRIBUTES = (Public, ); }; };
DC3C7FE221A6EDE00064D193 /* NSError+OCHTTPStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3C7FE021A6EDE00064D193 /* NSError+OCHTTPStatus.m */; };
DC3CE03F2429FAA200AB8B88 /* OCMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = DC3CE03B2429FAA200AB8B88 /* OCMessage.m */; };
Expand Down Expand Up @@ -1141,6 +1143,8 @@
DC39DC4D2041B53000189B9A /* AuthenticationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AuthenticationTests.m; sourceTree = "<group>"; };
DC39DC57204215A800189B9A /* NSProgress+OCEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSProgress+OCEvent.h"; sourceTree = "<group>"; };
DC39DC58204215A800189B9A /* NSProgress+OCEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSProgress+OCEvent.m"; sourceTree = "<group>"; };
DC3AB18F2808B3C400789435 /* OCItem+OCDataItem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "OCItem+OCDataItem.h"; sourceTree = "<group>"; };
DC3AB1902808B3C400789435 /* OCItem+OCDataItem.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "OCItem+OCDataItem.m"; sourceTree = "<group>"; };
DC3C7FDF21A6EDE00064D193 /* NSError+OCHTTPStatus.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSError+OCHTTPStatus.h"; sourceTree = "<group>"; };
DC3C7FE021A6EDE00064D193 /* NSError+OCHTTPStatus.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSError+OCHTTPStatus.m"; sourceTree = "<group>"; };
DC3CE03B2429FAA200AB8B88 /* OCMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OCMessage.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3094,6 +3098,8 @@
DCFF1AAE21655C8800ABE40A /* OCItem+OCFileURLMetadata.h */,
DC85571B2050196000189B9A /* OCItem+OCXMLObjectCreation.m */,
DC85571A2050196000189B9A /* OCItem+OCXMLObjectCreation.h */,
DC3AB1902808B3C400789435 /* OCItem+OCDataItem.m */,
DC3AB18F2808B3C400789435 /* OCItem+OCDataItem.h */,
DC4E0A5720927048007EB05F /* OCItemVersionIdentifier.m */,
DC4E0A5620927048007EB05F /* OCItemVersionIdentifier.h */,
DC0283652090A8EE005B6334 /* Images */,
Expand Down Expand Up @@ -4025,6 +4031,7 @@
DC8EB30423952084009148F9 /* OCAuthenticationBrowserSessionUIWebView.h in Headers */,
DC708CE0214135D100FE43CA /* OCSyncActionDelete.h in Headers */,
DCC8FA33202B443D00EB6701 /* OCEventTarget.h in Headers */,
DC3AB1912808B3C400789435 /* OCItem+OCDataItem.h in Headers */,
DC8913642092088600028999 /* NSString+OCVersionCompare.h in Headers */,
DCF00BF527E28A77001F2AFC /* OCDataSourceSubscription+Internal.h in Headers */,
DCC8F9E62028556500EB6701 /* OCConnection.h in Headers */,
Expand Down Expand Up @@ -4655,6 +4662,7 @@
DCE26621211348B00001FB2C /* OCCore+CommandLocalImport.m in Sources */,
DCF1C6732631BFD5004D8B0F /* OCMeasurement.m in Sources */,
DC2565F62260C86A00828AA5 /* OCCertificateRuleChecker.m in Sources */,
DC3AB1922808B3C400789435 /* OCItem+OCDataItem.m in Sources */,
DC35969722403E5B00C4D6E6 /* OCQueryCondition+SQLBuilder.m in Sources */,
DCDBEE302048A71200189B9A /* OCConnection+Tools.m in Sources */,
DCFE3B8927A16AE800939415 /* OCConnection+GraphAPI.m in Sources */,
Expand Down
6 changes: 6 additions & 0 deletions ownCloudSDK/Core/ItemList/OCCore+ItemList.m
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,7 @@ - (void)handleUpdatedTask:(OCCoreItemListTask *)task
[queryResults addObject:cacheItem];

// Update cache
[cacheItem updateSeedFrom:retrievedItem.versionSeed];
[changedCacheItems addObject:cacheItem];
}
else
Expand All @@ -573,6 +574,7 @@ - (void)handleUpdatedTask:(OCCoreItemListTask *)task
(retrievedItem.isFavorite != cacheItem.isFavorite)) // Favorite mismatch
{
// Update item in the cache if the server has a different version
[retrievedItem updateSeedFrom:cacheItem.versionSeed];
[changedCacheItems addObject:retrievedItem];
}
}
Expand All @@ -592,6 +594,7 @@ - (void)handleUpdatedTask:(OCCoreItemListTask *)task
// Result: new file's item still points to the local copy it downloaded, but which has been removed by vacuuming of the OLD file -> viewing and other actions requiring the local copy fail unexpectedly

// Remove cacheItem (with different fileID)
[cacheItem updateSeed];
[deletedCacheItems addObject:cacheItem];

// Add retrievedItem (with different fileID + different localID)
Expand Down Expand Up @@ -634,6 +637,7 @@ - (void)handleUpdatedTask:(OCCoreItemListTask *)task
else
{
// Remove item
[cacheItem updateSeed];
[deletedCacheItems addObject:cacheItem];
}
}
Expand Down Expand Up @@ -745,6 +749,7 @@ - (void)handleUpdatedTask:(OCCoreItemListTask *)task
}

// Add to updatedItems
[newItem updateSeedFrom:knownItem.versionSeed];
[changedCacheItems addObject:newItem];
}

Expand Down Expand Up @@ -843,6 +848,7 @@ - (void)handleUpdatedTask:(OCCoreItemListTask *)task
containedItem.removed = NO;
}

[containedItem updateSeedFrom:item.versionSeed];
[movedItems addObject:containedItem];
}
else
Expand Down
4 changes: 4 additions & 0 deletions ownCloudSDK/Core/OCCore+ItemUpdates.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ - (void)performUpdatesForAddedItems:(nullable NSArray<OCItem *> *)addedItems
return;
}

// Update version seeds for updated and removed items
[updatedItems makeObjectsPerformSelector:@selector(updateSeed)];
[removedItems makeObjectsPerformSelector:@selector(updateSeed)];

// Update metaData table and queries
if ((addedItems.count > 0) || (removedItems.count > 0) || (updatedItems.count > 0) || (beforeQueryUpdatesAction!=nil))
{
Expand Down
2 changes: 1 addition & 1 deletion ownCloudSDK/Core/OCCore.m
Original file line number Diff line number Diff line change
Expand Up @@ -2132,7 +2132,7 @@ - (void)updateWithDrives:(NSArray<OCDrive *> *)drives initialize:(BOOL)doInitial
return (NO);
}] mutableCopy];

[hierarchicDrivesTopLevelItems addObject:_hierarchicDrivesLogicalProjectsFolderPresentable];
// [hierarchicDrivesTopLevelItems addObject:_hierarchicDrivesLogicalProjectsFolderPresentable];

[_hierarchicDrivesDataSource setVersionedItems:hierarchicDrivesTopLevelItems];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ - (void)provideResourceForRequest:(OCResourceRequest *)request resultHandler:(OC
// Text
OCResourceText *resource = [[OCResourceText alloc] initWithRequest:driveItemRequest];

resource.text = response.bodyAsString; // takes encoding passed in Content-Type into account
resource.text = [response bodyAsStringWithFallbackEncoding:NSUTF8StringEncoding]; // takes encoding passed in Content-Type into account, defaults to UTF-8

returnResource = resource;
}
Expand Down
2 changes: 1 addition & 1 deletion ownCloudSDK/Core/Resources/OCResourceTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ typedef NSString* OCResourceVersion; //!< A string that can be used to distingui
typedef NSString* OCResourceStructureDescription; //!< A string describing the structure properties of the resource that can affect resource generation or return, such as f.ex. the MIME type (which can change after a rename, without causing ID or version to change)
typedef NSString* OCResourceMetadata; //!< A resource-specific string with metadata on the resource's data

typedef NSString* OCResourceMIMEType NS_TYPED_ENUM;
typedef NSString* OCResourceMIMEType;
5 changes: 3 additions & 2 deletions ownCloudSDK/Core/Resources/Resource/OCResourceText.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@
*/

#import "OCResource.h"
#import "OCDataTypes.h"

NS_ASSUME_NONNULL_BEGIN

@interface OCResourceText : OCResource
@interface OCResourceText : OCResource <OCDataItem, OCDataItemVersion>

@property(strong) NSString *text;
@property(strong,nullable) NSString *text;

@end

Expand Down
17 changes: 17 additions & 0 deletions ownCloudSDK/Core/Resources/Resource/OCResourceText.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

#import "OCResourceText.h"
#import "OCDataTypes.h"

@implementation OCResourceText

Expand All @@ -43,4 +44,20 @@ - (nullable instancetype)initWithCoder:(nonnull NSCoder *)coder
return (self);
}

#pragma mark - Data Item
- (OCDataItemType)dataItemType
{
return (OCDataItemTypeTextResource);
}

- (OCDataItemReference)dataItemReference
{
return (self.identifier);
}

- (OCDataItemVersion)dataItemVersion
{
return (self.version);
}

@end
3 changes: 2 additions & 1 deletion ownCloudSDK/Data Sources/OCDataTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ typedef NSComparisonResult(^OCDataSourceItemComparator)(OCDataSource *source1, O
typedef BOOL(^OCDataSourceItemRecordFilter)(OCDataItemRecord * _Nullable itemRecord);
typedef NSComparisonResult(^OCDataSourceItemRecordComparator)(OCDataItemRecord * _Nullable itemRecord1, OCDataItemRecord * _Nullable itemRecord2);

extern OCDataItemType OCDataItemTypeItem; //!< Item of type OCItem
extern OCDataItemType OCDataItemTypeDrive; //!< Item of type OCDrive
extern OCDataItemType OCDataItemTypePresentable; //!< Item of type OCDataItemPresentable
extern OCDataItemType OCDataItemTypeListContentConfiguration; //!< Item of type UIListContentConfiguration
extern OCDataItemType OCDataItemTypeTextResource; //!< Item of type OCResourceText

extern OCDataViewOption OCDataViewOptionCore; //!< OCCore instance
extern OCDataViewOption OCDataViewOptionListContentConfiguration; //!< UIListContentConfiguration instance to fill
Expand Down
3 changes: 2 additions & 1 deletion ownCloudSDK/Data Sources/OCDataTypes.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

#import "OCDataTypes.h"

OCDataItemType OCDataItemTypeItem = @"item";
OCDataItemType OCDataItemTypeDrive = @"drive";
OCDataItemType OCDataItemTypePresentable = @"presentable";
OCDataItemType OCDataItemTypeListContentConfiguration = @"listContentConfiguration";
OCDataItemType OCDataItemTypeTextResource = @"textResource";

OCDataViewOption OCDataViewOptionCore = @"core";
OCDataViewOption OCDataViewOptionListContentConfiguration = @"listContentConfiguration";
11 changes: 9 additions & 2 deletions ownCloudSDK/Drive/OCDrive.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,14 @@ + (instancetype)personalDrive
return(nil);
}

#pragma mark - OCDataConverter for OCDrives
+ (void)load
{
OCDataConverter *driveToPresentableConverter;

driveToPresentableConverter = [[OCDataConverter alloc] initWithInputType:OCDataItemTypeDrive outputType:OCDataItemTypePresentable conversion:^id _Nullable(OCDataConverter * _Nonnull converter, OCDrive * _Nullable inDrive, OCDataRenderer * _Nullable renderer, NSError * _Nullable __autoreleasing * _Nullable outError, OCDataViewOptions _Nullable options) {
OCDataItemPresentable *presentable = nil;
__weak OCCore *weakCore = options[OCDataViewOptionCore];

if (inDrive != nil)
{
Expand All @@ -77,7 +79,7 @@ + (void)load

presentable = [[OCDataItemPresentable alloc] initWithItem:inDrive];
presentable.title = inDrive.name;
presentable.subtitle = inDrive.type;
presentable.subtitle = (inDrive.desc.length > 0) ? inDrive.desc : inDrive.type;

presentable.availableResources = (imageDriveItem != nil) ?
((readmeDriveItem != nil) ? @[OCDataItemPresentableResourceCoverImage, OCDataItemPresentableResourceCoverDescription] :
Expand All @@ -99,6 +101,7 @@ + (void)load
}

resourceRequest.lifetime = OCResourceRequestLifetimeSingleRun;
resourceRequest.core = weakCore;

return (resourceRequest);
};
Expand All @@ -112,16 +115,20 @@ + (void)load
]];
}

#pragma mark - Comparison
- (BOOL)isSubstantiallyDifferentFrom:(OCDrive *)drive
{
return (![drive.identifier isEqual:_identifier] ||
![drive.type isEqual:_type] ||
![drive.name isEqual:_name] ||
![drive.desc isEqual:_desc] ||
![drive.davRootURL isEqual:_davRootURL] ||
OCNANotEqual([drive.gaDrive specialDriveItemFor:GASpecialFolderNameImage].eTag, [_gaDrive specialDriveItemFor:GASpecialFolderNameImage].eTag) ||
OCNANotEqual([drive.gaDrive specialDriveItemFor:GASpecialFolderNameReadme].eTag, [_gaDrive specialDriveItemFor:GASpecialFolderNameReadme].eTag) ||
(![drive.rootETag isEqual:self.rootETag] && (drive.rootETag != self.rootETag)));
}

#pragma mark - Utility accessors
- (OCLocation *)rootLocation
{
return ([[OCLocation alloc] initWithDriveID:_identifier path:@"/"]);
Expand Down Expand Up @@ -193,7 +200,7 @@ - (OCDataItemReference)dataItemReference

- (OCDataItemVersion)dataItemVersion
{
return ([NSString stringWithFormat:@"%@:%@:%@:%@:%@:%@", _identifier, _type, _name, _desc, _davRootURL, _gaDrive.eTag]);
return ([NSString stringWithFormat:@"%@:%@:%@:%@:%@:%@:%@:%@", _identifier, _type, _name, _desc, _davRootURL, _gaDrive.eTag, [_gaDrive specialDriveItemFor:GASpecialFolderNameImage].eTag, [_gaDrive specialDriveItemFor:GASpecialFolderNameReadme].eTag]);
}

#pragma mark - Comparison
Expand Down
8 changes: 7 additions & 1 deletion ownCloudSDK/GraphAPI/Parser Support/GAGraphData+Decoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,13 @@ + (nullable id)object:(id)inObject key:(NSString *)key ofClass:(Class)class inCo
{
// Convert string to URL
NSURL *url;
if ((url = [NSURL URLWithString:(NSString *)object]) != nil)
if ((url = [NSURL URLWithString:(NSString *)object]) == nil)
{
// Implement fallback in case of unescaped URLs (https://github.com/owncloud/ocis/issues/3538)
url = [NSURL URLWithString:[(NSString *)object stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]];
}

if (url != nil)
{
// Block file URLs
if (url.isFileURL)
Expand Down
4 changes: 3 additions & 1 deletion ownCloudSDK/HTTP/Response/OCHTTPResponse.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,11 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSString *)contentType; //!< Content-Type (stripped of charset and other parameters)

#pragma mark - Convenience body conversions
- (NSStringEncoding)bodyStringEncoding; //!< Returns the body's string encoding
- (NSStringEncoding)bodyStringEncoding; //!< Returns the body's string encoding - or ISO-8859-1 (Latin1) if none was found
- (NSStringEncoding)bodyStringEncodingWithFallback:(NSStringEncoding)fallbackEncoding; //!< Returns the body's string encoding - or fallbackEncoding if none was found

- (nullable NSString *)bodyAsString; //!< Returns the response body as a string formatted using the text encoding provided by the server. If no text encoding is provided, ISO-8859-1 is used.
- (nullable NSString *)bodyAsStringWithFallbackEncoding:(NSStringEncoding)fallbackEncoding; //!< Returns the response body as a string formatted using the text encoding provided by the server. If no text encoding is provided, fallbackEncoding is used.

- (nullable NSDictionary *)bodyConvertedDictionaryFromJSONWithError:(NSError * _Nullable *)outError; //!< Returns the response body as dictionary as converted by the JSON deserializer
- (nullable NSArray *)bodyConvertedArrayFromJSONWithError:(NSError * _Nullable *)error; //!< Returns the response body as array as converted by the JSON deserializer
Expand Down
22 changes: 14 additions & 8 deletions ownCloudSDK/HTTP/Response/OCHTTPResponse.m
Original file line number Diff line number Diff line change
Expand Up @@ -126,36 +126,42 @@ - (nullable NSString *)contentType
}

#pragma mark - Convenience body conversions
- (NSStringEncoding)bodyStringEncoding
- (NSStringEncoding)bodyStringEncodingWithFallback:(NSStringEncoding)fallbackEncoding; //!< Returns the body's string encoding - or fallbackEncoding if none was found
{
NSString *textEncodingName;
NSStringEncoding stringEncoding;
NSStringEncoding stringEncoding = fallbackEncoding;

if ((textEncodingName = self.httpURLResponse.textEncodingName) != nil)
{
stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)textEncodingName));
}
else
{
stringEncoding = NSISOLatin1StringEncoding; // ISO-8859-1
}

return(stringEncoding);
}

- (NSString *)bodyAsString
- (NSStringEncoding)bodyStringEncoding
{
return ([self bodyStringEncodingWithFallback:NSISOLatin1StringEncoding]);
}

- (NSString *)bodyAsStringWithFallbackEncoding:(NSStringEncoding)fallbackEncoding
{
NSString *responseBodyAsString = nil;
NSData *responseBodyData;

if ((responseBodyData = self.bodyData) != nil)
{
responseBodyAsString = [[NSString alloc] initWithData:responseBodyData encoding:self.bodyStringEncoding];
responseBodyAsString = [[NSString alloc] initWithData:responseBodyData encoding:[self bodyStringEncodingWithFallback:fallbackEncoding]];
}

return (responseBodyAsString);
}

- (NSString *)bodyAsString
{
return ([self bodyAsStringWithFallbackEncoding:NSISOLatin1StringEncoding]);
}

- (NSDictionary *)bodyConvertedDictionaryFromJSONWithError:(NSError **)outError
{
id jsonObject;
Expand Down
29 changes: 29 additions & 0 deletions ownCloudSDK/Item/OCItem+OCDataItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// OCItem+OCDataItem.h
// ownCloudSDK
//
// Created by Felix Schwarz on 14.04.22.
// Copyright © 2022 ownCloud GmbH. All rights reserved.
//

/*
* Copyright (C) 2022, ownCloud GmbH.
*
* This code is covered by the GNU Public License Version 3.
*
* For distribution utilizing Apple mechanisms please see https://owncloud.org/contribute/iOS-license-exception/
* You should have received a copy of this license along with this program. If not, see <http://www.gnu.org/licenses/gpl-3.0.en.html>.
*
*/

#import <ownCloudSDK/ownCloudSDK.h>
#import "OCDataTypes.h"

NS_ASSUME_NONNULL_BEGIN

@interface OCItem (DataItem) <OCDataItem, OCDataItemVersion>


@end

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 8dfb50e

Please sign in to comment.