2016-09-10 17:08:58 +00:00
# import < QuickLook / QuickLook . h >
2018-09-30 10:37:30 +00:00
# include < libtransmission / transmission . h >
2012-08-12 12:11:33 +00:00
# import "NSStringAdditions.h"
OSStatus GeneratePreviewForURL ( void * thisInterface , QLPreviewRequestRef preview , CFURLRef url , CFStringRef contentTypeUTI , CFDictionaryRef options ) ;
void CancelPreviewGeneration ( void * thisInterface , QLPreviewRequestRef preview ) ;
NSString * generateIconData ( NSString * fileExtension , NSUInteger width , NSMutableDictionary * allImgProps )
{
NSString * rawFilename = ! [ fileExtension isEqualToString : @ "" ] ? fileExtension : @ "blank_file_name_transmission" ;
NSString * iconFileName = [ NSString stringWithFormat : @ "%ldx%@.tiff" , width , rawFilename ] ; // we need to do this once per file extension , per size
2017-01-24 17:53:16 +00:00
2012-08-12 14:05:55 +00:00
if ( ! [ allImgProps objectForKey : iconFileName ] )
2012-08-12 12:11:33 +00:00
{
NSImage * icon = [ [ NSWorkspace sharedWorkspace ] iconForFileType : fileExtension ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
const NSRect iconFrame = NSMakeRect ( 0.0 , 0.0 , width , width ) ;
NSImage * renderedIcon = [ [ NSImage alloc ] initWithSize : iconFrame . size ] ;
[ renderedIcon lockFocus ] ;
[ icon drawInRect : iconFrame fromRect : NSZeroRect operation : NSCompositeCopy fraction : 1.0 ] ;
[ renderedIcon unlockFocus ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSData * iconData = [ renderedIcon TIFFRepresentation ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSDictionary * imgProps = @ {
( NSString * ) kQLPreviewPropertyMIMETypeKey : @ "image/png" ,
( NSString * ) kQLPreviewPropertyAttachmentDataKey : iconData } ;
[ allImgProps setObject : imgProps forKey : iconFileName ] ;
}
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
return [ @ "cid:" stringByAppendingString : iconFileName ] ;
}
OSStatus GeneratePreviewForURL ( void * thisInterface , QLPreviewRequestRef preview , CFURLRef url , CFStringRef contentTypeUTI , CFDictionaryRef options )
{
// Before proceeding make sure the user didn ' t cancel the request
if ( QLPreviewRequestIsCancelled ( preview ) )
return noErr ;
2017-01-24 17:53:16 +00:00
2012-09-06 01:15:31 +00:00
// we need this call to ensure NSApp is initialized ( not done automatically for plugins )
[ NSApplication sharedApplication ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
// try to parse the torrent file
tr_info inf ;
tr_ctor * ctor = tr_ctorNew ( NULL ) ;
2017-08-01 10:26:49 +00:00
tr_ctorSetMetainfoFromFile ( ctor , [ [ ( __bridge NSURL * ) url path ] UTF8String ] ) ;
2012-08-12 12:11:33 +00:00
const int err = tr_torrentParse ( ctor , & inf ) ;
tr_ctorFree ( ctor ) ;
if ( err )
return noErr ;
2017-01-24 17:53:16 +00:00
2012-09-03 18:37:18 +00:00
NSBundle * bundle = [ NSBundle bundleWithIdentifier : @ "org.m0k.transmission.QuickLookPlugin" ] ;
2017-01-24 17:53:16 +00:00
2012-09-03 18:37:18 +00:00
NSURL * styleURL = [ bundle URLForResource : @ "style" withExtension : @ "css" ] ;
2012-08-12 12:11:33 +00:00
NSString * styleContents = [ NSString stringWithContentsOfURL : styleURL encoding : NSUTF8StringEncoding error : NULL ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSMutableString * htmlString = [ NSMutableString string ] ;
[ htmlString appendFormat : @ "<html><style type=\" text / css \ ">%@</style><body>" , styleContents ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSMutableDictionary * allImgProps = [ NSMutableDictionary dictionary ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSString * name = [ NSString stringWithUTF8String : inf . name ] ;
2014-06-08 22:16:01 +00:00
NSString * fileTypeString = inf . isFolder ? NSFileTypeForHFSTypeCode ( kGenericFolderIcon ) : [ name pathExtension ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
const NSUInteger width = 32 ;
2012-08-12 20:14:26 +00:00
[ htmlString appendFormat : @ "<h2><img class=\" icon \ " src=\" % @ \ " width=\" % ld \ " height=\" % ld \ " />%@</h2>" , generateIconData ( fileTypeString , width , allImgProps ) , width , width , name ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSString * fileSizeString = [ NSString stringForFileSize : inf . totalSize ] ;
2014-06-08 22:16:01 +00:00
if ( inf . isFolder )
2012-08-12 12:11:33 +00:00
{
NSString * fileCountString ;
if ( inf . fileCount = = 1 )
2012-09-03 18:37:18 +00:00
fileCountString = NSLocalizedStringFromTableInBundle ( @ "1 file" , nil , bundle , "quicklook file count" ) ;
2012-08-12 12:11:33 +00:00
else
2012-09-03 18:37:18 +00:00
fileCountString = [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "%@ files" , nil , bundle , "quicklook file count" ) , [ NSString formattedUInteger : inf . fileCount ] ] ;
2012-08-12 12:11:33 +00:00
fileSizeString = [ NSString stringWithFormat : @ "%@, %@" , fileCountString , fileSizeString ] ;
}
[ htmlString appendFormat : @ "<p>%@</p>" , fileSizeString ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 14:05:55 +00:00
NSString * dateCreatedString = inf . dateCreated > 0 ? [ NSDateFormatter localizedStringFromDate : [ NSDate dateWithTimeIntervalSince1970 : inf . dateCreated ] dateStyle : NSDateFormatterLongStyle timeStyle : NSDateFormatterShortStyle ] : nil ;
NSString * creatorString = inf . creator ? [ NSString stringWithUTF8String : inf . creator ] : nil ;
if ( [ creatorString isEqualToString : @ "" ] ) creatorString = nil ;
NSString * creationString = nil ;
if ( dateCreatedString && creatorString )
2012-09-03 18:37:18 +00:00
creationString = [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "Created on %@ with %@" , nil , bundle , "quicklook creation info" ) , dateCreatedString , creatorString ] ;
2012-08-12 14:05:55 +00:00
else if ( dateCreatedString )
2012-09-03 18:37:18 +00:00
creationString = [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "Created on %@" , nil , bundle , "quicklook creation info" ) , dateCreatedString ] ;
2012-08-12 14:05:55 +00:00
else if ( creatorString )
2012-09-03 18:37:18 +00:00
creationString = [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "Created with %@" , nil , bundle , "quicklook creation info" ) , creatorString ] ;
2012-08-12 14:05:55 +00:00
if ( creationString )
[ htmlString appendFormat : @ "<p>%@</p>" , creationString ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
if ( inf . comment )
{
NSString * comment = [ NSString stringWithUTF8String : inf . comment ] ;
if ( ! [ comment isEqualToString : @ "" ] )
[ htmlString appendFormat : @ "<p>%@</p>" , comment ] ;
}
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
NSMutableArray * lists = [ NSMutableArray array ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
if ( inf . webseedCount > 0 )
{
2012-08-12 20:14:26 +00:00
NSMutableString * listSection = [ NSMutableString string ] ;
[ listSection appendString : @ "<table>" ] ;
2017-01-24 17:53:16 +00:00
2012-09-03 18:37:18 +00:00
NSString * headerTitleString = inf . webseedCount = = 1 ? NSLocalizedStringFromTableInBundle ( @ "1 Web Seed" , nil , bundle , "quicklook web seed header" ) : [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "%@ Web Seeds" , nil , bundle , "quicklook web seed header" ) , [ NSString formattedUInteger : inf . webseedCount ] ] ;
2012-08-12 20:14:26 +00:00
[ listSection appendFormat : @ "<tr><th>%@</th></tr>" , headerTitleString ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
for ( int i = 0 ; i < inf . webseedCount ; + + i )
2012-08-12 20:14:26 +00:00
[ listSection appendFormat : @ "<tr><td>%s<td></tr>" , inf . webseeds [ i ] ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
[ listSection appendString : @ "</table>" ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
[ lists addObject : listSection ] ;
2012-08-12 12:11:33 +00:00
}
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
if ( inf . trackerCount > 0 )
{
2012-08-12 20:14:26 +00:00
NSMutableString * listSection = [ NSMutableString string ] ;
[ listSection appendString : @ "<table>" ] ;
2017-01-24 17:53:16 +00:00
2012-09-03 18:37:18 +00:00
NSString * headerTitleString = inf . trackerCount = = 1 ? NSLocalizedStringFromTableInBundle ( @ "1 Tracker" , nil , bundle , "quicklook tracker header" ) : [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "%@ Trackers" , nil , bundle , "quicklook tracker header" ) , [ NSString formattedUInteger : inf . trackerCount ] ] ;
2012-08-12 20:14:26 +00:00
[ listSection appendFormat : @ "<tr><th>%@</th></tr>" , headerTitleString ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
# warning handle tiers ?
for ( int i = 0 ; i < inf . trackerCount ; + + i )
2012-08-12 20:14:26 +00:00
[ listSection appendFormat : @ "<tr><td>%s<td></tr>" , inf . trackers [ i ] . announce ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
[ listSection appendString : @ "</table>" ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
[ lists addObject : listSection ] ;
2012-08-12 12:11:33 +00:00
}
2017-01-24 17:53:16 +00:00
2014-06-08 22:16:01 +00:00
if ( inf . isFolder )
2012-08-12 12:11:33 +00:00
{
2012-08-12 20:14:26 +00:00
NSMutableString * listSection = [ NSMutableString string ] ;
[ listSection appendString : @ "<table>" ] ;
2017-01-24 17:53:16 +00:00
2012-09-03 18:37:18 +00:00
NSString * fileTitleString = inf . fileCount = = 1 ? NSLocalizedStringFromTableInBundle ( @ "1 File" , nil , bundle , "quicklook file header" ) : [ NSString stringWithFormat : NSLocalizedStringFromTableInBundle ( @ "%@ Files" , nil , bundle , "quicklook file header" ) , [ NSString formattedUInteger : inf . fileCount ] ] ;
2012-08-12 20:14:26 +00:00
[ listSection appendFormat : @ "<tr><th>%@</th></tr>" , fileTitleString ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
# warning display size ?
# warning display folders ?
for ( int i = 0 ; i < inf . fileCount ; + + i )
{
NSString * fullFilePath = [ NSString stringWithUTF8String : inf . files [ i ] . name ] ;
NSCAssert ( [ fullFilePath hasPrefix : [ name stringByAppendingString : @ "/" ] ] , @ "Expected file path %@ to begin with %@/" , fullFilePath , name ) ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSString * shortenedFilePath = [ fullFilePath substringFromIndex : [ name length ] + 1 ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
const NSUInteger width = 16 ;
2012-08-12 20:14:26 +00:00
[ listSection appendFormat : @ "<tr><td><img class=\" icon \ " src=\" % @ \ " width=\" % ld \ " height=\" % ld \ " />%@<td></tr>" , generateIconData ( [ shortenedFilePath pathExtension ] , width , allImgProps ) , width , width , shortenedFilePath ] ;
2012-08-12 12:11:33 +00:00
}
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
[ listSection appendString : @ "</table>" ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
[ lists addObject : listSection ] ;
2012-08-12 12:11:33 +00:00
}
2017-01-24 17:53:16 +00:00
2012-08-12 20:14:26 +00:00
if ( [ lists count ] > 0 )
2012-08-13 00:52:04 +00:00
[ htmlString appendFormat : @ "<hr/><br>%@" , [ lists componentsJoinedByString : @ "<br>" ] ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
[ htmlString appendString : @ "</body></html>" ] ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
tr_metainfoFree ( & inf ) ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
NSDictionary * props = @ { ( NSString * ) kQLPreviewPropertyTextEncodingNameKey : @ "UTF-8" ,
( NSString * ) kQLPreviewPropertyMIMETypeKey : @ "text/html" ,
( NSString * ) kQLPreviewPropertyAttachmentsKey : allImgProps } ;
2017-01-24 17:53:16 +00:00
2017-08-01 10:26:49 +00:00
QLPreviewRequestSetDataRepresentation ( preview , ( __bridge CFDataRef ) [ htmlString dataUsingEncoding : NSUTF8StringEncoding ] , kUTTypeHTML , ( __bridge CFDictionaryRef ) props ) ;
2017-01-24 17:53:16 +00:00
2012-08-12 12:11:33 +00:00
return noErr ;
}
void CancelPreviewGeneration ( void * thisInterface , QLPreviewRequestRef preview )
{
// Implement only if supported
}