Image content types.

pull/1/head
Matthew Chen 7 years ago
parent c7714b09ab
commit 1607aa7f57

@ -645,7 +645,7 @@ NS_ASSUME_NONNULL_BEGIN
NSString *_Nullable filePath = [strongSelf.attachmentStream filePath];
YYImage *_Nullable animatedImage = nil;
if (filePath && [NSData ows_isValidImageAtPath:filePath]) {
if (strongSelf.attachmentStream.isValidImage && filePath) {
animatedImage = [YYImage imageWithContentsOfFile:filePath];
}
return animatedImage;

@ -383,7 +383,7 @@ NS_ASSUME_NONNULL_BEGIN
dispatch_once(&onceToken, ^{
instance = [DebugUIMessagesAssetLoader
fakeAssetLoaderWithUrl:@"https://s3.amazonaws.com/ows-data/example_attachment_media/random-gif.gif"
mimeType:@"image/gif"];
mimeType:OWSMimeTypeImageGif];
});
return instance;
}
@ -395,7 +395,7 @@ NS_ASSUME_NONNULL_BEGIN
dispatch_once(&onceToken, ^{
instance =
[DebugUIMessagesAssetLoader fakeAssetLoaderWithUrl:@"https://i.giphy.com/media/LTw0F3GAdaao8/source.gif"
mimeType:@"image/gif"];
mimeType:OWSMimeTypeImageGif];
});
return instance;
}

@ -224,7 +224,7 @@ NS_ASSUME_NONNULL_BEGIN
[scrollView autoPinToSuperviewEdges];
if (self.isAnimated) {
if ([self.fileData ows_isValidImage]) {
if (self.attachmentStream.isValidImage) {
YYImage *animatedGif = [YYImage imageWithData:self.fileData];
YYAnimatedImageView *animatedView = [YYAnimatedImageView new];
animatedView.image = animatedGif;

@ -76,12 +76,12 @@
- (ConversationViewItem *)stillImageViewItem
{
return [self viewItemWithAttachmentMimetype:@"image/jpeg" filename:@"test-jpg.jpg"];
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageJpeg filename:@"test-jpg.jpg"];
}
- (ConversationViewItem *)animatedImageViewItem
{
return [self viewItemWithAttachmentMimetype:@"image/gif" filename:@"test-gif.gif"];
return [self viewItemWithAttachmentMimetype:OWSMimeTypeImageGif filename:@"test-gif.gif"];
}
- (ConversationViewItem *)videoViewItem

@ -2270,7 +2270,7 @@
"VERIFICATION_STATE_CHANGE_GENERIC" = "Verification state changed.";
/* Label for button or row which allows users to verify the safety number of another user. */
"VERIFY_PRIVACY" = "Show Safety Number";
"VERIFY_PRIVACY" = "View Safety Number";
/* Label for button or row which allows users to verify the safety numbers of multiple users. */
"VERIFY_PRIVACY_MULTIPLE" = "Review Safety Numbers";

@ -74,6 +74,10 @@ NS_ASSUME_NONNULL_BEGIN
// Non-nil for attachments which need "lazy backup restore."
- (nullable OWSBackupFragment *)lazyRestoreFragment;
#pragma mark - Image Validation
- (BOOL)isValidImage;
#pragma mark - Update With... Methods
// Marks attachment as needing "lazy backup restore."

@ -312,6 +312,25 @@ NS_ASSUME_NONNULL_BEGIN
return [MIMETypeUtil isAudio:self.contentType];
}
#pragma mark - Image Validation
- (BOOL)isValidImageWithData:(NSData *)data
{
OWSAssert(self.isImage || self.isAnimated);
OWSAssert(data);
return [data ows_isValidImageWithMimeType:self.contentType];
}
- (BOOL)isValidImage
{
OWSAssert(self.isImage || self.isAnimated);
return [NSData ows_isValidImageAtPath:self.filePath mimeType:self.contentType];
}
#pragma mark -
- (nullable UIImage *)image
{
if ([self isVideo]) {
@ -322,7 +341,7 @@ NS_ASSUME_NONNULL_BEGIN
return nil;
}
NSData *data = [NSData dataWithContentsOfURL:mediaUrl];
if (![data ows_isValidImage]) {
if (![self isValidImageWithData:data]) {
return nil;
}
return [UIImage imageWithData:data];
@ -348,7 +367,7 @@ NS_ASSUME_NONNULL_BEGIN
}
NSData *data = [NSData dataWithContentsOfURL:mediaUrl];
if (![data ows_isValidImage]) {
if (![self isValidImageWithData:data]) {
return nil;
}
@ -422,7 +441,7 @@ NS_ASSUME_NONNULL_BEGIN
UIImage *_Nullable result;
if (self.isImage || self.isAnimated) {
if (![NSData ows_isValidImageAtPath:self.filePath]) {
if (![self isValidImage]) {
DDLogWarn(@"%@ skipping thumbnail generation for invalid image at path: %@", self.logTag, self.filePath);
return;
}
@ -516,7 +535,7 @@ NS_ASSUME_NONNULL_BEGIN
if (!mediaUrl) {
return CGSizeZero;
}
if (![NSData ows_isValidImageAtPath:mediaUrl.path]) {
if (![self isValidImage]) {
return CGSizeZero;
}

@ -72,7 +72,7 @@ NS_ASSUME_NONNULL_BEGIN
// if ows_isValidImage is given a file path, it will
// avoid loading most of the data into memory, which
// is considerably more performant, so try to do that.
return [NSData ows_isValidImageAtPath:dataPath];
return [NSData ows_isValidImageAtPath:dataPath mimeType:self.mimeType];
}
NSData *data = [self data];
return [data ows_isValidImage];
@ -83,6 +83,14 @@ NS_ASSUME_NONNULL_BEGIN
_sourceFilename = sourceFilename.filterFilename;
}
// Returns the MIME type, if known.
- (nullable NSString *)mimeType
{
OWS_ABSTRACT_METHOD();
return nil;
}
@end
#pragma mark -
@ -222,6 +230,11 @@ NS_ASSUME_NONNULL_BEGIN
}
}
- (nullable NSString *)mimeType
{
return (self.fileExtension ? [MIMETypeUtil mimeTypeForFileExtension:self.fileExtension] : nil);
}
@end
#pragma mark -
@ -372,6 +385,12 @@ NS_ASSUME_NONNULL_BEGIN
}
}
- (nullable NSString *)mimeType
{
NSString *_Nullable fileExtension = self.filePath.pathExtension;
return (fileExtension ? [MIMETypeUtil mimeTypeForFileExtension:fileExtension] : nil);
}
@end
NS_ASSUME_NONNULL_END

@ -8,6 +8,11 @@ extern NSString *const OWSMimeTypeApplicationOctetStream;
extern NSString *const OWSMimeTypeApplicationZip;
extern NSString *const OWSMimeTypeImagePng;
extern NSString *const OWSMimeTypeImageJpeg;
extern NSString *const OWSMimeTypeImageGif;
extern NSString *const OWSMimeTypeImageTiff1;
extern NSString *const OWSMimeTypeImageTiff2;
extern NSString *const OWSMimeTypeImageBmp1;
extern NSString *const OWSMimeTypeImageBmp2;
extern NSString *const OWSMimeTypeOversizeTextMessage;
extern NSString *const OWSMimeTypeUnknownForTests;

@ -18,6 +18,11 @@ NS_ASSUME_NONNULL_BEGIN
NSString *const OWSMimeTypeApplicationOctetStream = @"application/octet-stream";
NSString *const OWSMimeTypeImagePng = @"image/png";
NSString *const OWSMimeTypeImageJpeg = @"image/jpeg";
NSString *const OWSMimeTypeImageGif = @"image/gif";
NSString *const OWSMimeTypeImageTiff1 = @"image/tiff";
NSString *const OWSMimeTypeImageTiff2 = @"image/x-tiff";
NSString *const OWSMimeTypeImageBmp1 = @"image/bmp";
NSString *const OWSMimeTypeImageBmp2 = @"image/x-windows-bmp";
NSString *const OWSMimeTypeOversizeTextMessage = @"text/x-signal-plain";
NSString *const OWSMimeTypeUnknownForTests = @"unknown/mimetype";
NSString *const OWSMimeTypeApplicationZip = @"application/zip";
@ -76,7 +81,7 @@ NSString *const kSyncMessageFileExtension = @"bin";
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
result = @{
@"image/jpeg" : @"jpeg",
OWSMimeTypeImageJpeg : @"jpeg",
@"image/pjpeg" : @"jpeg",
OWSMimeTypeImagePng : @"png",
@"image/tiff" : @"tif",
@ -93,7 +98,7 @@ NSString *const kSyncMessageFileExtension = @"bin";
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
result = @{
@"image/gif" : @"gif",
OWSMimeTypeImageGif : @"gif",
};
});
return result;
@ -183,7 +188,7 @@ NSString *const kSyncMessageFileExtension = @"bin";
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
result = @{
@"gif" : @"image/gif",
@"gif" : OWSMimeTypeImageGif,
};
});
return result;

@ -1,10 +1,14 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
@interface NSData (Image)
// If mimeType is non-nil, we ensure that the magic numbers agree with the
// mimeType.
+ (BOOL)ows_isValidImageAtPath:(NSString *)filePath;
+ (BOOL)ows_isValidImageAtPath:(NSString *)filePath mimeType:(nullable NSString *)mimeType;
- (BOOL)ows_isValidImage;
- (BOOL)ows_isValidImageWithMimeType:(nullable NSString *)mimeType;
@end

@ -1,7 +1,8 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "MIMETypeUtil.h"
#import "NSData+Image.h"
typedef NS_ENUM(NSInteger, ImageFormat) {
@ -16,6 +17,16 @@ typedef NS_ENUM(NSInteger, ImageFormat) {
@implementation NSData (Image)
+ (BOOL)ows_isValidImageAtPath:(NSString *)filePath
{
return [self ows_isValidImageAtPath:filePath mimeType:nil];
}
- (BOOL)ows_isValidImage
{
return [self ows_isValidImageWithMimeType:nil];
}
+ (BOOL)ows_isValidImageAtPath:(NSString *)filePath mimeType:(nullable NSString *)mimeType
{
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];
@ -23,16 +34,32 @@ typedef NS_ENUM(NSInteger, ImageFormat) {
DDLogError(@"%@ could not read image data: %@", self.logTag, error);
}
return [data ows_isValidImage];
return [data ows_isValidImageWithMimeType:mimeType];
}
- (BOOL)ows_isValidImage
- (BOOL)ows_isValidImageWithMimeType:(nullable NSString *)mimeType
{
// Don't trust the file extension; iOS (e.g. UIKit, Core Graphics) will happily
// load a .gif with a .png file extension.
//
// Instead, use the "magic numbers" in the file data to determine the image format.
ImageFormat imageFormat = [self ows_guessImageFormat];
switch (imageFormat) {
case ImageFormat_Unknown:
return NO;
case ImageFormat_Png:
return (mimeType == nil || [mimeType isEqualToString:OWSMimeTypeImagePng]);
case ImageFormat_Gif:
return (mimeType == nil || [mimeType isEqualToString:OWSMimeTypeImageGif]);
case ImageFormat_Tiff:
return (mimeType == nil || [mimeType isEqualToString:OWSMimeTypeImageTiff1] ||
[mimeType isEqualToString:OWSMimeTypeImageTiff2]);
case ImageFormat_Jpeg:
return (mimeType == nil || [mimeType isEqualToString:OWSMimeTypeImageJpeg]);
case ImageFormat_Bmp:
return (mimeType == nil || [mimeType isEqualToString:OWSMimeTypeImageBmp1] ||
[mimeType isEqualToString:OWSMimeTypeImageBmp2]);
}
if (imageFormat == ImageFormat_Gif) {
return [self ows_hasValidGifSize];
} else if (imageFormat == ImageFormat_Unknown) {

Loading…
Cancel
Save