Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ end

def wordpress_kit

pod 'WordPressKit', '~> 4.18.0-beta'
#pod 'WordPressKit', '~> 4.18.0-beta'
#pod 'WordPressKit', :git => 'https://github.com/wordpress-mobile/WordPressKit-iOS.git', :tag => ''
#pod 'WordPressKit', :git => 'https://github.com/wordpress-mobile/WordPressKit-iOS.git', :branch => ''
pod 'WordPressKit', :git => 'https://github.com/Deco354/WordPressKit-iOS.git', :branch => 'feature/remote-content-hash'
#pod 'WordPressKit', :git => 'https://github.com/wordpress-mobile/WordPressKit-iOS.git', :commit => ''
#pod 'WordPressKit', :path => '../WordPressKit-iOS'
end
Expand Down
15 changes: 10 additions & 5 deletions Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ PODS:
- WordPressKit (~> 4.18-beta)
- WordPressShared (~> 1.12-beta)
- WordPressUI (~> 1.7.0)
- WordPressKit (4.18.0):
- WordPressKit (4.19-beta.3):
- Alamofire (~> 4.8.0)
- CocoaLumberjack (~> 3.4)
- NSObject-SafeExpectations (= 0.0.4)
Expand Down Expand Up @@ -506,7 +506,7 @@ DEPENDENCIES:
- SVProgressHUD (= 2.2.5)
- WordPress-Editor-iOS (~> 1.19.3)
- WordPressAuthenticator (~> 1.26.0-beta)
- WordPressKit (~> 4.18.0-beta)
- WordPressKit (from `https://github.com/Deco354/WordPressKit-iOS.git`, branch `feature/remote-content-hash`)
- WordPressMocks (~> 0.0.8)
- WordPressShared (~> 1.12.0)
- WordPressUI (~> 1.7.1)
Expand Down Expand Up @@ -556,7 +556,6 @@ SPEC REPOS:
- WordPress-Aztec-iOS
- WordPress-Editor-iOS
- WordPressAuthenticator
- WordPressKit
- WordPressMocks
- WordPressShared
- WordPressUI
Expand Down Expand Up @@ -657,6 +656,9 @@ EXTERNAL SOURCES:
:commit: 5ff93360313e9919c7a4b7f0faa1cb9e5e9c3542
:git: http://github.com/wordpress-mobile/gutenberg-mobile/
:submodules: true
WordPressKit:
:branch: feature/remote-content-hash
:git: https://github.com/Deco354/WordPressKit-iOS.git
Yoga:
:podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/5ff93360313e9919c7a4b7f0faa1cb9e5e9c3542/third-party-podspecs/Yoga.podspec.json

Expand All @@ -675,6 +677,9 @@ CHECKOUT OPTIONS:
:commit: 5ff93360313e9919c7a4b7f0faa1cb9e5e9c3542
:git: http://github.com/wordpress-mobile/gutenberg-mobile/
:submodules: true
WordPressKit:
:commit: 7dc25bbdbdd22dfe2772ac38da2c058087ce5f9b
:git: https://github.com/Deco354/WordPressKit-iOS.git

SPEC CHECKSUMS:
1PasswordExtension: f97cc80ae58053c331b2b6dc8843ba7103b33794
Expand Down Expand Up @@ -756,7 +761,7 @@ SPEC CHECKSUMS:
WordPress-Aztec-iOS: b7ac8b30f746992e85d9668453ac87c2cdcecf4f
WordPress-Editor-iOS: 1886f7fe464d79ee64ccfe7985281f8cf45f75eb
WordPressAuthenticator: 31bceb4ab25de663a327b791e76a405b9c903b73
WordPressKit: 1d10fa14ea185600472d31cf25e677c7d938b17d
WordPressKit: 8a7cf458497a593cf8b1bfa6c965dcfd5d072ec0
WordPressMocks: b4064b99a073117bbc304abe82df78f2fbe60992
WordPressShared: 38cb62e9cb998d4dc3c1611f17934c6875a6b3e8
WordPressUI: 9da5d966b8beb091950cd96880db398d7f30e246
Expand All @@ -772,6 +777,6 @@ SPEC CHECKSUMS:
ZendeskSupportSDK: a87ab1e4badace92c75eb11dc77ede1e995b2adc
ZIPFoundation: 249fa8890597086cd536bb2df5c9804d84e122b0

PODFILE CHECKSUM: 6141b62876d49dbc9b2e5735cff154f0244a888f
PODFILE CHECKSUM: 267bf560442ff5d1b7cadc184cd0a691b3eb5c10

COCOAPODS: 1.9.3
84 changes: 15 additions & 69 deletions WordPress/Classes/Models/AbstractPost+HashHelpers.m
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "AbstractPost+HashHelpers.h"
#import "Media+WPMediaAsset.h"
#import "WordPress-Swift.h"
@import WordPressKit;

@implementation AbstractPost (HashHelpers)

Expand All @@ -10,25 +11,23 @@ - (NSString *)calculateConfirmedChangesContentHash {
// that's the purpose of the `-additionalContentHashes` extension point.

NSArray<NSData *> *hashedContents = @[
[self hashForNSInteger:self.blog.dotComID.integerValue],
[self hashForNSInteger:self.postID.integerValue],
[self hashForString:self.postTitle],
[self hashForString:self.content],
[self hashForDouble:self.dateCreated.timeIntervalSinceReferenceDate],
[self hashForString:self.permaLink],
[self hashForString:self.mt_excerpt],
[self hashForString:self.status],
[self hashForString:self.password],
[self hashForString:self.author],
[self hashForNSInteger:self.authorID.integerValue],
[self hashForString:self.featuredImage.identifier],
[self hashForString:self.wp_slug]];
[SHAHasher hashForNSInteger:self.blog.dotComID.integerValue],
[SHAHasher hashForNSInteger:self.postID.integerValue],
[SHAHasher hashForString:self.postTitle],
[SHAHasher hashForString:self.content],
[SHAHasher hashForDouble:self.dateCreated.timeIntervalSinceReferenceDate],
[SHAHasher hashForString:self.permaLink],
[SHAHasher hashForString:self.mt_excerpt],
[SHAHasher hashForString:self.status],
[SHAHasher hashForString:self.password],
[SHAHasher hashForString:self.author],
[SHAHasher hashForNSInteger:self.authorID.integerValue],
[SHAHasher hashForString:self.featuredImage.identifier],
[SHAHasher hashForString:self.wp_slug]];


NSArray<NSData *> *finalHashes = [hashedContents arrayByAddingObjectsFromArray:self.additionalContentHashes];

NSMutableData *mutableData = [NSMutableData data];

// So, there are multiple ways of combining all those hashes. You need to be careful not to lose the entropy though.
// Initially, I wanted to just XOR them together, which is totally reasonable thing to do!
// ...however, things get tricky when you XOR things that might be similar/the same.
Expand All @@ -42,64 +41,11 @@ - (NSString *)calculateConfirmedChangesContentHash {
// What I'm doing here instead is just treating all the "partial" hashes as a dumb bag of bits,
// combining them together and the final hash is SHA256 of _that_.
// Hopefully that'll be enough.

for (NSData *hash in finalHashes) {
[mutableData appendData:hash];
}

unsigned char finalDigest[CC_SHA256_DIGEST_LENGTH];

CC_SHA256(mutableData.bytes, (CC_LONG)mutableData.length, finalDigest);

return [self sha256StringFromData:[NSData dataWithBytes:finalDigest length:CC_SHA256_DIGEST_LENGTH]];
return [SHAHasher combineHashes:finalHashes];
}


- (NSArray<NSData *> *)additionalContentHashes {
return @[];
}

#pragma mark - SHA256 calculations

- (NSData *)hashForString:(NSString *) string {
if (!string) {
return [[NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH] copy];
}

NSData *encodedBytes = [string dataUsingEncoding:NSUTF8StringEncoding];
unsigned char digest[CC_SHA256_DIGEST_LENGTH];

CC_SHA256(encodedBytes.bytes, (CC_LONG)encodedBytes.length, digest);

return [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
}

- (NSData *)hashForNSInteger:(NSInteger)integer {
unsigned char digest[CC_SHA256_DIGEST_LENGTH];

CC_SHA256(&integer, sizeof(integer), digest);

return [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
}

- (NSData *)hashForDouble:(double)dbl {
unsigned char digest[CC_SHA256_DIGEST_LENGTH];

CC_SHA256(&dbl, sizeof(dbl), digest);

return [NSData dataWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
}

- (NSString *)sha256StringFromData:(NSData *)data {
NSMutableString *mutableString = [NSMutableString string];

const char *hashBytes = [data bytes];

for (int i = 0; i < data.length; i++) {
[mutableString appendFormat:@"%02.2hhx", hashBytes[i]];
}

return [mutableString copy];
}

@end
1 change: 1 addition & 0 deletions WordPress/Classes/Models/AbstractPost.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ typedef NS_ENUM(NSUInteger, AbstractPostRemoteStatus) {
@property (nonatomic, copy, nullable) NSNumber *autosaveIdentifier;

@property (nonatomic) BOOL hasVersionConflict;
@property (nonatomic, copy, nullable) NSString *lastRemoteUpdateHash;

// Revision management
- (AbstractPost *)createRevision;
Expand Down
1 change: 1 addition & 0 deletions WordPress/Classes/Models/AbstractPost.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ @implementation AbstractPost
@dynamic autosaveModifiedDate;
@dynamic autosaveIdentifier;
@dynamic hasVersionConflict;
@dynamic lastRemoteUpdateHash;

@synthesize restorableStatus;

Expand Down
14 changes: 7 additions & 7 deletions WordPress/Classes/Models/Post.swift
Original file line number Diff line number Diff line change
Expand Up @@ -318,12 +318,12 @@ class Post: AbstractPost {
return acc + obj
} ?? ""

return [hash(for: publicID ?? ""),
hash(for: tags ?? ""),
hash(for: postFormat ?? ""),
hash(for: stringifiedCategories),
hash(for: geolocation?.latitude ?? 0),
hash(for: geolocation?.longitude ?? 0),
hash(for: isStickyPost ? 1 : 0)]
return [SHAHasher.hash(for: publicID ?? ""),
SHAHasher.hash(for: tags ?? ""),
SHAHasher.hash(for: postFormat ?? ""),
SHAHasher.hash(for: stringifiedCategories),
SHAHasher.hash(for: geolocation?.latitude ?? 0),
SHAHasher.hash(for: geolocation?.longitude ?? 0),
SHAHasher.hash(for: isStickyPost ? 1 : 0)]
}
}
6 changes: 4 additions & 2 deletions WordPress/Classes/Services/PostService.m
Original file line number Diff line number Diff line change
Expand Up @@ -775,21 +775,22 @@ - (NSDictionary *)remoteSyncParametersDictionaryForRemote:(nonnull id <PostServi
}

- (void)updatePost:(AbstractPost *)post withRemotePost:(RemotePost *)remotePost {
NSString *remotePostHash = [remotePost contentHash];
NSNumber *previousPostID = post.postID;
post.postID = remotePost.postID;
post.author = remotePost.authorDisplayName;
post.authorID = remotePost.authorID;
post.date_created_gmt = remotePost.date;
post.dateModified = remotePost.dateModified;
post.postTitle = remotePost.title;
post.permaLink = [remotePost.URL absoluteString];
post.content = remotePost.content;
post.status = remotePost.status;
post.password = remotePost.password;
if (post.dateModified != remotePost.dateModified) {
if (post.lastRemoteUpdateHash != nil && ![post.lastRemoteUpdateHash isEqualToString:remotePostHash]) {
post.hasVersionConflict = post.hasRevision;
post.revision.hasVersionConflict = post.hasRevision;
}
post.dateModified = remotePost.dateModified;

if (remotePost.postThumbnailID != nil) {
post.featuredImage = [Media existingOrStubMediaWithMediaID: remotePost.postThumbnailID inBlog:post.blog];
Expand Down Expand Up @@ -881,6 +882,7 @@ - (void)updatePost:(AbstractPost *)post withRemotePost:(RemotePost *)remotePost
}

post.statusAfterSync = post.status;
post.lastRemoteUpdateHash = remotePostHash;
}

- (RemotePost *)remotePostWithPost:(AbstractPost *)post
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ class PostCardStatusViewModel: NSObject {
return .neutral(.shade70)
}

if post.hasVersionConflict {
return .error(.shade50)
}

if MediaCoordinator.shared.isUploadingMedia(for: post) || post.remoteStatus == .pushing {
return .neutral(.shade30)
}
Expand All @@ -111,10 +115,6 @@ class PostCardStatusViewModel: NSObject {
return (autoUploadAction == .upload || post.wasAutoUploadCancelled) ? .warning : .error
}

if post.hasVersionConflict {
return .error(.shade50)
}

if post.hasAutosaveRevision {
return .warning(.shade40)
}
Expand Down
2 changes: 1 addition & 1 deletion WordPress/Classes/WordPress.xcdatamodeld/.xccurrentversion
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>WordPress 100.xcdatamodel</string>
<string>WordPress 101.xcdatamodel</string>
</dict>
</plist>
Loading