diff --git a/Riot/Assets/Riot-Defaults.plist b/Riot/Assets/Riot-Defaults.plist index 9c18e135d..7ad072f6b 100644 --- a/Riot/Assets/Riot-Defaults.plist +++ b/Riot/Assets/Riot-Defaults.plist @@ -28,6 +28,11 @@ https://scalar-staging.riot.im/scalar-web/ integrationsRestUrl https://scalar-staging.riot.im/scalar/api + integrationsWidgetsUrls + + https://scalar-staging.riot.im/scalar/api + https://scalar.vector.im/api + piwik url diff --git a/Riot/Generated/RiotDefaults.swift b/Riot/Generated/RiotDefaults.swift index 5c063181b..51897ad61 100644 --- a/Riot/Generated/RiotDefaults.swift +++ b/Riot/Generated/RiotDefaults.swift @@ -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"] diff --git a/Riot/Managers/Widgets/Widget.m b/Riot/Managers/Widgets/Widget.m index 3831d9a02..bbff04049 100644 --- a/Riot/Managers/Widgets/Widget.m +++ b/Riot/Managers/Widgets/Widget.m @@ -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 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 diff --git a/Riot/Managers/Widgets/WidgetManager.h b/Riot/Managers/Widgets/WidgetManager.h index a95ba83e1..626c1f835 100644 --- a/Riot/Managers/Widgets/WidgetManager.h +++ b/Riot/Managers/Widgets/WidgetManager.h @@ -195,4 +195,12 @@ WidgetManagerErrorCode; 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 diff --git a/Riot/Managers/Widgets/WidgetManager.m b/Riot/Managers/Widgets/WidgetManager.m index c225e140e..4c18e62d9 100644 --- a/Riot/Managers/Widgets/WidgetManager.m +++ b/Riot/Managers/Widgets/WidgetManager.m @@ -509,6 +509,28 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain"; return operation; } ++ (BOOL)isScalarUrl:(NSString *)urlString +{ + BOOL isScalarUrl = NO; + + NSArray *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