Skip to content
This repository has been archived by the owner on Oct 5, 2019. It is now read-only.

Commit

Permalink
[TK iOS] Update TwitterKit due to security issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Rajul Arora committed Oct 12, 2018
1 parent bb96560 commit 27c849f
Show file tree
Hide file tree
Showing 116 changed files with 170 additions and 180 deletions.
26 changes: 0 additions & 26 deletions DemoApp/DemoApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,6 @@
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
377783821E95C71000BC4830 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 379A6D291E95B77C00625984 /* TwitterKit.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = BFE8395F1ADF23590035CBA1;
remoteInfo = TwitterKit;
};
377783841E95CAD800BC4830 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 379A6D1D1E95B77600625984 /* TwitterCore.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 9D5A92451AAA8D600039EFCC;
remoteInfo = TwitterCore;
};
377783EA1E96B7CA00BC4830 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 379A6D291E95B77C00625984 /* TwitterKit.xcodeproj */;
Expand Down Expand Up @@ -501,8 +487,6 @@
buildRules = (
);
dependencies = (
377783851E95CAD800BC4830 /* PBXTargetDependency */,
377783831E95C71000BC4830 /* PBXTargetDependency */,
);
name = DemoApp;
productName = DemoApp;
Expand Down Expand Up @@ -800,16 +784,6 @@
/* End PBXSourcesBuildPhase section */

/* Begin PBXTargetDependency section */
377783831E95C71000BC4830 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = TwitterKit;
targetProxy = 377783821E95C71000BC4830 /* PBXContainerItemProxy */;
};
377783851E95CAD800BC4830 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = TwitterCore;
targetProxy = 377783841E95CAD800BC4830 /* PBXContainerItemProxy */;
};
377783EB1E96B7CA00BC4830 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "TwitterKit Tests";
Expand Down
9 changes: 5 additions & 4 deletions DemoApp/DemoApp/Authentication/LoginViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,14 @@ class LoginViewController: UIViewController {
return view
}()

private lazy var loginButton: TWTRLogInButton = { [unowned self] in
private lazy var loginButton: TWTRLogInButton = { [weak self] in
let button = TWTRLogInButton() { (session, error) in
guard let weakSelf = self else { return }
if let error = error {
UIAlertController.showAlert(with: error, on: self)
UIAlertController.showAlert(with: error, on: weakSelf)
} else if let session = session {
self.dismiss(animated: true) {
self.delegate?.loginViewController(viewController: self, didAuthWith: session)
weakSelf.dismiss(animated: true) {
weakSelf.delegate?.loginViewController(viewController: weakSelf, didAuthWith: session)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions TwitterCore/TwitterCore-dynamic/TwitterCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#import "TWTRAPIErrorCode.h"
#import "TWTRAuthConfig.h"
#import "TWTRAuthSession.h"
#import "TWTRColorUtil.h"
#import "TWTRConstants.h"
#import "TWTRCoreOAuthSigning.h"
#import "TWTRGuestSession.h"
Expand Down
7 changes: 4 additions & 3 deletions TwitterCore/TwitterCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
377783AF1E96B78A00BC4830 /* TUDelorean.m in Sources */ = {isa = PBXBuildFile; fileRef = 377783A21E96B78A00BC4830 /* TUDelorean.m */; };
377941381E96BF910049A022 /* TWTRMockURLSessionProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 377941311E96BF910049A022 /* TWTRMockURLSessionProtocol.m */; };
377941471E96DA9A0049A022 /* OCMock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 377941461E96DA9A0049A022 /* OCMock.framework */; };
3789B0F31E96E6230026BBBC /* OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 377941461E96DA9A0049A022 /* OCMock.framework */; };
379A6D5B1E95B97300625984 /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 379A6D581E95B97300625984 /* EXTKeyPathCoding.h */; };
379A6D5C1E95B97300625984 /* EXTKeyPathCoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 379A6D581E95B97300625984 /* EXTKeyPathCoding.h */; };
379A6D5D1E95B97300625984 /* EXTScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 379A6D591E95B97300625984 /* EXTScope.h */; };
Expand Down Expand Up @@ -241,6 +240,7 @@
AAAAF73D1F9E5129002F1991 /* TWTRAuthConfigSessionsValidator_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AAAAF73B1F9E510B002F1991 /* TWTRAuthConfigSessionsValidator_Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
AAAAF7491FA12F17002F1991 /* TWTRAuthConfigStore_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AAAAF7481FA12F17002F1991 /* TWTRAuthConfigStore_Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
AAAAF74A1FA12F17002F1991 /* TWTRAuthConfigStore_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AAAAF7481FA12F17002F1991 /* TWTRAuthConfigStore_Private.h */; };
AAEA30D0216FBC430027E9D3 /* OCMock.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = AAEA30CF216FBC430027E9D3 /* OCMock.framework */; };
BF318EB41ADF32990082353A /* TWTRMultiThreadUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D30C5A61ACE5EA000D0B1FA /* TWTRMultiThreadUtil.m */; };
BF8EF2C81AFD3E9F008B4829 /* TWTRCoreOAuthSigning+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = BF8EF2C71AFD3E98008B4829 /* TWTRCoreOAuthSigning+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
BF8EF2C91AFD3E9F008B4829 /* TWTRCoreOAuthSigning+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = BF8EF2C71AFD3E98008B4829 /* TWTRCoreOAuthSigning+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -318,7 +318,7 @@
dstPath = "";
dstSubfolderSpec = 16;
files = (
3789B0F31E96E6230026BBBC /* OCMock.framework in CopyFiles */,
AAEA30D0216FBC430027E9D3 /* OCMock.framework in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -511,6 +511,7 @@
AAAE73BE1FB380BC005BEEAD /* EXTKeyPathCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTKeyPathCoding.h; sourceTree = "<group>"; };
AAAE73BF1FB380BC005BEEAD /* EXTScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EXTScope.h; sourceTree = "<group>"; };
AAAE73C01FB380BC005BEEAD /* metamacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metamacros.h; sourceTree = "<group>"; };
AAEA30CF216FBC430027E9D3 /* OCMock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OCMock.framework; path = ../vendor/OCMock.framework; sourceTree = "<group>"; };
BF8EF2C71AFD3E98008B4829 /* TWTRCoreOAuthSigning+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TWTRCoreOAuthSigning+Private.h"; sourceTree = "<group>"; };
BFA0EAF01B01277A000D712D /* TWTRCoreOAuthSigningTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TWTRCoreOAuthSigningTests.m; sourceTree = "<group>"; };
DB0908971B6057B000FE4CD3 /* TWTRSessionMigrating.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TWTRSessionMigrating.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -830,6 +831,7 @@
9D5A92181AAA89730039EFCC = {
isa = PBXGroup;
children = (
AAEA30CF216FBC430027E9D3 /* OCMock.framework */,
24AC143D1BE7B174000029B5 /* Config */,
9D4545431AB0D3C800730817 /* TwitterCore-module.private.modulemap */,
9D348B411AAFE73B007837FB /* TwitterCore-ios-module.modulemap */,
Expand Down Expand Up @@ -1181,7 +1183,6 @@
3D98960F1B9621CF00B9CABD /* TWTRTokenOnlyAuthSession.h in Headers */,
9D30C5CF1ACE60E200D0B1FA /* TWTRIdentifier.h in Headers */,
9D0AE5B71AC7400500884B45 /* TWTRDateUtil.h in Headers */,
9DF52D9C1ABB67F6004345D0 /* TWTRColorUtil.h in Headers */,
6C37A1CA1B22505900C360B4 /* TWTRCoreLanguage.h in Headers */,
3DEEF7C31B7A769A00A1B457 /* TWTRNetworkingConstants.h in Headers */,
9DBB70511ABB76BB00ED4051 /* TWTRResourcesUtil.h in Headers */,
Expand Down
3 changes: 2 additions & 1 deletion TwitterKit.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"3.2.1": "https://ton.twimg.com/syndication/twitterkit/ios/3.2.1/Dynamic/TwitterKit.framework.zip",
"3.3.0": "https://ton.twimg.com/syndication/twitterkit/ios/3.3.0/Dynamic/TwitterKit.framework.zip",
"3.4.0": "https://ton.twimg.com/syndication/twitterkit/ios/3.4.0/Dynamic/TwitterKit.framework.zip"
"3.4.0": "https://ton.twimg.com/syndication/twitterkit/ios/3.4.0/Dynamic/TwitterKit.framework.zip",
"3.4.1": "https://ton.twimg.com/syndication/twitterkit/ios/3.4.1/Dynamic/TwitterKit.framework.zip"
}
2 changes: 1 addition & 1 deletion TwitterKit/Config/Project.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ GCC_WARN_ABOUT_MISSING_NEWLINE = YES
APPLICATION_EXTENSION_API_ONLY = NO

// Versioning
CURRENT_PROJECT_VERSION = 3.4.0
CURRENT_PROJECT_VERSION = 3.4.1
DYLIB_CURRENT_VERSION = $(CURRENT_PROJECT_VERSION)

// Can *probably* remove this
Expand Down
4 changes: 2 additions & 2 deletions TwitterKit/TwitterKit-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.4.0</string>
<string>3.4.1</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
<string>iPhoneSimulator</string>
</array>
<key>CFBundleVersion</key>
<string>1030</string>
<string>1031</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright 2014 Twitter Inc.</string>
</dict>
Expand Down
2 changes: 1 addition & 1 deletion TwitterKit/TwitterKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "TwitterKit"
s.version = "3.4.0"
s.version = "3.4.1"
s.summary = "Increase user engagement and app growth."
s.homepage = "https://github.com/twitter/twitter-kit-ios"
s.documentation_url = "https://github.com/twitter/twitter-kit-ios/wiki"
Expand Down
6 changes: 4 additions & 2 deletions TwitterKit/TwitterKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3546,6 +3546,7 @@
"$(PROJECT_DIR)/../vendor",
"$(PROJECT_DIR)",
);
SDKROOT = iphoneos;
};
name = Debug;
};
Expand All @@ -3558,6 +3559,7 @@
"$(PROJECT_DIR)/../vendor",
"$(PROJECT_DIR)",
);
SDKROOT = iphoneos;
};
name = Release;
};
Expand All @@ -3574,7 +3576,7 @@
"-all_load",
);
PRODUCT_BUNDLE_IDENTIFIER = com.twitter.sdk.ios;
SDKROOT = iphoneos11.1;
SDKROOT = iphoneos;
};
name = Debug;
};
Expand All @@ -3591,7 +3593,7 @@
"-all_load",
);
PRODUCT_BUNDLE_IDENTIFIER = com.twitter.sdk.ios;
SDKROOT = iphoneos11.1;
SDKROOT = iphoneos;
};
name = Release;
};
Expand Down
14 changes: 13 additions & 1 deletion TwitterKit/TwitterKit/Social/Identity/TWTRMobileSSO.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,19 @@ typedef void (^TWTRMobileSSOCompletion)(BOOL twitterAppInstalled);
*
* Returns YES if the source application is Twitter sanctioned, NO otherwise.
*/
- (BOOL)verifySourceApplication:(NSString *)sourceApplication;
- (BOOL)isSSOWithSourceApplication:(NSString *)sourceApplication;

/**
* Determines if the source application sent from web is valid.
*
* Returns YES if the source application is Twitter sanctioned, NO otherwise.
*/
- (BOOL)isWebWithSourceApplication:(NSString *)sourceApplication;

/**
* Triggers an error completion when invalid source is detected
*/
- (void)triggerInvalidSourceError;

/**
* Verifies if the token embedded in the url is the same one received by oauth/request_token.
Expand Down
43 changes: 24 additions & 19 deletions TwitterKit/TwitterKit/Social/Identity/TWTRMobileSSO.m
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ - (void)attemptAppLoginWithCompletion:(TWTRLogInCompletion)completion

// Attempt to open Twitter app with Mobile SSO URL
if (iOS10) {
[[UIApplication sharedApplication] openURL:twitterAuthURL options:@{} completionHandler:^(BOOL success) {
if (!success) {
completion(nil, [TWTRErrors noTwitterAppError]);
}
}];
[[UIApplication sharedApplication] openURL:twitterAuthURL
options:@{}
completionHandler:^(BOOL success) {
if (!success) {
completion(nil, [TWTRErrors noTwitterAppError]);
}
}];

} else {
if ([[UIApplication sharedApplication] canOpenURL:twitterAuthURL]) {
Expand All @@ -60,21 +62,23 @@ - (void)attemptAppLoginWithCompletion:(TWTRLogInCompletion)completion
}
}

- (BOOL)verifySourceApplication:(NSString *)sourceApplication
- (BOOL)isSSOWithSourceApplication:(NSString *)sourceApplication
{
// If using auth with web view, check that the source application bundle identifier is the same as the app bundle identifier.
return [sourceApplication hasPrefix:@"com.twitter"] || [sourceApplication hasPrefix:@"com.atebits"];
}

- (BOOL)isWebWithSourceApplication:(NSString *)sourceApplication
{
NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
BOOL isExpectedSourceApplication = [sourceApplication hasPrefix:@"com.twitter"] || [sourceApplication hasPrefix:@"com.apple"] || [sourceApplication hasPrefix:@"com.atebits"] || [sourceApplication isEqualToString:bundleID];
if (!isExpectedSourceApplication) {
// The source application for Mobile SSO is not from a valid bundle id
dispatch_async(dispatch_get_main_queue(), ^{
self.completion(nil, [TWTRErrors invalidSourceApplicationError]);
});
return [sourceApplication hasPrefix:@"com.apple"] || [sourceApplication isEqualToString:bundleID];
}

return NO;
} else {
return YES;
}
- (void)triggerInvalidSourceError
{
dispatch_async(dispatch_get_main_queue(), ^{
self.completion(nil, [TWTRErrors invalidSourceApplicationError]);
});
}

- (BOOL)verifyOauthTokenResponsefromURL:(NSURL *)url
Expand All @@ -95,9 +99,10 @@ - (BOOL)processRedirectURL:(NSURL *)url
NSDictionary *parameters = [self.loginURLParser parametersForSSOURL:url];
TWTRSession *newSession = [[TWTRSession alloc] initWithSSOResponse:parameters];
TWTRSessionStore *store = [TWTRTwitter sharedInstance].sessionStore;
[store saveSession:newSession completion:^(id<TWTRAuthSession> session, NSError *error) {
self.completion(session, error);
}];
[store saveSession:newSession
completion:^(id<TWTRAuthSession> session, NSError *error) {
self.completion(session, error);
}];
return YES;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

#pragma mark - Twitter kit constants

NSString *const TWTRVersion = @"3.4.0";
NSString *const TWTRVersion = @"3.4.1";
NSString *const TWTRResourceBundleLocation = @"TwitterKitResources.bundle";
NSString *const TWTRBundleID = @"com.twitter.sdk.ios";

Expand Down
24 changes: 14 additions & 10 deletions TwitterKit/TwitterKit/TWTRTwitter.m
Original file line number Diff line number Diff line change
Expand Up @@ -379,17 +379,21 @@ - (BOOL)shouldShowWebBasedLogin:(NSError *)error

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options
{
// Handle Mobile SSO redirect
if ([self.mobileSSO verifySourceApplication:options[UIApplicationOpenURLOptionsSourceApplicationKey]]) {
BOOL wasMobileSSO = [self.mobileSSO processRedirectURL:url];
if (!wasMobileSSO) {
BOOL isTokenValid = [self.mobileSSO verifyOauthTokenResponsefromURL:url];
if (isTokenValid) {
// If it wasn't a Mobile SSO redirect, try to handle as
// SFSafariViewController redirect
return [self.webAuthenticationFlow resumeAuthenticationWithRedirectURL:url];
}
NSString *sourceApplication = options[UIApplicationOpenURLOptionsSourceApplicationKey];
BOOL isSSOBundle = [self.mobileSSO isSSOWithSourceApplication:sourceApplication];
BOOL isWeb = [self.mobileSSO isWebWithSourceApplication:sourceApplication];

if (isSSOBundle) {
[self.mobileSSO processRedirectURL:url];
} else if (isWeb) {
BOOL isTokenValid = [self.mobileSSO verifyOauthTokenResponsefromURL:url];
if (isTokenValid) {
// If it wasn't a Mobile SSO redirect, try to handle as
// SFSafariViewController redirect
return [self.webAuthenticationFlow resumeAuthenticationWithRedirectURL:url];
}
} else {
[self.mobileSSO triggerInvalidSourceError];
}

return NO;
Expand Down
17 changes: 3 additions & 14 deletions TwitterKit/TwitterKitTests/SocialTests/TWTRMobileSSOTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,13 @@ - (void)testProcessURL_savesCorrectSession

- (void)testVerifySourceApplication_validDomains
{
XCTAssertTrue([self.mobileSSO verifySourceApplication:@"com.twitter.dogfood.internal"]);
XCTAssertTrue([self.mobileSSO verifySourceApplication:@"com.apple.SafariViewService"]);
XCTAssertTrue([self.mobileSSO verifySourceApplication:@"com.atebits.tweetie2"]);
XCTAssertTrue([self.mobileSSO isSSOWithSourceApplication:@"com.twitter.dogfood.internal"]);
XCTAssertTrue([self.mobileSSO isSSOWithSourceApplication:@"com.atebits.tweetie2"]);
}

- (void)testVerifySourceApplication_invalidDomain
{
XCTestExpectation *errorExpectation = [self expectationWithDescription:@"Error has been raised."];

self.mobileSSO.completion = ^(TWTRSession *_Nullable session, NSError *_Nullable error) {
if (error) {
[errorExpectation fulfill];
}
};

XCTAssertFalse([self.mobileSSO verifySourceApplication:@"com.otherapp.appname"]);

[self waitForExpectations:@[errorExpectation] timeout:0.5];
XCTAssertFalse([self.mobileSSO isSSOWithSourceApplication:@"com.otherapp.appname"]);
}

@end
2 changes: 1 addition & 1 deletion docs/appledocs/TwitterKit/docset/Contents/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@
<key>DocSetPublisherName</key>
<string>Twitter Inc.</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2017 Twitter Inc.. All rights reserved.</string>
<string>Copyright © 2018 Twitter Inc.. All rights reserved.</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ <h3 class="subsubtitle method-title">TWTRAuthenticationCompletionHandler</h3>
<footer>
<div class="footer-copyright">

<p class="copyright">Copyright &copy; 2017 Twitter Inc. All rights reserved. Updated: 2017-12-13</p>
<p class="copyright">Copyright &copy; 2018 Twitter Inc. All rights reserved. Updated: 2018-10-11</p>


<p class="generator">Generated by <a href="http://appledoc.gentlebytes.com">appledoc 2.2.1 (build 1333)</a>.</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ <h4 class="method-subtitle">Declared In</h4>
<footer>
<div class="footer-copyright">

<p class="copyright">Copyright &copy; 2017 Twitter Inc. All rights reserved. Updated: 2017-12-13</p>
<p class="copyright">Copyright &copy; 2018 Twitter Inc. All rights reserved. Updated: 2018-10-11</p>


<p class="generator">Generated by <a href="http://appledoc.gentlebytes.com">appledoc 2.2.1 (build 1333)</a>.</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ <h4 class="method-subtitle">Declared In</h4>
<footer>
<div class="footer-copyright">

<p class="copyright">Copyright &copy; 2017 Twitter Inc. All rights reserved. Updated: 2017-12-13</p>
<p class="copyright">Copyright &copy; 2018 Twitter Inc. All rights reserved. Updated: 2018-10-11</p>


<p class="generator">Generated by <a href="http://appledoc.gentlebytes.com">appledoc 2.2.1 (build 1333)</a>.</p>
Expand Down
Loading

1 comment on commit 27c849f

@Radar966
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sorry

Please sign in to comment.