1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-02 09:27:55 +01:00
Telegram/Telegraph/TGAudioDownloadActor.m
2016-02-25 01:03:51 +01:00

189 lines
6.6 KiB
Objective-C

/*
* This is the source code of Telegram for iOS v. 1.1
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Peter Iakovlev, 2013.
*/
#import "TGAudioDownloadActor.h"
#import "ActionStage.h"
#import "TL/TLMetaScheme.h"
#import "TGAudioMediaAttachment.h"
#import "TGStringUtils.h"
#import <CommonCrypto/CommonDigest.h>
@implementation TGAudioDownloadActor
+ (void)load {
[ASActor registerActorClass:self];
}
- (instancetype)initWithPath:(NSString *)path
{
self = [super initWithPath:path];
if (self != nil)
{
_actionHandle = [[ASHandle alloc] initWithDelegate:self releaseOnMainThread:false];
}
return self;
}
- (void)dealloc
{
[_actionHandle reset];
[ActionStageInstance() removeWatcher:self];
}
+ (NSString *)genericPath
{
return @"/tg/media/audio/@";
}
- (void)prepare:(NSDictionary *)options
{
[super prepare:options];
self.requestQueueName = @"documentDownload";
}
- (void)execute:(NSDictionary *)options
{
TGAudioMediaAttachment *audioAttachment = options[@"audioAttachment"];
if (audioAttachment != nil)
{
TLInputFileLocation *inputFileLocation = nil;
int datacenterId = 0;
int encryptedSize = audioAttachment.fileSize;
int decryptedSize = audioAttachment.fileSize;
NSDictionary *encryptionArgs = @{};
NSString *storeAudioPathDirectory = nil;
NSString *audioFilePath = nil;
if (audioAttachment.audioId != 0)
{
storeAudioPathDirectory = [TGAudioMediaAttachment localAudioFileDirectoryForRemoteAudioId:audioAttachment.audioId];
audioFilePath = [TGAudioMediaAttachment localAudioFilePathForRemoteAudioId:audioAttachment.audioId];
}
else
{
storeAudioPathDirectory = [TGAudioMediaAttachment localAudioFileDirectoryForLocalAudioId:audioAttachment.localAudioId];
audioFilePath = [TGAudioMediaAttachment localAudioFilePathForLocalAudioId:audioAttachment.localAudioId];
}
[[NSFileManager defaultManager] createDirectoryAtPath:storeAudioPathDirectory withIntermediateDirectories:true attributes:nil error:nil];
// NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:audioFilePath error:nil];
if (audioAttachment.audioUri.length != 0)
{
if ([audioAttachment.audioUri hasPrefix:@"mt-encrypted-file://"])
{
NSDictionary *args = [TGStringUtils argumentDictionaryInUrlString:[audioAttachment.audioUri substringFromIndex:@"mt-encrypted-file://?".length]];
NSData *key = [args[@"key"] dataByDecodingHexString];
if (key.length != 64)
TGLog(@"***** Invalid file key length");
else
{
NSData *encryptionKey = [key subdataWithRange:NSMakeRange(0, 32)];
NSData *encryptionIv = [key subdataWithRange:NSMakeRange(32, 32)];
unsigned char digest[CC_MD5_DIGEST_LENGTH];
CC_MD5(key.bytes, 32 + 32, digest);
int32_t digestHigh = 0;
int32_t digestLow = 0;
memcpy(&digestHigh, digest, 4);
memcpy(&digestLow, digest + 4, 4);
int32_t key_fingerprint = digestHigh ^ digestLow;
if (args[@"fingerprint"] != nil && [args[@"fingerprint"] intValue] != key_fingerprint)
TGLog(@"***** Invalid file key fingerprint");
else
{
TLInputFileLocation$inputEncryptedFileLocation *inputEncryptedLocation = [[TLInputFileLocation$inputEncryptedFileLocation alloc] init];
inputEncryptedLocation.n_id = [args[@"id"] longLongValue];
inputEncryptedLocation.access_hash = [args[@"accessHash"] longLongValue];
inputFileLocation = inputEncryptedLocation;
datacenterId = [args[@"dc"] intValue];
encryptedSize = [args[@"size"] intValue];
decryptedSize = [args[@"decryptedSize"] intValue];
encryptionArgs = @{@"key": encryptionKey, @"iv": encryptionIv};
}
}
}
}
else
{
TLInputFileLocation$inputDocumentFileLocation *inputDocumentLocation = [[TLInputFileLocation$inputDocumentFileLocation alloc] init];
inputDocumentLocation.n_id = audioAttachment.audioId;
inputDocumentLocation.access_hash = audioAttachment.accessHash;
inputFileLocation = inputDocumentLocation;
datacenterId = audioAttachment.datacenterId;
}
if (inputFileLocation != nil)
{
[ActionStageInstance() requestActor:[[NSString alloc] initWithFormat:@"/tg/multipart-file/(audio:%" PRId64 ":%d:%@)", audioAttachment.audioId, audioAttachment.datacenterId, audioAttachment.audioUri.length != 0 ? audioAttachment.audioUri : @""] options:@{
@"fileLocation": inputFileLocation,
@"encryptedSize": @(encryptedSize),
@"decryptedSize": @(decryptedSize),
@"storeFilePath": audioFilePath,
@"datacenterId": @(datacenterId),
@"encryptionArgs": encryptionArgs
} watcher:self];
}
else
[ActionStageInstance() actionFailed:self.path reason:-1];
}
else
{
[ActionStageInstance() actionFailed:self.path reason:-1];
}
}
- (void)cancel
{
[ActionStageInstance() removeWatcher:self];
[super cancel];
}
- (void)actorMessageReceived:(NSString *)path messageType:(NSString *)messageType message:(id)message
{
if ([path hasPrefix:@"/tg/multipart-file/"])
{
if ([messageType isEqualToString:@"progress"])
{
[ActionStageInstance() dispatchMessageToWatchers:self.path messageType:messageType message:message];
}
}
}
- (void)actorCompleted:(int)status path:(NSString *)path result:(id)__unused result
{
if ([path hasPrefix:@"/tg/multipart-file/"])
{
if (status == ASStatusSuccess)
{
[ActionStageInstance() actionCompleted:self.path result:nil];
}
else
{
[ActionStageInstance() actionFailed:self.path reason:-1];
}
}
}
@end