Respond to Cr.

pull/1/head
Matthew Chen 6 years ago
parent 55376975f5
commit f13c1de738

@ -45,8 +45,15 @@ NS_ASSUME_NONNULL_BEGIN
_quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread transaction:transaction]; _quotedMessage = [TSQuotedMessage quotedMessageForDataMessage:_dataMessage thread:_thread transaction:transaction];
_contact = [OWSContacts contactForDataMessage:_dataMessage transaction:transaction]; _contact = [OWSContacts contactForDataMessage:_dataMessage transaction:transaction];
_linkPreview =
[OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:_dataMessage body:_body transaction:transaction]; NSError *linkPreviewError;
_linkPreview = [OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:_dataMessage
body:_body
transaction:transaction
error:&linkPreviewError];
if (linkPreviewError && ![OWSLinkPreview isNoPreviewError:linkPreviewError]) {
OWSLogError(@"linkPreviewError: %@", linkPreviewError);
}
if (sentProto.unidentifiedStatus.count > 0) { if (sentProto.unidentifiedStatus.count > 0) {
NSMutableArray<NSString *> *nonUdRecipientIds = [NSMutableArray new]; NSMutableArray<NSString *> *nonUdRecipientIds = [NSMutableArray new];

@ -4,6 +4,13 @@
import Foundation import Foundation
@objc
public enum LinkPreviewError: Int, Error {
case invalidInput
case assertionFailure
case noPreview
}
@objc(OWSLinkPreview) @objc(OWSLinkPreview)
public class OWSLinkPreview: MTLModel { public class OWSLinkPreview: MTLModel {
@objc @objc
@ -13,13 +20,13 @@ public class OWSLinkPreview: MTLModel {
public var title: String? public var title: String?
@objc @objc
public var attachmentId: String? public var imageAttachmentId: String?
@objc @objc
public init(urlString: String, title: String?, attachmentId: String?) { public init(urlString: String, title: String?, imageAttachmentId: String?) {
self.urlString = urlString self.urlString = urlString
self.title = title self.title = title
self.attachmentId = attachmentId self.imageAttachmentId = imageAttachmentId
super.init() super.init()
} }
@ -34,28 +41,36 @@ public class OWSLinkPreview: MTLModel {
try super.init(dictionary: dictionaryValue) try super.init(dictionary: dictionaryValue)
} }
@objc
public class func isNoPreviewError(_ error: Error) -> Bool {
guard let error = error as? LinkPreviewError else {
return false
}
return error == .noPreview
}
@objc @objc
public class func buildValidatedLinkPreview(dataMessage: SSKProtoDataMessage, public class func buildValidatedLinkPreview(dataMessage: SSKProtoDataMessage,
body: String?, body: String?,
transaction: YapDatabaseReadWriteTransaction) -> OWSLinkPreview? { transaction: YapDatabaseReadWriteTransaction) throws -> OWSLinkPreview {
guard let previewProto = dataMessage.preview else { guard let previewProto = dataMessage.preview else {
return nil throw LinkPreviewError.noPreview
} }
let urlString = previewProto.url let urlString = previewProto.url
guard URL(string: urlString) != nil else { guard URL(string: urlString) != nil else {
owsFailDebug("Could not parse preview URL.") Logger.error("Could not parse preview URL.")
return nil throw LinkPreviewError.invalidInput
} }
guard let body = body else { guard let body = body else {
owsFailDebug("Preview for message without body.") Logger.error("Preview for message without body.")
return nil throw LinkPreviewError.invalidInput
} }
let bodyComponents = body.components(separatedBy: .whitespacesAndNewlines) let bodyComponents = body.components(separatedBy: .whitespacesAndNewlines)
guard bodyComponents.contains(urlString) else { guard bodyComponents.contains(urlString) else {
owsFailDebug("URL not present in body.") Logger.error("URL not present in body.")
return nil throw LinkPreviewError.invalidInput
} }
// TODO: Verify that url host is in whitelist. // TODO: Verify that url host is in whitelist.
@ -68,7 +83,8 @@ public class OWSLinkPreview: MTLModel {
imageAttachmentPointer.save(with: transaction) imageAttachmentPointer.save(with: transaction)
imageAttachmentId = imageAttachmentPointer.uniqueId imageAttachmentId = imageAttachmentPointer.uniqueId
} else { } else {
owsFailDebug("Could not parse image proto.") Logger.error("Could not parse image proto.")
throw LinkPreviewError.invalidInput
} }
} }
@ -78,20 +94,20 @@ public class OWSLinkPreview: MTLModel {
} }
let hasImage = imageAttachmentId != nil let hasImage = imageAttachmentId != nil
if !hasTitle && !hasImage { if !hasTitle && !hasImage {
owsFailDebug("Preview has neither title nor image.") Logger.error("Preview has neither title nor image.")
return nil throw LinkPreviewError.invalidInput
} }
return OWSLinkPreview(urlString: urlString, title: title, attachmentId: imageAttachmentId) return OWSLinkPreview(urlString: urlString, title: title, imageAttachmentId: imageAttachmentId)
} }
@objc @objc
public func removeAttachment(transaction: YapDatabaseReadWriteTransaction) { public func removeAttachment(transaction: YapDatabaseReadWriteTransaction) {
guard let attachmentId = attachmentId else { guard let imageAttachmentId = imageAttachmentId else {
owsFailDebug("No attachment id.") owsFailDebug("No attachment id.")
return return
} }
guard let attachment = TSAttachment.fetch(uniqueId: attachmentId, transaction: transaction) else { guard let attachment = TSAttachment.fetch(uniqueId: imageAttachmentId, transaction: transaction) else {
owsFailDebug("Could not load attachment.") owsFailDebug("Could not load attachment.")
return return
} }

@ -351,7 +351,7 @@ static const NSUInteger OWSMessageSchemaVersion = 4;
[self.contactShare removeAvatarAttachmentWithTransaction:transaction]; [self.contactShare removeAvatarAttachmentWithTransaction:transaction];
} }
if (self.linkPreview.attachmentId) { if (self.linkPreview.imageAttachmentId) {
[self.linkPreview removeAttachmentWithTransaction:transaction]; [self.linkPreview removeAttachmentWithTransaction:transaction];
} }

@ -1287,10 +1287,15 @@ NS_ASSUME_NONNULL_BEGIN
thread:oldGroupThread thread:oldGroupThread
transaction:transaction]; transaction:transaction];
NSError *linkPreviewError;
OWSLinkPreview *_Nullable linkPreview = OWSLinkPreview *_Nullable linkPreview =
[OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:dataMessage [OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:dataMessage
body:body body:body
transaction:transaction]; transaction:transaction
error:&linkPreviewError];
if (linkPreviewError && ![OWSLinkPreview isNoPreviewError:linkPreviewError]) {
OWSLogError(@"linkPreviewError: %@", linkPreviewError);
}
OWSLogDebug(@"incoming message from: %@ for group: %@ with timestamp: %lu", OWSLogDebug(@"incoming message from: %@ for group: %@ with timestamp: %lu",
envelopeAddress(envelope), envelopeAddress(envelope),
@ -1355,8 +1360,15 @@ NS_ASSUME_NONNULL_BEGIN
thread:thread thread:thread
transaction:transaction]; transaction:transaction];
NSError *linkPreviewError;
OWSLinkPreview *_Nullable linkPreview = OWSLinkPreview *_Nullable linkPreview =
[OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:dataMessage body:body transaction:transaction]; [OWSLinkPreview buildValidatedLinkPreviewWithDataMessage:dataMessage
body:body
transaction:transaction
error:&linkPreviewError];
if (linkPreviewError && ![OWSLinkPreview isNoPreviewError:linkPreviewError]) {
OWSLogError(@"linkPreviewError: %@", linkPreviewError);
}
// Legit usage of senderTimestamp when creating incoming message from received envelope // Legit usage of senderTimestamp when creating incoming message from received envelope
TSIncomingMessage *incomingMessage = TSIncomingMessage *incomingMessage =

@ -18,6 +18,77 @@ class OWSLinkPreviewTest: SSKBaseTestSwift {
super.tearDown() super.tearDown()
} }
func testBuildValidatedLinkPreview_TitleAndImage() {
let url = "https://www.youtube.com/watch?v=tP-Ipsat90c"
let body = "\(url)"
let previewBuilder = SSKProtoDataMessagePreview.builder(url: url)
previewBuilder.setTitle("Some Youtube Video")
let imageAttachmentBuilder = SSKProtoAttachmentPointer.builder(id: 1)
imageAttachmentBuilder.setKey(Randomness.generateRandomBytes(32))
imageAttachmentBuilder.setContentType(OWSMimeTypeImageJpeg)
previewBuilder.setImage(try! imageAttachmentBuilder.build())
let dataBuilder = SSKProtoDataMessage.builder()
dataBuilder.setPreview(try! previewBuilder.build())
self.readWrite { (transaction) in
XCTAssertNotNil(try! OWSLinkPreview.buildValidatedLinkPreview(dataMessage: try! dataBuilder.build(),
body: body,
transaction: transaction))
}
}
func testBuildValidatedLinkPreview_Title() {
let url = "https://www.youtube.com/watch?v=tP-Ipsat90c"
let body = "\(url)"
let previewBuilder = SSKProtoDataMessagePreview.builder(url: url)
previewBuilder.setTitle("Some Youtube Video")
let dataBuilder = SSKProtoDataMessage.builder()
dataBuilder.setPreview(try! previewBuilder.build())
self.readWrite { (transaction) in
XCTAssertNotNil(try! OWSLinkPreview.buildValidatedLinkPreview(dataMessage: try! dataBuilder.build(),
body: body,
transaction: transaction))
}
}
func testBuildValidatedLinkPreview_Image() {
let url = "https://www.youtube.com/watch?v=tP-Ipsat90c"
let body = "\(url)"
let previewBuilder = SSKProtoDataMessagePreview.builder(url: url)
let imageAttachmentBuilder = SSKProtoAttachmentPointer.builder(id: 1)
imageAttachmentBuilder.setKey(Randomness.generateRandomBytes(32))
imageAttachmentBuilder.setContentType(OWSMimeTypeImageJpeg)
previewBuilder.setImage(try! imageAttachmentBuilder.build())
let dataBuilder = SSKProtoDataMessage.builder()
dataBuilder.setPreview(try! previewBuilder.build())
self.readWrite { (transaction) in
XCTAssertNotNil(try! OWSLinkPreview.buildValidatedLinkPreview(dataMessage: try! dataBuilder.build(),
body: body,
transaction: transaction))
}
}
func testBuildValidatedLinkPreview_NoTitleOrImage() {
let url = "https://www.youtube.com/watch?v=tP-Ipsat90c"
let body = "\(url)"
let previewBuilder = SSKProtoDataMessagePreview.builder(url: url)
let dataBuilder = SSKProtoDataMessage.builder()
dataBuilder.setPreview(try! previewBuilder.build())
self.readWrite { (transaction) in
do {
_ = try OWSLinkPreview.buildValidatedLinkPreview(dataMessage: try! dataBuilder.build(),
body: body,
transaction: transaction)
XCTFail("Missing expected error.")
} catch {
// Do nothing.
}
}
}
func testIsValidLinkUrl() { func testIsValidLinkUrl() {
XCTAssertTrue(OWSLinkPreview.isValidLinkUrl("https://www.youtube.com/watch?v=tP-Ipsat90c")) XCTAssertTrue(OWSLinkPreview.isValidLinkUrl("https://www.youtube.com/watch?v=tP-Ipsat90c"))
XCTAssertTrue(OWSLinkPreview.isValidLinkUrl("https://youtube.com/watch?v=tP-Ipsat90c")) XCTAssertTrue(OWSLinkPreview.isValidLinkUrl("https://youtube.com/watch?v=tP-Ipsat90c"))

Loading…
Cancel
Save