Finish v0.8.3

This commit is contained in:
manuroe
2019-03-13 09:10:34 +01:00
14 changed files with 319 additions and 133 deletions
+8 -2
View File
@@ -1,13 +1,19 @@
Changes in 0.8.3 (2019-xx-xx)
Changes in 0.8.3 (2019-03-13)
===============================================
Improvements:
* Upgrade MatrixKit version ([v0.9.7](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.7)).
Bug fix:
* Widgets: Attempt to re-register for a scalar token if ours is invalid (#2326).
* Widgets: Pass scalar_token only when required.
Changes in 0.8.2 (2019-03-11)
===============================================
Improvements:
* Upgrade MatrixKit version ([v0.9.6](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.6).
* Upgrade MatrixKit version ([v0.9.6](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.6)).
* Maintenance: Update cocopoads and pods. Automatic update to Swift4.2.
* Add app store description as app string resource to make them available for translation on weblate (#2201).
* Update deprecated contact availability checks (#2222).
+1 -1
View File
@@ -7,7 +7,7 @@ use_frameworks!
# Different flavours of pods to MatrixKit
# The current MatrixKit pod version
$matrixKitVersion = '0.9.6'
$matrixKitVersion = '0.9.7'
# The develop branch version
#$matrixKitVersion = 'develop'
+8 -8
View File
@@ -44,21 +44,21 @@ PODS:
- HPGrowingTextView (1.1)
- libbase58 (0.1.4)
- libPhoneNumber-iOS (0.9.13)
- MatrixKit (0.9.6):
- MatrixKit (0.9.7):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.9.6)
- MatrixKit/Core (= 0.9.7)
- MatrixSDK (= 0.12.3)
- MatrixKit/AppExtension (0.9.6):
- MatrixKit/AppExtension (0.9.7):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21)
- DTCoreText/Extension
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.12.3)
- MatrixKit/Core (0.9.6):
- MatrixKit/Core (0.9.7):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21)
- HPGrowingTextView (~> 1.1)
@@ -102,8 +102,8 @@ DEPENDENCIES:
- cmark
- DTCoreText
- GBDeviceInfo (~> 5.2.0)
- MatrixKit (= 0.9.6)
- MatrixKit/AppExtension (= 0.9.6)
- MatrixKit (= 0.9.7)
- MatrixKit/AppExtension (= 0.9.7)
- MatrixSDK/JingleCallStack
- MatrixSDK/SwiftSupport
- OLMKit
@@ -154,7 +154,7 @@ SPEC CHECKSUMS:
HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
libPhoneNumber-iOS: e444379ac18bbfbdefad571da735b2cd7e096caa
MatrixKit: 3cc6fdb1254a076875215d43b5b8100f136634c7
MatrixKit: da43b16842298fe0987ca8a98267bee775c10a35
MatrixSDK: 36c1a0da01a2745d4ffcca73e080610f05d47009
OLMKit: 88eda69110489f817d59bcb4353b7c247570aa4f
PiwikTracker: 42862c7b13028065c3dfd36b4dc38db8a5765acf
@@ -165,6 +165,6 @@ SPEC CHECKSUMS:
WebRTC: f2a6203584745fe53532633397557876b5d71640
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
PODFILE CHECKSUM: 1f4241c97f15817bdef6c94f78a778f7d175e103
PODFILE CHECKSUM: 033d67e4bbc8604bb6e37bac1d0ca1d90b8688dd
COCOAPODS: 1.6.1
+5
View File
@@ -28,6 +28,11 @@
<string>https://scalar-staging.riot.im/scalar-web/</string>
<key>integrationsRestUrl</key>
<string>https://scalar-staging.riot.im/scalar/api</string>
<key>integrationsWidgetsUrls</key>
<array>
<string>https://scalar-staging.riot.im/scalar/api</string>
<string>https://scalar.vector.im/api</string>
</array>
<key>piwik</key>
<dict>
<key>url</key>
+1
View File
@@ -21,6 +21,7 @@ internal enum RiotDefaults {
internal static let identityserverurl: String = _document["identityserverurl"]
internal static let integrationsRestUrl: String = _document["integrationsRestUrl"]
internal static let integrationsUiUrl: String = _document["integrationsUiUrl"]
internal static let integrationsWidgetsUrls: [String] = _document["integrationsWidgetsUrls"]
internal static let matrixApps: Bool = _document["matrixApps"]
internal static let maxAllowedMediaCacheSize: Int = _document["maxAllowedMediaCacheSize"]
internal static let pinRoomsWithMissedNotif: Bool = _document["pinRoomsWithMissedNotif"]
+63 -58
View File
@@ -49,68 +49,73 @@
- (MXHTTPOperation *)widgetUrl:(void (^)(NSString * _Nonnull))success failure:(void (^)(NSError * _Nonnull))failure
{
// Format the url string with user data (including their scalar token)
__weak typeof(self) weakSelf = self;
return [[WidgetManager sharedManager] getScalarTokenForMXSession:_mxSession success:^(NSString *scalarToken) {
__block NSString *widgetUrl = _url;
if (weakSelf)
// Format the url string with user data
NSString *userId = self.mxSession.myUser.userId;
NSString *displayName = self.mxSession.myUser.displayname ? self.mxSession.myUser.displayname : self.mxSession.myUser.userId;
NSString *avatarUrl = self.mxSession.myUser.avatarUrl ? self.mxSession.myUser.avatarUrl : @"";
// Escape everything to build a valid URL string
// We can't know where the values escaped here will be inserted in the URL, so the alphanumeric charset is used
userId = [MXTools encodeURIComponent:userId];
displayName = [MXTools encodeURIComponent:displayName];
avatarUrl = [MXTools encodeURIComponent:avatarUrl];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:@"$matrix_user_id" withString:userId];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:@"$matrix_display_name" withString:displayName];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:@"$matrix_avatar_url" withString:avatarUrl];
// Integrate widget data into widget url
for (NSString *key in _data)
{
NSString *paramKey = [NSString stringWithFormat:@"$%@", key];
NSString *dataString;
MXJSONModelSetString(dataString, _data[key]);
// Fix number data instead of expected string data
if (!dataString && [_data[key] isKindOfClass:NSNumber.class])
{
typeof(self) self = weakSelf;
NSString *userId = self.mxSession.myUser.userId;
NSString *displayName = self.mxSession.myUser.displayname ? self.mxSession.myUser.displayname : self.mxSession.myUser.userId;
NSString *avatarUrl = self.mxSession.myUser.avatarUrl ? self.mxSession.myUser.avatarUrl : @"";
// Escape everything to build a valid URL string
// We can't know where the values escaped here will be inserted in the URL, so the alphanumeric charset is used
userId = [MXTools encodeURIComponent:userId];
displayName = [MXTools encodeURIComponent:displayName];
avatarUrl = [MXTools encodeURIComponent:avatarUrl];
NSString *widgetUrl = _url;
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:@"$matrix_user_id" withString:userId];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:@"$matrix_display_name" withString:displayName];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:@"$matrix_avatar_url" withString:avatarUrl];
// Integrate widget data into widget url
for (NSString *key in _data)
{
NSString *paramKey = [NSString stringWithFormat:@"$%@", key];
NSString *dataString;
MXJSONModelSetString(dataString, _data[key]);
// Fix number data instead of expected string data
if (!dataString && [_data[key] isKindOfClass:NSNumber.class])
{
dataString = [((NSNumber*)_data[key]) stringValue];
}
if (dataString)
{
// same question as above
NSString *value = [MXTools encodeURIComponent:dataString];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:paramKey
withString:value];
}
else
{
NSLog(@"[Widget] Error: Invalid data field value in %@ for key %@ in data %@", self, key, _data);
}
}
// Add the user scalar token
widgetUrl = [widgetUrl stringByAppendingString:[NSString stringWithFormat:@"%@scalar_token=%@",
[widgetUrl containsString:@"?"] ? @"&" : @"?",
scalarToken]];
// Add the widget id
widgetUrl = [widgetUrl stringByAppendingString:[NSString stringWithFormat:@"&widgetId=%@", _widgetId]];
success(widgetUrl);
dataString = [((NSNumber*)_data[key]) stringValue];
}
} failure:failure];
if (dataString)
{
// same question as above
NSString *value = [MXTools encodeURIComponent:dataString];
widgetUrl = [widgetUrl stringByReplacingOccurrencesOfString:paramKey
withString:value];
}
else
{
NSLog(@"[Widget] Error: Invalid data field value in %@ for key %@ in data %@", self, key, _data);
}
}
// Add the widget id
widgetUrl = [widgetUrl stringByAppendingString:[NSString stringWithFormat:@"%@widgetId=%@",
[widgetUrl containsString:@"?"] ? @"&" : @"?",
_widgetId]];
// Check if their scalar token must added
if ([WidgetManager isScalarUrl:widgetUrl])
{
return [[WidgetManager sharedManager] getScalarTokenForMXSession:_mxSession validate:NO success:^(NSString *scalarToken) {
// Add the user scalar token
widgetUrl = [widgetUrl stringByAppendingString:[NSString stringWithFormat:@"&scalar_token=%@",
scalarToken]];
success(widgetUrl);
} failure:failure];
}
else
{
success(widgetUrl);
}
return nil;
}
- (BOOL)isActive
+10
View File
@@ -187,12 +187,22 @@ WidgetManagerErrorCode;
to get one.
@param mxSession the session to check.
@param validate if it is cached, check its validity on the scalar server.
@param success A block object called when the operation succeeds.
@param failure A block object called when the operation fails.
*/
- (MXHTTPOperation *)getScalarTokenForMXSession:(MXSession*)mxSession
validate:(BOOL)validate
success:(void (^)(NSString *scalarToken))success
failure:(void (^)(NSError *error))failure;
/**
Returns true if specified url is a scalar URL, typically https://scalar.vector.im/api
@param urlString the URL to check.
@return YES if specified URL is a scalar URL.
*/
+ (BOOL)isScalarUrl:(NSString*)urlString;
@end
+143 -51
View File
@@ -442,6 +442,7 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
#pragma mark - Modular interface
- (MXHTTPOperation *)getScalarTokenForMXSession:(MXSession*)mxSession
validate:(BOOL)validate
success:(void (^)(NSString *scalarToken))success
failure:(void (^)(NSError *error))failure;
{
@@ -450,65 +451,156 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
__block NSString *scalarToken = [self scalarTokenForMXSession:mxSession];
if (scalarToken)
{
success(scalarToken);
if (!validate)
{
success(scalarToken);
}
else
{
operation = [self validateScalarToken:scalarToken forMXSession:mxSession complete:^(BOOL valid) {
if (valid)
{
success(scalarToken);
}
else
{
NSLog(@"[WidgetManager] getScalarTokenForMXSession: Invalid stored token. Need to register for a new token");
MXHTTPOperation *operation2 = [self registerForScalarToken:mxSession success:success failure:failure];
[operation mutateTo:operation2];
}
} failure:failure];
}
}
else
{
NSLog(@"[WidgetManager] getScalarTokenForMXSession: Need to register to get a token");
__weak __typeof__(self) weakSelf = self;
operation = [mxSession.matrixRestClient openIdToken:^(MXOpenIdToken *tokenObject) {
typeof(self) self = weakSelf;
if (self)
{
// Exchange the token for a scalar token
NSString *modularRestUrl = [[NSUserDefaults standardUserDefaults] objectForKey:@"integrationsRestUrl"];
MXHTTPClient *httpClient = [[MXHTTPClient alloc] initWithBaseURL:modularRestUrl andOnUnrecognizedCertificateBlock:nil];
MXHTTPOperation *operation2 = [httpClient requestWithMethod:@"POST"
path:@"register"
parameters:tokenObject.JSONDictionary
success:^(NSDictionary *JSONResponse) {
MXJSONModelSetString(scalarToken, JSONResponse[@"scalar_token"])
self->scalarTokens[mxSession.myUser.userId] = scalarToken;
[self save];
if (success)
{
success(scalarToken);
}
} failure:^(NSError *error) {
NSLog(@"[WidgetManager] getScalarTokenForMXSession. Error in modular/register request");
if (failure)
{
failure(error);
}
}];
[operation mutateTo:operation2];
}
} failure:^(NSError *error) {
NSLog(@"[WidgetManager] getScalarTokenForMXSession. Error in openIdToken request");
if (failure)
{
failure(error);
}
}];
NSLog(@"[WidgetManager] getScalarTokenForMXSession: Need to register for a token");
operation = [self registerForScalarToken:mxSession success:success failure:failure];
}
return operation;
}
- (MXHTTPOperation *)registerForScalarToken:(MXSession*)mxSession
success:(void (^)(NSString *scalarToken))success
failure:(void (^)(NSError *error))failure
{
MXHTTPOperation *operation;
MXWeakify(self);
operation = [mxSession.matrixRestClient openIdToken:^(MXOpenIdToken *tokenObject) {
MXStrongifyAndReturnIfNil(self);
// Exchange the token for a scalar token
NSString *modularRestUrl = [[NSUserDefaults standardUserDefaults] objectForKey:@"integrationsRestUrl"];
MXHTTPClient *httpClient = [[MXHTTPClient alloc] initWithBaseURL:modularRestUrl andOnUnrecognizedCertificateBlock:nil];
MXHTTPOperation *operation2 =
[httpClient requestWithMethod:@"POST"
path:@"register?v=1.1"
parameters:tokenObject.JSONDictionary
success:^(NSDictionary *JSONResponse)
{
NSString *scalarToken;
MXJSONModelSetString(scalarToken, JSONResponse[@"scalar_token"])
self->scalarTokens[mxSession.myUser.userId] = scalarToken;
[self save];
if (success)
{
success(scalarToken);
}
} failure:^(NSError *error) {
NSLog(@"[WidgetManager] registerForScalarToken. Error in modular/register request");
if (failure)
{
failure(error);
}
}];
[operation mutateTo:operation2];
} failure:^(NSError *error) {
NSLog(@"[WidgetManager] registerForScalarToken. Error in openIdToken request");
if (failure)
{
failure(error);
}
}];
return operation;
}
- (MXHTTPOperation *)validateScalarToken:(NSString*)scalarToken forMXSession:(MXSession*)mxSession
complete:(void (^)(BOOL valid))complete
failure:(void (^)(NSError *error))failure
{
NSString *modularRestUrl = [[NSUserDefaults standardUserDefaults] objectForKey:@"integrationsRestUrl"];
MXHTTPClient *httpClient = [[MXHTTPClient alloc] initWithBaseURL:modularRestUrl andOnUnrecognizedCertificateBlock:nil];
return [httpClient requestWithMethod:@"GET"
path:[NSString stringWithFormat:@"account?v=1.1&scalar_token=%@", scalarToken]
parameters:nil
success:^(NSDictionary *JSONResponse) {
NSString *userId;
MXJSONModelSetString(userId, JSONResponse[@"user_id"])
if ([userId isEqualToString:mxSession.myUser.userId])
{
complete(YES);
}
else
{
NSLog(@"[WidgetManager] validateScalarToken. Unexpected modular/account response: %@", JSONResponse);
complete(NO);
}
} failure:^(NSError *error) {
NSHTTPURLResponse *urlResponse = [MXHTTPOperation urlResponseFromError:error];
NSLog(@"[WidgetManager] validateScalarToken. Error in modular/account request. statusCode: %@", @(urlResponse.statusCode));
if (urlResponse && urlResponse.statusCode / 100 != 2)
{
complete(NO);
}
else if (failure)
{
failure(error);
}
}];
}
+ (BOOL)isScalarUrl:(NSString *)urlString
{
BOOL isScalarUrl = NO;
NSArray<NSString*> *scalarUrlStrings = [[NSUserDefaults standardUserDefaults] objectForKey:@"integrationsWidgetsUrls"];
if (scalarUrlStrings.count == 0)
{
scalarUrlStrings = @[[[NSUserDefaults standardUserDefaults] objectForKey:@"integrationsRestUrl"]];
}
for (NSString *scalarUrlString in scalarUrlStrings)
{
if ([urlString hasPrefix:scalarUrlString])
{
isScalarUrl = YES;
break;
}
}
return isScalarUrl;
}
#pragma mark - Private methods
- (NSString *)scalarTokenForMXSession:(MXSession *)mxSession
@@ -73,7 +73,7 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
// Make sure we have a scalar token
MXWeakify(self);
operation = [[WidgetManager sharedManager] getScalarTokenForMXSession:mxSession success:^(NSString *theScalarToken) {
operation = [[WidgetManager sharedManager] getScalarTokenForMXSession:mxSession validate:YES success:^(NSString *theScalarToken) {
MXStrongifyAndReturnIfNil(self);
self->operation = nil;
@@ -172,12 +172,7 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
{
// Filter out the users's scalar token
NSString *errorDescription = error.description;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"scalar_token=\\w*"
options:NSRegularExpressionCaseInsensitive error:nil];
errorDescription = [regex stringByReplacingMatchesInString:errorDescription
options:0
range:NSMakeRange(0, errorDescription.length)
withTemplate:@"scalar_token=..."];
errorDescription = [self stringByReplacingScalarTokenInString:errorDescription byScalarToken:@"..."];
NSLog(@"[WidgetVC] didFailLoadWithError: %@", errorDescription);
@@ -185,6 +180,24 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
[self showErrorAsAlert:error];
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
if ([navigationResponse.response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse * response = (NSHTTPURLResponse *)navigationResponse.response;
if (response.statusCode != 200)
{
NSLog(@"[WidgetVC] decidePolicyForNavigationResponse: statusCode: %@", @(response.statusCode));
}
if (response.statusCode == 403 && [WidgetManager isScalarUrl:self.URL])
{
[self fixScalarToken];
}
}
decisionHandler(WKNavigationResponsePolicyAllow);
}
#pragma mark - postMessage API
- (void)onPostMessageRequest:(NSString*)requestId data:(NSDictionary*)requestData
@@ -315,4 +328,50 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
[self sendError:NSLocalizedStringFromTable(errorKey, @"Vector", nil) toRequest:requestId];
}
#pragma mark - Private methods
- (NSString *)stringByReplacingScalarTokenInString:(NSString*)string byScalarToken:(NSString*)scalarToken
{
if (!string)
{
return nil;
}
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"scalar_token=\\w*"
options:NSRegularExpressionCaseInsensitive error:nil];
return [regex stringByReplacingMatchesInString:string
options:0
range:NSMakeRange(0, string.length)
withTemplate:[NSString stringWithFormat:@"scalar_token=%@", scalarToken]];
}
/**
Reset the scalar token used in the webview URL.
*/
- (void)fixScalarToken
{
NSLog(@"[WidgetVC] fixScalarToken");
self->webView.hidden = YES;
// Get a fresh new scalar token
[WidgetManager.sharedManager deleteDataForUser:widget.mxSession.myUser.userId];
MXWeakify(self);
[WidgetManager.sharedManager getScalarTokenForMXSession:widget.mxSession validate:NO success:^(NSString *scalarToken) {
MXStrongifyAndReturnIfNil(self);
NSLog(@"[WidgetVC] fixScalarToken: DONE");
self.URL = [self stringByReplacingScalarTokenInString:self.URL byScalarToken:scalarToken];
self->webView.hidden = NO;
} failure:^(NSError *error) {
NSLog(@"[WidgetVC] fixScalarToken: Error: %@", error);
[self showErrorAsAlert:error];
}];
}
@end
+2 -2
View File
@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.8.2</string>
<string>0.8.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>0.8.2</string>
<string>0.8.3</string>
<key>ITSAppUsesNonExemptEncryption</key>
<true/>
<key>ITSEncryptionExportComplianceCode</key>
@@ -67,6 +67,9 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
// Add observer on the Extension host
[[NSNotificationCenter defaultCenter] addObserver:sharedInstance selector:@selector(checkUserAccount) name:NSExtensionHostWillEnterForegroundNotification object:nil];
// Add observer to handle memory warning
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
MXSDKOptions *sdkOptions = [MXSDKOptions sharedInstance];
// Apply the application group
sdkOptions.applicationGroupIdentifier = @"group.im.vector";
@@ -840,6 +843,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode)
}
}
- (void)didReceiveMemoryWarning:(NSNotification*)notification
{
NSLog(@"[ShareExtensionManager] Did receive memory warning");
}
#pragma mark - Sharing
- (void)sendText:(NSString *)text toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock
@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.8.2</string>
<string>0.8.3</string>
<key>CFBundleVersion</key>
<string>0.8.2</string>
<string>0.8.3</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>
+2 -2
View File
@@ -17,9 +17,9 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.8.2</string>
<string>0.8.3</string>
<key>CFBundleVersion</key>
<string>0.8.2</string>
<string>0.8.3</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionAttributes</key>