Repository: Airmail/AirmailPlugIn-Framework
Branch: master
Commit: f2f8458ac0fa
Files: 145
Total size: 347.7 KB
Directory structure:
gitextract_zaxo75me/
├── .gitignore
├── .gitmodules
├── AMPCrypto/
│ ├── AMPCrypto/
│ │ ├── AMPCrypto-Info.plist
│ │ ├── AMPCrypto-Prefix.pch
│ │ ├── AMPCrypto.h
│ │ ├── AMPCrypto.m
│ │ ├── AMPCryptoView.h
│ │ ├── AMPCryptoView.m
│ │ ├── NSData+AESCrypt.h
│ │ ├── NSData+AESCrypt.m
│ │ ├── NSData+Base64.h
│ │ ├── NSData+Base64.m
│ │ ├── NSString+AESCrypt.h
│ │ ├── NSString+AESCrypt.m
│ │ ├── SSKeychain.h
│ │ ├── SSKeychain.m
│ │ ├── Unlocked.psd
│ │ ├── en.lproj/
│ │ │ └── InfoPlist.strings
│ │ └── locked.psd
│ └── AMPCrypto.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ └── contents.xcworkspacedata
├── AMPCustomTemplates/
│ ├── AMPCustomTemplate.xcodeproj/
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── CssComposer/
│ ├── AMPCssComposerView.h
│ ├── AMPCssComposerView.m
│ ├── AMPCustomTemplate-Info.plist
│ ├── AMPCustomTemplate-Prefix.pch
│ ├── AMPCustomTemplate.h
│ ├── AMPCustomTemplate.m
│ ├── Taxi.css
│ ├── Yellow.css
│ ├── base1.css
│ ├── base2.css
│ ├── base3.css
│ ├── base4.css
│ ├── en.lproj/
│ │ └── InfoPlist.strings
│ └── helvetica.css
├── AMPFramework.xcworkspace/
│ └── contents.xcworkspacedata
├── AMPGpg/
│ ├── AMPGpg/
│ │ ├── AMPGpg-Info.plist
│ │ ├── AMPGpg-Prefix.pch
│ │ ├── AMPGpg.h
│ │ ├── AMPGpg.m
│ │ ├── AMPGpgBodyView.h
│ │ ├── AMPGpgBodyView.m
│ │ ├── AMPGpgButton.h
│ │ ├── AMPGpgButton.m
│ │ ├── AMPGpgEncryption.h
│ │ ├── AMPGpgEncryption.m
│ │ ├── AMPGpgView.h
│ │ ├── AMPGpgView.m
│ │ ├── en.lproj/
│ │ │ └── InfoPlist.strings
│ │ ├── g_active.psd
│ │ ├── g_inactive.psd
│ │ ├── g_locked.psd
│ │ ├── g_unlocked.psd
│ │ ├── gpg_active.psd
│ │ ├── gpg_bad.psd
│ │ ├── gpg_locked.psd
│ │ ├── gpg_unlocked.psd
│ │ ├── pluginsGPG.psd
│ │ └── s_active.psd
│ └── AMPGpg.xcodeproj/
│ └── project.pbxproj
├── AMPMessageStyle/
│ ├── AMPMessageStyle.xcodeproj/
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── AirmailCss/
│ ├── AMPMessageStyle-Info.plist
│ ├── AMPMessageStyle-Prefix.pch
│ ├── AMPMessageStyle.h
│ ├── AMPMessageStyle.m
│ ├── AMPMessageStyleView.h
│ ├── AMPMessageStyleView.m
│ ├── AirmailCss.h
│ ├── AirmailCss.m
│ ├── Taxi.css
│ ├── Yellow.css
│ ├── base1.css
│ ├── base2.css
│ ├── base3.css
│ ├── base4.css
│ ├── en.lproj/
│ │ └── InfoPlist.strings
│ └── es-419.lproj/
│ └── InfoPlist.strings
├── AMPNotify/
│ ├── AMPSimpleNotifier.xcodeproj/
│ │ ├── project.pbxproj
│ │ └── project.xcworkspace/
│ │ └── contents.xcworkspacedata
│ └── Notify/
│ ├── AMPNotifyWindow.h
│ ├── AMPNotifyWindow.m
│ ├── AMPNotifyWindowController.h
│ ├── AMPNotifyWindowController.m
│ ├── AMPNotifyWindowView.h
│ ├── AMPNotifyWindowView.m
│ ├── AMPSimpleNotifier-Info.plist
│ ├── AMPSimpleNotifier-Prefix.pch
│ ├── AMPSimpleNotifier.h
│ ├── AMPSimpleNotifier.m
│ ├── AMPSimpleNotifierView.h
│ ├── AMPSimpleNotifierView.m
│ ├── en.lproj/
│ │ └── InfoPlist.strings
│ └── es-419.lproj/
│ └── InfoPlist.strings
├── AMPTranslate/
│ ├── AMPTranslate-Info.plist
│ ├── AMPTranslate-Prefix.pch
│ ├── AMPTranslate.h
│ ├── AMPTranslate.m
│ ├── AMPTranslateView.h
│ ├── AMPTranslateView.m
│ ├── GTMDefines.h
│ ├── GTMNSString+HTML.h
│ ├── GTMNSString+HTML.m
│ ├── NSString+HTML.h
│ ├── NSString+HTML.m
│ └── en.lproj/
│ └── InfoPlist.strings
├── AMPluginFramework.framework/
│ └── Versions/
│ └── A/
│ ├── AMPluginFramework
│ ├── Headers/
│ │ ├── AMPAccount.h
│ │ ├── AMPAddress.h
│ │ ├── AMPAlias.h
│ │ ├── AMPAttachment.h
│ │ ├── AMPCallBack.h
│ │ ├── AMPComposerInfo.h
│ │ ├── AMPFolder.h
│ │ ├── AMPGroup.h
│ │ ├── AMPMCOAbstractMessage.h
│ │ ├── AMPMCOAbstractMessagePart.h
│ │ ├── AMPMCOAbstractMultipart.h
│ │ ├── AMPMCOAbstractPart.h
│ │ ├── AMPMCOAddress.h
│ │ ├── AMPMCOAttachment.h
│ │ ├── AMPMCOMessageBuilder.h
│ │ ├── AMPMCOMessageHeader.h
│ │ ├── AMPMCOMessageParser.h
│ │ ├── AMPMCOMessagePart.h
│ │ ├── AMPMCOMultiPart.h
│ │ ├── AMPMenuAction.h
│ │ ├── AMPMessage.h
│ │ ├── AMPObject.h
│ │ ├── AMPProvider.h
│ │ ├── AMPSendResult.h
│ │ ├── AMPSignature.h
│ │ ├── AMPSignatureVerify.h
│ │ ├── AMPUidFlag.h
│ │ ├── AMPView.h
│ │ ├── AMPlugin.h
│ │ ├── AMPluginFramework.h
│ │ ├── NSData+AMPBase64.h
│ │ └── NSScanner+Utility.h
│ └── Resources/
│ ├── Info.plist
│ └── en.lproj/
│ └── InfoPlist.strings
├── LICENSE
└── README.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Xcode
.DS_Store
*/build/*
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
profile
*.moved-aside
DerivedData
.idea/
*.hmap
*.xccheckout
#CocoaPods
Pods
================================================
FILE: .gitmodules
================================================
[submodule "AMPGpg/Dependencies/Libmacgpg"]
path = AMPGpg/Dependencies/Libmacgpg
url = https://github.com/GPGTools/Libmacgpg.git
[submodule "AMPGpg/Dependencies/Libmacgpg/Dependencies/GPGTools_Core"]
path = AMPGpg/Dependencies/Libmacgpg/Dependencies/GPGTools_Core
url = https://github.com/GPGTools/GPGTools_Core.git
================================================
FILE: AMPCrypto/AMPCrypto/AMPCrypto-Info.plist
================================================
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
it.bloop.airmail.plugin.${PRODUCT_NAME:rfc1034identifier}
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2014 bloop. All rights reserved.
NSPrincipalClass
AMPCrypto
================================================
FILE: AMPCrypto/AMPCrypto/AMPCrypto-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import
#endif
================================================
FILE: AMPCrypto/AMPCrypto/AMPCrypto.h
================================================
//
// AMPCrypto.h
// AMPCrypto
//
// Created by Gio on 11/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import
@interface AMPCrypto : AMPlugin
{
BOOL encrypt;
}
@property (strong) NSString *password, *mail;
- (BOOL) savePswd:(NSString*)pswd;
- (void) saveMail:(NSString*)mailIn;
@end
================================================
FILE: AMPCrypto/AMPCrypto/AMPCrypto.m
================================================
//
// AMPCrypto.m
// AMPCrypto
//
// Created by Gio on 11/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import "AMPCrypto.h"
#import "AMPCryptoView.h"
#import "SSKeychain.h"
#import "NSString+AESCrypt.h"
#import "NSData+Base64.h"
@implementation AMPCrypto
NSString *myCryptoCtype = @"Content-Type: myCrypto";
NSString *myCryptoBoundary = @"5347b703_327b23c6_6e65_crypto";
const NSString *amp_crypto_option = @"amp_crypto_option";
- (id)init
{
self = [super init];
if (self)
{
}
return self;
}
- (NSString*) cryptoCtype
{
return [NSString stringWithFormat:@"%@; %@\r\nContent-Transfer-Encoding: base64",myCryptoCtype,myCryptoBoundary];
}
- (BOOL) Load
{
if(![super Load])
return NO;
self.password = [self loadPswd];
self.mail = [self savedMail];
return YES;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (void) Reload
{
return [self.myView ReloadView];
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPCryptoView alloc] initWithFrame:NSZeroRect plugin:self];
return self.myView;
}
- (NSString*) nametext
{
return @"AMPlugin Crypto SDK Sample";
}
- (NSString*) description
{
return self.nametext;
}
- (NSString*) descriptiontext
{
return @"This plugin show how to implement an encryption system";
}
- (NSString*) authortext
{
return @"Airmail SDK Sample";
}
- (NSString*) supportlink
{
return @"http://airmail.zendesk.com/entries/46555427-AMPlug-Translate-SDK-Sample";
}
- (NSImage*) icon
{
return [NSImage imageNamed:@"iconx"];
}
#pragma mark - preferences
- (NSString*) savedMail
{
return [self.preferences objectForKey:amp_crypto_option];
}
- (void) saveMail:(NSString*)mailIn
{
self.mail = mailIn;
[self.preferences removeObjectForKey:amp_crypto_option];
[self.preferences setObject:mailIn forKey:amp_crypto_option];
[self SavePreferences];
}
#pragma mark - actions
- (void) BtnClicked:(id)sender
{
NSButton *btn = (NSButton*)sender;
encrypt = NO;
if(btn.state == NSOnState)
encrypt = YES;
NSImage *currentImage = btn.image;
[btn setImage:btn.alternateImage];
[btn setAlternateImage:currentImage];
NSLog(@"BtnClicked %d",encrypt);
}
#pragma mark - pswd
- (NSString*) loadPswd
{
return [SSKeychain passwordForService:@"AMPCrypto" account:@"MyAccount"];
}
- (BOOL) savePswd:(NSString*)pswd
{
if(pswd)
{
if([SSKeychain setPassword:pswd forService:@"AMPCrypto" account:@"MyAccount"])
{
self.password = pswd;
return YES;
}
}
return NO;
}
#pragma mark - crypto_decrypto
//This is an encryption fast sample the methods used are not reliable
- (NSString*) Encrypt:(NSString*)rfc
{
//Split Rfc to divide the body from the headers
NSArray *arr = [self ParseRfc:rfc];
NSString *header = arr[0];
NSString *body = arr[1];
NSString *cType = arr[2];
header = [header stringByReplacingOccurrencesOfString:cType withString:@""]; //remove old Content-Type
header = [header stringByAppendingFormat:@"%@",self.cryptoCtype]; //add a new one Content-Type for test purpose
body = [cType stringByAppendingString:body]; //add the old Content-Type to the start of the body
NSString* finalBoundary = [NSString stringWithFormat:@"\r\n--%@--\r\n",myCryptoBoundary];
NSData *data = [body dataUsingEncoding:NSUTF8StringEncoding];
NSString *encryptedBody = [[data AES256EncryptWithKey:self.password] base64Encoding];
encryptedBody = [encryptedBody stringByAppendingString:finalBoundary];
NSString *ret = [NSString stringWithFormat:@"%@\r\n\r\n%@",header,encryptedBody];
return ret;
}
- (NSString*) Decrypt:(NSString*)rfc message:(AMPMessage*)message
{
NSArray *arr = [self ParseRfc:rfc];
NSString *header = arr[0];
NSString *body = arr[1];
//NSString *cType = arr[2];
header = [header stringByReplacingOccurrencesOfString:self.cryptoCtype withString:@""]; //remove crypto Content-Type
NSString* finalBoundary = [NSString stringWithFormat:@"\r\n--%@--\r\n",myCryptoBoundary];
body = [body stringByReplacingOccurrencesOfString:finalBoundary withString:@""]; //remove final boundary Content-Type
NSData *decodedData = [[NSData dataWithBase64EncodedString:body] AES256DecryptWithKey:self.password];
NSString *decryptedBody = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSString *ret = [NSString stringWithFormat:@"%@%@",header,decryptedBody];
return ret;
}
#pragma mark - calls
//Composer
//IS ALL TIME CALLED IN A BACKGORUND THREAD
- (NSNumber*) ampPileChangedRecipients:(AMPComposerInfo *)info
{
NSLog(@"ampPileChangedRecipients");
NSButton *composerBtn = [info composerBtn:self];
if(!composerBtn)
[self LogError:@"No Button for the plugin"];
//recipients are changed we need to check if there is a mail that cparmits encryption
NSLog(@"From: %@",info.localMessage.from.mail);
NSMutableArray *arr = [NSMutableArray array];
NSLog(@"To:");
[arr addObjectsFromArray:[self GetMails:info.localMessage.to]];
NSLog(@"Cc:");
[arr addObjectsFromArray:[self GetMails:info.localMessage.cc]];
NSLog(@"Bcc:");
[arr addObjectsFromArray:[self GetMails:info.localMessage.bcc]];
for(NSString *mail in arr)
{
if([mail.lowercaseString isEqualToString:self.mail])
{
dispatch_async(dispatch_get_main_queue(), ^{
[composerBtn setState:NSOnState];
[composerBtn setEnabled:YES];
});
return @(YES);
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[composerBtn setState:NSOffState];
[composerBtn setEnabled:NO];
encrypt = NO;
});
return @(NO);
}
//GIVES AM A BUTTON IN THE COMPOSER WINDOW
- (NSArray*) ampPileComposerView:(AMPComposerInfo *)info
{
//Return a new composer btn for new created the composer
NSButton *composerBtn = [[NSButton alloc] initWithFrame:NSMakeRect(0, 0, 20, 20)]; //it will be rendered with the size 20,20
[composerBtn setTitle:@"En"];
[composerBtn setTarget:self];
[composerBtn setAction:@selector(BtnClicked:)];
[composerBtn setEnabled:NO];
[composerBtn setState:NSOffState];
[composerBtn setBordered:NO];
[composerBtn setImage:[NSImage imageNamed:@"locked"]];
[composerBtn setAlternateImage:[NSImage imageNamed:@"unlocked"]];
[composerBtn setButtonType:NSToggleButton];
[[composerBtn cell] setRepresentedObject:self];
return composerBtn;
}
//USED BY AM TO CHECK IF THE RFC IS ENCRYPTED
- (NSNumber*) ampPileIsEncrypted:(AMPMCOMessageParser*)parser
{
// //Is encrypted?
// if([rfc rangeOfString:myCryptoCtype].location != NSNotFound)
// return @(YES);
return @(NO);
}
//USED BY AM TO DECRYPT BEFORE RENDERING
- (NSData*) ampStackDecrypt:(AMPMessage*)message
{
return nil; //[self Decrypt:message];
}
//USED BY AM TO CHANGETHE RFC BEFORE SENDING
- (AMPSendResult*) ampStackSendRfc:(NSString*)rfc composer:(AMPComposerInfo*)info
{
if(encrypt)
return [self Encrypt:rfc];
return rfc;
}
#pragma mark - utilities
-(NSArray*) GetMails:(NSArray*)arr
{
NSMutableArray *ret = [NSMutableArray array];
for(id obj in arr)
{
if([obj isKindOfClass:[AMPAddress class]])
{
AMPAddress *addr = (AMPAddress*)obj;
if(addr.mail)
{
NSLog(@"%@",addr.mail);
[ret addObject:addr.mail];
}
}
else if([obj isKindOfClass:[AMPGroup class]])
{
AMPGroup *group = (AMPGroup*)obj;
for(AMPAddress *addr in group.addresses)
{
if(addr.mail)
{
NSLog(@"Group %@ %@",group.name, addr.mail);
[ret addObject:addr.mail];
}
}
}
}
return ret;
}
-(NSArray*) ParseRfc:(NSString*)rfc
{
NSMutableArray *ret = [NSMutableArray array];
//Split Rfc to divide the body from the headers
NSScanner *scanner = [NSScanner scannerWithString:rfc];
NSString *header = nil;
[scanner scanUpToString:@"\r\n\r\n" intoString:&header]; //split body from headers
if(!header)
return nil;
[ret addObject:header];
NSString *body = [rfc substringFromIndex:scanner.scanLocation];
if(!body)
return nil;
[ret addObject:body];
//Search for Content-Type
//Content-Type: multipart/alternative; boundary="5347b703_327b23c6_6e65"
NSString *contentType = nil;
NSScanner *scanner2 = [NSScanner scannerWithString:header];
[scanner2 scanUpToString:@"\r\nContent-Type:" intoString:nil];
[scanner2 scanUpToString:@"\r\n" intoString:&contentType]; //scan till the boundary
if(!contentType)
return nil;
[ret addObject:contentType];
return ret;
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/AMPCryptoView.h
================================================
//
// AMPCryptoView.h
// AMPCrypto
//
// Created by Gio on 11/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import
@interface AMPCryptoView : AMPView
{
NSSecureTextField *secureField;
NSTextField *mailField;
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/AMPCryptoView.m
================================================
//
// AMPCryptoView.m
// AMPCrypto
//
// Created by Gio on 11/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import "AMPCryptoView.h"
#import "AMPCrypto.h"
#import "SSKeychain.h"
@implementation AMPCryptoView
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin *)pluginIn
{
self = [super initWithFrame:frame plugin:pluginIn];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(x+3, y, 100, 20)];
[textField setStringValue:NSLocalizedString(@"Password:",@"Password:")];
[textField setBezeled:NO];
[textField setDrawsBackground:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont systemFontOfSize:13]];
[[textField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[textField setAlignment: NSRightTextAlignment];
[self addSubview:textField];
secureField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(x+170, y, 150, 20)];
[secureField setBezeled:NO];
[secureField setDrawsBackground:YES];
[secureField setEditable:YES];
[secureField setSelectable:YES];
[secureField setFont:[NSFont systemFontOfSize:13]];
[[secureField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[self addSubview:secureField];
x = 20;
y += 30;
NSTextField *textField2 = [[NSTextField alloc] initWithFrame:NSMakeRect(x+3, y, 100, 20)];
[textField2 setStringValue:NSLocalizedString(@"Email:",@"Email:")];
[textField2 setBezeled:NO];
[textField2 setDrawsBackground:NO];
[textField2 setEditable:NO];
[textField2 setSelectable:NO];
[textField2 setFont:[NSFont systemFontOfSize:13]];
[[textField2 cell] setBackgroundStyle:NSBackgroundStyleRaised];
[textField2 setAlignment: NSRightTextAlignment];
[self addSubview:textField2];
mailField = [[NSTextField alloc] initWithFrame:NSMakeRect(x+170, y, 150, 20)];
[mailField setBezeled:NO];
[mailField setDrawsBackground:YES];
[mailField setEditable:YES];
[mailField setSelectable:YES];
[mailField setFont:[NSFont systemFontOfSize:13]];
[[mailField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[self addSubview:mailField];
NSButton *btn = [[NSButton alloc] initWithFrame:NSMakeRect(x+170, y+60, 200, 30)];
[btn setTitle:@"Save"];
[btn setTarget:self];
[btn setAction:@selector(Save:)];
[self addSubview:btn];
[self LoadView];
}
return self;
}
- (AMPCrypto*) myPlugin
{
return (AMPCrypto*)self.plugin;
}
- (void) ReloadView
{
dispatch_async(dispatch_get_main_queue(), ^{
[self LoadView];
});
}
- (void) LoadView
{
}
- (void) RenderView
{
if(secureField.stringValue.length == 0 && self.myPlugin.password)
[secureField setStringValue:self.myPlugin.password];
if(mailField.stringValue.length == 0 && self.myPlugin.mail)
[mailField setStringValue:self.myPlugin.mail];
// [[secureField currentEditor] setSelectedRange:NSMakeRange([[secureField stringValue] length], 0)];
}
-(void) Save:(id)sender
{
[self.myPlugin saveMail:mailField.stringValue];
if(![self.myPlugin savePswd:secureField.stringValue])
{
NSAlert *alert = [[NSAlert alloc] init];
[alert addButtonWithTitle:@"OK"];
[alert setMessageText:@"Save Password"];
[alert setInformativeText:@"Cannot save the password"];
[alert setAlertStyle:NSWarningAlertStyle];
[alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:nil];
}
}
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/NSData+AESCrypt.h
================================================
//
// NSData+AESCrypt.h
//
// AES Encrypt/Decrypt
// Created by Jim Dovey and 'Jean'
// See http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html
//
// BASE64 Encoding/Decoding
// Copyright (c) 2001 Kyle Hammond. All rights reserved.
// Original development by Dave Winer.
//
// Put together by Michael Sedlaczek, Gone Coding on 2011-02-22
//
#import
@interface NSData (AESCrypt)
- (NSData *)AES256EncryptWithKey:(NSString *)key;
- (NSData *)AES256DecryptWithKey:(NSString *)key;
+ (NSData *)dataWithBase64EncodedString:(NSString *)string;
- (id)initWithBase64EncodedString:(NSString *)string;
- (NSString *)base64Encoding;
- (NSString *)base64EncodingWithLineLength:(NSUInteger)lineLength;
- (BOOL)hasPrefixBytes:(const void *)prefix length:(NSUInteger)length;
- (BOOL)hasSuffixBytes:(const void *)suffix length:(NSUInteger)length;
@end
================================================
FILE: AMPCrypto/AMPCrypto/NSData+AESCrypt.m
================================================
//
// NSData+AESCrypt.m
//
// AES Encrypt/Decrypt
// Created by Jim Dovey and 'Jean'
// See http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html
//
// BASE64 Encoding/Decoding
// Copyright (c) 2001 Kyle Hammond. All rights reserved.
// Original development by Dave Winer.
//
// Put together by Michael Sedlaczek, Gone Coding on 2011-02-22
//
#import "NSData+AESCrypt.h"
#import
static char encodingTable[64] =
{
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
};
@implementation NSData (AESCrypt)
- (NSData *)AES256EncryptWithKey:(NSString *)key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
free( buffer ); //free the buffer
return nil;
}
- (NSData *)AES256DecryptWithKey:(NSString *)key
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
// fetch key data
[key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
//See the doc: For block ciphers, the output size will always be less than or
//equal to the input size plus the size of one block.
//That's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc( bufferSize );
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES256,
NULL /* initialization vector (optional) */,
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted );
if( cryptStatus == kCCSuccess )
{
//the returned NSData takes ownership of the buffer and will free it on deallocation
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free( buffer ); //free the buffer
return nil;
}
#pragma mark -
+ (NSData *)dataWithBase64EncodedString:(NSString *)string
{
return [[[NSData allocWithZone:nil] initWithBase64EncodedString:string] autorelease];
}
- (id)initWithBase64EncodedString:(NSString *)string
{
NSMutableData *mutableData = nil;
if( string )
{
unsigned long ixtext = 0;
unsigned long lentext = 0;
unsigned char ch = 0;
unsigned char inbuf[4], outbuf[3];
short i = 0, ixinbuf = 0;
BOOL flignore = NO;
BOOL flendtext = NO;
NSData *base64Data = nil;
const unsigned char *base64Bytes = nil;
// Convert the string to ASCII data.
base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];
base64Bytes = [base64Data bytes];
mutableData = [NSMutableData dataWithCapacity:base64Data.length];
lentext = base64Data.length;
while( YES )
{
if( ixtext >= lentext ) break;
ch = base64Bytes[ixtext++];
flignore = NO;
if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A';
else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26;
else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52;
else if( ch == '+' ) ch = 62;
else if( ch == '=' ) flendtext = YES;
else if( ch == '/' ) ch = 63;
else flignore = YES;
if( ! flignore )
{
short ctcharsinbuf = 3;
BOOL flbreak = NO;
if( flendtext )
{
if( ! ixinbuf ) break;
if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;
else ctcharsinbuf = 2;
ixinbuf = 3;
flbreak = YES;
}
inbuf [ixinbuf++] = ch;
if( ixinbuf == 4 )
{
ixinbuf = 0;
outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 );
outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 );
outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F );
for( i = 0; i < ctcharsinbuf; i++ )
[mutableData appendBytes:&outbuf[i] length:1];
}
if( flbreak ) break;
}
}
}
self = [self initWithData:mutableData];
return self;
}
#pragma mark -
- (NSString *)base64Encoding
{
return [self base64EncodingWithLineLength:0];
}
- (NSString *)base64EncodingWithLineLength:(NSUInteger)lineLength
{
const unsigned char *bytes = [self bytes];
NSMutableString *result = [NSMutableString stringWithCapacity:self.length];
unsigned long ixtext = 0;
unsigned long lentext = self.length;
long ctremaining = 0;
unsigned char inbuf[3], outbuf[4];
unsigned short i = 0;
unsigned short charsonline = 0, ctcopy = 0;
unsigned long ix = 0;
while( YES )
{
ctremaining = lentext - ixtext;
if( ctremaining <= 0 ) break;
for( i = 0; i < 3; i++ )
{
ix = ixtext + i;
if( ix < lentext ) inbuf[i] = bytes[ix];
else inbuf [i] = 0;
}
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
outbuf [3] = inbuf [2] & 0x3F;
ctcopy = 4;
switch( ctremaining )
{
case 1:
ctcopy = 2;
break;
case 2:
ctcopy = 3;
break;
}
for( i = 0; i < ctcopy; i++ )
[result appendFormat:@"%c", encodingTable[outbuf[i]]];
for( i = ctcopy; i < 4; i++ )
[result appendString:@"="];
ixtext += 3;
charsonline += 4;
if( lineLength > 0 )
{
if( charsonline >= lineLength )
{
charsonline = 0;
[result appendString:@"\n"];
}
}
}
return [NSString stringWithString:result];
}
#pragma mark -
- (BOOL)hasPrefixBytes:(const void *)prefix length:(NSUInteger)length
{
if( ! prefix || ! length || self.length < length ) return NO;
return ( memcmp( [self bytes], prefix, length ) == 0 );
}
- (BOOL)hasSuffixBytes:(const void *)suffix length:(NSUInteger)length
{
if( ! suffix || ! length || self.length < length ) return NO;
return ( memcmp( ((const char *)[self bytes] + (self.length - length)), suffix, length ) == 0 );
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/NSData+Base64.h
================================================
//
// NSData+Base64.h
// base64
//
// Created by Matt Gallagher on 2009/06/03.
// Copyright 2009 Matt Gallagher. All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software. Permission is granted to anyone to
// use this software for any purpose, including commercial applications, and to
// alter it and redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source
// distribution.
//
#import
void *NewBase64Decode(
const char *inputBuffer,
size_t length,
size_t *outputLength);
char *NewBase64Encode(
const void *inputBuffer,
size_t length,
bool separateLines,
size_t *outputLength);
@interface NSData (Base64)
+ (NSData *)dataFromBase64String:(NSString *)aString;
- (NSString *)base64EncodedString;
@end
================================================
FILE: AMPCrypto/AMPCrypto/NSData+Base64.m
================================================
//
// NSData+Base64.m
// base64
//
// Created by Matt Gallagher on 2009/06/03.
// Copyright 2009 Matt Gallagher. All rights reserved.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software. Permission is granted to anyone to
// use this software for any purpose, including commercial applications, and to
// alter it and redistribute it freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source
// distribution.
//
#import "NSData+Base64.h"
//
// Mapping from 6 bit pattern to ASCII character.
//
static unsigned char base64EncodeLookup[65] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//
// Definition for "masked-out" areas of the base64DecodeLookup mapping
//
#define xx 65
//
// Mapping from ASCII character to 6 bit pattern.
//
static unsigned char base64DecodeLookup[256] =
{
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx,
xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
};
//
// Fundamental sizes of the binary and base64 encode/decode units in bytes
//
#define BINARY_UNIT_SIZE 3
#define BASE64_UNIT_SIZE 4
//
// NewBase64Decode
//
// Decodes the base64 ASCII string in the inputBuffer to a newly malloced
// output buffer.
//
// inputBuffer - the source ASCII string for the decode
// length - the length of the string or -1 (to specify strlen should be used)
// outputLength - if not-NULL, on output will contain the decoded length
//
// returns the decoded buffer. Must be free'd by caller. Length is given by
// outputLength.
//
void *NewBase64Decode(
const char *inputBuffer,
size_t length,
size_t *outputLength)
{
if (length == -1)
{
length = strlen(inputBuffer);
}
size_t outputBufferSize =
((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;
unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);
size_t i = 0;
size_t j = 0;
while (i < length)
{
//
// Accumulate 4 valid characters (ignore everything else)
//
unsigned char accumulated[BASE64_UNIT_SIZE];
size_t accumulateIndex = 0;
while (i < length)
{
unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
if (decode != xx)
{
accumulated[accumulateIndex] = decode;
accumulateIndex++;
if (accumulateIndex == BASE64_UNIT_SIZE)
{
break;
}
}
}
//
// Store the 6 bits from each of the 4 characters as 3 bytes
//
// (Uses improved bounds checking suggested by Alexandre Colucci)
//
if(accumulateIndex >= 2)
outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
if(accumulateIndex >= 3)
outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
if(accumulateIndex >= 4)
outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
j += accumulateIndex - 1;
}
if (outputLength)
{
*outputLength = j;
}
return outputBuffer;
}
//
// NewBase64Encode
//
// Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
// output buffer.
//
// inputBuffer - the source data for the encode
// length - the length of the input in bytes
// separateLines - if zero, no CR/LF characters will be added. Otherwise
// a CR/LF pair will be added every 64 encoded chars.
// outputLength - if not-NULL, on output will contain the encoded length
// (not including terminating 0 char)
//
// returns the encoded buffer. Must be free'd by caller. Length is given by
// outputLength.
//
char *NewBase64Encode(
const void *buffer,
size_t length,
bool separateLines,
size_t *outputLength)
{
const unsigned char *inputBuffer = (const unsigned char *)buffer;
#define MAX_NUM_PADDING_CHARS 2
#define OUTPUT_LINE_LENGTH 64
#define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)
#define CR_LF_SIZE 2
//
// Byte accurate calculation of final buffer size
//
size_t outputBufferSize =
((length / BINARY_UNIT_SIZE)
+ ((length % BINARY_UNIT_SIZE) ? 1 : 0))
* BASE64_UNIT_SIZE;
if (separateLines)
{
outputBufferSize +=
(outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
}
//
// Include space for a terminating zero
//
outputBufferSize += 1;
//
// Allocate the output buffer
//
char *outputBuffer = (char *)malloc(outputBufferSize);
if (!outputBuffer)
{
return NULL;
}
size_t i = 0;
size_t j = 0;
const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
size_t lineEnd = lineLength;
while (true)
{
if (lineEnd > length)
{
lineEnd = length;
}
for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE)
{
//
// Inner loop: turn 48 bytes into 64 base64 characters
//
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
| ((inputBuffer[i + 1] & 0xF0) >> 4)];
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
| ((inputBuffer[i + 2] & 0xC0) >> 6)];
outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];
}
if (lineEnd == length)
{
break;
}
//
// Add the newline
//
outputBuffer[j++] = '\r';
outputBuffer[j++] = '\n';
lineEnd += lineLength;
}
if (i + 1 < length)
{
//
// Handle the single '=' case
//
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
| ((inputBuffer[i + 1] & 0xF0) >> 4)];
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
outputBuffer[j++] = '=';
}
else if (i < length)
{
//
// Handle the double '=' case
//
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
outputBuffer[j++] = '=';
outputBuffer[j++] = '=';
}
outputBuffer[j] = 0;
//
// Set the output length and return the buffer
//
if (outputLength)
{
*outputLength = j;
}
return outputBuffer;
}
@implementation NSData (Base64)
//
// dataFromBase64String:
//
// Creates an NSData object containing the base64 decoded representation of
// the base64 string 'aString'
//
// Parameters:
// aString - the base64 string to decode
//
// returns the autoreleased NSData representation of the base64 string
//
+ (NSData *)dataFromBase64String:(NSString *)aString
{
NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];
size_t outputLength;
void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);
NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];
free(outputBuffer);
return result;
}
//
// base64EncodedString
//
// Creates an NSString object that contains the base 64 encoding of the
// receiver's data. Lines are broken at 64 characters long.
//
// returns an autoreleased NSString being the base 64 representation of the
// receiver.
//
- (NSString *)base64EncodedString
{
size_t outputLength = 0;
char *outputBuffer = NewBase64Encode([self bytes], [self length], true, &outputLength);
NSString *result =
[[[NSString alloc]
initWithBytes:outputBuffer
length:outputLength
encoding:NSASCIIStringEncoding]
autorelease];
free(outputBuffer);
return result;
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/NSString+AESCrypt.h
================================================
//
// NSString+AESCrypt.h
//
// Created by Michael Sedlaczek, Gone Coding on 2011-02-22
//
#import
#import "NSData+AESCrypt.h"
@interface NSString (AESCrypt)
- (NSString *)AES256EncryptWithKey:(NSString *)key;
- (NSString *)AES256DecryptWithKey:(NSString *)key;
@end
================================================
FILE: AMPCrypto/AMPCrypto/NSString+AESCrypt.m
================================================
//
// NSString+AESCrypt.m
//
// Created by Michael Sedlaczek, Gone Coding on 2011-02-22
//
#import "NSString+AESCrypt.h"
@implementation NSString (AESCrypt)
- (NSString *)AES256EncryptWithKey:(NSString *)key
{
NSData *plainData = [self dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [plainData AES256EncryptWithKey:key];
NSString *encryptedString = [encryptedData base64Encoding];
return encryptedString;
}
- (NSString *)AES256DecryptWithKey:(NSString *)key
{
NSData *encryptedData = [NSData dataWithBase64EncodedString:self];
NSData *plainData = [encryptedData AES256DecryptWithKey:key];
NSString *plainString = [[NSString alloc] initWithData:plainData encoding:NSUTF8StringEncoding];
return plainString;
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/SSKeychain.h
================================================
//
// SSKeychain.h
// SSToolkit
//
// Created by Sam Soffes on 5/19/10.
// Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
//
#import
#import
/** Error codes that can be returned in NSError objects. */
typedef enum {
/** No error. */
SSKeychainErrorNone = noErr,
/** Some of the arguments were invalid. */
SSKeychainErrorBadArguments = -1001,
/** There was no password. */
SSKeychainErrorNoPassword = -1002,
/** One or more parameters passed internally were not valid. */
SSKeychainErrorInvalidParameter = errSecParam,
/** Failed to allocate memory. */
SSKeychainErrorFailedToAllocated = errSecAllocate,
/** No trust results are available. */
SSKeychainErrorNotAvailable = errSecNotAvailable,
/** Authorization/Authentication failed. */
SSKeychainErrorAuthorizationFailed = errSecAuthFailed,
/** The item already exists. */
SSKeychainErrorDuplicatedItem = errSecDuplicateItem,
/** The item cannot be found.*/
SSKeychainErrorNotFound = errSecItemNotFound,
/** Interaction with the Security Server is not allowed. */
SSKeychainErrorInteractionNotAllowed = errSecInteractionNotAllowed,
/** Unable to decode the provided data. */
SSKeychainErrorFailedToDecode = errSecDecode
} SSKeychainErrorCode;
extern NSString *const kSSKeychainErrorDomain;
/** Account name. */
extern NSString *const kSSKeychainAccountKey;
/**
Time the item was created.
The value will be a string.
*/
extern NSString *const kSSKeychainCreatedAtKey;
/** Item class. */
extern NSString *const kSSKeychainClassKey;
/** Item description. */
extern NSString *const kSSKeychainDescriptionKey;
/** Item label. */
extern NSString *const kSSKeychainLabelKey;
/** Time the item was last modified.
The value will be a string.
*/
extern NSString *const kSSKeychainLastModifiedKey;
/** Where the item was created. */
extern NSString *const kSSKeychainWhereKey;
/**
Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system
Keychain on Mac OS X and iOS.
This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors.
SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it).
*/
@interface SSKeychain : NSObject
///-----------------------
/// @name Getting Accounts
///-----------------------
/**
Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts.
See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
dictionaries returned by this method.
@return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
accounts. The order of the objects in the array isn't defined.
@see allAccounts:
*/
+ (NSArray *)allAccounts;
/**
Returns an array containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
accounts.
See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
dictionaries returned by this method.
@param error If accessing the accounts fails, upon return contains an error that describes the problem.
@return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
accounts. The order of the objects in the array isn't defined.
@see allAccounts
*/
+ (NSArray *)allAccounts:(NSError **)error;
/**
Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
accounts for the given service.
See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
dictionaries returned by this method.
@param serviceName The service for which to return the corresponding accounts.
@return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain
doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
@see accountsForService:error:
*/
+ (NSArray *)accountsForService:(NSString *)serviceName;
/**
Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
accounts for the given service.
@param serviceName The service for which to return the corresponding accounts.
@param error If accessing the accounts fails, upon return contains an error that describes the problem.
@return An array of dictionaries containing the Keychain's accountsfor a given `serviceName`, or `nil` if the Keychain
doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
@see accountsForService:
*/
+ (NSArray *)accountsForService:(NSString *)serviceName error:(NSError **)error;
///------------------------
/// @name Getting Passwords
///------------------------
/**
Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
password for the given parameters.
@param serviceName The service for which to return the corresponding password.
@param account The account for which to return the corresponding password.
@return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
have a password for the given parameters.
@see passwordForService:account:error:
*/
+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;
/**
Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
password for the given parameters.
@param serviceName The service for which to return the corresponding password.
@param account The account for which to return the corresponding password.
@param error If accessing the password fails, upon return contains an error that describes the problem.
@return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
have a password for the given parameters.
@see passwordForService:account:
*/
+ (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
/**
Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data
for the given parameters.
@param serviceName The service for which to return the corresponding password.
@param account The account for which to return the corresponding password.
@param error If accessing the password fails, upon return contains an error that describes the problem.
@return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't
have data for the given parameters.
@see passwordDataForService:account:error:
*/
+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account;
/**
Returns the password data for a given account and service, or `nil` if the Keychain doesn't have data
for the given parameters.
@param serviceName The service for which to return the corresponding password.
@param account The account for which to return the corresponding password.
@param error If accessing the password fails, upon return contains an error that describes the problem.
@return Returns a the password data for the given account and service, or `nil` if the Keychain doesn't
have a password for the given parameters.
@see passwordDataForService:account:
*/
+ (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
///-------------------------
/// @name Deleting Passwords
///-------------------------
/**
Deletes a password from the Keychain.
@param serviceName The service for which to delete the corresponding password.
@param account The account for which to delete the corresponding password.
@return Returns `YES` on success, or `NO` on failure.
@see deletePasswordForService:account:error:
*/
+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;
/**
Deletes a password from the Keychain.
@param serviceName The service for which to delete the corresponding password.
@param account The account for which to delete the corresponding password.
@param error If deleting the password fails, upon return contains an error that describes the problem.
@return Returns `YES` on success, or `NO` on failure.
@see deletePasswordForService:account:
*/
+ (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
///------------------------
/// @name Setting Passwords
///------------------------
/**
Sets a password in the Keychain.
@param password The password to store in the Keychain.
@param serviceName The service for which to set the corresponding password.
@param account The account for which to set the corresponding password.
@return Returns `YES` on success, or `NO` on failure.
@see setPassword:forService:account:error:
*/
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;
/**
Sets a password in the Keychain.
@param password The password to store in the Keychain.
@param serviceName The service for which to set the corresponding password.
@param account The account for which to set the corresponding password.
@param error If setting the password fails, upon return contains an error that describes the problem.
@return Returns `YES` on success, or `NO` on failure.
@see setPassword:forService:account:
*/
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
/**
Sets arbirary data in the Keychain.
@param password The data to store in the Keychain.
@param serviceName The service for which to set the corresponding password.
@param account The account for which to set the corresponding password.
@param error If setting the password fails, upon return contains an error that describes the problem.
@return Returns `YES` on success, or `NO` on failure.
@see setPasswordData:forService:account:error:
*/
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account;
/**
Sets arbirary data in the Keychain.
@param password The data to store in the Keychain.
@param serviceName The service for which to set the corresponding password.
@param account The account for which to set the corresponding password.
@param error If setting the password fails, upon return contains an error that describes the problem.
@return Returns `YES` on success, or `NO` on failure.
@see setPasswordData:forService:account:
*/
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
///--------------------
/// @name Configuration
///--------------------
#if __IPHONE_4_0 && TARGET_OS_IPHONE
/**
Returns the accessibility type for all future passwords saved to the Keychain.
@return Returns the accessibility type.
The return value will be `NULL` or one of the "Keychain Item Accessibility Constants" used for determining when a
keychain item should be readable.
@see accessibilityType
*/
+ (CFTypeRef)accessibilityType;
/**
Sets the accessibility type for all future passwords saved to the Keychain.
@param accessibilityType One of the "Keychain Item Accessibility Constants" used for determining when a keychain item
should be readable.
If the value is `NULL` (the default), the Keychain default will be used.
@see accessibilityType
*/
+ (void)setAccessibilityType:(CFTypeRef)accessibilityType;
#endif
@end
================================================
FILE: AMPCrypto/AMPCrypto/SSKeychain.m
================================================
//
// SSKeychain.m
// SSToolkit
//
// Created by Sam Soffes on 5/19/10.
// Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
//
#import "SSKeychain.h"
NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain";
NSString *const kSSKeychainAccountKey = @"acct";
NSString *const kSSKeychainCreatedAtKey = @"cdat";
NSString *const kSSKeychainClassKey = @"labl";
NSString *const kSSKeychainDescriptionKey = @"desc";
NSString *const kSSKeychainLabelKey = @"labl";
NSString *const kSSKeychainLastModifiedKey = @"mdat";
NSString *const kSSKeychainWhereKey = @"svce";
#if __IPHONE_4_0 && TARGET_OS_IPHONE
CFTypeRef SSKeychainAccessibilityType = NULL;
#endif
@interface SSKeychain ()
+ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account;
@end
@implementation SSKeychain
#pragma mark - Getting Accounts
+ (NSArray *)allAccounts {
return [self accountsForService:nil error:nil];
}
+ (NSArray *)allAccounts:(NSError **)error {
return [self accountsForService:nil error:error];
}
+ (NSArray *)accountsForService:(NSString *)service {
return [self accountsForService:service error:nil];
}
+ (NSArray *)accountsForService:(NSString *)service error:(NSError **)error {
OSStatus status = SSKeychainErrorBadArguments;
NSMutableDictionary *query = [self _queryForService:service account:nil];
#if __has_feature(objc_arc)
[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
[query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
#else
[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
[query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
#endif
CFTypeRef result = NULL;
#if __has_feature(objc_arc)
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
#else
status = SecItemCopyMatching((CFDictionaryRef)query, &result);
#endif
if (status != noErr && error != NULL) {
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
return nil;
}
#if __has_feature(objc_arc)
return (__bridge_transfer NSArray *)result;
#else
return [(NSArray *)result autorelease];
#endif
}
#pragma mark - Getting Passwords
+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account {
return [self passwordForService:service account:account error:nil];
}
+ (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
NSData *data = [self passwordDataForService:service account:account error:error];
if (data.length > 0) {
NSString *string = [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding];
#if !__has_feature(objc_arc)
[string autorelease];
#endif
return string;
}
return nil;
}
+ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account {
return [self passwordDataForService:service account:account error:nil];
}
+ (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
OSStatus status = SSKeychainErrorBadArguments;
if (!service || !account) {
if (error) {
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
}
return nil;
}
CFTypeRef result = NULL;
NSMutableDictionary *query = [self _queryForService:service account:account];
#if __has_feature(objc_arc)
[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
[query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
#else
[query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
status = SecItemCopyMatching((CFDictionaryRef)query, &result);
#endif
if (status != noErr && error != NULL) {
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
return nil;
}
#if __has_feature(objc_arc)
return (__bridge_transfer NSData *)result;
#else
return [(NSData *)result autorelease];
#endif
}
#pragma mark - Deleting Passwords
+ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account {
return [self deletePasswordForService:service account:account error:nil];
}
+ (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
OSStatus status = SSKeychainErrorBadArguments;
if (service && account) {
NSMutableDictionary *query = [self _queryForService:service account:account];
#if __has_feature(objc_arc)
status = SecItemDelete((__bridge CFDictionaryRef)query);
#else
status = SecItemDelete((CFDictionaryRef)query);
#endif
}
if (status != noErr && error != NULL) {
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
}
return (status == noErr);
}
#pragma mark - Setting Passwords
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account {
return [self setPassword:password forService:service account:account error:nil];
}
+ (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding];
return [self setPasswordData:data forService:service account:account error:error];
}
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account {
return [self setPasswordData:password forService:service account:account error:nil];
}
+ (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
OSStatus status = SSKeychainErrorBadArguments;
if (password && service && account) {
[self deletePasswordForService:service account:account];
NSMutableDictionary *query = [self _queryForService:service account:account];
#if __has_feature(objc_arc)
[query setObject:password forKey:(__bridge id)kSecValueData];
#else
[query setObject:password forKey:(id)kSecValueData];
#endif
#if __IPHONE_4_0 && TARGET_OS_IPHONE
if (SSKeychainAccessibilityType) {
#if __has_feature(objc_arc)
[query setObject:(id)[self accessibilityType] forKey:(__bridge id)kSecAttrAccessible];
#else
[query setObject:(id)[self accessibilityType] forKey:(id)kSecAttrAccessible];
#endif
}
#endif
#if __has_feature(objc_arc)
status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
#else
status = SecItemAdd((CFDictionaryRef)query, NULL);
#endif
}
if (status != noErr && error != NULL) {
*error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
}
return (status == noErr);
}
#pragma mark - Configuration
#if __IPHONE_4_0 && TARGET_OS_IPHONE
+ (CFTypeRef)accessibilityType {
return SSKeychainAccessibilityType;
}
+ (void)setAccessibilityType:(CFTypeRef)accessibilityType {
CFRetain(accessibilityType);
if (SSKeychainAccessibilityType) {
CFRelease(SSKeychainAccessibilityType);
}
SSKeychainAccessibilityType = accessibilityType;
}
#endif
#pragma mark - Private
+ (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3];
#if __has_feature(objc_arc)
[dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
#else
[dictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
#endif
if (service) {
#if __has_feature(objc_arc)
[dictionary setObject:service forKey:(__bridge id)kSecAttrService];
#else
[dictionary setObject:service forKey:(id)kSecAttrService];
#endif
}
if (account) {
#if __has_feature(objc_arc)
[dictionary setObject:account forKey:(__bridge id)kSecAttrAccount];
#else
[dictionary setObject:account forKey:(id)kSecAttrAccount];
#endif
}
return dictionary;
}
@end
================================================
FILE: AMPCrypto/AMPCrypto/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPCrypto/AMPCrypto.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
B30FF5A618FADCD40053FD49 /* AMPluginFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8DB0EA018F755C800FA795F /* AMPluginFramework.framework */; };
B30FF5DD18FF19AD0053FD49 /* locked.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF5DC18FF19AD0053FD49 /* locked.psd */; };
D89DF28118F7D598004319A9 /* SSKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = D89DF28018F7D598004319A9 /* SSKeychain.m */; };
D89DF28318F7D5A1004319A9 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D89DF28218F7D5A1004319A9 /* Security.framework */; };
D89DF29F18F7EBC5004319A9 /* NSData+AESCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = D89DF29C18F7EBC5004319A9 /* NSData+AESCrypt.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
D89DF2A018F7EBC5004319A9 /* NSString+AESCrypt.m in Sources */ = {isa = PBXBuildFile; fileRef = D89DF29E18F7EBC5004319A9 /* NSString+AESCrypt.m */; };
D8DB0E4D18F7548700FA795F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8DB0E4C18F7548700FA795F /* Cocoa.framework */; };
D8DB0E5718F7548700FA795F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D8DB0E5518F7548700FA795F /* InfoPlist.strings */; };
D8DB0EA418F755F700FA795F /* AMPCrypto.m in Sources */ = {isa = PBXBuildFile; fileRef = D8DB0EA318F755F700FA795F /* AMPCrypto.m */; };
D8DB0EA718F7565400FA795F /* AMPCryptoView.m in Sources */ = {isa = PBXBuildFile; fileRef = D8DB0EA618F7565400FA795F /* AMPCryptoView.m */; };
D8DB0EAA18F7714400FA795F /* AMPCrypto.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = D8DB0E4918F7548700FA795F /* AMPCrypto.bundle */; };
D8F9FF2118F81E8C00A47564 /* unlocked.psd in Resources */ = {isa = PBXBuildFile; fileRef = D8F9FF2018F81E8C00A47564 /* unlocked.psd */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
D8DB0EA918F770CB00FA795F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "~/Library/Containers/it.bloop.airmail.beta8/Data/Library/Application Support/Airmail/General/Plugins";
dstSubfolderSpec = 0;
files = (
D8DB0EAA18F7714400FA795F /* AMPCrypto.bundle in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
B30FF58D18F827FE0053FD49 /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = AMPluginFramework.framework; sourceTree = ""; };
B30FF5DC18FF19AD0053FD49 /* locked.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = locked.psd; sourceTree = ""; };
D89DF27F18F7D598004319A9 /* SSKeychain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSKeychain.h; sourceTree = ""; };
D89DF28018F7D598004319A9 /* SSKeychain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSKeychain.m; sourceTree = ""; };
D89DF28218F7D5A1004319A9 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
D89DF29B18F7EBC5004319A9 /* NSData+AESCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+AESCrypt.h"; sourceTree = ""; };
D89DF29C18F7EBC5004319A9 /* NSData+AESCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+AESCrypt.m"; sourceTree = ""; };
D89DF29D18F7EBC5004319A9 /* NSString+AESCrypt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+AESCrypt.h"; sourceTree = ""; };
D89DF29E18F7EBC5004319A9 /* NSString+AESCrypt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+AESCrypt.m"; sourceTree = ""; };
D8DB0E4918F7548700FA795F /* AMPCrypto.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMPCrypto.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
D8DB0E4C18F7548700FA795F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
D8DB0E4F18F7548700FA795F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D8DB0E5018F7548700FA795F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
D8DB0E5118F7548700FA795F /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
D8DB0E5418F7548700FA795F /* AMPCrypto-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AMPCrypto-Info.plist"; sourceTree = ""; };
D8DB0E5618F7548700FA795F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
D8DB0E5818F7548700FA795F /* AMPCrypto-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AMPCrypto-Prefix.pch"; sourceTree = ""; };
D8DB0EA018F755C800FA795F /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPluginFramework.framework; path = ../AMPluginFramework/build/Debug/AMPluginFramework.framework; sourceTree = ""; };
D8DB0EA218F755F700FA795F /* AMPCrypto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPCrypto.h; sourceTree = ""; };
D8DB0EA318F755F700FA795F /* AMPCrypto.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPCrypto.m; sourceTree = ""; };
D8DB0EA518F7565400FA795F /* AMPCryptoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPCryptoView.h; sourceTree = ""; };
D8DB0EA618F7565400FA795F /* AMPCryptoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPCryptoView.m; sourceTree = ""; };
D8F9FF2018F81E8C00A47564 /* unlocked.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = unlocked.psd; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D8DB0E4618F7548700FA795F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
B30FF5A618FADCD40053FD49 /* AMPluginFramework.framework in Frameworks */,
D89DF28318F7D5A1004319A9 /* Security.framework in Frameworks */,
D8DB0E4D18F7548700FA795F /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
D8DB0E4018F7548600FA795F = {
isa = PBXGroup;
children = (
D8DB0E5218F7548700FA795F /* AMPCrypto */,
D8DB0E4B18F7548700FA795F /* Frameworks */,
D8DB0E4A18F7548700FA795F /* Products */,
);
sourceTree = "";
};
D8DB0E4A18F7548700FA795F /* Products */ = {
isa = PBXGroup;
children = (
D8DB0E4918F7548700FA795F /* AMPCrypto.bundle */,
);
name = Products;
sourceTree = "";
};
D8DB0E4B18F7548700FA795F /* Frameworks */ = {
isa = PBXGroup;
children = (
B30FF58D18F827FE0053FD49 /* AMPluginFramework.framework */,
D89DF28218F7D5A1004319A9 /* Security.framework */,
D8DB0EA018F755C800FA795F /* AMPluginFramework.framework */,
D8DB0E4C18F7548700FA795F /* Cocoa.framework */,
D8DB0E4E18F7548700FA795F /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "";
};
D8DB0E4E18F7548700FA795F /* Other Frameworks */ = {
isa = PBXGroup;
children = (
D8DB0E4F18F7548700FA795F /* Foundation.framework */,
D8DB0E5018F7548700FA795F /* CoreData.framework */,
D8DB0E5118F7548700FA795F /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "";
};
D8DB0E5218F7548700FA795F /* AMPCrypto */ = {
isa = PBXGroup;
children = (
D8DB0EA218F755F700FA795F /* AMPCrypto.h */,
D8DB0EA318F755F700FA795F /* AMPCrypto.m */,
D8DB0EA518F7565400FA795F /* AMPCryptoView.h */,
D8DB0EA618F7565400FA795F /* AMPCryptoView.m */,
D89DF27F18F7D598004319A9 /* SSKeychain.h */,
D89DF28018F7D598004319A9 /* SSKeychain.m */,
D89DF29B18F7EBC5004319A9 /* NSData+AESCrypt.h */,
D89DF29C18F7EBC5004319A9 /* NSData+AESCrypt.m */,
D89DF29D18F7EBC5004319A9 /* NSString+AESCrypt.h */,
D89DF29E18F7EBC5004319A9 /* NSString+AESCrypt.m */,
D8DB0E5318F7548700FA795F /* Supporting Files */,
);
path = AMPCrypto;
sourceTree = "";
};
D8DB0E5318F7548700FA795F /* Supporting Files */ = {
isa = PBXGroup;
children = (
B30FF5DC18FF19AD0053FD49 /* locked.psd */,
D8F9FF2018F81E8C00A47564 /* unlocked.psd */,
D8DB0E5418F7548700FA795F /* AMPCrypto-Info.plist */,
D8DB0E5518F7548700FA795F /* InfoPlist.strings */,
D8DB0E5818F7548700FA795F /* AMPCrypto-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
D8DB0E4818F7548700FA795F /* AMPCrypto */ = {
isa = PBXNativeTarget;
buildConfigurationList = D8DB0E5B18F7548700FA795F /* Build configuration list for PBXNativeTarget "AMPCrypto" */;
buildPhases = (
D8DB0E4518F7548700FA795F /* Sources */,
D8DB0E4618F7548700FA795F /* Frameworks */,
D8DB0E4718F7548700FA795F /* Resources */,
D8DB0EA918F770CB00FA795F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = AMPCrypto;
productName = AMPCrypto;
productReference = D8DB0E4918F7548700FA795F /* AMPCrypto.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D8DB0E4118F7548600FA795F /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = bloop;
};
buildConfigurationList = D8DB0E4418F7548600FA795F /* Build configuration list for PBXProject "AMPCrypto" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = D8DB0E4018F7548600FA795F;
productRefGroup = D8DB0E4A18F7548700FA795F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D8DB0E4818F7548700FA795F /* AMPCrypto */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D8DB0E4718F7548700FA795F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D8DB0E5718F7548700FA795F /* InfoPlist.strings in Resources */,
D8F9FF2118F81E8C00A47564 /* unlocked.psd in Resources */,
B30FF5DD18FF19AD0053FD49 /* locked.psd in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D8DB0E4518F7548700FA795F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D8DB0EA718F7565400FA795F /* AMPCryptoView.m in Sources */,
D89DF2A018F7EBC5004319A9 /* NSString+AESCrypt.m in Sources */,
D89DF29F18F7EBC5004319A9 /* NSData+AESCrypt.m in Sources */,
D8DB0EA418F755F700FA795F /* AMPCrypto.m in Sources */,
D89DF28118F7D598004319A9 /* SSKeychain.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
D8DB0E5518F7548700FA795F /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
D8DB0E5618F7548700FA795F /* en */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
D8DB0E5918F7548700FA795F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
D8DB0E5A18F7548700FA795F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
};
D8DB0E5C18F7548700FA795F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail_1.4/AMPCrypto,
"\"$(SRCROOT)/../AMPluginFramework/build/Debug/\"",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AMPCrypto/AMPCrypto-Prefix.pch";
INFOPLIST_FILE = "AMPCrypto/AMPCrypto-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
D8DB0E5D18F7548700FA795F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail_1.4/AMPCrypto,
"\"$(SRCROOT)/../AMPluginFramework/build/Debug/\"",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AMPCrypto/AMPCrypto-Prefix.pch";
INFOPLIST_FILE = "AMPCrypto/AMPCrypto-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
MACOSX_DEPLOYMENT_TARGET = 10.7;
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D8DB0E4418F7548600FA795F /* Build configuration list for PBXProject "AMPCrypto" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D8DB0E5918F7548700FA795F /* Debug */,
D8DB0E5A18F7548700FA795F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D8DB0E5B18F7548700FA795F /* Build configuration list for PBXNativeTarget "AMPCrypto" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D8DB0E5C18F7548700FA795F /* Debug */,
D8DB0E5D18F7548700FA795F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D8DB0E4118F7548600FA795F /* Project object */;
}
================================================
FILE: AMPCrypto/AMPCrypto.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: AMPCustomTemplates/AMPCustomTemplate.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
880B3309183ACF6A0053B7E4 /* AMPluginFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 887975F81837F69B00C008FB /* AMPluginFramework.framework */; };
880B330C183ACF7D0053B7E4 /* AMPCustomTemplate.m in Sources */ = {isa = PBXBuildFile; fileRef = 880B330B183ACF7D0053B7E4 /* AMPCustomTemplate.m */; };
887975FE1837F74100C008FB /* AMPCssComposerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 887975FD1837F74100C008FB /* AMPCssComposerView.m */; };
887975FF1837F85B00C008FB /* AMPCustomTemplate.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 88DB2C0C1837C234003CC988 /* AMPCustomTemplate.bundle */; };
88DB2C101837C234003CC988 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88DB2C0F1837C234003CC988 /* Cocoa.framework */; };
88DB2C1A1837C234003CC988 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 88DB2C181837C234003CC988 /* InfoPlist.strings */; };
D86D3C751838F81E0097697F /* helvetica.css in Resources */ = {isa = PBXBuildFile; fileRef = D86D3C6F1838F81E0097697F /* helvetica.css */; };
D86D3C771838F81E0097697F /* Taxi.css in Resources */ = {isa = PBXBuildFile; fileRef = D86D3C711838F81E0097697F /* Taxi.css */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
887975FA1837F6B500C008FB /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "~/Library/Containers/it.bloop.airmail.beta8/Data/Library/Application Support/Airmail/General/Plugins";
dstSubfolderSpec = 0;
files = (
887975FF1837F85B00C008FB /* AMPCustomTemplate.bundle in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
880B330A183ACF7D0053B7E4 /* AMPCustomTemplate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPCustomTemplate.h; sourceTree = ""; };
880B330B183ACF7D0053B7E4 /* AMPCustomTemplate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPCustomTemplate.m; sourceTree = ""; };
887975F81837F69B00C008FB /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPluginFramework.framework; path = ../AMPluginFramework/build/Debug/AMPluginFramework.framework; sourceTree = ""; };
887975FC1837F74100C008FB /* AMPCssComposerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPCssComposerView.h; sourceTree = ""; };
887975FD1837F74100C008FB /* AMPCssComposerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPCssComposerView.m; sourceTree = ""; };
88DB2C0C1837C234003CC988 /* AMPCustomTemplate.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMPCustomTemplate.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
88DB2C0F1837C234003CC988 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
88DB2C121837C234003CC988 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
88DB2C131837C234003CC988 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
88DB2C141837C234003CC988 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
88DB2C171837C234003CC988 /* AMPCustomTemplate-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AMPCustomTemplate-Info.plist"; sourceTree = ""; };
88DB2C191837C234003CC988 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
88DB2C1B1837C234003CC988 /* AMPCustomTemplate-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AMPCustomTemplate-Prefix.pch"; sourceTree = ""; };
D86D3C6F1838F81E0097697F /* helvetica.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = helvetica.css; sourceTree = ""; };
D86D3C711838F81E0097697F /* Taxi.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = Taxi.css; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
88DB2C091837C234003CC988 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
880B3309183ACF6A0053B7E4 /* AMPluginFramework.framework in Frameworks */,
88DB2C101837C234003CC988 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
88DB2C031837C234003CC988 = {
isa = PBXGroup;
children = (
88DB2C151837C234003CC988 /* CssComposer */,
88DB2C0E1837C234003CC988 /* Frameworks */,
88DB2C0D1837C234003CC988 /* Products */,
);
sourceTree = "";
};
88DB2C0D1837C234003CC988 /* Products */ = {
isa = PBXGroup;
children = (
88DB2C0C1837C234003CC988 /* AMPCustomTemplate.bundle */,
);
name = Products;
sourceTree = "";
};
88DB2C0E1837C234003CC988 /* Frameworks */ = {
isa = PBXGroup;
children = (
887975F81837F69B00C008FB /* AMPluginFramework.framework */,
88DB2C0F1837C234003CC988 /* Cocoa.framework */,
88DB2C111837C234003CC988 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "";
};
88DB2C111837C234003CC988 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
88DB2C121837C234003CC988 /* Foundation.framework */,
88DB2C131837C234003CC988 /* CoreData.framework */,
88DB2C141837C234003CC988 /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "";
};
88DB2C151837C234003CC988 /* CssComposer */ = {
isa = PBXGroup;
children = (
880B330A183ACF7D0053B7E4 /* AMPCustomTemplate.h */,
880B330B183ACF7D0053B7E4 /* AMPCustomTemplate.m */,
887975FC1837F74100C008FB /* AMPCssComposerView.h */,
887975FD1837F74100C008FB /* AMPCssComposerView.m */,
88DB2C161837C234003CC988 /* Supporting Files */,
);
path = CssComposer;
sourceTree = "";
};
88DB2C161837C234003CC988 /* Supporting Files */ = {
isa = PBXGroup;
children = (
D86D3C791838F8230097697F /* css */,
88DB2C171837C234003CC988 /* AMPCustomTemplate-Info.plist */,
88DB2C181837C234003CC988 /* InfoPlist.strings */,
88DB2C1B1837C234003CC988 /* AMPCustomTemplate-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "";
};
D86D3C791838F8230097697F /* css */ = {
isa = PBXGroup;
children = (
D86D3C6F1838F81E0097697F /* helvetica.css */,
D86D3C711838F81E0097697F /* Taxi.css */,
);
name = css;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
88DB2C0B1837C234003CC988 /* AMPCustomTemplate */ = {
isa = PBXNativeTarget;
buildConfigurationList = 88DB2C1E1837C234003CC988 /* Build configuration list for PBXNativeTarget "AMPCustomTemplate" */;
buildPhases = (
88DB2C081837C234003CC988 /* Sources */,
88DB2C091837C234003CC988 /* Frameworks */,
88DB2C0A1837C234003CC988 /* Resources */,
887975FA1837F6B500C008FB /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = AMPCustomTemplate;
productName = CssComposer;
productReference = 88DB2C0C1837C234003CC988 /* AMPCustomTemplate.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
88DB2C041837C234003CC988 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = Joe;
};
buildConfigurationList = 88DB2C071837C234003CC988 /* Build configuration list for PBXProject "AMPCustomTemplate" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 88DB2C031837C234003CC988;
productRefGroup = 88DB2C0D1837C234003CC988 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
88DB2C0B1837C234003CC988 /* AMPCustomTemplate */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
88DB2C0A1837C234003CC988 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D86D3C771838F81E0097697F /* Taxi.css in Resources */,
D86D3C751838F81E0097697F /* helvetica.css in Resources */,
88DB2C1A1837C234003CC988 /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
88DB2C081837C234003CC988 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
880B330C183ACF7D0053B7E4 /* AMPCustomTemplate.m in Sources */,
887975FE1837F74100C008FB /* AMPCssComposerView.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
88DB2C181837C234003CC988 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
88DB2C191837C234003CC988 /* en */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
88DB2C1C1837C234003CC988 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
88DB2C1D1837C234003CC988 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
SDKROOT = macosx;
};
name = Release;
};
88DB2C1F1837C234003CC988 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail/AMPluginFramework/build/Debug,
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "CssComposer/AMPCustomTemplate-Prefix.pch";
INFOPLIST_FILE = "CssComposer/AMPCustomTemplate-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_NAME = AMPCustomTemplate;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
88DB2C201837C234003CC988 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail/AMPluginFramework/build/Debug,
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "CssComposer/AMPCustomTemplate-Prefix.pch";
INFOPLIST_FILE = "CssComposer/AMPCustomTemplate-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_NAME = AMPCustomTemplate;
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
88DB2C071837C234003CC988 /* Build configuration list for PBXProject "AMPCustomTemplate" */ = {
isa = XCConfigurationList;
buildConfigurations = (
88DB2C1C1837C234003CC988 /* Debug */,
88DB2C1D1837C234003CC988 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
88DB2C1E1837C234003CC988 /* Build configuration list for PBXNativeTarget "AMPCustomTemplate" */ = {
isa = XCConfigurationList;
buildConfigurations = (
88DB2C1F1837C234003CC988 /* Debug */,
88DB2C201837C234003CC988 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 88DB2C041837C234003CC988 /* Project object */;
}
================================================
FILE: AMPCustomTemplates/AMPCustomTemplate.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: AMPCustomTemplates/CssComposer/AMPCssComposerView.h
================================================
//
// AMPCssComposerView.h
// AirmailCssComposer
//
// Created by Joe on 16/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
@interface AMPCssComposerView : AMPView
{
NSPopUpButton *popUpBtnRender;
}
@end
================================================
FILE: AMPCustomTemplates/CssComposer/AMPCssComposerView.m
================================================
//
// AMPCssComposerView.m
// AirmailCssComposer
//
// Created by Joe on 16/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import "AMPCssComposerView.h"
#import "AMPCustomTemplate.h"
@implementation AMPCssComposerView
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin *)pluginIn
{
self = [super initWithFrame:frame plugin:pluginIn];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(x+3, y+5, 250, 20)];
[textField setStringValue:NSLocalizedString(@"Template Selector:",@"Template Selector:")];
[textField setBezeled:NO];
[textField setDrawsBackground:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont systemFontOfSize:13]];
[[textField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[textField setAlignment: NSRightTextAlignment];
[self addSubview:textField];
popUpBtnRender = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(x+270, y, 200, 30) pullsDown:NO];
[(NSPopUpButtonCell *)[popUpBtnRender cell] setBezelStyle:NSTexturedRoundedBezelStyle];
[[popUpBtnRender cell] setArrowPosition:NSPopUpArrowAtBottom];
[popUpBtnRender setAutoresizingMask:NSViewMaxYMargin];
[self addSubview:popUpBtnRender];
[self LoadView];
}
return self;
}
- (AMPCustomTemplate*) myPlugin
{
return (AMPCustomTemplate*)self.plugin;
}
- (void) ReloadView
{
dispatch_async(dispatch_get_main_queue(), ^{
[self LoadView];
});
}
- (void) LoadView
{
NSMenu *menu = [self.myPlugin stylesMenu];
[popUpBtnRender setMenu:menu];
//Selection
NSString *pathRender = [self.myPlugin savedPath];
if(pathRender && [pathRender isKindOfClass:[NSString class]])
{
for(NSMenuItem *item in popUpBtnRender.menu.itemArray)
{
if([item.representedObject isEqualToString:pathRender])
{
[popUpBtnRender selectItem:item];
break;
}
}
}
}
- (void) RenderView
{
}
@end
================================================
FILE: AMPCustomTemplates/CssComposer/AMPCustomTemplate-Info.plist
================================================
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
it.bloop.airmail.plugin.${PRODUCT_NAME:rfc1034identifier}
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2013 Joe. All rights reserved.
NSPrincipalClass
AMPCssComposer
================================================
FILE: AMPCustomTemplates/CssComposer/AMPCustomTemplate-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import
#endif
================================================
FILE: AMPCustomTemplates/CssComposer/AMPCustomTemplate.h
================================================
//
// AMPCssComposer.h
// CssComposer
//
// Created by Joe on 16/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
#import
@interface AMPCustomTemplate : AMPlugin
{
}
@property (strong) NSMutableArray *cssList;
@property (strong) NSString *cssString,*cssStringComposer;
-(NSString*)savedPath;
-(void) changeCss:(NSString*)str;
- (NSMenu*) stylesMenuComposerButton;
- (NSMenu*) stylesMenu;
@end
================================================
FILE: AMPCustomTemplates/CssComposer/AMPCustomTemplate.m
================================================
//
// AMPCssComposer.m
// CssComposer
//
// Created by Joe on 16/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import "AMPCustomTemplate.h"
#import "AMPCssComposerView.h"
const NSString *ampcss_composer_css_option = @"ampcss_composer_css_option";
@implementation AMPCustomTemplate
- (id)init
{
self = [super init];
if (self)
{
self.cssString = @"";
}
return self;
}
- (BOOL) Load
{
if(![super Load])
return NO;
self.cssList = [NSMutableArray array];
//Load Bundle
NSMutableArray *allpaths = [NSMutableArray array];
NSArray *bundlesPath = [self bundlepathContents];
if(!bundlesPath)
return NO;
[allpaths addObjectsFromArray:bundlesPath];
NSArray *dirPaths = [self suggestedpathContents];
if(!dirPaths)
return NO;
[allpaths addObjectsFromArray:dirPaths];
for(NSString *path in allpaths)
{
if([path.pathExtension isEqualToString:@"css"])
[self.cssList addObject:path];
}
//Load Preference
NSString *path = [self.preferences objectForKey:ampcss_composer_css_option];
if(path && [path isKindOfClass:[NSString class]])
self.cssString = [self LoadCssStringForPath:path];
[self Reload];
return YES;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (void) Reload
{
return [(AMPCssComposerView*)self.myView ReloadView];
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPCssComposerView alloc] initWithFrame:NSZeroRect plugin:self];
return self.myView;
}
- (NSString*) nametext
{
return @"Composer Template SDK";
}
- (NSString*) description
{
return self.nametext;
}
- (NSString*) descriptiontext
{
return @"This plugin is a Composert Template sample to show how to customize your message,";
}
- (NSString*) authortext
{
return @"Airmail SDK Sample";
}
- (NSString*) supportlink
{
return @"http://adv.bloop.info/airmail/sdk.php";
}
- (NSImage*) icon
{
return [NSImage imageNamed:@"iconx"];
}
#pragma mark - AM called methods
-(NSMenuItem*) ampMenuComposerItem:(AMPComposerInfo *)info
{
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Change Style", @"Change Style") action:nil keyEquivalent:@""];
[item setState:NSOffState];
NSMenu *menu = [self stylesMenuComposerButton];
[item setSubmenu:menu];
return item;
}
- (NSString*) ampStackComposerRenderHtmlFromHtml:(NSString *)html composerInfo:(AMPComposerInfo *)info
{
if(self.cssString.length == 0)
return html;
NSString *htmlRet = [NSString stringWithFormat:@"%@",ampcss_composer_css_option,self.cssString,html];
return htmlRet;
}
#pragma mark - manage css
-(NSString*) savedPath
{
return [self.preferences objectForKey:ampcss_composer_css_option];
}
- (NSString*) LoadCssStringForPath:(NSString*)path
{
NSError *err = nil;
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
if(err)
{
str = @"";
[self LogError:[NSString stringWithFormat:@"Cannot load css %@",path]];
}
return str;
}
- (NSMenu*) stylesMenu
{
NSMenu *menu = [NSMenu new];
NSArray *csss = [self.cssList sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
return [a caseInsensitiveCompare:b];
}];
NSMenuItem *itemRender = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"None", @"None") action:nil keyEquivalent:@""];
[itemRender setRepresentedObject:@""];
[itemRender setAction:@selector(changeCss:)];
[itemRender setTarget:self];
[menu addItem:itemRender];
[csss enumerateObjectsUsingBlock:^(NSString *path, NSUInteger idx, BOOL *stop) {
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:path.lastPathComponent.stringByDeletingPathExtension action:nil keyEquivalent:@""];
[item setRepresentedObject:path];
[item setAction:@selector(changeCss:)];
[item setTarget:self];
[menu addItem:item];
}];
return menu;
}
- (NSMenu*) stylesMenuComposerButton
{
NSMenu *menu = [self stylesMenu];
[menu.itemArray enumerateObjectsUsingBlock:^(NSMenuItem *item, NSUInteger idx, BOOL *stop) {
if([item.representedObject isEqualToString:self.cssStringComposer])
[item setState:NSOnState];
[item setAction:@selector(changeCssComposer:)];
[item setTarget:self];
}];
return menu;
}
- (void) changeCss:(NSMenuItem*)item
{
[self changeCssString:item.representedObject];
}
- (void) changeCssString:(NSString*)str
{
if(str.length == 0)
{
[self.preferences removeObjectForKey:ampcss_composer_css_option];
self.cssString = @"";
}
else
{
[self.preferences removeObjectForKey:ampcss_composer_css_option];
[self.preferences setObject:str forKey:ampcss_composer_css_option];
self.cssString = [self LoadCssStringForPath:str];
}
[self SavePreferences];
}
//From composer
- (void) changeCssComposer:(NSMenuItem*)item
{
//NSLog(@"changeCssComposer %@",str);
if([item.representedObject isKindOfClass:[AMPComposerInfo class]])
{
AMPComposerInfo *info = item.representedObject;
if([info.representedObject isKindOfClass:[NSString class]])
{
NSString *path = (NSString*)info.representedObject;
self.cssStringComposer = [self LoadCssStringForPath:path];
if(info.webView)
{
DOMDocument *domDoc = [[info.webView mainFrame] DOMDocument];
NSString *idx = [NSString stringWithFormat:@"%@",ampcss_composer_css_option];
DOMHTMLStyleElement *cssNode = (DOMHTMLStyleElement*)[domDoc createElement:@"style"];
[cssNode setInnerHTML:self.cssStringComposer];
[cssNode setIdName:idx];
DOMElement *el = [domDoc getElementById:idx];
if(el && el.parentNode)
{
[el.parentNode replaceChild:cssNode oldChild:el];
}
else
{
DOMNodeList *list = [domDoc getElementsByTagName:@"head"];;
if(list.length > 0)
{
DOMHTMLHeadElement *head = (DOMHTMLHeadElement*)[list item:0];
[head appendChild:cssNode];
}
}
}
}
}
}
@end
================================================
FILE: AMPCustomTemplates/CssComposer/Taxi.css
================================================
*,tr,td,table,html,th,hr,body,tbody,div {
font-size: 18px !important;
font-family:"avenir next" !important;
color:Black; !important;
background-color:Yellow !important;
border:0px!important;
border-top: 0px;
background-color:Yellow !important;
background-image:url('') !important;
}
img {
Display:none;
}
a * {
color:green; !important;
}
================================================
FILE: AMPCustomTemplates/CssComposer/Yellow.css
================================================
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
* {
font-size: 25px !important;
font-family:"lucida-grande" !important;
Color-Black; !important;
Background-Color:Yellow; !important;
}
img {
display: none !important;
}
================================================
FILE: AMPCustomTemplates/CssComposer/base1.css
================================================
* {
font-size: 25px;
font-family:"helvetica";
}
================================================
FILE: AMPCustomTemplates/CssComposer/base2.css
================================================
* {
font-size: 11px;
font-family:"helvetica";
}
================================================
FILE: AMPCustomTemplates/CssComposer/base3.css
================================================
* {
font-size: 35px;
font-family:"helvetica";
}
================================================
FILE: AMPCustomTemplates/CssComposer/base4.css
================================================
* {
font-size: 49px;
font-family:"helvetica";
}
================================================
FILE: AMPCustomTemplates/CssComposer/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPCustomTemplates/CssComposer/helvetica.css
================================================
* {
font-size: 35px;
font-family:"helvetica" !important;
}
================================================
FILE: AMPFramework.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: AMPGpg/AMPGpg/AMPGpg-Info.plist
================================================
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
it.bloop.airmail.plugin.gpg
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
8
NSHumanReadableCopyright
Copyright © 2014 bloop. All rights reserved.
NSPrincipalClass
AMPGpg
================================================
FILE: AMPGpg/AMPGpg/AMPGpg-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import
#endif
================================================
FILE: AMPGpg/AMPGpg/AMPGpg.h
================================================
//
// AMPGpg.h
// AMPGpg
//
// Created by Gio on 16/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import
extern NSString * const AMPGpgRemeberChoice;
@interface AMPGpg : AMPlugin
{
}
@property NSInteger rememberChoice;
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpg.m
================================================
//
// AMPGpg.m
// AMPGpg
//
// Created by Gio on 16/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import "AMPGpg.h"
#import "AMPGpgView.h"
#import "AMPGpgEncryption.h"
#import "AMPGpgButton.h"
#import "AMPGpgBodyView.h"
//#import "Libmacgpg.h"
#import
enum amp_composer_gpg_btn_type {
AMP_GPG_COMPOSER_TYPE_BTN_ENCRYPT = 123456,
AMP_GPG_COMPOSER_TYPE_BTN_SIGN = 234567,
};
NSString * const AMPGpgRemeberChoice = @"AMPGpgRemeberChoices";
@interface AMPGpg()
{
}
@property (strong) AMPGpgEncryption *encryption;
@property (strong) NSImage *imSignOn,*imSignOff,*imEncryptOn,*imEncryptOff,*imSignedOK,*imSignedBad,*imLockedKPI,*imUnLockedKPI,*imIcon;
@property (strong) NSMutableDictionary *encryptedMessages, *signedMessages,*composerViews;
@end
@implementation AMPGpg
@synthesize rememberChoice;
- (id)init
{
self = [super init];
if (self)
{
self.encryptedMessages = [NSMutableDictionary dictionary];
self.signedMessages = [NSMutableDictionary dictionary];
self.encryption = [AMPGpgEncryption new];
}
return self;
}
- (BOOL) Load
{
if(![super Load])
return NO;
self.imIcon = [self loadImage:@"pluginsGPG.psd"];
self.imSignOn = [self loadImage:@"g_active.psd"];
self.imSignOff = [self loadImage:@"g_inactive.psd"];
self.imEncryptOn = [self loadImage:@"g_locked.psd"];
self.imEncryptOff = [self loadImage:@"g_unlocked.psd"];
self.imSignedOK = [self loadImage:@"gpg_active.psd"];
self.imSignedBad = [self loadImage:@"gpg_bad.psd"];
self.imLockedKPI = [self loadImage:@"gpg_locked.psd"];
self.imUnLockedKPI = [self loadImage:@"gpg_unlocked.psd"];
return YES;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (void) Reload
{
return [self.myView ReloadView];
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPGpgView alloc] initWithFrame:NSZeroRect plugin:self];
return self.myView;
}
- (NSString*) nametext
{
return @"GPG BETA";
}
- (NSString*) description
{
return self.nametext;
}
- (NSString*) descriptiontext
{
return @"This plug-in implements the PGP/GPG email security standard for encryption and signing.";
}
- (NSString*) authortext
{
return @"Airmail GPG Beta";
}
- (NSString*) supportlink
{
return @"http://airmailapp.com/gpg";
}
- (NSImage*) icon
{
return self.imIcon;
}
#pragma mark - calls
//GIVES AM A BUTTON IN THE COMPOSER WINDOW
- (NSArray*) ampPileComposerView:(AMPComposerInfo *)info
{
//Return a new composer btn for new created the composer
NSView *v = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 44, 20)];
AMPGpgButton *lockBtn = [[AMPGpgButton alloc] initWithFrame:NSMakeRect(0, 0, 22, 20)
image:self.imEncryptOn
alt:self.imEncryptOff
tag:AMP_GPG_COMPOSER_TYPE_BTN_ENCRYPT
rememberChoice:self.rememberChoice];
[lockBtn setToolTip:NSLocalizedString(@"PGP Encrypt/Decrypt",@"PGP Sign/Unsign")];
[v addSubview:lockBtn];
AMPGpgButton *signBtn = [[AMPGpgButton alloc] initWithFrame:NSMakeRect(22, 0, 22, 20)
image:self.imSignOn
alt:self.imSignOff
tag:AMP_GPG_COMPOSER_TYPE_BTN_SIGN
rememberChoice:self.rememberChoice];
[signBtn setToolTip:NSLocalizedString(@"PGP Sign/Unsign",@"PGP Sign/Unsign")];
[v addSubview:signBtn];
return @[v];
}
//Composer
//IS ALL TIME CALLED IN A BACKGROUND THREAD
- (NSNumber*) ampPileChangedRecipients:(AMPComposerInfo *)info
{
AMPGpgButton *encryptBtn = [self btnForTag:AMP_GPG_COMPOSER_TYPE_BTN_ENCRYPT info:info];
AMPGpgButton *signBtn = [self btnForTag:AMP_GPG_COMPOSER_TYPE_BTN_SIGN info:info];
NSInteger canSign = [self.encryption CheckSender:info];
NSInteger canEncrypt = [self.encryption CheckRecipients:info];
//Some unicors will die for such nested if... structure :)
dispatch_async(dispatch_get_main_queue(), ^{
if(canSign)
{
[signBtn ManageState:YES];
if(canEncrypt)
[encryptBtn ManageState:YES];
else
[encryptBtn ManageState:NO];
}
else
{
[encryptBtn ManageState:NO];
[signBtn ManageState:NO];
}
});
return @(1);
}
//USED BY AM TO CHECK IF THE RFC IS ENCRYPTED
- (NSNumber*) ampPileIsEncrypted:(AMPMCOMessageParser*)parser
{
// NSLog(@"CHECKING ENCRYPTION");
return @([self.encryption isEncrypted:parser]);
}
//USED BY AM TO CHECK IF THE RFC IS Signed
- (AMPSignatureVerify*) ampPileVerifySignature:(AMPMessage*)message
{
AMPSignatureVerify *sv = nil;
@try
{
sv = [self.encryption VerifySignature:message];
if(sv)
[self.signedMessages setObject:@(sv.signatureVerify) forKey:message.idx];
}
@catch (NSException *exception) {
[self LogError:exception.reason];
}
return sv;
}
//USED BY AM TO DECRYPT BEFORE RENDERING
- (NSData*) ampStackDecrypt:(AMPMessage*)message
{
NSData *data = nil;
@try{
data = [self.encryption Decrypt:message];
if(data) {
[self.encryptedMessages setObject:@(YES) forKey:message.idx];
}
}
@catch (NSException *exception) {
NSLog(@"Failed to decrypt message due to %@", exception.reason);
[self LogError:exception.reason];
[self.encryptedMessages setObject:@(NO) forKey:message.idx];
}
@finally {
}
return data;
}
//USED BY AM TO CHANGE THE RFC BEFORE SENDING
- (AMPSendResult*) ampStackSendRfc:(NSString*)rfc composer:(AMPComposerInfo*)info
{
AMPSendResult *sr = [AMPSendResult new];
sr.result = AMP_SEND_RESULT_NONE;
AMPGpgButton *encryptBtn = [self btnForTag:AMP_GPG_COMPOSER_TYPE_BTN_ENCRYPT info:info];
AMPGpgButton *signBtn = [self btnForTag:AMP_GPG_COMPOSER_TYPE_BTN_SIGN info:info];
if(encryptBtn.isActive || signBtn.isActive)
{
@try{
sr.rfc = [self.encryption Envelope:rfc info:info enc:encryptBtn.isActive sign:signBtn.isActive];
sr.result = AMP_SEND_RESULT_SUCCESS;
}
@catch (NSException *exception) {
[self LogError:exception.reason];
sr.err = exception.reason;
sr.result = AMP_SEND_RESULT_FAIL;
}
}
return sr;
}
- (NSString*) ampUniqueMessageRender:(AMPMessage*)message
{
// XXX this is very much of a hack to just be able to read email.
// Many thing actually don't work.
// The root of the problem, I suspect, is that the callback ampPileMessageView does not get called with all messages
NSData *data = nil;
NSString *rfc = [[NSString alloc] initWithData:message.rfcData encoding:NSUTF8StringEncoding];
@try{
NSScanner *scanner = [NSScanner scannerWithString:rfc];
[scanner setCharactersToBeSkipped:nil];
NSString *ctype = [self.encryption GetHeader:scanner header:@"Content-Type"];
if (!ctype || ![ctype hasPrefix:@" multipart/encrypted"]) {
return message.htmlBody;
}
/*Content-Type: multipart/encrypted; boundary="Apple-Mail=_45365103-713A-4FD2-B339-A5A401563C8F"; protocol="application/pgp-encrypted";
*/
data = [self.encryption Decrypt:message];
if (data) {
[self.encryptedMessages setObject:@(YES) forKey:message.idx];
}
}
@catch (NSException *exception) {
NSLog(@"Failed to decrypt message due to %@", exception.reason);
return nil;
}
@finally {
}
return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
//USED BY AM TO RENDER IN THE BODYVIEW
- (NSArray*) ampPileMessageView:(AMPMessage*)message
{
NSMutableArray *ret = [NSMutableArray array];
NSNumber *enc = [self.encryptedMessages objectForKey:message.idx];
if(enc.integerValue > 0)
{
NSImageView *imvEncrypted = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)];
[imvEncrypted setImageAlignment:NSImageAlignTopLeft];
[imvEncrypted setImageScaling:NSImageScaleProportionallyUpOrDown];
if(enc.boolValue)
{
[imvEncrypted setImage:self.imUnLockedKPI];
[imvEncrypted setToolTip:NSLocalizedString(@"Decrypted",@"Decrypted")];
}
else
{
[imvEncrypted setImage:self.imLockedKPI];
[imvEncrypted setToolTip:NSLocalizedString(@"Failed to Decrypt",@"Failed to Decrypt")];
}
[ret addObject:imvEncrypted];
[self.encryptedMessages removeObjectForKey:message.idx];
}
NSNumber *sign = [self.signedMessages objectForKey:message.idx];
if(sign.integerValue > 0)
{
NSImageView *imvSign = [[NSImageView alloc] initWithFrame:NSMakeRect(0, 0, 16, 16)];
if(sign.integerValue == AMP_SIGNED_SUCCESS)
{
[imvSign setImage:self.imSignedOK];
[imvSign setToolTip:NSLocalizedString(@"Verified",@"Verified")];
}
else if(sign.integerValue == AMP_SIGNED_FAILS)
{
[imvSign setImage:self.imSignedBad];
[imvSign setToolTip:NSLocalizedString(@"Not Verified",@"Not Verified")];
}
[ret addObject:imvSign];
[self.signedMessages removeObjectForKey:message.idx];
}
return ret;
}
#pragma mark - utilities
-(AMPGpgButton*) btnForTag:(NSInteger)tag info:(AMPComposerInfo*)info
{
NSArray *composerBtns = [info composerBtn:self];
if(!composerBtns || composerBtns.count == 0)
{
[self LogError:@"No Button for the plugin"];
return nil;
}
NSView *v = composerBtns[0];
for(AMPGpgButton *btn in v.subviews)
{
if(btn.tag == tag)
return btn;
}
return nil;
}
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgBodyView.h
================================================
//
// AMPGpgBodyView.h
// AMPGpg
//
// Created by Giovanni Simonicca on 17/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import
@interface AMPGpgBodyView : NSView
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgBodyView.m
================================================
//
// AMPGpgBodyView.m
// AMPGpg
//
// Created by Giovanni Simonicca on 17/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import "AMPGpgBodyView.h"
@implementation AMPGpgBodyView
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
[[NSColor redColor] set];
NSRectFill(dirtyRect);
}
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgButton.h
================================================
//
// AMPSwitchButton.h
// AMPSmime
//
// Created by Gio on 15/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
@interface AMPGpgButton : NSButton
{
}
- (id)initWithFrame:(NSRect)frame
image:(NSImage*)image
alt:(NSImage*)altImage
tag:(NSInteger)tag
rememberChoice:(NSInteger)rememberChoiceIn;
- (void) ManageState:(BOOL)enable;
- (BOOL) isActive;
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgButton.m
================================================
//
// AMPSwitchButton.m
// AMPSmime
//
// Created by Gio on 15/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import "AMPGpgButton.h"
@interface AMPGpgButton()
{
BOOL firstInit;
NSInteger rememberChoice;
NSInteger savedState;
}
@end
@implementation AMPGpgButton
- (id)initWithFrame:(NSRect)frame
image:(NSImage*)image
alt:(NSImage*)altImage
tag:(NSInteger)tag
rememberChoice:(NSInteger)rememberChoiceIn
{
self = [super initWithFrame:frame];
if (self)
{
rememberChoice = rememberChoiceIn;
[self setAction:@selector(SwitchBtn:)];
[self setTarget:self];
[self setBordered:NO];
[self setButtonType:NSToggleButton];
[self setTitle:@""];
[self setTag:tag];
[self setImage:altImage];
[self setAlternateImage:image];
savedState = [[NSUserDefaults standardUserDefaults] integerForKey:[NSString stringWithFormat:@"AMPGpgButton_%ld",self.tag]];
[self setState:NSOffState];
}
return self;
}
- (void) SwitchBtn:(NSButton*)btn
{
[[NSUserDefaults standardUserDefaults] setInteger:self.state forKey:[NSString stringWithFormat:@"AMPGpgButton_%ld",self.tag]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (BOOL) isActive;
{
return (BOOL)self.state;
}
- (void) ManageState:(BOOL)enable
{
if(enable)
{
[self setEnabled:YES];
if(rememberChoice == 2 && !firstInit)
{
firstInit = YES;
[self setState:savedState];
}
else
{
[self setState:enable];
}
}
else
{
[self setState:NSOffState];
[self setEnabled:NO];
}
}
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgEncryption.h
================================================
//
// AMPGpgEncryption.h
// AMPGpg
//
// Created by Giovanni Simonicca on 16/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import
@class AMPMessage;
@class AMPMCOMessageParser;
@class AMPComposerInfo;
@class AMPCertManager;
@class AMPComposerInfo;
@class AMPSignatureVerify;
@interface AMPGpgEncryption : NSObject
- (NSInteger) isEncrypted:(AMPMCOMessageParser*)parser;
- (NSInteger) CheckSender:(AMPComposerInfo *)info;
- (NSInteger) CheckRecipients:(AMPComposerInfo *)info;
- (NSString*) Envelope:(NSString*)rfc info:(AMPComposerInfo*)info enc:(BOOL)enc sign:(BOOL)sign;
- (NSData*) Decrypt:(AMPMessage*)message;
- (AMPSignatureVerify*) VerifySignature:(AMPMessage*)message;
- (NSString*) GetHeader:(NSScanner*)scanner header:(NSString*)headerName;
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgEncryption.m
================================================
//
// AMPGpgEncryption.m
// AMPGpg
//
// Created by Giovanni Simonicca on 16/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import "AMPGpgEncryption.h"
#import
#import
//#import "Libmacgpg.h"
NSString * const AMPGpgEncryptionException = @"AMPGpgEncryption_Exception";
@implementation AMPGpgEncryption
#pragma mark - Calls
- (NSInteger) isEncrypted:(AMPMCOMessageParser*)parser
{
NSInteger flag = AMP_ENCRYPTED_NONE;
if(!parser) {
return flag;
}
for(AMPMCOAbstractPart *part in [parser.mainPart AllParts])
{
if(part.mimeType)
{
if([part.mimeType isEqualToString:@"application/pgp-signature"])
flag |= AMP_ENCRYPTED_SIGNED;
if([part.mimeType isEqualToString:@"application/pgp-encrypted"]) //or check multipart/encrypted
flag |= AMP_ENCRYPTED;
}
}
return flag;
}
- (NSInteger) CheckSender:(AMPComposerInfo *)info
{
GPGKey *key = [self GetValidKeyForMail:info.localMessage.from.mail];
if(key.canAnySign)
return 1;
return 0;
}
- (GPGKey*) GetValidKeyForMail:(NSString*)mail
{
NSSet *keys = [[GPGKeyManager sharedInstance] allKeys];
for (GPGKey *key in keys)
{
if ([self isKey: key forEmail: mail] && [self checkValidityOfKey: key])
{
return key;
}
}
return nil;
}
- (BOOL)isKey: (GPGKey *)key
forEmail: (NSString *)email
{
for (GPGUserID *uid in key.userIDs)
{
if([uid.email isEqualToString: email])
{
return true;
}
}
return false;
}
- (BOOL)checkValidityOfKey: (GPGKey *)key
{
if(key.validity == GPGValidityFull || key.validity == GPGValidityUltimate)
{
return true;
}
return false;
}
- (GPGKey *) getKeyFromMail: (NSString *)mail
{
for(GPGKey *key in [[GPGKeyManager sharedInstance] allKeys])
{
for (GPGUserID *uid in key.userIDs) {
if([uid.email isEqualToString:mail])
{
return key;
}
}
}
return nil;
}
- (NSInteger) CheckRecipients:(AMPComposerInfo *)info
{
NSArray *mails = [info.localMessage GetMails];
if(mails.count == 0)
return 0;
NSSet *keys = [[GPGKeyManager sharedInstance] allKeys];
if(keys.count == 0)
return 0;
for(NSString *mail in mails)
{
GPGKey *key = [self GetValidKeyForMail:mail];
if(!key || !key.canAnyEncrypt || key.validity >= GPGValidityInvalid)
return 0;
}
return 1;
}
- (NSString*) Envelope:(NSString*)rfc info:(AMPComposerInfo*)info enc:(BOOL)enc sign:(BOOL)sign
{
if(!rfc)
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Envelope missing rfc input" userInfo:nil];
NSString *from = info.localMessage.from.mail;
if(!from)
@throw ([NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Envelope cannot get the from of the message" userInfo:nil]);
NSDictionary *maps = [info.localMessage GetMailsMaps];
NSMutableArray *recipients = [NSMutableArray array];
[recipients addObjectsFromArray:maps[@"to"]];
[recipients addObjectsFromArray:maps[@"cc"]];
[recipients addObject:from]; //Encrypt also with my key to read it in sent messages
NSArray *hiddenRecipients = maps[@"bcc"];
NSString *rfcFinal = rfc;
//SIGN
if(sign)
rfcFinal = [self Sign:rfc from:from recipients:recipients hiddenRecipients:hiddenRecipients];
if(!rfcFinal)
@throw ([NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Envelope cannot sign the message" userInfo:nil]);
//ENCRYPT
if(enc)
rfcFinal = [self Encrypt:rfcFinal from:from recipients:recipients hiddenRecipients:hiddenRecipients];
if(!rfcFinal)
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Envelope cannot encrypt the message" userInfo:nil];
return rfcFinal;
}
- (NSData*) Decrypt:(AMPMessage*)message
{
NSData *data = message.rfcData;
if(!data)
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Decrypt missing data to decrypt" userInfo:nil];
AMPMCOMessageParser *parser = [AMPMCOMessageParser messageParserWithData:data];
if(!parser)
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Decrypt cannot parse the data" userInfo:nil];;
NSArray *encParts = [parser.mainPart PartsForMime:@"application/octet-stream"];
for (int i = 0; i < [encParts count]; i++) {
AMPMCOAbstractPart *part = [encParts objectAtIndex:i];
if(![part.filename hasSuffix:@".asc"])
continue;
/*@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Decrypt cannot find encrypted.asc" userInfo:nil];;*/
NSData *dataAttachment = [part callSelector:@selector(data)];
if(!dataAttachment || dataAttachment.length == 0) {
NSLog(@"GPG Decrypt cannot get data from encrypted attachment");
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Decrypt cannot get data from encrypted attachment" userInfo:nil];
}
NSData *decodedData = [[GPGController gpgController] decryptData:dataAttachment];
if(!decodedData || decodedData.length == 0) {
NSLog(@"GPG Decrypt cannot decryptData");
continue;
/*@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG Decrypt cannot decryptData" userInfo:nil];*/
}
return decodedData;
}
NSLog(@"GPG Decrypt Failed");
return nil;
}
- (AMPSignatureVerify*) VerifySignature:(AMPMessage*)message
{
AMPSignatureVerify *ver = [AMPSignatureVerify new];
ver.signatureVerify = AMP_SIGNED_NONE;
ver.mimetoRemove = @[@"application/pgp-signature"];
NSData *messageData = message.rfcData;
if(!messageData)
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG VerifySignature missing data to decrypt" userInfo:nil];;
NSData *detachedData = nil;
//Se e' signed uso detached content
AMPMCOMessageParser *parser = [AMPMCOMessageParser messageParserWithData:messageData];
if(parser.mainPart.partType == AMPMCOPartTypeMultipartSigned)
{
NSString *rfc = [[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding];
detachedData = [self GetSignedPart:rfc];
if(!detachedData)
@throw [NSException exceptionWithName:AMPGpgEncryptionException reason:@"GPG VerifySignature cannot extract detached data" userInfo:nil];;
}
NSArray *encParts = [parser.mainPart PartsForMime:@"application/pgp-signature"];
if(encParts.count == 1)
{
ver.signatureVerify = AMP_SIGNED_FAILS;
AMPMCOAbstractPart *part = encParts[0];
if(![part.filename isEqualToString:@"signature.asc"])
return ver;
NSData *dataAttachment = [part callSelector:@selector(data)];
if(!dataAttachment)
return ver;
NSArray *arr = [[GPGController gpgController] verifySignature:dataAttachment originalData:detachedData];
//CASE 1 Signer >> multi-signer does not work we have only 1 sender
for(GPGSignature *sign in arr)
{
if(sign.trust < GPGValidityInvalid )
{
for(GPGKey *key in [[GPGKeyManager sharedInstance] allKeys])
{
if( [sign.email isEqualToString:key.email] ) {
for (GPGUserID *uid in key.userIDs) {
if([uid.email isEqualToString:message.from.mail])
{
ver.signatureVerify = AMP_SIGNED_SUCCESS;
return ver;
}
}
}
}
}
}
}
return ver;
}
#pragma mark - Encrypt/Sign
- (NSString*) Encrypt:(NSString*)rfc from:(NSString*)mail recipients:(NSArray*)recipients hiddenRecipients:(NSArray*)hiddenRecipients
{
//Exctract ctype + body
NSString *stringToEncrypt = [self GetBodyPartWithHeaders:rfc];
if(!stringToEncrypt) return nil;
NSData *dataToEncrypt = [stringToEncrypt dataUsingEncoding:NSUTF8StringEncoding];
if(!dataToEncrypt || dataToEncrypt.length == 0) return nil;
GPGController *gpgc = [GPGController gpgController];
gpgc.useArmor = YES;
gpgc.useTextMode = YES;
// gpgc.trustAllKeys = YES;
NSData *dataEncrypted = nil;
@try {
dataEncrypted = [gpgc processData:dataToEncrypt withEncryptSignMode:GPGPublicKeyEncrypt recipients:recipients hiddenRecipients:hiddenRecipients];
}
@catch (NSException *exception) {
return nil;
}
if(!dataEncrypted || dataEncrypted.length == 0) return nil;
//NSData *decodedData = [[GPGController gpgController] decryptData:dataEncrypted];
NSString *rfcret = [self CreateRfcEncrypted:rfc dataEncrypted:dataEncrypted];
return rfcret;
}
- (NSString*) Sign:(NSString*)rfc from:(NSString*)from recipients:(NSArray*)recipients hiddenRecipients:(NSArray*)hiddenRecipients
{
NSString *stringToSign = [self GetBodyPartWithHeaders:rfc];
stringToSign = [stringToSign stringByAppendingString:@"\r\n"];
if(!stringToSign) return nil;
//Sign the content
NSData *dataToSign = [stringToSign dataUsingEncoding:NSUTF8StringEncoding];
if(!dataToSign) return nil;
GPGController *gpgc = [GPGController gpgController];
gpgc.useArmor = YES;
gpgc.useTextMode = YES;
// gpgc.trustAllKeys = YES;
GPGKey *key = [self GetValidKeyForMail:from];
if(!key)
{
return nil;
}
[gpgc setSignerKey:key];
NSData *dataSigned = [gpgc processData:dataToSign withEncryptSignMode: GPGDetachedSign recipients:NULL hiddenRecipients:NULL];
if(!dataSigned) return nil;
NSString *nameForHashAlgorithm = [GPGController nameForHashAlgorithm: [gpgc hashAlgorithm]];
return [self CreateRfcSigned:rfc stringToSign:stringToSign dataSigned:dataSigned nameForHashAlgorithm:nameForHashAlgorithm];
}
#pragma mark Mime
- (NSString*) CreateRfcEncrypted:(NSString*)rfc dataEncrypted:(NSData*)dataEncrypted
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
NSString *boundary = (__bridge_transfer NSString *)string;
if(!boundary)
boundary = @"------=_Part_68593_50468503.1397487740428";
// Content-Type: multipart/encrypted;
// boundary="Apple-Mail=_A3AEE18D-B565-4A74-B695-C9C48DBE43AC";
// protocol="application/pgp-encrypted";
NSString *multipartSignedCtype = @"Content-Type: multipart/encrypted;\r\n";
multipartSignedCtype = [multipartSignedCtype stringByAppendingFormat:@"\tboundary=\"%@\";\r\n",boundary];
multipartSignedCtype = [multipartSignedCtype stringByAppendingString:@"\tprotocol=\"application/pgp-encrypted\";\r\n"];
multipartSignedCtype = [multipartSignedCtype stringByAppendingString:@"Content-Description: OpenPGP encrypted message"];
NSString *dataEncryptedStr = [[NSString alloc] initWithData:dataEncrypted encoding:NSASCIIStringEncoding];
NSString *body = @"This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)\r\n";
body = [body stringByAppendingFormat:@"--%@\r\n",boundary];
body = [body stringByAppendingString:@"Content-Transfer-Encoding: 7bit\r\n"];
body = [body stringByAppendingString:@"Content-Type: application/pgp-encrypted\r\n"];
body = [body stringByAppendingString:@"Content-Description: PGP/MIME Versions Identification\r\n"];
body = [body stringByAppendingString:@"\r\n"];
body = [body stringByAppendingString:@"Version: 1\r\n"];
body = [body stringByAppendingString:@"\r\n"];
body = [body stringByAppendingFormat:@"--%@\r\n",boundary];
body = [body stringByAppendingString:@"Content-Transfer-Encoding: 7bit\r\n"];
body = [body stringByAppendingString:@"Content-Disposition: inline; filename=encrypted.asc\r\n"];
body = [body stringByAppendingString:@"Content-Type: application/octet-stream; name=encrypted.asc\r\n"];
body = [body stringByAppendingString:@"Content-Description: OpenPGP encrypted message\r\n"];
body = [body stringByAppendingString:@"\r\n"];
body = [body stringByAppendingString:dataEncryptedStr];
body = [body stringByAppendingString:@"\r\n"];
body = [body stringByAppendingFormat:@"--%@--",boundary];
NSMutableString *rfcOut = [NSMutableString new];
NSString *headersWithNewCType = [self TrascriptHeaders:rfc withNewContentType:multipartSignedCtype];
[rfcOut appendString:headersWithNewCType];
[rfcOut appendString:body];
return rfcOut;
}
- (NSString*) CreateRfcSigned:(NSString*)rfc stringToSign:(NSString*)stringToSign dataSigned:(NSData*)dataSigned nameForHashAlgorithm:(NSString*)nameForHashAlgorithm
{
// Recreate RFC
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
NSString *boundary = (__bridge_transfer NSString *)string;
if(!boundary)
boundary = @"------=_Part_68593_50468503.1397487740428";
//Content-Type: multipart/signed; boundary="Apple-Mail=_1DF223E0-8C6F-4931-9C66-57559AD94CB5"; protocol="application/pgp-signature"; micalg=pgp-sha512
NSString *multipartSignedCtype = @"Content-Type: multipart/signed;\r\n";
multipartSignedCtype = [multipartSignedCtype stringByAppendingFormat:@"\tboundary=\"%@\";\r\n",boundary];
multipartSignedCtype = [multipartSignedCtype stringByAppendingString:@"\tprotocol=\"application/pgp-signature\";\r\n"];
multipartSignedCtype = [multipartSignedCtype stringByAppendingFormat:@"\tmicalg=pgp-%@\r\n",nameForHashAlgorithm];
// ------=_Part_68593_50468503.1397487740429
NSString *partSigned = [NSString stringWithFormat:@"--%@\r\n",boundary];
NSString *dataSignedStr = [[NSString alloc] initWithData:dataSigned encoding:NSASCIIStringEncoding];
// --Apple-Mail=_1DF223E0-8C6F-4931-9C66-57559AD94CB5
// Content-Transfer-Encoding: 7bit
// Content-Disposition: attachment; filename=signature.asc
// Content-Type: application/pgp-signature; name=signature.asc
// Content-Description: Message signed with OpenPGP using GPGMail
NSString *partSignature = [NSString stringWithFormat:@"--%@\r\n",boundary];
partSignature = [partSignature stringByAppendingString:@"Content-Transfer-Encoding: 7bit\r\n"];
partSignature = [partSignature stringByAppendingString:@"Content-Disposition: attachment; filename=signature.asc\r\n"];
partSignature = [partSignature stringByAppendingString:@"Content-Type: application/pgp-signature; name=signature.asc\r\n"];
partSignature = [partSignature stringByAppendingString:@"Content-Description: Message signed with OpenPGP using AMPGpg\r\n"];
partSignature = [partSignature stringByAppendingString:@"\r\n"];
partSignature = [partSignature stringByAppendingString: dataSignedStr];
partSignature = [partSignature stringByAppendingString:@"\r\n"];
partSignature = [partSignature stringByAppendingFormat:@"--%@--",boundary];
NSMutableString *rfcOut = [NSMutableString new];
NSString *headersWithNewCType = [self TrascriptHeaders:rfc withNewContentType:multipartSignedCtype];
[rfcOut appendString:headersWithNewCType];
[rfcOut appendString:partSigned];
[rfcOut appendString:stringToSign];
[rfcOut appendString:@"\r\n"];
[rfcOut appendString:partSignature];
return rfcOut;
}
//Extract the detached content signed
- (NSData*) GetSignedPart:(NSString*)rfc
{
//Content-Type: multipart/signed; boundary="Apple-Mail=_9A3F1E72-6E76-46E6-A41E-A410E2637A5A"; protocol="application/pkcs7-signature"; micalg=sha1
if(!rfc) return nil;
NSScanner *scan = [NSScanner scannerWithString:rfc];
[scan setCharactersToBeSkipped:nil];
if(![scan scanUpAndScan:@"Content-Type:" intoString:nil]) return nil;
NSString *boundary = [self ParseBoundary:scan];
if(!boundary) return nil;
NSArray *boundaries = [self ParsePartsForBoundary:scan boundary:boundary];
if(boundaries && boundaries.count > 0)
{
NSString *detachedString = boundaries[0];
if(detachedString)
return [detachedString dataUsingEncoding:NSASCIIStringEncoding];
}
return nil;
}
//Extract the part to sign/encrypt with its headers
- (NSString*) GetBodyPartWithHeaders:(NSString*)rfc
{
//Content-Type: multipart/signed; boundary="Apple-Mail=_9A3F1E72-6E76-46E6-A41E-A410E2637A5A"; protocol="application/pkcs7-signature"; micalg=sha1
if(!rfc)
return nil;
NSScanner *scanner = [NSScanner scannerWithString:rfc];
[scanner setCharactersToBeSkipped:nil];
NSString *ctype = [self GetHeader:scanner header:@"Content-Type"];
if(!ctype) return nil;
NSScanner *scanner2 = [NSScanner scannerWithString:ctype];
[scanner2 setCharactersToBeSkipped:nil];
NSString *boundary = [self ParseBoundary:scanner2];
if(!boundary)
{
NSScanner *scannerSinglePart = [NSScanner scannerWithString:rfc];
[scannerSinglePart setCharactersToBeSkipped:nil];
if(![scannerSinglePart scanUpAndScan:@"\r\n\r\n" intoString:nil])return nil;
NSString *rfcToSign = [rfc substringFromIndex:scannerSinglePart.scanLocation];
return rfcToSign;
}
NSString *preBoundary = [NSString stringWithFormat:@"--%@",boundary];
NSString *closeBoundary = [NSString stringWithFormat:@"--%@--",boundary];
if(![scanner scanUpToString:preBoundary intoString:nil]) return nil;
NSString *detachedString = nil;
if(![scanner scanUpToString:closeBoundary intoString:&detachedString]) return nil;
if(!detachedString) return nil;
detachedString = [NSString stringWithFormat:@"Content-Type:%@\r\n\r\n%@%@",ctype,detachedString,closeBoundary];
return detachedString; //[detachedString dataUsingEncoding:NSASCIIStringEncoding];
}
- (NSString*) ParseBoundary:(NSScanner*)scanner
{
if(![scanner scanUpToString:@"boundary" intoString:nil]) return nil;
if(![scanner scanUpToString:@"=" intoString:nil]) return nil;
if(![scanner scanUpToString:@"\"" intoString:nil]) return nil;
if(![scanner scanString:@"\"" intoString:nil]) return nil;
NSString *boundary = nil;
if(![scanner scanUpToString:@"\"" intoString:&boundary]) return nil;
if(!boundary) return nil;
return boundary;
}
//Extract the part2 for a given boudary
- (NSArray*) ParsePartsForBoundary:(NSScanner*)scanner boundary:(NSString*)boundary
{
NSMutableArray *ret = [NSMutableArray array];
NSString *preBoundary = [NSString stringWithFormat:@"--%@",boundary];
while(YES)
{
if(![scanner scanUpAndScan:preBoundary intoString:nil]) break;
if([scanner scanString:@"--" intoString:nil]) //chiusura
break;
if(![scanner scanUpAndScan:@"\n" intoString:nil]) break;
NSString *detachedString = nil;
if(![scanner scanUpToString:[NSString stringWithFormat:@"\n%@",preBoundary] intoString:&detachedString])
break;
[ret addObject:detachedString];
}
return ret;
}
//Extract an header from an rfc
- (NSString*) GetHeader:(NSScanner*)scanner header:(NSString*)headerName
{
NSString *header = [headerName stringByAppendingString:@":"];
NSString *newline = @"\r\n";
//Content-Type: application/pkcs7-mime; name=smime.p7m; smime-type=enveloped-data
//Content-Transfer-Encoding: base64
//Content-Disposition:
//Se e' il primo o e' dopo alcuni caratteri
if(![scanner scanUpAndScan:header intoString:nil]) return nil;
NSMutableString *valuex = [NSMutableString new];
while(YES)
{
NSString *valueNext = nil;
if([scanner nextString:newline])
{
valueNext = @"";
}
else if(![scanner scanUpToString:newline intoString:&valueNext])
{
NSLog(@"Error Cannot parse multi header next values in ParseHeader %@",headerName);
return nil;
}
//[valuex appendString:valueNext stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
[valuex appendString:valueNext];
//skippo la newline
if(![scanner scanNext:2])
{
NSLog(@"Error Cannot scan multi header next 2 chars MA_NEWLINE in ParseHeader %@",headerName);
return nil;
}
unichar c = scanner.currentCharacter;
if ([[NSCharacterSet letterCharacterSet] characterIsMember:c] ||
[[NSCharacterSet decimalDigitCharacterSet] characterIsMember:c] ||
[scanner nextString:newline])
{
if(!valuex)
{
NSLog(@"Error value is null in ParseHeader %@",headerName);
return nil;
}
break;
}
else
{
[valuex appendString:newline]; //appendo la newline che ho torvato e continuo a parsare l'header
}
}
return valuex;
}
//Rewrite headers with a new ContentType
- (NSString*) TrascriptHeaders:(NSString*)rfc withNewContentType:(NSString*)ctype
{
NSMutableString *rfcOut = [NSMutableString new];
__block NSInteger ctypeMode = 0;
[rfc enumerateLinesUsingBlock:^(NSString *line, BOOL *stop) {
if([line isEqualToString:@""]) //end of header
{
[rfcOut appendString:@"\r\n"];
*stop = YES;
return;
}
if([line hasPrefix:@"Content-Type"])
ctypeMode = 1; //start
switch (ctypeMode)
{
case 0:
{
[rfcOut appendFormat:@"%@\r\n",line];
}
break;
case 1: //start ctype
{
[rfcOut appendFormat:@"%@\r\n",ctype];
ctypeMode = 2;
}
break;
case 2: //during ctype
{
if([line rangeOfString:@":"].location != NSNotFound) //nuovo header
ctypeMode = 0;
}
break;
}
}];
return rfcOut;
}
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgView.h
================================================
//
// AMPGpgView.h
// AMPGpg
//
// Created by Giovanni Simonicca on 16/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import
@interface AMPGpgView : AMPView
{
}
@end
================================================
FILE: AMPGpg/AMPGpg/AMPGpgView.m
================================================
//
// AMPGpgView.m
// AMPGpg
//
// Created by Giovanni Simonicca on 16/04/14.
// Copyright (c) 2014 bloop. All rights reserved.
//
#import "AMPGpgView.h"
#import "AMPGpg.h"
#import
@interface AMPGpgView()
{
NSPopUpButton *popUpBtnRender;
}
@end
@implementation AMPGpgView
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin *)pluginIn
{
self = [super initWithFrame:frame plugin:pluginIn];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
NSTextField *textSystem = [[NSTextField alloc] initWithFrame:NSMakeRect(x, y+5, 140, 30)];
[textSystem setStringValue:NSLocalizedString(@"Composer:",@"Composer:")];
[textSystem setBezeled:NO];
[textSystem setDrawsBackground:NO];//deprecated
[textSystem setEditable:NO];
[textSystem setSelectable:NO];
[textSystem setAlignment: NSRightTextAlignment];
[self addSubview:textSystem];
NSButton *savePref = [[NSButton alloc] initWithFrame:NSMakeRect(x+160, y, 250, 30)]; //[savePref AssignTEXTUREDROUNDED];
[savePref setButtonType:NSSwitchButton];
[savePref setTitle:NSLocalizedString(@"Remember Choice",@"Remember Choice")];
[savePref setAction:@selector(RememberChoice:)];
[savePref setTarget:self];
[self addSubview:savePref];
[savePref setState:self.myPlugin.rememberChoice-1];
[self LoadView];
}
return self;
}
- (void) RememberChoice:(id)sender
{
self.myPlugin.rememberChoice = [sender state]+1;
[[NSUserDefaults standardUserDefaults] setInteger:self.myPlugin.rememberChoice forKey:AMPGpgRemeberChoice];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (AMPGpg*) myPlugin
{
return (AMPGpg*)self.plugin;
}
- (void) ReloadView
{
dispatch_async(dispatch_get_main_queue(), ^{
[self LoadView];
});
}
- (void) LoadView
{
// NSDictionary *xxx = [AMPCertManager listCertificates];
// NSMenu *menu = [NSMenu new];
//
// [xxx enumerateKeysAndObjectsUsingBlock:^(NSString *name, NSArray *mails, BOOL *stop) {
//
// if(mails.count == 0)
// return;
//
// NSMenuItem *itemRender = [[NSMenuItem alloc] initWithTitle:name action:nil keyEquivalent:@""];
// [itemRender setRepresentedObject:@""];
// [itemRender setTarget:self];
//
// NSMenu *menu2 = [NSMenu new];
// for(NSString *mail in mails)
// {
// NSMenuItem *itemRender2 = [[NSMenuItem alloc] initWithTitle:mail action:@selector(selectedMail:) keyEquivalent:@""];
// [itemRender2 setRepresentedObject:@""];
// [itemRender2 setTarget:self];
// [menu2 addItem:itemRender2];
// }
// [itemRender setSubmenu:menu2];
// [menu addItem:itemRender];
// }];
// [popUpBtnRender setMenu:menu];
}
- (void) selectedMail:(id)sender
{
}
- (void) RenderView
{
}
-(void) Save:(id)sender
{
}
- (void)drawRect:(NSRect)dirtyRect
{
[super drawRect:dirtyRect];
// Drawing code here.
}
@end
================================================
FILE: AMPGpg/AMPGpg/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPGpg/AMPGpg.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
4EBCCA801A975DF7009532B2 /* Libmacgpg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EBCCA751A975DDB009532B2 /* Libmacgpg.framework */; };
B30FF64518FFFCE40053FD49 /* g_unlocked.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF64118FFFCE40053FD49 /* g_unlocked.psd */; };
B30FF64618FFFCE40053FD49 /* g_locked.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF64218FFFCE40053FD49 /* g_locked.psd */; };
B30FF64718FFFCE40053FD49 /* g_inactive.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF64318FFFCE40053FD49 /* g_inactive.psd */; };
B30FF64818FFFCE40053FD49 /* g_active.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF64418FFFCE40053FD49 /* g_active.psd */; };
B30FF67019009F430053FD49 /* gpg_active.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF66C19009F430053FD49 /* gpg_active.psd */; };
B30FF67119009F430053FD49 /* gpg_bad.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF66D19009F430053FD49 /* gpg_bad.psd */; };
B30FF67219009F430053FD49 /* gpg_locked.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF66E19009F430053FD49 /* gpg_locked.psd */; };
B30FF67319009F430053FD49 /* gpg_unlocked.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF66F19009F430053FD49 /* gpg_unlocked.psd */; };
B30FF68919017D2B0053FD49 /* pluginsGPG.psd in Resources */ = {isa = PBXBuildFile; fileRef = B30FF68819017D2B0053FD49 /* pluginsGPG.psd */; };
D83863E32180666D000BE713 /* AMPluginFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F57AC48619E222D7001BE387 /* AMPluginFramework.framework */; };
D84DFB0018FECEDA007B4E49 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D84DFAFF18FECEDA007B4E49 /* Cocoa.framework */; };
D84DFB0A18FECEDA007B4E49 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D84DFB0818FECEDA007B4E49 /* InfoPlist.strings */; };
D84DFB3318FECF12007B4E49 /* AMPGpg.m in Sources */ = {isa = PBXBuildFile; fileRef = D84DFB3218FECF12007B4E49 /* AMPGpg.m */; };
D8E1A6E518FEDF5F00352E29 /* AMPGpgView.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E1A6E418FEDF5F00352E29 /* AMPGpgView.m */; };
D8E1A6E818FEE0BF00352E29 /* AMPGpgEncryption.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E1A6E718FEE0BF00352E29 /* AMPGpgEncryption.m */; };
D8E1A71F18FEEC7100352E29 /* AMPGpgButton.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E1A71E18FEEC7100352E29 /* AMPGpgButton.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
173A8A601F03EB3600E65436 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 30BE73BE1B54015C001A2137;
remoteInfo = UnitTests;
};
4EBCCA741A975DDB009532B2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 8DC2EF5B0486A6940098B216;
remoteInfo = Libmacgpg;
};
4EBCCA781A975DDB009532B2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 1B46CFCC161555DF00CF9C5F;
remoteInfo = org.gpgtools.Libmacgpg.xpc;
};
4EBCCA7C1A975DDB009532B2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 1BD78B9F1726B2820005F251;
remoteInfo = LeakFinder;
};
4EBCCA7E1A975DF1009532B2 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 8DC2EF4F0486A6940098B216;
remoteInfo = Libmacgpg;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
D8CCFE93198A00FA00503D22 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D8E1A71718FEE7B800352E29 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
B30FF64118FFFCE40053FD49 /* g_unlocked.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = g_unlocked.psd; sourceTree = ""; };
B30FF64218FFFCE40053FD49 /* g_locked.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = g_locked.psd; sourceTree = ""; };
B30FF64318FFFCE40053FD49 /* g_inactive.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = g_inactive.psd; sourceTree = ""; };
B30FF64418FFFCE40053FD49 /* g_active.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = g_active.psd; sourceTree = ""; };
B30FF66C19009F430053FD49 /* gpg_active.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = gpg_active.psd; sourceTree = ""; };
B30FF66D19009F430053FD49 /* gpg_bad.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = gpg_bad.psd; sourceTree = ""; };
B30FF66E19009F430053FD49 /* gpg_locked.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = gpg_locked.psd; sourceTree = ""; };
B30FF66F19009F430053FD49 /* gpg_unlocked.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = gpg_unlocked.psd; sourceTree = ""; };
B30FF68819017D2B0053FD49 /* pluginsGPG.psd */ = {isa = PBXFileReference; lastKnownFileType = file; path = pluginsGPG.psd; sourceTree = ""; };
D84DFAFC18FECEDA007B4E49 /* AMPGpg.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMPGpg.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
D84DFAFF18FECEDA007B4E49 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
D84DFB0218FECEDA007B4E49 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D84DFB0318FECEDA007B4E49 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
D84DFB0418FECEDA007B4E49 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
D84DFB0718FECEDA007B4E49 /* AMPGpg-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AMPGpg-Info.plist"; sourceTree = ""; };
D84DFB0918FECEDA007B4E49 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
D84DFB0B18FECEDA007B4E49 /* AMPGpg-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AMPGpg-Prefix.pch"; sourceTree = ""; };
D84DFB3118FECF12007B4E49 /* AMPGpg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPGpg.h; sourceTree = ""; };
D84DFB3218FECF12007B4E49 /* AMPGpg.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPGpg.m; sourceTree = ""; };
D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Libmacgpg.xcodeproj; path = Dependencies/Libmacgpg/Libmacgpg.xcodeproj; sourceTree = ""; };
D8E1A6E318FEDF5F00352E29 /* AMPGpgView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPGpgView.h; sourceTree = ""; };
D8E1A6E418FEDF5F00352E29 /* AMPGpgView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPGpgView.m; sourceTree = ""; };
D8E1A6E618FEE0BF00352E29 /* AMPGpgEncryption.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPGpgEncryption.h; sourceTree = ""; };
D8E1A6E718FEE0BF00352E29 /* AMPGpgEncryption.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPGpgEncryption.m; sourceTree = ""; };
D8E1A71D18FEEC7100352E29 /* AMPGpgButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPGpgButton.h; sourceTree = ""; };
D8E1A71E18FEEC7100352E29 /* AMPGpgButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPGpgButton.m; sourceTree = ""; };
F57AC48619E222D7001BE387 /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPluginFramework.framework; path = ../AMPluginFramework.framework; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D84DFAF918FECEDA007B4E49 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4EBCCA801A975DF7009532B2 /* Libmacgpg.framework in Frameworks */,
D84DFB0018FECEDA007B4E49 /* Cocoa.framework in Frameworks */,
D83863E32180666D000BE713 /* AMPluginFramework.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
4EBCCA6D1A975DDB009532B2 /* Products */ = {
isa = PBXGroup;
children = (
4EBCCA751A975DDB009532B2 /* Libmacgpg.framework */,
173A8A611F03EB3600E65436 /* UnitTests.xctest */,
4EBCCA7D1A975DDB009532B2 /* LeakFinder.app */,
4EBCCA791A975DDB009532B2 /* org.gpgtools.Libmacgpg.xpc */,
);
name = Products;
sourceTree = "";
};
D84DFAF318FECEDA007B4E49 = {
isa = PBXGroup;
children = (
D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */,
D84DFB0518FECEDA007B4E49 /* AMPGpg */,
D84DFAFE18FECEDA007B4E49 /* Frameworks */,
D84DFAFD18FECEDA007B4E49 /* Products */,
);
sourceTree = "";
};
D84DFAFD18FECEDA007B4E49 /* Products */ = {
isa = PBXGroup;
children = (
D84DFAFC18FECEDA007B4E49 /* AMPGpg.bundle */,
);
name = Products;
sourceTree = "";
};
D84DFAFE18FECEDA007B4E49 /* Frameworks */ = {
isa = PBXGroup;
children = (
F57AC48619E222D7001BE387 /* AMPluginFramework.framework */,
D84DFAFF18FECEDA007B4E49 /* Cocoa.framework */,
D84DFB0118FECEDA007B4E49 /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "";
};
D84DFB0118FECEDA007B4E49 /* Other Frameworks */ = {
isa = PBXGroup;
children = (
D84DFB0218FECEDA007B4E49 /* Foundation.framework */,
D84DFB0318FECEDA007B4E49 /* CoreData.framework */,
D84DFB0418FECEDA007B4E49 /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "";
};
D84DFB0518FECEDA007B4E49 /* AMPGpg */ = {
isa = PBXGroup;
children = (
D84DFB3118FECF12007B4E49 /* AMPGpg.h */,
D84DFB3218FECF12007B4E49 /* AMPGpg.m */,
D8E1A6E318FEDF5F00352E29 /* AMPGpgView.h */,
D8E1A6E418FEDF5F00352E29 /* AMPGpgView.m */,
D8E1A6E618FEE0BF00352E29 /* AMPGpgEncryption.h */,
D8E1A6E718FEE0BF00352E29 /* AMPGpgEncryption.m */,
D8E1A71D18FEEC7100352E29 /* AMPGpgButton.h */,
D8E1A71E18FEEC7100352E29 /* AMPGpgButton.m */,
D84DFB0618FECEDA007B4E49 /* Supporting Files */,
);
path = AMPGpg;
sourceTree = "";
};
D84DFB0618FECEDA007B4E49 /* Supporting Files */ = {
isa = PBXGroup;
children = (
B30FF68819017D2B0053FD49 /* pluginsGPG.psd */,
B30FF66C19009F430053FD49 /* gpg_active.psd */,
B30FF66D19009F430053FD49 /* gpg_bad.psd */,
B30FF66E19009F430053FD49 /* gpg_locked.psd */,
B30FF66F19009F430053FD49 /* gpg_unlocked.psd */,
B30FF64118FFFCE40053FD49 /* g_unlocked.psd */,
B30FF64218FFFCE40053FD49 /* g_locked.psd */,
B30FF64318FFFCE40053FD49 /* g_inactive.psd */,
B30FF64418FFFCE40053FD49 /* g_active.psd */,
D84DFB0718FECEDA007B4E49 /* AMPGpg-Info.plist */,
D84DFB0818FECEDA007B4E49 /* InfoPlist.strings */,
D84DFB0B18FECEDA007B4E49 /* AMPGpg-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
D84DFAFB18FECEDA007B4E49 /* AMPGpg */ = {
isa = PBXNativeTarget;
buildConfigurationList = D84DFB0E18FECEDA007B4E49 /* Build configuration list for PBXNativeTarget "AMPGpg" */;
buildPhases = (
D84DFAF818FECEDA007B4E49 /* Sources */,
D84DFAF918FECEDA007B4E49 /* Frameworks */,
D8E1A71718FEE7B800352E29 /* CopyFiles */,
D84DFAFA18FECEDA007B4E49 /* Resources */,
D8CCFE93198A00FA00503D22 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
4EBCCA7F1A975DF1009532B2 /* PBXTargetDependency */,
);
name = AMPGpg;
productName = AMPGpg;
productReference = D84DFAFC18FECEDA007B4E49 /* AMPGpg.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D84DFAF418FECEDA007B4E49 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = bloop;
TargetAttributes = {
D84DFAFB18FECEDA007B4E49 = {
DevelopmentTeam = 2E337YPCZY;
};
};
};
buildConfigurationList = D84DFAF718FECEDA007B4E49 /* Build configuration list for PBXProject "AMPGpg" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = D84DFAF318FECEDA007B4E49;
productRefGroup = D84DFAFD18FECEDA007B4E49 /* Products */;
projectDirPath = "";
projectReferences = (
{
ProductGroup = 4EBCCA6D1A975DDB009532B2 /* Products */;
ProjectRef = D8CCFE97198A01A900503D22 /* Libmacgpg.xcodeproj */;
},
);
projectRoot = "";
targets = (
D84DFAFB18FECEDA007B4E49 /* AMPGpg */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
173A8A611F03EB3600E65436 /* UnitTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = UnitTests.xctest;
remoteRef = 173A8A601F03EB3600E65436 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4EBCCA751A975DDB009532B2 /* Libmacgpg.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = Libmacgpg.framework;
remoteRef = 4EBCCA741A975DDB009532B2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4EBCCA791A975DDB009532B2 /* org.gpgtools.Libmacgpg.xpc */ = {
isa = PBXReferenceProxy;
fileType = "wrapper.xpc-service";
path = org.gpgtools.Libmacgpg.xpc;
remoteRef = 4EBCCA781A975DDB009532B2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4EBCCA7D1A975DDB009532B2 /* LeakFinder.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = LeakFinder.app;
remoteRef = 4EBCCA7C1A975DDB009532B2 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
D84DFAFA18FECEDA007B4E49 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B30FF67319009F430053FD49 /* gpg_unlocked.psd in Resources */,
B30FF64718FFFCE40053FD49 /* g_inactive.psd in Resources */,
B30FF64818FFFCE40053FD49 /* g_active.psd in Resources */,
B30FF67219009F430053FD49 /* gpg_locked.psd in Resources */,
B30FF64518FFFCE40053FD49 /* g_unlocked.psd in Resources */,
B30FF68919017D2B0053FD49 /* pluginsGPG.psd in Resources */,
B30FF64618FFFCE40053FD49 /* g_locked.psd in Resources */,
B30FF67019009F430053FD49 /* gpg_active.psd in Resources */,
D84DFB0A18FECEDA007B4E49 /* InfoPlist.strings in Resources */,
B30FF67119009F430053FD49 /* gpg_bad.psd in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D84DFAF818FECEDA007B4E49 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D8E1A71F18FEEC7100352E29 /* AMPGpgButton.m in Sources */,
D8E1A6E518FEDF5F00352E29 /* AMPGpgView.m in Sources */,
D8E1A6E818FEE0BF00352E29 /* AMPGpgEncryption.m in Sources */,
D84DFB3318FECF12007B4E49 /* AMPGpg.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
4EBCCA7F1A975DF1009532B2 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = Libmacgpg;
targetProxy = 4EBCCA7E1A975DF1009532B2 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
D84DFB0818FECEDA007B4E49 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
D84DFB0918FECEDA007B4E49 /* en */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
D84DFB0C18FECEDA007B4E49 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
D84DFB0D18FECEDA007B4E49 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
};
D84DFB0F18FECEDA007B4E49 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "Developer ID Application";
COMBINE_HIDPI_IMAGES = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 2E337YPCZY;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
"\"$(SRCROOT)/../",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AMPGpg/AMPGpg-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"\"$(SRCROOT)/Dependencies/Libmacgpg/build/Debug/Libmacgpg.framework/Headers/\"",
"\"$(SRCROOT)/../AMPluginFramework.framework/Headers/\"",
);
INFOPLIST_FILE = "AMPGpg/AMPGpg-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = "-L/usr/local/opt/openssl/lib/";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
D84DFB1018FECEDA007B4E49 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
"\"$(SRCROOT)/../",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AMPGpg/AMPGpg-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"\"$(SRCROOT)/Dependencies/Libmacgpg/build/Debug/Libmacgpg.framework/Headers/\"",
"\"$(SRCROOT)/../AMPluginFramework.framework/Headers/\"/**",
);
INFOPLIST_FILE = "AMPGpg/AMPGpg-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
OTHER_CODE_SIGN_FLAGS = "--deep";
OTHER_LDFLAGS = "-L/usr/local/opt/openssl/lib/";
PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D84DFAF718FECEDA007B4E49 /* Build configuration list for PBXProject "AMPGpg" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D84DFB0C18FECEDA007B4E49 /* Debug */,
D84DFB0D18FECEDA007B4E49 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D84DFB0E18FECEDA007B4E49 /* Build configuration list for PBXNativeTarget "AMPGpg" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D84DFB0F18FECEDA007B4E49 /* Debug */,
D84DFB1018FECEDA007B4E49 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D84DFAF418FECEDA007B4E49 /* Project object */;
}
================================================
FILE: AMPMessageStyle/AMPMessageStyle.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
88468D42183AB9B800E0E092 /* AMPluginFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8E492341832308F00E39B37 /* AMPluginFramework.framework */; };
889343EC1838499E00DCC2F9 /* AMPMessageStyle.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = D87723AA18321026001C10AE /* AMPMessageStyle.bundle */; };
D876CA4A18334FAB00FFB561 /* Taxi.css in Resources */ = {isa = PBXBuildFile; fileRef = D876CA4618334FAB00FFB561 /* Taxi.css */; };
D876CA4B18334FAB00FFB561 /* base2.css in Resources */ = {isa = PBXBuildFile; fileRef = D876CA4718334FAB00FFB561 /* base2.css */; };
D876CA4C18334FAB00FFB561 /* base3.css in Resources */ = {isa = PBXBuildFile; fileRef = D876CA4818334FAB00FFB561 /* base3.css */; };
D876CA4D18334FAB00FFB561 /* base4.css in Resources */ = {isa = PBXBuildFile; fileRef = D876CA4918334FAB00FFB561 /* base4.css */; };
D87723B818321026001C10AE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D87723B618321026001C10AE /* InfoPlist.strings */; };
D87723C118321074001C10AE /* AMPMessageStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = D87723C018321074001C10AE /* AMPMessageStyle.m */; };
D8E0A41E1832234C00A294AF /* AMPMessageStyleView.m in Sources */ = {isa = PBXBuildFile; fileRef = D8E0A41D1832234C00A294AF /* AMPMessageStyleView.m */; };
D8E4922718322F1400E39B37 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D87723AD18321026001C10AE /* Cocoa.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
889343EB1838497E00DCC2F9 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "~/Library/Containers/it.bloop.airmail.beta8/Data/Library/Application Support/Airmail/General/Plugins";
dstSubfolderSpec = 0;
files = (
889343EC1838499E00DCC2F9 /* AMPMessageStyle.bundle in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
B3F625B718D7ABB000A3AA80 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/InfoPlist.strings"; sourceTree = ""; };
D876CA4618334FAB00FFB561 /* Taxi.css */ = {isa = PBXFileReference; explicitFileType = text.css; fileEncoding = 4; path = Taxi.css; sourceTree = ""; };
D876CA4718334FAB00FFB561 /* base2.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = base2.css; sourceTree = ""; };
D876CA4818334FAB00FFB561 /* base3.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = base3.css; sourceTree = ""; };
D876CA4918334FAB00FFB561 /* base4.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = base4.css; sourceTree = ""; };
D87723AA18321026001C10AE /* AMPMessageStyle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMPMessageStyle.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
D87723AD18321026001C10AE /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
D87723B018321026001C10AE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D87723B118321026001C10AE /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
D87723B218321026001C10AE /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
D87723B518321026001C10AE /* AMPMessageStyle-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AMPMessageStyle-Info.plist"; sourceTree = ""; };
D87723B718321026001C10AE /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
D87723B918321026001C10AE /* AMPMessageStyle-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AMPMessageStyle-Prefix.pch"; sourceTree = ""; };
D87723BF18321074001C10AE /* AMPMessageStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPMessageStyle.h; sourceTree = ""; };
D87723C018321074001C10AE /* AMPMessageStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPMessageStyle.m; sourceTree = ""; };
D8E0A41C1832234C00A294AF /* AMPMessageStyleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPMessageStyleView.h; sourceTree = ""; };
D8E0A41D1832234C00A294AF /* AMPMessageStyleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPMessageStyleView.m; sourceTree = ""; };
D8E492341832308F00E39B37 /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPluginFramework.framework; path = ../AMPluginFramework/build/Debug/AMPluginFramework.framework; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D87723A718321026001C10AE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
88468D42183AB9B800E0E092 /* AMPluginFramework.framework in Frameworks */,
D8E4922718322F1400E39B37 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
886FF103183783C100247F22 /* css */ = {
isa = PBXGroup;
children = (
D876CA4618334FAB00FFB561 /* Taxi.css */,
D876CA4718334FAB00FFB561 /* base2.css */,
D876CA4818334FAB00FFB561 /* base3.css */,
D876CA4918334FAB00FFB561 /* base4.css */,
);
name = css;
sourceTree = "";
};
D87723A118321026001C10AE = {
isa = PBXGroup;
children = (
D87723B318321026001C10AE /* AirmailCss */,
D87723AC18321026001C10AE /* Frameworks */,
D87723AB18321026001C10AE /* Products */,
);
sourceTree = "";
};
D87723AB18321026001C10AE /* Products */ = {
isa = PBXGroup;
children = (
D87723AA18321026001C10AE /* AMPMessageStyle.bundle */,
);
name = Products;
sourceTree = "";
};
D87723AC18321026001C10AE /* Frameworks */ = {
isa = PBXGroup;
children = (
D87723AD18321026001C10AE /* Cocoa.framework */,
D87723AF18321026001C10AE /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "";
};
D87723AF18321026001C10AE /* Other Frameworks */ = {
isa = PBXGroup;
children = (
D8E492341832308F00E39B37 /* AMPluginFramework.framework */,
D87723B018321026001C10AE /* Foundation.framework */,
D87723B118321026001C10AE /* CoreData.framework */,
D87723B218321026001C10AE /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "";
};
D87723B318321026001C10AE /* AirmailCss */ = {
isa = PBXGroup;
children = (
D87723BF18321074001C10AE /* AMPMessageStyle.h */,
D87723C018321074001C10AE /* AMPMessageStyle.m */,
D8E0A41C1832234C00A294AF /* AMPMessageStyleView.h */,
D8E0A41D1832234C00A294AF /* AMPMessageStyleView.m */,
D87723B418321026001C10AE /* Supporting Files */,
);
path = AirmailCss;
sourceTree = "";
};
D87723B418321026001C10AE /* Supporting Files */ = {
isa = PBXGroup;
children = (
886FF103183783C100247F22 /* css */,
D87723B518321026001C10AE /* AMPMessageStyle-Info.plist */,
D87723B618321026001C10AE /* InfoPlist.strings */,
D87723B918321026001C10AE /* AMPMessageStyle-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
D87723A918321026001C10AE /* AMPMessageStyle */ = {
isa = PBXNativeTarget;
buildConfigurationList = D87723BC18321026001C10AE /* Build configuration list for PBXNativeTarget "AMPMessageStyle" */;
buildPhases = (
D87723A618321026001C10AE /* Sources */,
D87723A718321026001C10AE /* Frameworks */,
D87723A818321026001C10AE /* Resources */,
889343EB1838497E00DCC2F9 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = AMPMessageStyle;
productName = AirmailCss;
productReference = D87723AA18321026001C10AE /* AMPMessageStyle.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D87723A218321026001C10AE /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = Bloop;
};
buildConfigurationList = D87723A518321026001C10AE /* Build configuration list for PBXProject "AMPMessageStyle" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
"es-419",
);
mainGroup = D87723A118321026001C10AE;
productRefGroup = D87723AB18321026001C10AE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D87723A918321026001C10AE /* AMPMessageStyle */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D87723A818321026001C10AE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D876CA4A18334FAB00FFB561 /* Taxi.css in Resources */,
D876CA4B18334FAB00FFB561 /* base2.css in Resources */,
D876CA4C18334FAB00FFB561 /* base3.css in Resources */,
D876CA4D18334FAB00FFB561 /* base4.css in Resources */,
D87723B818321026001C10AE /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D87723A618321026001C10AE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D8E0A41E1832234C00A294AF /* AMPMessageStyleView.m in Sources */,
D87723C118321074001C10AE /* AMPMessageStyle.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
D87723B618321026001C10AE /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
D87723B718321026001C10AE /* en */,
B3F625B718D7ABB000A3AA80 /* es-419 */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
D87723BA18321026001C10AE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
D87723BB18321026001C10AE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx;
};
name = Release;
};
D87723BD18321026001C10AE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail/AMPluginFramework/build/Debug,
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AirmailCss/AMPMessageStyle-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/AMPluginFramework/build/Debug/AMPluginFramework.framework/Versions/A/Headers,
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = "AirmailCss/AMPMessageStyle-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_NAME = AMPMessageStyle;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
D87723BE18321026001C10AE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail/AMPluginFramework/build/Debug,
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "AirmailCss/AMPMessageStyle-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/AMPluginFramework/build/Debug/AMPluginFramework.framework/Versions/A/Headers,
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
);
INFOPLIST_FILE = "AirmailCss/AMPMessageStyle-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_NAME = AMPMessageStyle;
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D87723A518321026001C10AE /* Build configuration list for PBXProject "AMPMessageStyle" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D87723BA18321026001C10AE /* Debug */,
D87723BB18321026001C10AE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D87723BC18321026001C10AE /* Build configuration list for PBXNativeTarget "AMPMessageStyle" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D87723BD18321026001C10AE /* Debug */,
D87723BE18321026001C10AE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D87723A218321026001C10AE /* Project object */;
}
================================================
FILE: AMPMessageStyle/AMPMessageStyle.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: AMPMessageStyle/AirmailCss/AMPMessageStyle-Info.plist
================================================
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
it.bloop.airmail.plugin.css.render
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2013 Bloop. All rights reserved.
NSPrincipalClass
AMPMessageStyle
================================================
FILE: AMPMessageStyle/AirmailCss/AMPMessageStyle-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import
#endif
================================================
FILE: AMPMessageStyle/AirmailCss/AMPMessageStyle.h
================================================
//
// AirmailCss.h
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
#import
@interface AMPMessageStyle : AMPlugin
{
}
@property (strong) NSMutableArray *cssList;
@property (strong) NSString *cssString;
- (NSString*) savedPath;
- (void) changeCss:(NSString*)str;
@end
================================================
FILE: AMPMessageStyle/AirmailCss/AMPMessageStyle.m
================================================
//
// AirmailCss.m
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import "AMPMessageStyle.h"
#import "AMPMessageStyleView.h"
const NSString *ampcss_render_css_option = @"ampcss_render_css_option";
@implementation AMPMessageStyle
- (id)init
{
self = [super init];
if (self)
{
self.cssString = @"";
}
return self;
}
- (BOOL) Load
{
if(![super Load])
return NO;
self.cssList = [NSMutableArray array];
//Load Bundle
NSMutableArray *allpaths = [NSMutableArray array];
NSArray *bundlesPath = [self bundlepathContents];
if(!bundlesPath)
return NO;
[allpaths addObjectsFromArray:bundlesPath];
NSArray *dirPaths = [self suggestedpathContents];
if(!dirPaths)
return NO;
[allpaths addObjectsFromArray:dirPaths];
for(NSString *path in allpaths)
{
if([path.pathExtension isEqualToString:@"css"])
[self.cssList addObject:path];
}
//Load Preference
NSString *path = [self.preferences objectForKey:ampcss_render_css_option];
if(path && [path isKindOfClass:[NSString class]])
self.cssString = [self LoadCssStringForPath:path];
[self Reload];
return YES;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (void) Reload
{
[self.myView ReloadView];
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPMessageStyleView alloc] initWithFrame:NSZeroRect plugin:self];
return self.myView;
}
- (NSString*) nametext
{
return @"Message Style SDK";
}
- (NSString*) description
{
return self.nametext;
}
- (NSString*) descriptiontext
{
return @"With this plugin you can override the rendering css of the messages.";
}
- (NSString*) authortext
{
return @"Airmail SDK Sample";
}
- (NSString*) supportlink
{
return @"http://adv.bloop.info/airmail/sdk.php";
}
- (NSImage*) icon
{
return [NSImage imageNamed:@"iconx"];
}
#pragma mark - AM called methods
- (NSString*) ampStackMessageRenderFromHtml:(NSString*)html message:(AMPMessage*)message
{
if(self.cssString.length == 0 || !message)
return html;
NSString *htmlRet = [NSString stringWithFormat:@"%@",self.cssString,html];
return htmlRet;
}
#pragma mark - manage css
-(NSString*) savedPath
{
return [self.preferences objectForKey:ampcss_render_css_option];
}
- (NSString*) LoadCssStringForPath:(NSString*)path
{
NSError *err = nil;
NSString *str = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&err];
if(err)
{
str = @"";
[self LogError:[NSString stringWithFormat:@"Cannot load css %@",path]];
}
return str;
}
- (void) changeCss:(NSString*)str
{
if(str.length == 0)
{
[self.preferences removeObjectForKey:ampcss_render_css_option];
self.cssString = @"";
}
else
{
[self.preferences removeObjectForKey:ampcss_render_css_option];
[self.preferences setObject:str forKey:ampcss_render_css_option];
self.cssString = [self LoadCssStringForPath:str];
}
[self SavePreferences];
}
@end
================================================
FILE: AMPMessageStyle/AirmailCss/AMPMessageStyleView.h
================================================
//
// CssView.h
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@class AMPMessageStyle;
@interface AMPMessageStyleView : AMPView
{
NSPopUpButton *popUpBtnRender;
}
@end
================================================
FILE: AMPMessageStyle/AirmailCss/AMPMessageStyleView.m
================================================
//
// CssView.m
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import "AMPMessageStyleView.h"
#import "AMPMessageStyle.h"
@implementation AMPMessageStyleView
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin *)pluginIn
{
self = [super initWithFrame:frame plugin:pluginIn];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(x+3, y, 250, 20)];
[textField setStringValue:NSLocalizedString(@"Style Selector:",@"Style Selector:")];
[textField setBezeled:NO];
[textField setDrawsBackground:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont systemFontOfSize:13]];
[[textField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[textField setAlignment: NSRightTextAlignment];
[self addSubview:textField];
popUpBtnRender = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(x+270, y, 200, 30) pullsDown:NO];
[(NSPopUpButtonCell *)[popUpBtnRender cell] setBezelStyle:NSTexturedRoundedBezelStyle];
[[popUpBtnRender cell] setArrowPosition:NSPopUpArrowAtBottom];
[popUpBtnRender setAutoresizingMask:NSViewMaxYMargin];
[self addSubview:popUpBtnRender];
[self LoadView];
}
return self;
}
- (AMPMessageStyle*) myPlugin
{
return (AMPMessageStyle*)self.plugin;
}
- (void) ReloadView
{
dispatch_async(dispatch_get_main_queue(), ^{
[self LoadView];
});
}
- (void) LoadView
{
//Render
NSArray *csss = [self.myPlugin.cssList sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
return [a caseInsensitiveCompare:b];
}];
[popUpBtnRender.menu removeAllItems];
NSMenuItem *itemRender = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"None", @"None") action:nil keyEquivalent:@""];
[itemRender setRepresentedObject:@""];
[itemRender setAction:@selector(changeCss:)];
[itemRender setTarget:self];
[popUpBtnRender.menu addItem:itemRender];
[csss enumerateObjectsUsingBlock:^(NSString *path, NSUInteger idx, BOOL *stop) {
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:path.lastPathComponent.stringByDeletingPathExtension action:nil keyEquivalent:@""];
[item setRepresentedObject:path];
[item setAction:@selector(changeCss:)];
[item setTarget:self];
[popUpBtnRender.menu addItem:item];
}];
NSString *pathRender = [self.myPlugin savedPath];
if(pathRender && [pathRender isKindOfClass:[NSString class]])
{
for(NSMenuItem *item in popUpBtnRender.menu.itemArray)
{
if([item.representedObject isEqualToString:pathRender])
{
[popUpBtnRender selectItem:item];
break;
}
}
}
}
- (void) RenderView
{
}
- (void) changeCss:(NSMenuItem*)item
{
[self.myPlugin changeCss:item.representedObject];
}
//- (void)drawRect:(NSRect)dirtyRect
//{
// [super drawRect:dirtyRect];
//
// // Drawing code here.
// [[NSColor purpleColor] set];
// NSRectFill(dirtyRect);
//}
@end
================================================
FILE: AMPMessageStyle/AirmailCss/AirmailCss.h
================================================
//
// AirmailCss.h
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
#import
@interface AirmailCss : AMPlugin
{
}
@property (strong) NSMutableArray *cssList;
@end
================================================
FILE: AMPMessageStyle/AirmailCss/AirmailCss.m
================================================
//
// AirmailCss.m
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import "AirmailCss.h"
#import "AMPCssView.h"
@implementation AirmailCss
- (id)init
{
self = [super init];
if (self)
{
}
return self;
}
- (BOOL) Load
{
if([super Load])
{
NSError *err = nil;
NSArray *arr = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:self.suggestedpath error:&err];
if(err)
{
NSLog(@"Load directory %@ %@", self,self.suggestedpath);
return NO;
}
self.cssList = [NSMutableArray array];
if(arr && arr.count > 0)
{
for(NSString *s in arr)
{
if([s hasPrefix:@"."] == NO)
{
NSString *sx = [self.suggestedpath stringByAppendingPathComponent:s];
[self.cssList addObject:sx];
}
}
}
}
return NO;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPCssView alloc] initWithFrame:NSZeroRect];
return self.myView;
}
- (NSString*) nametext
{
return @"Airmail Css";
}
- (NSString*) description
{
return @"Airmail Css Plugin";
}
- (NSString*) descriptiontext
{
return @"Airmail Css Description";
}
- (NSImage*) icon
{
return [NSImage imageNamed:@"iconx"];
}
@end
================================================
FILE: AMPMessageStyle/AirmailCss/Taxi.css
================================================
*,tr,td,table,html,th,hr,body,tbody,div {
font-size: 18px !important;
font-family:"avenir next" !important;
color:Black; !important;
background-color:Yellow !important;
border:0px!important;
border-top: 0px;
background-color:Yellow !important;
background-image:url('') !important;
}
img {
Display:none;
}
a{
color:green; !important;
}
================================================
FILE: AMPMessageStyle/AirmailCss/Yellow.css
================================================
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
* {
font-size: 25px !important;
font-family:"lucida-grande" !important;
Color-Black; !important;
Background-Color:Yellow; !important;
}
img {
display: none !important;
}
================================================
FILE: AMPMessageStyle/AirmailCss/base1.css
================================================
* {
font-size: 25px;
font-family:"helvetica";
}
================================================
FILE: AMPMessageStyle/AirmailCss/base2.css
================================================
* {
font-size: 11px;
font-family:"helvetica";
}
================================================
FILE: AMPMessageStyle/AirmailCss/base3.css
================================================
* {
font-size: 35px;
font-family:"helvetica";
}
================================================
FILE: AMPMessageStyle/AirmailCss/base4.css
================================================
* {
font-size: 49px;
font-family:"helvetica";
}
================================================
FILE: AMPMessageStyle/AirmailCss/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPMessageStyle/AirmailCss/es-419.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPNotify/AMPSimpleNotifier.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
88934418183A94D600DCC2F9 /* AMPNotifyWindowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 88934417183A94D600DCC2F9 /* AMPNotifyWindowView.m */; };
88C1AA4C183AB47100AA55A8 /* AMPluginFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88E51F6B183AA93C00BEA819 /* AMPluginFramework.framework */; };
B368572B183AE6D70094F6A2 /* demo1.wav in Resources */ = {isa = PBXBuildFile; fileRef = B3685729183AE6D70094F6A2 /* demo1.wav */; };
B368572C183AE6D70094F6A2 /* demo2.wav in Resources */ = {isa = PBXBuildFile; fileRef = B368572A183AE6D70094F6A2 /* demo2.wav */; };
D86D3C8E183972520097697F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D86D3C8D183972520097697F /* Cocoa.framework */; };
D86D3C98183972520097697F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D86D3C96183972520097697F /* InfoPlist.strings */; };
D86D3CA7183972720097697F /* AMPSimpleNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = D86D3CA6183972720097697F /* AMPSimpleNotifier.m */; };
D86D3CAA183972930097697F /* AMPSimpleNotifierView.m in Sources */ = {isa = PBXBuildFile; fileRef = D86D3CA9183972930097697F /* AMPSimpleNotifierView.m */; };
D86D3CB31839794F0097697F /* AMPSimpleNotifier.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = D86D3C8A183972520097697F /* AMPSimpleNotifier.bundle */; };
D86D3CB818397C840097697F /* AMPNotifyWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = D86D3CB718397C840097697F /* AMPNotifyWindowController.m */; };
D86D3CBB18397D290097697F /* AMPNotifyWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = D86D3CBA18397D290097697F /* AMPNotifyWindow.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
D86D3CB2183979430097697F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "~/Library/Containers/it.bloop.airmail.beta8/Data/Library/Application Support/Airmail/General/Plugins";
dstSubfolderSpec = 0;
files = (
D86D3CB31839794F0097697F /* AMPSimpleNotifier.bundle in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
88934416183A94D600DCC2F9 /* AMPNotifyWindowView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPNotifyWindowView.h; sourceTree = ""; };
88934417183A94D600DCC2F9 /* AMPNotifyWindowView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPNotifyWindowView.m; sourceTree = ""; };
88E51F6B183AA93C00BEA819 /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPluginFramework.framework; path = ../AMPluginFramework/build/Debug/AMPluginFramework.framework; sourceTree = ""; };
B3685729183AE6D70094F6A2 /* demo1.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = demo1.wav; sourceTree = ""; };
B368572A183AE6D70094F6A2 /* demo2.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = demo2.wav; sourceTree = ""; };
B3F625B518D7ABB000A3AA80 /* es-419 */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "es-419"; path = "es-419.lproj/InfoPlist.strings"; sourceTree = ""; };
D86D3C8A183972520097697F /* AMPSimpleNotifier.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AMPSimpleNotifier.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
D86D3C8D183972520097697F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
D86D3C90183972520097697F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
D86D3C91183972520097697F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
D86D3C92183972520097697F /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
D86D3C95183972520097697F /* AMPSimpleNotifier-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AMPSimpleNotifier-Info.plist"; sourceTree = ""; };
D86D3C97183972520097697F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
D86D3C99183972520097697F /* AMPSimpleNotifier-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AMPSimpleNotifier-Prefix.pch"; sourceTree = ""; };
D86D3CA5183972720097697F /* AMPSimpleNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPSimpleNotifier.h; sourceTree = ""; };
D86D3CA6183972720097697F /* AMPSimpleNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPSimpleNotifier.m; sourceTree = ""; };
D86D3CA8183972930097697F /* AMPSimpleNotifierView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPSimpleNotifierView.h; sourceTree = ""; };
D86D3CA9183972930097697F /* AMPSimpleNotifierView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPSimpleNotifierView.m; sourceTree = ""; };
D86D3CB4183979BF0097697F /* AMPluginFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AMPluginFramework.framework; path = ../../AMPluginFramework/build/Debug/AMPluginFramework.framework; sourceTree = ""; };
D86D3CB618397C840097697F /* AMPNotifyWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPNotifyWindowController.h; sourceTree = ""; };
D86D3CB718397C840097697F /* AMPNotifyWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPNotifyWindowController.m; sourceTree = ""; };
D86D3CB918397D290097697F /* AMPNotifyWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AMPNotifyWindow.h; sourceTree = ""; };
D86D3CBA18397D290097697F /* AMPNotifyWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AMPNotifyWindow.m; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
D86D3C87183972520097697F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
88C1AA4C183AB47100AA55A8 /* AMPluginFramework.framework in Frameworks */,
D86D3C8E183972520097697F /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
D86D3C81183972520097697F = {
isa = PBXGroup;
children = (
D86D3C93183972520097697F /* Notify */,
D86D3C8C183972520097697F /* Frameworks */,
D86D3C8B183972520097697F /* Products */,
);
sourceTree = "";
};
D86D3C8B183972520097697F /* Products */ = {
isa = PBXGroup;
children = (
D86D3C8A183972520097697F /* AMPSimpleNotifier.bundle */,
);
name = Products;
sourceTree = "";
};
D86D3C8C183972520097697F /* Frameworks */ = {
isa = PBXGroup;
children = (
88E51F6B183AA93C00BEA819 /* AMPluginFramework.framework */,
D86D3CB4183979BF0097697F /* AMPluginFramework.framework */,
D86D3C8D183972520097697F /* Cocoa.framework */,
D86D3C8F183972520097697F /* Other Frameworks */,
);
name = Frameworks;
sourceTree = "";
};
D86D3C8F183972520097697F /* Other Frameworks */ = {
isa = PBXGroup;
children = (
D86D3C90183972520097697F /* Foundation.framework */,
D86D3C91183972520097697F /* CoreData.framework */,
D86D3C92183972520097697F /* AppKit.framework */,
);
name = "Other Frameworks";
sourceTree = "";
};
D86D3C93183972520097697F /* Notify */ = {
isa = PBXGroup;
children = (
D86D3CA5183972720097697F /* AMPSimpleNotifier.h */,
D86D3CA6183972720097697F /* AMPSimpleNotifier.m */,
D86D3CA8183972930097697F /* AMPSimpleNotifierView.h */,
D86D3CA9183972930097697F /* AMPSimpleNotifierView.m */,
D86D3CB618397C840097697F /* AMPNotifyWindowController.h */,
D86D3CB718397C840097697F /* AMPNotifyWindowController.m */,
D86D3CB918397D290097697F /* AMPNotifyWindow.h */,
D86D3CBA18397D290097697F /* AMPNotifyWindow.m */,
88934416183A94D600DCC2F9 /* AMPNotifyWindowView.h */,
88934417183A94D600DCC2F9 /* AMPNotifyWindowView.m */,
D86D3C94183972520097697F /* Supporting Files */,
);
path = Notify;
sourceTree = "";
};
D86D3C94183972520097697F /* Supporting Files */ = {
isa = PBXGroup;
children = (
B3685729183AE6D70094F6A2 /* demo1.wav */,
B368572A183AE6D70094F6A2 /* demo2.wav */,
D86D3C95183972520097697F /* AMPSimpleNotifier-Info.plist */,
D86D3C96183972520097697F /* InfoPlist.strings */,
D86D3C99183972520097697F /* AMPSimpleNotifier-Prefix.pch */,
);
name = "Supporting Files";
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
D86D3C89183972520097697F /* AMPSimpleNotifier */ = {
isa = PBXNativeTarget;
buildConfigurationList = D86D3C9C183972520097697F /* Build configuration list for PBXNativeTarget "AMPSimpleNotifier" */;
buildPhases = (
D86D3C86183972520097697F /* Sources */,
D86D3C87183972520097697F /* Frameworks */,
D86D3C88183972520097697F /* Resources */,
D86D3CB2183979430097697F /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = AMPSimpleNotifier;
productName = Notify;
productReference = D86D3C8A183972520097697F /* AMPSimpleNotifier.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
D86D3C82183972520097697F /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0500;
ORGANIZATIONNAME = Boop;
};
buildConfigurationList = D86D3C85183972520097697F /* Build configuration list for PBXProject "AMPSimpleNotifier" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
"es-419",
);
mainGroup = D86D3C81183972520097697F;
productRefGroup = D86D3C8B183972520097697F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
D86D3C89183972520097697F /* AMPSimpleNotifier */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
D86D3C88183972520097697F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D86D3C98183972520097697F /* InfoPlist.strings in Resources */,
B368572C183AE6D70094F6A2 /* demo2.wav in Resources */,
B368572B183AE6D70094F6A2 /* demo1.wav in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
D86D3C86183972520097697F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D86D3CB818397C840097697F /* AMPNotifyWindowController.m in Sources */,
88934418183A94D600DCC2F9 /* AMPNotifyWindowView.m in Sources */,
D86D3CAA183972930097697F /* AMPSimpleNotifierView.m in Sources */,
D86D3CA7183972720097697F /* AMPSimpleNotifier.m in Sources */,
D86D3CBB18397D290097697F /* AMPNotifyWindow.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
D86D3C96183972520097697F /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
D86D3C97183972520097697F /* en */,
B3F625B518D7ABB000A3AA80 /* es-419 */,
);
name = InfoPlist.strings;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
D86D3C9A183972520097697F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
};
name = Debug;
};
D86D3C9B183972520097697F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
SDKROOT = macosx;
};
name = Release;
};
D86D3C9D183972520097697F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail/AMPluginFramework/build/Debug,
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Notify/AMPSimpleNotifier-Prefix.pch";
INFOPLIST_FILE = "Notify/AMPSimpleNotifier-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_NAME = AMPSimpleNotifier;
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
D86D3C9E183972520097697F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
/Users/Shared/DevelopMac/Airmail/AMPluginFramework/build/Debug,
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Notify/AMPSimpleNotifier-Prefix.pch";
INFOPLIST_FILE = "Notify/AMPSimpleNotifier-Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_NAME = AMPSimpleNotifier;
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
D86D3C85183972520097697F /* Build configuration list for PBXProject "AMPSimpleNotifier" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D86D3C9A183972520097697F /* Debug */,
D86D3C9B183972520097697F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D86D3C9C183972520097697F /* Build configuration list for PBXNativeTarget "AMPSimpleNotifier" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D86D3C9D183972520097697F /* Debug */,
D86D3C9E183972520097697F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = D86D3C82183972520097697F /* Project object */;
}
================================================
FILE: AMPNotify/AMPSimpleNotifier.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: AMPNotify/Notify/AMPNotifyWindow.h
================================================
//
// AMPNotifyWindow.h
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import
@interface AMPNotifyWindow : NSWindow
{
}
- (id)initWithContentRect:(NSRect)contentRect defer:(BOOL)flag;
@end
================================================
FILE: AMPNotify/Notify/AMPNotifyWindow.m
================================================
//
// AMPNotifyWindow.m
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import "AMPNotifyWindow.h"
@implementation AMPNotifyWindow
- (id)initWithContentRect:(NSRect)contentRect defer:(BOOL)flag {
return [self initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
}
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag {
// Regardless of what is passed via the styleMask paramenter, always create a NSBorderlessWindowMask window
self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:bufferingType defer:flag];
if (self) {
// This window is always has a shadow and is transparent. Force those setting here.
[self setHasShadow:YES];
[self setBackgroundColor:[[NSColor whiteColor]colorWithAlphaComponent:0.05f]];
[self setMovableByWindowBackground:YES];
[self setOpaque:NO];
[self setAnimationBehavior:NSWindowAnimationBehaviorAlertPanel];
}
return self;
}
//- (void) dealloc
//{
//}
-(BOOL) canBecomeKeyWindow
{
return YES;
}
-(BOOL) canBecomeMainWindow
{
return YES;
}
@end
================================================
FILE: AMPNotify/Notify/AMPNotifyWindowController.h
================================================
//
// AMPNotifyWindowController.h
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import
@class AMPMessage;
@class AMPNotifyWindowView;
@interface AMPNotifyWindowController : NSWindowController
{
NSRect contentRect;
AMPNotifyWindowView *av;
}
- (id) initWithRect:(NSRect)rect;
- (void) Render:(AMPMessage*)message;
@end
================================================
FILE: AMPNotify/Notify/AMPNotifyWindowController.m
================================================
//
// AMPNotifyWindowController.m
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import "AMPNotifyWindowController.h"
#import "AMPNotifyWindow.h"
#import "AMPNotifyWindowView.h"
@interface AMPNotifyWindowController ()
@end
@implementation AMPNotifyWindowController
//- (id)initWithWindow:(NSWindow *)window
//{
// self = [super initWithWindow:window];
// if (self) {
// // Initialization code here.
// }
// return self;
//}
- (id) initWithRect:(NSRect)rect
{
contentRect = rect;
AMPNotifyWindow *window = [[AMPNotifyWindow alloc] initWithContentRect:contentRect defer:YES];
[window setTitle:@"NotifyWindow"];
self = [super initWithWindow:window];
if (self)
{
av = [[AMPNotifyWindowView alloc] initWithFrame:NSMakeRect(0, 0, contentRect.size.width, contentRect.size.height)];
[window.contentView addSubview:av];
}
return self;
}
- (void) Render:(AMPMessage*)message
{
[av Render:message];
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
@end
================================================
FILE: AMPNotify/Notify/AMPNotifyWindowView.h
================================================
//
// AMPNotifyWindowView.h
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import
@class AMPMessage;
@interface AMPNotifyWindowView : NSView
{
NSImageView *imageMsgView, *imageAccView;
NSTextField *fromTextField, *subjectTextField, *excerptTextField;
}
@property (strong) AMPMessage *message;
- (void) Render:(AMPMessage*)messageIn;
@end
================================================
FILE: AMPNotify/Notify/AMPNotifyWindowView.m
================================================
//
// AMPNotifyWindowView.m
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import "AMPNotifyWindowView.h"
#import
@implementation AMPNotifyWindowView
- (BOOL) isFlipped
{
return YES;
}
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
imageMsgView = [[NSImageView alloc] initWithFrame:NSMakeRect(x, y, 48 , 48)];
[self addSubview:imageMsgView];
imageAccView = [[NSImageView alloc] initWithFrame:NSMakeRect(56, 54, 24 , 24)];
[self addSubview:imageAccView];
fromTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(90 , y, self.frame.size.width-110, 20)];
[fromTextField setStringValue:@""];
[fromTextField setBezeled:NO];
[fromTextField setDrawsBackground:NO];
[fromTextField setEditable:NO];
[fromTextField setSelectable:NO];
[fromTextField setFont:[NSFont systemFontOfSize:12]];
[[fromTextField cell] setTruncatesLastVisibleLine:YES];
[[fromTextField cell] setBackgroundStyle:NSBackgroundStyleRaised];
// [subjectTextField setAlignment: NSRightTextAlignment];
[self addSubview:fromTextField];
y+=30;
subjectTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(90, y, self.frame.size.width-110, 20)];
[subjectTextField setStringValue:@""];
[subjectTextField setBezeled:NO];
[subjectTextField setDrawsBackground:NO];
[subjectTextField setEditable:NO];
[subjectTextField setSelectable:NO];
[subjectTextField setFont:[NSFont boldSystemFontOfSize:12]];
[[subjectTextField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[[subjectTextField cell] setTruncatesLastVisibleLine:YES];
// [subjectTextField setAlignment: NSRightTextAlignment];
[self addSubview:subjectTextField];
y+=30;
excerptTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(x , y, self.frame.size.width-x, self.frame.size.height - y - 60)];
[excerptTextField setStringValue:@""];
[excerptTextField setBezeled:NO];
[excerptTextField setDrawsBackground:NO];
[excerptTextField setEditable:NO];
[excerptTextField setSelectable:NO];
[excerptTextField setFont:[NSFont systemFontOfSize:11]];
[[excerptTextField cell] setTruncatesLastVisibleLine:YES];
[[excerptTextField cell] setBackgroundStyle:NSBackgroundStyleRaised];
// [subjectTextField setAlignment: NSRightTextAlignment];
[self addSubview:excerptTextField];
NSInteger x1 = 20;
NSButton *btnReply = [[NSButton alloc] initWithFrame:NSMakeRect(x1, self.frame.size.height-40, 60, 24)];
[btnReply setTitle:@"Reply"];
[btnReply setBezelStyle:10];
[btnReply setAction:@selector(Reply:)];
[btnReply setTarget:self];
[self addSubview:btnReply];
x1+=70;
NSButton *btnForward = [[NSButton alloc] initWithFrame:NSMakeRect(x1, self.frame.size.height-40, 60, 24)];
[btnForward setTitle:@"Forward"];
[btnForward setBezelStyle:10];
[btnForward setAction:@selector(Forward:)];
[btnForward setTarget:self];
[self addSubview:btnForward];
x1+=70;
NSButton *btnArchive = [[NSButton alloc] initWithFrame:NSMakeRect(x1, self.frame.size.height-40, 60, 24)];
[btnArchive setTitle:@"Archive"];
[btnArchive setBezelStyle:10];
[btnArchive setAction:@selector(Archive:)];
[btnArchive setTarget:self];
[self addSubview:btnArchive];
x1+=70;
NSButton *btnTrash = [[NSButton alloc] initWithFrame:NSMakeRect(x1, self.frame.size.height-40, 60, 24)];
[btnTrash setTitle:@"Trash"];
[btnTrash setBezelStyle:10];
[btnTrash setAction:@selector(Trash:)];
[btnTrash setTarget:self];
[self addSubview:btnTrash];
x1+=70;
NSButton *btnClose = [[NSButton alloc] initWithFrame:NSMakeRect(x1, self.frame.size.height-40, 60, 24)];
[btnClose setTitle:@"Close"];
[btnClose setBezelStyle:10];
[btnClose setAction:@selector(Close:)];
[btnClose setTarget:self];
[self addSubview:btnClose];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// [super drawRect:dirtyRect];
//// Color Declarations
NSColor* color4 = [NSColor colorWithCalibratedHue:0.0 saturation:0.2f brightness:1 alpha:0.7];
//// Gradient Declarations
NSGradient* gradients = [[NSGradient alloc] initWithColorsAndLocations:
[NSColor whiteColor], 0.0,
[NSColor colorWithCalibratedHue:0.0 saturation:0.1f brightness:1 alpha:0.95], 0.5,
color4, 1.0, nil];
//// Rounded Rectangle Drawing
NSBezierPath* roundedRectanglePath = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(0, 0, self.bounds.size.width, self.bounds.size.height) xRadius: 10 yRadius: 10];
[gradients drawInBezierPath: roundedRectanglePath angle: -90];
[[NSColor colorWithCalibratedHue:0.0 saturation:0.0f brightness:1 alpha:0.8] setStroke];
// [roundedRectanglePath setLineWidth: 1];
// [roundedRectanglePath stroke];
// Drawing code here.
}
- (void) Render:(AMPMessage*)messageIn
{
self.message = messageIn;
if(self.message.account.profileIcon)
[imageAccView setImage:self.message.account.profileIcon];
NSImage *im = [[AMPCallBack shared] MessageImage:self.message];
if(im)
{
NSImage *flipim = [[NSImage alloc] initWithData:im.TIFFRepresentation];
[flipim setFlipped:NO];
[imageMsgView setImage:flipim];
}
if(self.message.from.description)
[fromTextField setStringValue:self.message.from.description];
if(self.message.subject)
[subjectTextField setStringValue:self.message.subject];
if(self.message.excerpt)
[excerptTextField setStringValue:self.message.excerpt];
}
- (void) Reply:(NSButton*)btn
{
if(self.message)
[[AMPCallBack shared] ReplyMessages:@[self.message]];
}
- (void) Archive:(NSButton*)btn
{
if(self.message)
[[AMPCallBack shared] ArchiveMessages:@[self.message]];
}
- (void) Forward:(NSButton*)btn
{
if(self.message)
[[AMPCallBack shared] ForwardMessages:@[self.message]];
}
- (void) Trash:(NSButton*)btn
{
if(self.message)
[[AMPCallBack shared] TrashMessages:@[self.message]];
}
- (void) Close:(NSButton*)btn
{
[self.window close];
}
@end
================================================
FILE: AMPNotify/Notify/AMPSimpleNotifier-Info.plist
================================================
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
it.bloop.airmail.plugin.${PRODUCT_NAME:rfc1034identifier}
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2013 Boop. All rights reserved.
NSPrincipalClass
AMPSimpleNotifier
================================================
FILE: AMPNotify/Notify/AMPSimpleNotifier-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import
#endif
================================================
FILE: AMPNotify/Notify/AMPSimpleNotifier.h
================================================
//
// AMPNotify.h
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import
#import
@interface AMPSimpleNotifier : AMPlugin
{
}
@property (strong) NSSound *sound;
@property (strong) NSMutableArray *soundsarray;
@property (strong) NSMutableArray *windows;
- (NSMenu*) soundsMenu;
- (NSString*)savedPath;
@end
================================================
FILE: AMPNotify/Notify/AMPSimpleNotifier.m
================================================
//
// AMPNotify.m
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import "AMPSimpleNotifier.h"
#import "AMPSimpleNotifierView.h"
#import "AMPNotifyWindowController.h"
const NSString *amp_notify_option = @"amp_notify_option";
@implementation AMPSimpleNotifier
{
}
- (BOOL) Load
{
if(![super Load])
return NO;
self.windows = [NSMutableArray array];
self.soundsarray = [NSMutableArray array];
//Load Bundle
NSMutableArray *allpaths = [NSMutableArray array];
NSArray *bundlesPath = [self bundlepathContents];
if(!bundlesPath)
return NO;
[allpaths addObjectsFromArray:bundlesPath];
NSArray *dirPaths = [self suggestedpathContents];
if(!dirPaths)
return NO;
[allpaths addObjectsFromArray:dirPaths];
for(NSString *path in allpaths)
{
if([path.pathExtension isEqualToString:@"wav"])
[self.soundsarray addObject:path];
}
//Load Preference
NSString *path = [self.preferences objectForKey:amp_notify_option];
if(path && [path isKindOfClass:[NSString class]])
self.sound = [[NSSound alloc] initWithContentsOfFile:path byReference:NO];
[self Reload];
return YES;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (void) Reload
{
return [self.myView ReloadView];
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPSimpleNotifierView alloc] initWithFrame:NSZeroRect plugin:self];
return self.myView;
}
- (NSString*) description
{
return self.nametext;
}
- (NSString*) nametext
{
return @"Simple Notifier SDK";
}
- (NSString*) descriptiontext
{
return @"This plugin is a side note for messages, is asample where you can store additional data to your messages.";
}
- (NSString*) supportlink
{
return @"http://adv.bloop.info/airmail/sdk.php";
}
- (NSString*) authortext
{
return @"Airmail SDK Sample";
}
- (NSImage*) icon
{
return [NSImage imageNamed:@"iconx"];
}
- (NSNumber*) ampQueueNotify:(AMPMessage*)message
{
return @([self CallNotifier:message]);
}
- (NSNumber*) ampRuleActionItem:(AMPMessage*)message
{
return @([self CallNotifier:message]);
}
- (BOOL) CallNotifier:(AMPMessage*)message
{
dispatch_async(dispatch_get_main_queue(), ^{
if(self.sound)
[self.sound play];
AMPNotifyWindowController *con = [[AMPNotifyWindowController alloc] initWithRect:NSMakeRect(0,0, 400, 200)];
NSScreen *screen = [NSScreen mainScreen];
NSRect screenRect = [screen visibleFrame];
NSRect frame = NSZeroRect;
frame.origin.x = screenRect.size.width - con.window.frame.size.width-20;
frame.origin.y = screenRect.size.height - con.window.frame.size.height;
frame.size.width = con.window.frame.size.width;
frame.size.height = con.window.frame.size.height;
[con.window setDelegate:self];
[con.window setFrame:frame display:NO];
[con Render:message];
[con showWindow:con];
[self.windows addObject:con];
});
return YES;
}
- (void)windowWillClose:(NSNotification *)notification
{
NSWindow *win = notification.object;
if([win.windowController isKindOfClass:[AMPNotifyWindowController class]])
{
AMPNotifyWindowController *con = win.windowController;
[self.windows removeObject:con];
}
}
#pragma mark - manage sounds
- (NSMenu*) soundsMenu
{
NSMenu *menu = [NSMenu new];
NSArray *soundsss = [self.soundsarray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
return [a caseInsensitiveCompare:b];
}];
NSMenuItem *itemRender = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"No Sound", @"No Sound") action:nil keyEquivalent:@""];
[itemRender setRepresentedObject:@""];
[itemRender setAction:@selector(changeSound:)];
[itemRender setTarget:self];
[menu addItem:itemRender];
[soundsss enumerateObjectsUsingBlock:^(NSString *path, NSUInteger idx, BOOL *stop) {
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:path.lastPathComponent.stringByDeletingPathExtension action:nil keyEquivalent:@""];
[item setRepresentedObject:path];
[item setAction:@selector(changeSound:)];
[item setTarget:self];
[menu addItem:item];
}];
return menu;
}
-(NSString*) savedPath
{
return [self.preferences objectForKey:amp_notify_option];
}
-(void) changeSound:(NSMenuItem*)item
{
NSString *str = item.representedObject;
if(str.length == 0)
{
[self.preferences removeObjectForKey:amp_notify_option];
self.sound = nil;
}
else
{
[self.preferences removeObjectForKey:amp_notify_option];
[self.preferences setObject:str forKey:amp_notify_option];
self.sound = [[NSSound alloc] initWithContentsOfFile:str byReference:NO];
[self.sound play];
}
[self SavePreferences];
}
@end
================================================
FILE: AMPNotify/Notify/AMPSimpleNotifierView.h
================================================
//
// AMPNotifyView.h
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import
@interface AMPSimpleNotifierView : AMPView
{
NSPopUpButton *popUpBtn;
}
@end
================================================
FILE: AMPNotify/Notify/AMPSimpleNotifierView.m
================================================
//
// AMPNotifyView.m
// Notify
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Boop. All rights reserved.
//
#import "AMPSimpleNotifierView.h"
#import "AMPSimpleNotifier.h"
@implementation AMPSimpleNotifierView
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin *)pluginIn
{
self = [super initWithFrame:frame plugin:pluginIn];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(x+3, y+5, 250, 20)];
[textField setStringValue:NSLocalizedString(@"Notification Sound:",@"Notification Sound:")];
[textField setBezeled:NO];
[textField setDrawsBackground:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont systemFontOfSize:13]];
[[textField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[textField setAlignment: NSRightTextAlignment];
[self addSubview:textField];
popUpBtn = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(x+270, y, 200, 30) pullsDown:NO];
[(NSPopUpButtonCell *)[popUpBtn cell] setBezelStyle:NSTexturedRoundedBezelStyle];
[[popUpBtn cell] setArrowPosition:NSPopUpArrowAtBottom];
[popUpBtn setAutoresizingMask:NSViewMaxYMargin];
[self addSubview:popUpBtn];
[self LoadView];
}
return self;
}
- (AMPSimpleNotifier*) myPlugin
{
return (AMPSimpleNotifier*)self.plugin;
}
- (void) ReloadView
{
dispatch_async(dispatch_get_main_queue(), ^{
[self LoadView];
});
}
- (void) LoadView
{
NSMenu *menu = [self.myPlugin soundsMenu];
[popUpBtn setMenu:menu];
//Selection
NSString *pathRender = [self.myPlugin savedPath];
if(pathRender && [pathRender isKindOfClass:[NSString class]])
{
for(NSMenuItem *item in popUpBtn.menu.itemArray)
{
if([item.representedObject isEqualToString:pathRender])
{
[popUpBtn selectItem:item];
break;
}
}
}
}
- (void) RenderView
{
}
@end
================================================
FILE: AMPNotify/Notify/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPNotify/Notify/es-419.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPTranslate/AMPTranslate-Info.plist
================================================
CFBundleDevelopmentRegion
English
CFBundleExecutable
${EXECUTABLE_NAME}
CFBundleIconFile
CFBundleIdentifier
it.bloop.airmail.plugin.${PRODUCT_NAME:rfc1034identifier}
CFBundleInfoDictionaryVersion
6.0
CFBundleName
${PRODUCT_NAME}
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
NSHumanReadableCopyright
Copyright © 2013 Bloop. All rights reserved.
NSPrincipalClass
AMPTranslate
================================================
FILE: AMPTranslate/AMPTranslate-Prefix.pch
================================================
//
// Prefix header
//
// The contents of this file are implicitly included at the beginning of every source file.
//
#ifdef __OBJC__
#import
#endif
================================================
FILE: AMPTranslate/AMPTranslate.h
================================================
//
// AMPTranslate.h
// AMPTranslate
//
// Created by Joe on 19/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@interface AMPTranslate : AMPlugin
{
}
@property (strong) NSString *lang;
- (NSMenu*) langMenu;
- (NSString*) savedLang;
@end
================================================
FILE: AMPTranslate/AMPTranslate.m
================================================
//
// AMPTranslate.m
// AMPTranslate
//
// Created by Joe on 19/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import "AMPTranslate.h"
#import "AMPTranslateView.h"
#import "NSString+HTML.h"
const NSString *amp_translate_option = @"amp_translate_option";
@implementation AMPTranslate
- (id)init
{
self = [super init];
if (self)
{
self.lang = @"";
}
return self;
}
- (BOOL) Load
{
if(![super Load])
return NO;
self.lang = self.savedLang;
return YES;
}
- (void) Enable
{
}
- (void) Disable
{
}
- (void) Invalid
{
}
- (void) Reload
{
return [self.myView ReloadView];
}
- (AMPView*) pluginview
{
if(!self.myView)
self.myView = [[AMPTranslateView alloc] initWithFrame:NSZeroRect plugin:self];
return self.myView;
}
- (NSString*) nametext
{
return @"Airmail Translate SDK";
}
- (NSString*) description
{
return self.nametext;
}
- (NSString*) descriptiontext
{
return @"Airmail Translate Description, Airmail Translate Description";
}
- (NSString*) authortext
{
return @"Airmail SDK Sample";
}
- (NSString*) supportlink
{
return @"http://adv.bloop.info/airmail/sdk.php";
}
- (NSImage*) icon
{
return [NSImage imageNamed:@"iconx"];
}
- (NSMenu*) langMenu
{
NSMenu *menu = [NSMenu new];
NSMenuItem *itemRender = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Auto", @"Auto") action:@selector(changeLang:) keyEquivalent:@""];
[itemRender setRepresentedObject:@""];
[itemRender setTarget:self];
[menu addItem:itemRender];
NSMenuItem *itemSupport1 = [[NSMenuItem alloc] initWithTitle:@"English" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport1 setRepresentedObject:@"en"];
[itemSupport1 setTarget:self];
[menu addItem:itemSupport1];
NSMenuItem *itemSupport4 = [[NSMenuItem alloc] initWithTitle:@"Français" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport4 setRepresentedObject:@"fr_FR"];
[itemSupport4 setTarget:self];
[menu addItem:itemSupport4];
NSMenuItem *itemSupport2 = [[NSMenuItem alloc] initWithTitle:@"Deutsch" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport2 setRepresentedObject:@"de"];
[itemSupport2 setTarget:self];
[menu addItem:itemSupport2];
NSMenuItem *itemSupport3 = [[NSMenuItem alloc] initWithTitle:@"Español" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport3 setRepresentedObject:@"es"];
[itemSupport3 setTarget:self];
[menu addItem:itemSupport3];
NSMenuItem *itemSupport5 = [[NSMenuItem alloc] initWithTitle:@"Italiano" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport5 setRepresentedObject:@"it"];
[itemSupport5 setTarget:self];
[menu addItem:itemSupport5];
NSMenuItem *itemSupport51 = [[NSMenuItem alloc] initWithTitle:@"Hebrew" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport51 setRepresentedObject:@"he"];
[itemSupport51 setTarget:self];
[menu addItem:itemSupport51];
NSMenuItem *itemSupport52 = [[NSMenuItem alloc] initWithTitle:@"Greek" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport52 setRepresentedObject:@"el"];
[itemSupport52 setTarget:self];
[menu addItem:itemSupport52];
NSMenuItem *itemSupport8 = [[NSMenuItem alloc] initWithTitle:@"日本語" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport8 setTarget:self];
[itemSupport8 setRepresentedObject:@"ja"];
[menu addItem:itemSupport8];
NSMenuItem *itemSupport85 = [[NSMenuItem alloc] initWithTitle:@"中文简体" action:@selector(changeLang:) keyEquivalent:@""];
[itemSupport85 setTarget:self];
[itemSupport85 setRepresentedObject:@"zh-Hans"];
[menu addItem:itemSupport85];
return menu;
}
- (NSString *)urlencode:(NSString*)str
{
NSMutableString *output = [NSMutableString string];
const unsigned char *source = (const unsigned char *)[str UTF8String];
int sourceLen = (int)strlen((const char *)source);
for (int i = 0; i < sourceLen; ++i) {
const unsigned char thisChar = source[i];
if (thisChar == ' '){
[output appendString:@"+"];
} else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
(thisChar >= 'a' && thisChar <= 'z') ||
(thisChar >= 'A' && thisChar <= 'Z') ||
(thisChar >= '0' && thisChar <= '9')) {
[output appendFormat:@"%c", thisChar];
} else {
[output appendFormat:@"%%%02X", thisChar];
}
}
return output;
}
- (NSString*) savedLang
{
return [self.preferences objectForKey:amp_translate_option];
}
- (void) changeLang:(NSMenuItem*)item
{
NSString *str = item.representedObject;
if(str.length == 0)
{
[self.preferences removeObjectForKey:amp_translate_option];
self.lang = @"";
}
else
{
[self.preferences removeObjectForKey:amp_translate_option];
[self.preferences setObject:str forKey:amp_translate_option];
self.lang = str;
}
[self SavePreferences];
}
- (NSMenuItem*) ampMenuActionItem:(NSArray*)messages
{
NSMenuItem *itemNotes = [[NSMenuItem alloc] initWithTitle:NSLocalizedString(@"Translate", @"Translate") action:nil keyEquivalent:@""];
[itemNotes setRepresentedObject:@""];
[itemNotes setAction:@selector(translateAction:)];
[itemNotes setTarget:self];
return itemNotes;
}
- (NSNumber*) ampRuleActionItem:(AMPMessage*)message
{
NSString *s = @"http://translate.google.com/?sl=auto#auto/";
if(self.lang.length > 0)
s = [s stringByAppendingFormat:@"%@/",self.lang];
else
s = [s stringByAppendingFormat:@"destination_language/"];
NSString *sbody = [s stringByAppendingFormat:@"%@",[self urlencode:message.plainBody]];
NSURL *url = [NSURL URLWithString:sbody];
if(url)
[[NSWorkspace sharedWorkspace] openURL:url];
return @(YES);
}
-(void) translateAction:(NSMenuItem*)item
{
NSString *s = @"http://translate.google.com/?sl=auto#auto/";
if(self.lang.length > 0)
s = [s stringByAppendingFormat:@"%@/",self.lang];
else
s = [s stringByAppendingFormat:@"destination_language/"];
AMPMenuAction *action = item.representedObject;
if(action && [action isKindOfClass:[AMPMenuAction class]])
{
//http://translate.google.com/#origin_language_or_auto|destination_language|encoded_phrase
//http://translate.google.com/translate?js=n&sl=auto&tl=destination_language&text=encoded_phrase
//http://translate.google.com/?sl=auto#auto/it/gfrcdx%0Agrfcdsx%0Ab3gfcd%0A%0Ab3gvrwcda
for(AMPMessage *message in action.messages)
{
NSString *sbody = [s stringByAppendingFormat:@"%@",[self urlencode:[message.plainBody stringByConvertingHTMLToPlainText]]];
NSURL *url = [NSURL URLWithString:sbody];
if(url)
[[NSWorkspace sharedWorkspace] openURL:url];
}
}
}
@end
================================================
FILE: AMPTranslate/AMPTranslateView.h
================================================
//
// AMPTranslateView.h
// AMPTranslate
//
// Created by Joe on 19/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@interface AMPTranslateView : AMPView
{
NSPopUpButton *popUpBtnRender;
}
@end
================================================
FILE: AMPTranslate/AMPTranslateView.m
================================================
//
// AMPTranslateView.m
// AMPTranslate
//
// Created by Joe on 19/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import "AMPTranslateView.h"
#import "AMPTranslate.h"
@implementation AMPTranslateView
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin *)pluginIn
{
self = [super initWithFrame:frame plugin:pluginIn];
if (self) {
// Initialization code here.
NSInteger x = 20;
NSInteger y = 20;
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(x+3, y, 250, 20)];
[textField setStringValue:NSLocalizedString(@"Template Selector:",@"Template Selector:")];
[textField setBezeled:NO];
[textField setDrawsBackground:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont systemFontOfSize:13]];
[[textField cell] setBackgroundStyle:NSBackgroundStyleRaised];
[textField setAlignment: NSRightTextAlignment];
[self addSubview:textField];
popUpBtnRender = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(x+270, y, 200, 30) pullsDown:NO];
[(NSPopUpButtonCell *)[popUpBtnRender cell] setBezelStyle:NSTexturedRoundedBezelStyle];
[[popUpBtnRender cell] setArrowPosition:NSPopUpArrowAtBottom];
[popUpBtnRender setAutoresizingMask:NSViewMaxYMargin];
[self addSubview:popUpBtnRender];
[self LoadView];
}
return self;
}
- (AMPTranslate*) myPlugin
{
return (AMPTranslate*)self.plugin;
}
- (void) ReloadView
{
dispatch_async(dispatch_get_main_queue(), ^{
[self LoadView];
});
}
- (void) LoadView
{
NSMenu *menu = [self.myPlugin langMenu];
[popUpBtnRender setMenu:menu];
//Selection
NSString *lang = [self.myPlugin savedLang];
if(lang && [lang isKindOfClass:[NSString class]])
{
for(NSMenuItem *item in popUpBtnRender.menu.itemArray)
{
if([item.representedObject isEqualToString:lang])
{
[popUpBtnRender selectItem:item];
break;
}
}
}
}
- (void) RenderView
{
}
@end
================================================
FILE: AMPTranslate/GTMDefines.h
================================================
//
// GTMDefines.h
//
// Copyright 2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// ============================================================================
#include
#include
#if TARGET_OS_IPHONE
#include
#endif // TARGET_OS_IPHONE
// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
#ifndef MAC_OS_X_VERSION_10_5
#define MAC_OS_X_VERSION_10_5 1050
#endif
#ifndef MAC_OS_X_VERSION_10_6
#define MAC_OS_X_VERSION_10_6 1060
#endif
// Not all __IPHONE_X macros defined in past SDKs
#ifndef __IPHONE_2_1
#define __IPHONE_2_1 20100
#endif
#ifndef __IPHONE_2_2
#define __IPHONE_2_2 20200
#endif
#ifndef __IPHONE_3_0
#define __IPHONE_3_0 30000
#endif
#ifndef __IPHONE_3_1
#define __IPHONE_3_1 30100
#endif
#ifndef __IPHONE_3_2
#define __IPHONE_3_2 30200
#endif
#ifndef __IPHONE_4_0
#define __IPHONE_4_0 40000
#endif
// ----------------------------------------------------------------------------
// CPP symbols that can be overridden in a prefix to control how the toolbox
// is compiled.
// ----------------------------------------------------------------------------
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
// when a validation fails. If you implement your own validators, you may want
// to control their internals using the same macros for consistency.
#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
#endif
// Give ourselves a consistent way to do inlines. Apple's macros even use
// a few different actual definitions, so we're based off of the foundation
// one.
#if !defined(GTM_INLINE)
#if (defined (__GNUC__) && (__GNUC__ == 4)) || defined (__clang__)
#define GTM_INLINE static __inline__ __attribute__((always_inline))
#else
#define GTM_INLINE static __inline__
#endif
#endif
// Give ourselves a consistent way of doing externs that links up nicely
// when mixing objc and objc++
#if !defined (GTM_EXTERN)
#if defined __cplusplus
#define GTM_EXTERN extern "C"
#define GTM_EXTERN_C_BEGIN extern "C" {
#define GTM_EXTERN_C_END }
#else
#define GTM_EXTERN extern
#define GTM_EXTERN_C_BEGIN
#define GTM_EXTERN_C_END
#endif
#endif
// Give ourselves a consistent way of exporting things if we have visibility
// set to hidden.
#if !defined (GTM_EXPORT)
#define GTM_EXPORT __attribute__((visibility("default")))
#endif
// Give ourselves a consistent way of declaring something as unused. This
// doesn't use __unused because that is only supported in gcc 4.2 and greater.
#if !defined (GTM_UNUSED)
#define GTM_UNUSED(x) ((void)(x))
#endif
// _GTMDevLog & _GTMDevAssert
//
// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
// developer level errors. This implementation simply macros to NSLog/NSAssert.
// It is not intended to be a general logging/reporting system.
//
// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
// for a little more background on the usage of these macros.
//
// _GTMDevLog log some error/problem in debug builds
// _GTMDevAssert assert if conditon isn't met w/in a method/function
// in all builds.
//
// To replace this system, just provide different macro definitions in your
// prefix header. Remember, any implementation you provide *must* be thread
// safe since this could be called by anything in what ever situtation it has
// been placed in.
//
// We only define the simple macros if nothing else has defined this.
#ifndef _GTMDevLog
#ifdef DEBUG
#define _GTMDevLog(...) NSLog(__VA_ARGS__)
#else
#define _GTMDevLog(...) do { } while (0)
#endif
#endif // _GTMDevLog
#ifndef _GTMDevAssert
// we directly invoke the NSAssert handler so we can pass on the varargs
// (NSAssert doesn't have a macro we can use that takes varargs)
#if !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
file:[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ \
description:__VA_ARGS__]; \
} \
} while(0)
#else // !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) do { } while (0)
#endif // !defined(NS_BLOCK_ASSERTIONS)
#endif // _GTMDevAssert
// _GTMCompileAssert
// _GTMCompileAssert is an assert that is meant to fire at compile time if you
// want to check things at compile instead of runtime. For example if you
// want to check that a wchar is 4 bytes instead of 2 you would use
// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
// Note that the second "arg" is not in quotes, and must be a valid processor
// symbol in it's own right (no spaces, punctuation etc).
// Wrapping this in an #ifndef allows external groups to define their own
// compile time assert scheme.
#ifndef _GTMCompileAssert
// We got this technique from here:
// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
#define _GTMCompileAssert(test, msg) \
typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
#endif // _GTMCompileAssert
// ----------------------------------------------------------------------------
// CPP symbols defined based on the project settings so the GTM code has
// simple things to test against w/o scattering the knowledge of project
// setting through all the code.
// ----------------------------------------------------------------------------
// Provide a single constant CPP symbol that all of GTM uses for ifdefing
// iPhone code.
#if TARGET_OS_IPHONE // iPhone SDK
// For iPhone specific stuff
#define GTM_IPHONE_SDK 1
#if TARGET_IPHONE_SIMULATOR
#define GTM_IPHONE_SIMULATOR 1
#else
#define GTM_IPHONE_DEVICE 1
#endif // TARGET_IPHONE_SIMULATOR
// By default, GTM has provided it's own unittesting support, define this
// to use the support provided by Xcode, especially for the Xcode4 support
// for unittesting.
#ifndef GTM_IPHONE_USE_SENTEST
#define GTM_IPHONE_USE_SENTEST 0
#endif
#else
// For MacOS specific stuff
#define GTM_MACOS_SDK 1
#endif
// Some of our own availability macros
#if GTM_MACOS_SDK
#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
#define GTM_AVAILABLE_ONLY_ON_MACOS
#else
#define GTM_AVAILABLE_ONLY_ON_IPHONE
#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
#endif
// Provide a symbol to include/exclude extra code for GC support. (This mainly
// just controls the inclusion of finalize methods).
#ifndef GTM_SUPPORT_GC
#if GTM_IPHONE_SDK
// iPhone never needs GC
#define GTM_SUPPORT_GC 0
#else
// We can't find a symbol to tell if GC is supported/required, so best we
// do on Mac targets is include it if we're on 10.5 or later.
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define GTM_SUPPORT_GC 0
#else
#define GTM_SUPPORT_GC 1
#endif
#endif
#endif
// To simplify support for 64bit (and Leopard in general), we provide the type
// defines for non Leopard SDKs
#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
// NSInteger/NSUInteger and Max/Mins
#ifndef NSINTEGER_DEFINED
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
#define NSIntegerMax LONG_MAX
#define NSIntegerMin LONG_MIN
#define NSUIntegerMax ULONG_MAX
#define NSINTEGER_DEFINED 1
#endif // NSINTEGER_DEFINED
// CGFloat
#ifndef CGFLOAT_DEFINED
#if defined(__LP64__) && __LP64__
// This really is an untested path (64bit on Tiger?)
typedef double CGFloat;
#define CGFLOAT_MIN DBL_MIN
#define CGFLOAT_MAX DBL_MAX
#define CGFLOAT_IS_DOUBLE 1
#else /* !defined(__LP64__) || !__LP64__ */
typedef float CGFloat;
#define CGFLOAT_MIN FLT_MIN
#define CGFLOAT_MAX FLT_MAX
#define CGFLOAT_IS_DOUBLE 0
#endif /* !defined(__LP64__) || !__LP64__ */
#define CGFLOAT_DEFINED 1
#endif // CGFLOAT_DEFINED
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
// Some support for advanced clang static analysis functionality
// See http://clang-analyzer.llvm.org/annotations.html
#ifndef __has_feature // Optional.
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
#endif
#ifndef NS_RETURNS_RETAINED
#if __has_feature(attribute_ns_returns_retained)
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#else
#define NS_RETURNS_RETAINED
#endif
#endif
#ifndef NS_RETURNS_NOT_RETAINED
#if __has_feature(attribute_ns_returns_not_retained)
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
#else
#define NS_RETURNS_NOT_RETAINED
#endif
#endif
#ifndef CF_RETURNS_RETAINED
#if __has_feature(attribute_cf_returns_retained)
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
#else
#define CF_RETURNS_RETAINED
#endif
#endif
#ifndef CF_RETURNS_NOT_RETAINED
#if __has_feature(attribute_cf_returns_not_retained)
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
#else
#define CF_RETURNS_NOT_RETAINED
#endif
#endif
#ifndef NS_CONSUMED
#if __has_feature(attribute_ns_consumed)
#define NS_CONSUMED __attribute__((ns_consumed))
#else
#define NS_CONSUMED
#endif
#endif
#ifndef CF_CONSUMED
#if __has_feature(attribute_cf_consumed)
#define CF_CONSUMED __attribute__((cf_consumed))
#else
#define CF_CONSUMED
#endif
#endif
#ifndef NS_CONSUMES_SELF
#if __has_feature(attribute_ns_consumes_self)
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
#else
#define NS_CONSUMES_SELF
#endif
#endif
// Defined on 10.6 and above.
#ifndef NS_FORMAT_ARGUMENT
#define NS_FORMAT_ARGUMENT(A)
#endif
// Defined on 10.6 and above.
#ifndef NS_FORMAT_FUNCTION
#define NS_FORMAT_FUNCTION(F,A)
#endif
// Defined on 10.6 and above.
#ifndef CF_FORMAT_ARGUMENT
#define CF_FORMAT_ARGUMENT(A)
#endif
// Defined on 10.6 and above.
#ifndef CF_FORMAT_FUNCTION
#define CF_FORMAT_FUNCTION(F,A)
#endif
#ifndef GTM_NONNULL
#define GTM_NONNULL(x) __attribute__((nonnull(x)))
#endif
#ifdef __OBJC__
// Declared here so that it can easily be used for logging tracking if
// necessary. See GTMUnitTestDevLog.h for details.
@class NSString;
GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...);
// Macro to allow you to create NSStrings out of other macros.
// #define FOO foo
// NSString *fooString = GTM_NSSTRINGIFY(FOO);
#if !defined (GTM_NSSTRINGIFY)
#define GTM_NSSTRINGIFY_INNER(x) @#x
#define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
#endif
// Macro to allow fast enumeration when building for 10.5 or later, and
// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
// does keys, so pick the right thing, nothing is done on the FastEnumeration
// side to be sure you're getting what you wanted.
#ifndef GTM_FOREACH_OBJECT
#if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
for (element in enumeration)
#define GTM_FOREACH_OBJECT(element, collection) \
for (element in collection)
#define GTM_FOREACH_KEY(element, collection) \
for (element in collection)
#else
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
for (NSEnumerator *_ ## element ## _enum = enumeration; \
(element = [_ ## element ## _enum nextObject]) != nil; )
#define GTM_FOREACH_OBJECT(element, collection) \
GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
#define GTM_FOREACH_KEY(element, collection) \
GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
#endif
#endif
// ============================================================================
// To simplify support for both Leopard and Snow Leopard we declare
// the Snow Leopard protocols that we need here.
#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
#define GTM_10_6_PROTOCOLS_DEFINED 1
@protocol NSConnectionDelegate
@end
@protocol NSAnimationDelegate
@end
@protocol NSImageDelegate
@end
@protocol NSTabViewDelegate
@end
#endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
// GTM_SEL_STRING is for specifying selector (usually property) names to KVC
// or KVO methods.
// In debug it will generate warnings for undeclared selectors if
// -Wunknown-selector is turned on.
// In release it will have no runtime overhead.
#ifndef GTM_SEL_STRING
#ifdef DEBUG
#define GTM_SEL_STRING(selName) NSStringFromSelector(@selector(selName))
#else
#define GTM_SEL_STRING(selName) @#selName
#endif // DEBUG
#endif // GTM_SEL_STRING
#endif // __OBJC__
================================================
FILE: AMPTranslate/GTMNSString+HTML.h
================================================
//
// GTMNSString+HTML.h
// Dealing with NSStrings that contain HTML
//
// Copyright 2006-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import
/// Utilities for NSStrings containing HTML
@interface NSString (GTMNSStringHTMLAdditions)
/// Get a string where internal characters that need escaping for HTML are escaped
//
/// For example, '&' become '&'. This will only cover characters from table
/// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
/// which is what you want for a unicode encoded webpage. If you have a ascii
/// or non-encoded webpage, please use stringByEscapingAsciiHTML which will
/// encode all characters.
///
/// For obvious reasons this call is only safe once.
//
// Returns:
// Autoreleased NSString
//
- (NSString *)gtm_stringByEscapingForHTML;
/// Get a string where internal characters that need escaping for HTML are escaped
//
/// For example, '&' become '&'
/// All non-mapped characters (unicode that don't have a &keyword; mapping)
/// will be converted to the appropriate xx; value. If your webpage is
/// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is
/// faster, and produces less bloated and more readable HTML (as long as you
/// are using a unicode compliant HTML reader).
///
/// For obvious reasons this call is only safe once.
//
// Returns:
// Autoreleased NSString
//
- (NSString *)gtm_stringByEscapingForAsciiHTML;
/// Get a string where internal characters that are escaped for HTML are unescaped
//
/// For example, '&' becomes '&'
/// Handles and 2 cases as well
///
// Returns:
// Autoreleased NSString
//
- (NSString *)gtm_stringByUnescapingFromHTML;
@end
================================================
FILE: AMPTranslate/GTMNSString+HTML.m
================================================
//
// GTMNSString+HTML.m
// Dealing with NSStrings that contain HTML
//
// Copyright 2006-2008 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
#import "GTMDefines.h"
#import "GTMNSString+HTML.h"
typedef struct {
NSString *escapeSequence;
unichar uchar;
} HTMLEscapeMap;
// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
// Ordered by uchar lowest to highest for bsearching
static HTMLEscapeMap gAsciiHTMLEscapeMap[] = {
// A.2.2. Special characters
{ @""", 34 },
{ @"&", 38 },
{ @"'", 39 },
{ @"<", 60 },
{ @">", 62 },
// A.2.1. Latin-1 characters
{ @" ", 160 },
{ @"¡", 161 },
{ @"¢", 162 },
{ @"£", 163 },
{ @"¤", 164 },
{ @"¥", 165 },
{ @"¦", 166 },
{ @"§", 167 },
{ @"¨", 168 },
{ @"©", 169 },
{ @"ª", 170 },
{ @"«", 171 },
{ @"¬", 172 },
{ @"", 173 },
{ @"®", 174 },
{ @"¯", 175 },
{ @"°", 176 },
{ @"±", 177 },
{ @"²", 178 },
{ @"³", 179 },
{ @"´", 180 },
{ @"µ", 181 },
{ @"¶", 182 },
{ @"·", 183 },
{ @"¸", 184 },
{ @"¹", 185 },
{ @"º", 186 },
{ @"»", 187 },
{ @"¼", 188 },
{ @"½", 189 },
{ @"¾", 190 },
{ @"¿", 191 },
{ @"À", 192 },
{ @"Á", 193 },
{ @"Â", 194 },
{ @"Ã", 195 },
{ @"Ä", 196 },
{ @"Å", 197 },
{ @"Æ", 198 },
{ @"Ç", 199 },
{ @"È", 200 },
{ @"É", 201 },
{ @"Ê", 202 },
{ @"Ë", 203 },
{ @"Ì", 204 },
{ @"Í", 205 },
{ @"Î", 206 },
{ @"Ï", 207 },
{ @"Ð", 208 },
{ @"Ñ", 209 },
{ @"Ò", 210 },
{ @"Ó", 211 },
{ @"Ô", 212 },
{ @"Õ", 213 },
{ @"Ö", 214 },
{ @"×", 215 },
{ @"Ø", 216 },
{ @"Ù", 217 },
{ @"Ú", 218 },
{ @"Û", 219 },
{ @"Ü", 220 },
{ @"Ý", 221 },
{ @"Þ", 222 },
{ @"ß", 223 },
{ @"à", 224 },
{ @"á", 225 },
{ @"â", 226 },
{ @"ã", 227 },
{ @"ä", 228 },
{ @"å", 229 },
{ @"æ", 230 },
{ @"ç", 231 },
{ @"è", 232 },
{ @"é", 233 },
{ @"ê", 234 },
{ @"ë", 235 },
{ @"ì", 236 },
{ @"í", 237 },
{ @"î", 238 },
{ @"ï", 239 },
{ @"ð", 240 },
{ @"ñ", 241 },
{ @"ò", 242 },
{ @"ó", 243 },
{ @"ô", 244 },
{ @"õ", 245 },
{ @"ö", 246 },
{ @"÷", 247 },
{ @"ø", 248 },
{ @"ù", 249 },
{ @"ú", 250 },
{ @"û", 251 },
{ @"ü", 252 },
{ @"ý", 253 },
{ @"þ", 254 },
{ @"ÿ", 255 },
// A.2.2. Special characters cont'd
{ @"Œ", 338 },
{ @"œ", 339 },
{ @"Š", 352 },
{ @"š", 353 },
{ @"Ÿ", 376 },
// A.2.3. Symbols
{ @"ƒ", 402 },
// A.2.2. Special characters cont'd
{ @"ˆ", 710 },
{ @"˜", 732 },
// A.2.3. Symbols cont'd
{ @"Α", 913 },
{ @"Β", 914 },
{ @"Γ", 915 },
{ @"Δ", 916 },
{ @"Ε", 917 },
{ @"Ζ", 918 },
{ @"Η", 919 },
{ @"Θ", 920 },
{ @"Ι", 921 },
{ @"Κ", 922 },
{ @"Λ", 923 },
{ @"Μ", 924 },
{ @"Ν", 925 },
{ @"Ξ", 926 },
{ @"Ο", 927 },
{ @"Π", 928 },
{ @"Ρ", 929 },
{ @"Σ", 931 },
{ @"Τ", 932 },
{ @"Υ", 933 },
{ @"Φ", 934 },
{ @"Χ", 935 },
{ @"Ψ", 936 },
{ @"Ω", 937 },
{ @"α", 945 },
{ @"β", 946 },
{ @"γ", 947 },
{ @"δ", 948 },
{ @"ε", 949 },
{ @"ζ", 950 },
{ @"η", 951 },
{ @"θ", 952 },
{ @"ι", 953 },
{ @"κ", 954 },
{ @"λ", 955 },
{ @"μ", 956 },
{ @"ν", 957 },
{ @"ξ", 958 },
{ @"ο", 959 },
{ @"π", 960 },
{ @"ρ", 961 },
{ @"ς", 962 },
{ @"σ", 963 },
{ @"τ", 964 },
{ @"υ", 965 },
{ @"φ", 966 },
{ @"χ", 967 },
{ @"ψ", 968 },
{ @"ω", 969 },
{ @"ϑ", 977 },
{ @"ϒ", 978 },
{ @"ϖ", 982 },
// A.2.2. Special characters cont'd
{ @" ", 8194 },
{ @" ", 8195 },
{ @" ", 8201 },
{ @"", 8204 },
{ @"", 8205 },
{ @"", 8206 },
{ @"", 8207 },
{ @"–", 8211 },
{ @"—", 8212 },
{ @"‘", 8216 },
{ @"’", 8217 },
{ @"‚", 8218 },
{ @"“", 8220 },
{ @"”", 8221 },
{ @"„", 8222 },
{ @"†", 8224 },
{ @"‡", 8225 },
// A.2.3. Symbols cont'd
{ @"•", 8226 },
{ @"…", 8230 },
// A.2.2. Special characters cont'd
{ @"‰", 8240 },
// A.2.3. Symbols cont'd
{ @"′", 8242 },
{ @"″", 8243 },
// A.2.2. Special characters cont'd
{ @"‹", 8249 },
{ @"›", 8250 },
// A.2.3. Symbols cont'd
{ @"‾", 8254 },
{ @"⁄", 8260 },
// A.2.2. Special characters cont'd
{ @"€", 8364 },
// A.2.3. Symbols cont'd
{ @"ℑ", 8465 },
{ @"℘", 8472 },
{ @"ℜ", 8476 },
{ @"™", 8482 },
{ @"ℵ", 8501 },
{ @"←", 8592 },
{ @"↑", 8593 },
{ @"→", 8594 },
{ @"↓", 8595 },
{ @"↔", 8596 },
{ @"↵", 8629 },
{ @"⇐", 8656 },
{ @"⇑", 8657 },
{ @"⇒", 8658 },
{ @"⇓", 8659 },
{ @"⇔", 8660 },
{ @"∀", 8704 },
{ @"∂", 8706 },
{ @"∃", 8707 },
{ @"∅", 8709 },
{ @"∇", 8711 },
{ @"∈", 8712 },
{ @"∉", 8713 },
{ @"∋", 8715 },
{ @"∏", 8719 },
{ @"∑", 8721 },
{ @"−", 8722 },
{ @"∗", 8727 },
{ @"√", 8730 },
{ @"∝", 8733 },
{ @"∞", 8734 },
{ @"∠", 8736 },
{ @"∧", 8743 },
{ @"∨", 8744 },
{ @"∩", 8745 },
{ @"∪", 8746 },
{ @"∫", 8747 },
{ @"∴", 8756 },
{ @"∼", 8764 },
{ @"≅", 8773 },
{ @"≈", 8776 },
{ @"≠", 8800 },
{ @"≡", 8801 },
{ @"≤", 8804 },
{ @"≥", 8805 },
{ @"⊂", 8834 },
{ @"⊃", 8835 },
{ @"⊄", 8836 },
{ @"⊆", 8838 },
{ @"⊇", 8839 },
{ @"⊕", 8853 },
{ @"⊗", 8855 },
{ @"⊥", 8869 },
{ @"⋅", 8901 },
{ @"⌈", 8968 },
{ @"⌉", 8969 },
{ @"⌊", 8970 },
{ @"⌋", 8971 },
{ @"〈", 9001 },
{ @"〉", 9002 },
{ @"◊", 9674 },
{ @"♠", 9824 },
{ @"♣", 9827 },
{ @"♥", 9829 },
{ @"♦", 9830 }
};
// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
// This is table A.2.2 Special Characters
static HTMLEscapeMap gUnicodeHTMLEscapeMap[] = {
// C0 Controls and Basic Latin
{ @""", 34 },
{ @"&", 38 },
{ @"'", 39 },
{ @"<", 60 },
{ @">", 62 },
// Latin Extended-A
{ @"Œ", 338 },
{ @"œ", 339 },
{ @"Š", 352 },
{ @"š", 353 },
{ @"Ÿ", 376 },
// Spacing Modifier Letters
{ @"ˆ", 710 },
{ @"˜", 732 },
// General Punctuation
{ @" ", 8194 },
{ @" ", 8195 },
{ @" ", 8201 },
{ @"", 8204 },
{ @"", 8205 },
{ @"", 8206 },
{ @"", 8207 },
{ @"–", 8211 },
{ @"—", 8212 },
{ @"‘", 8216 },
{ @"’", 8217 },
{ @"‚", 8218 },
{ @"“", 8220 },
{ @"”", 8221 },
{ @"„", 8222 },
{ @"†", 8224 },
{ @"‡", 8225 },
{ @"‰", 8240 },
{ @"‹", 8249 },
{ @"›", 8250 },
{ @"€", 8364 },
};
// Utility function for Bsearching table above
static int EscapeMapCompare(const void *ucharVoid, const void *mapVoid) {
const unichar *uchar = (const unichar*)ucharVoid;
const HTMLEscapeMap *map = (const HTMLEscapeMap*)mapVoid;
int val;
if (*uchar > map->uchar) {
val = 1;
} else if (*uchar < map->uchar) {
val = -1;
} else {
val = 0;
}
return val;
}
@implementation NSString (GTMNSStringHTMLAdditions)
- (NSString *)gtm_stringByEscapingHTMLUsingTable:(HTMLEscapeMap*)table
ofSize:(NSUInteger)size
escapingUnicode:(BOOL)escapeUnicode {
NSUInteger length = [self length];
if (!length) {
return self;
}
NSMutableString *finalString = [NSMutableString string];
NSMutableData *data2 = [NSMutableData dataWithCapacity:sizeof(unichar) * length];
// this block is common between GTMNSString+HTML and GTMNSString+XML but
// it's so short that it isn't really worth trying to share.
const unichar *buffer = CFStringGetCharactersPtr((CFStringRef)self);
if (!buffer) {
// We want this buffer to be autoreleased.
NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)];
if (!data) {
// COV_NF_START - Memory fail case
_GTMDevLog(@"couldn't alloc buffer");
return nil;
// COV_NF_END
}
[self getCharacters:[data mutableBytes]];
buffer = [data bytes];
}
if (!buffer || !data2) {
// COV_NF_START
_GTMDevLog(@"Unable to allocate buffer or data2");
return nil;
// COV_NF_END
}
unichar *buffer2 = (unichar *)[data2 mutableBytes];
NSUInteger buffer2Length = 0;
for (NSUInteger i = 0; i < length; ++i) {
HTMLEscapeMap *val = bsearch(&buffer[i], table,
size / sizeof(HTMLEscapeMap),
sizeof(HTMLEscapeMap), EscapeMapCompare);
if (val || (escapeUnicode && buffer[i] > 127)) {
if (buffer2Length) {
CFStringAppendCharacters((CFMutableStringRef)finalString,
buffer2,
buffer2Length);
buffer2Length = 0;
}
if (val) {
[finalString appendString:val->escapeSequence];
}
else {
_GTMDevAssert(escapeUnicode && buffer[i] > 127, @"Illegal Character");
[finalString appendFormat:@"%d;", buffer[i]];
}
} else {
buffer2[buffer2Length] = buffer[i];
buffer2Length += 1;
}
}
if (buffer2Length) {
CFStringAppendCharacters((CFMutableStringRef)finalString,
buffer2,
buffer2Length);
}
return finalString;
}
- (NSString *)gtm_stringByEscapingForHTML {
return [self gtm_stringByEscapingHTMLUsingTable:gUnicodeHTMLEscapeMap
ofSize:sizeof(gUnicodeHTMLEscapeMap)
escapingUnicode:NO];
} // gtm_stringByEscapingHTML
- (NSString *)gtm_stringByEscapingForAsciiHTML {
return [self gtm_stringByEscapingHTMLUsingTable:gAsciiHTMLEscapeMap
ofSize:sizeof(gAsciiHTMLEscapeMap)
escapingUnicode:YES];
} // gtm_stringByEscapingAsciiHTML
- (NSString *)gtm_stringByUnescapingFromHTML {
NSRange range = NSMakeRange(0, [self length]);
NSRange subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range];
// if no ampersands, we've got a quick way out
if (subrange.length == 0) return self;
NSMutableString *finalString = [NSMutableString stringWithString:self];
do {
NSRange semiColonRange = NSMakeRange(subrange.location, NSMaxRange(range) - subrange.location);
semiColonRange = [self rangeOfString:@";" options:0 range:semiColonRange];
range = NSMakeRange(0, subrange.location);
// if we don't find a semicolon in the range, we don't have a sequence
if (semiColonRange.location == NSNotFound) {
continue;
}
NSRange escapeRange = NSMakeRange(subrange.location, semiColonRange.location - subrange.location + 1);
NSString *escapeString = [self substringWithRange:escapeRange];
NSUInteger length = [escapeString length];
// a squence must be longer than 3 (<) and less than 11 (ϑ)
if (length > 3 && length < 11) {
if ([escapeString characterAtIndex:1] == '#') {
unichar char2 = [escapeString characterAtIndex:2];
if (char2 == 'x' || char2 == 'X') {
// Hex escape squences £
NSString *hexSequence = [escapeString substringWithRange:NSMakeRange(3, length - 4)];
NSScanner *scanner = [NSScanner scannerWithString:hexSequence];
unsigned value;
if ([scanner scanHexInt:&value] &&
value < USHRT_MAX &&
value > 0
&& [scanner scanLocation] == length - 4) {
unichar uchar = value;
NSString *charString = [NSString stringWithCharacters:&uchar length:1];
[finalString replaceCharactersInRange:escapeRange withString:charString];
}
} else {
// Decimal Sequences {
NSString *numberSequence = [escapeString substringWithRange:NSMakeRange(2, length - 3)];
NSScanner *scanner = [NSScanner scannerWithString:numberSequence];
int value;
if ([scanner scanInt:&value] &&
value < USHRT_MAX &&
value > 0
&& [scanner scanLocation] == length - 3) {
unichar uchar = value;
NSString *charString = [NSString stringWithCharacters:&uchar length:1];
[finalString replaceCharactersInRange:escapeRange withString:charString];
}
}
} else {
// "standard" sequences
for (unsigned i = 0; i < sizeof(gAsciiHTMLEscapeMap) / sizeof(HTMLEscapeMap); ++i) {
if ([escapeString isEqualToString:gAsciiHTMLEscapeMap[i].escapeSequence]) {
[finalString replaceCharactersInRange:escapeRange withString:[NSString stringWithCharacters:&gAsciiHTMLEscapeMap[i].uchar length:1]];
break;
}
}
}
}
} while ((subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]).length != 0);
return finalString;
} // gtm_stringByUnescapingHTML
@end
================================================
FILE: AMPTranslate/NSString+HTML.h
================================================
//
// NSString+HTML.h
// MWFeedParser
//
// Copyright (c) 2010 Michael Waterfall
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// 1. The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// 2. This Software cannot be used to archive or collect data such as (but not
// limited to) that of events, news, experiences and activities, for the
// purpose of any concept relating to diary/journal keeping.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#import
// Dependant upon GTMNSString+HTML
@interface NSString (HTML)
// Strips HTML tags & comments, removes extra whitespace and decodes HTML character entities.
- (NSString *)stringByConvertingHTMLToPlainText;
// Decode all HTML entities using GTM.
- (NSString *)stringByDecodingHTMLEntities;
// Encode all HTML entities using GTM.
- (NSString *)stringByEncodingHTMLEntities;
// Minimal unicode encoding will only cover characters from table
// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
// which is what you want for a unicode encoded webpage.
- (NSString *)stringByEncodingHTMLEntities:(BOOL)isUnicode;
// Replace newlines with
tags.
- (NSString *)stringWithNewLinesAsBRs;
// Remove newlines and white space from string.
- (NSString *)stringByRemovingNewLinesAndWhitespace;
// Wrap plain URLs in ...
// - Ignores URLs inside tags (any URL beginning with =")
// - HTTP & HTTPS schemes only
// - Only works in iOS 4+ as we use NSRegularExpression (returns self if not supported so be careful with NSMutableStrings)
// - Expression: (?" intoString:NULL];
[scanner scanString:@"-->" intoString:NULL];
} else {
// Tag - remove and replace with space unless it's
// a closing inline tag then dont replace with a space
if ([scanner scanString:@"/" intoString:NULL]) {
// Closing tag - replace with space unless it's inline
tagName = nil; dontReplaceTagWithSpace = NO;
if ([scanner scanCharactersFromSet:tagNameCharacters intoString:&tagName]) {
tagName = [tagName lowercaseString];
dontReplaceTagWithSpace = (
[tagName isEqualToString:@"a"] ||
[tagName isEqualToString:@"b"] ||
[tagName isEqualToString:@"i"] ||
[tagName isEqualToString:@"q"] ||
[tagName isEqualToString:@"span"] ||
[tagName isEqualToString:@"em"] ||
[tagName isEqualToString:@"strong"] ||
[tagName isEqualToString:@"cite"] ||
[tagName isEqualToString:@"abbr"] ||
[tagName isEqualToString:@"acronym"] ||
[tagName isEqualToString:@"label"]);
}
// Replace tag with string unless it was an inline
if (!dontReplaceTagWithSpace && result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "];
}
// Scan past tag
[scanner scanUpToString:@">" intoString:NULL];
[scanner scanString:@">" intoString:NULL];
}
} else {
// Stopped at whitespace - replace all whitespace and newlines with a space
if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
if (result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "]; // Dont append space to beginning or end of result
}
}
} while (![scanner isAtEnd]);
// Cleanup
[scanner release];
// Decode HTML entities and return
NSString *retString = [[result stringByDecodingHTMLEntities] retain];
[result release];
// Drain
[pool drain];
// Return
return [retString autorelease];
}
- (NSString *)stringByDecodingHTMLEntities {
// Can return self so create new string if we're a mutable string
return [NSString stringWithString:[self gtm_stringByUnescapingFromHTML]];
}
- (NSString *)stringByEncodingHTMLEntities {
// Can return self so create new string if we're a mutable string
return [NSString stringWithString:[self gtm_stringByEscapingForAsciiHTML]];
}
- (NSString *)stringByEncodingHTMLEntities:(BOOL)isUnicode {
// Can return self so create new string if we're a mutable string
return [NSString stringWithString:(isUnicode ? [self gtm_stringByEscapingForHTML] : [self gtm_stringByEscapingForAsciiHTML])];
}
- (NSString *)stringWithNewLinesAsBRs {
// Pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Strange New lines:
// Next Line, U+0085
// Form Feed, U+000C
// Line Separator, U+2028
// Paragraph Separator, U+2029
// Scanner
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
[scanner setCharactersToBeSkipped:nil];
NSMutableString *result = [[NSMutableString alloc] init];
NSString *temp;
NSCharacterSet *newLineCharacters = [NSCharacterSet characterSetWithCharactersInString:
[NSString stringWithFormat:@"\n\r%c%c%c%c", 0x0085, 0x000C, 0x2028, 0x2029]];
// Scan
do {
// Get non new line characters
temp = nil;
[scanner scanUpToCharactersFromSet:newLineCharacters intoString:&temp];
if (temp) [result appendString:temp];
temp = nil;
// Add
s
if ([scanner scanString:@"\r\n" intoString:nil]) {
// Combine \r\n into just 1
[result appendString:@"
"];
} else if ([scanner scanCharactersFromSet:newLineCharacters intoString:&temp]) {
// Scan other new line characters and add
s
if (temp) {
for (NSUInteger i = 0; i < temp.length; i++) {
[result appendString:@"
"];
}
}
}
} while (![scanner isAtEnd]);
// Cleanup & return
[scanner release];
NSString *retString = [[NSString stringWithString:result] retain];
[result release];
// Drain
[pool drain];
// Return
return [retString autorelease];
}
- (NSString *)stringByRemovingNewLinesAndWhitespace {
// Pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Strange New lines:
// Next Line, U+0085
// Form Feed, U+000C
// Line Separator, U+2028
// Paragraph Separator, U+2029
// Scanner
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
[scanner setCharactersToBeSkipped:nil];
NSMutableString *result = [[NSMutableString alloc] init];
NSString *temp;
NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:
[NSString stringWithFormat:@" \t\n\r%c%c%c%c", 0x0085, 0x000C, 0x2028, 0x2029]];
// Scan
while (![scanner isAtEnd]) {
// Get non new line or whitespace characters
temp = nil;
[scanner scanUpToCharactersFromSet:newLineAndWhitespaceCharacters intoString:&temp];
if (temp) [result appendString:temp];
// Replace with a space
if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
if (result.length > 0 && ![scanner isAtEnd]) // Dont append space to beginning or end of result
[result appendString:@" "];
}
}
// Cleanup
[scanner release];
// Return
NSString *retString = [[NSString stringWithString:result] retain];
[result release];
// Drain
[pool drain];
// Return
return [retString autorelease];
}
- (NSString *)stringByLinkifyingURLs
{
if (!NSClassFromString(@"NSRegularExpression")) return self;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *pattern = @"(?$1"] retain];
[pool drain];
return [modifiedString autorelease];
}
- (NSString *)stringByStrippingTags {
// Pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Find first & and short-cut if we can
NSUInteger ampIndex = [self rangeOfString:@"<" options:NSLiteralSearch].location;
if (ampIndex == NSNotFound) {
return [NSString stringWithString:self]; // return copy of string as no tags found
}
// Scan and find all tags
NSScanner *scanner = [NSScanner scannerWithString:self];
[scanner setCharactersToBeSkipped:nil];
NSMutableSet *tags = [[NSMutableSet alloc] init];
NSString *tag;
do {
// Scan up to <
tag = nil;
[scanner scanUpToString:@"<" intoString:NULL];
[scanner scanUpToString:@">" intoString:&tag];
// Add to set
if (tag) {
NSString *t = [[NSString alloc] initWithFormat:@"%@>", tag];
[tags addObject:t];
[t release];
}
} while (![scanner isAtEnd]);
// Strings
NSMutableString *result = [[NSMutableString alloc] initWithString:self];
NSString *finalString;
// Replace tags
NSString *replacement;
for (NSString *t in tags) {
// Replace tag with space unless it's an inline element
replacement = @" ";
if ([t isEqualToString:@""] ||
[t isEqualToString:@""] ||
[t isEqualToString:@""] ||
[t isEqualToString:@""] ||
[t isEqualToString:@""] ||
[t isEqualToString:@""] ||
[t isEqualToString:@""] ||
[t isEqualToString:@""]) {
replacement = @"";
}
// Replace
[result replaceOccurrencesOfString:t
withString:replacement
options:NSLiteralSearch
range:NSMakeRange(0, result.length)];
}
// Remove multi-spaces and line breaks
finalString = [[result stringByRemovingNewLinesAndWhitespace] retain];
// Cleanup
[result release];
[tags release];
// Drain
[pool drain];
// Return
return [finalString autorelease];
}
@end
================================================
FILE: AMPTranslate/en.lproj/InfoPlist.strings
================================================
/* Localized versions of Info.plist keys */
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPAccount.h
================================================
//
// AMPAccount.h
// AirMail
//
// Created by Joe on 11/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
#import "AMPObject.h"
@class AMPProvider;
@class AMPSignature;
@interface AMPAccount : AMPObject
{
}
/**
* The account provider model
*
* @return The account provider
*/
- (AMPProvider*) provider;
/**
* the unique identifier of the account
*
* @return The ID
*/
- (NSNumber*) idx;
/**
* The account order position
*
* @return The account order
*/
- (NSNumber*) order;
/**
* The preference of the composer amp_composertype
*
* @return An integer of the amp_composertype
*/
- (NSNumber*) composerType;
/**
* A bool value if is unified inbox
*
* @return if is unified inbox
*/
- (NSNumber*) isAll;
/**
* If the account is enabled
*
* @return A bool value
*/
- (NSNumber*) enabled;
/**
* A bool value preference to use signature for the account
*
* @return A bool value
*/
- (NSNumber*) useSignature;
/**
* A bool value preference to use signature in Quick Reply for the account
*
* @return A bool value
*/
- (NSNumber*) useSignatureQuickReply;
/**
* A bool value preference to use signature in Reply for the account
*
* @return A bool value
*/
- (NSNumber*) useSignatureReply;
/**
* A bool value preference to use copy sent messages in the sent folder
*
* @return A bool value
*/
- (NSNumber*) copySent;
/**
* A bool value preference if the account have the notification enabled.
*
* @return A bool value
*/
- (NSNumber*) notify;
/**
* A bool value preference if the account have the automapped of folders enabled
*
* @return A bool value
*/
- (NSNumber*) autoMapping;
/**
* A bool value preference if the account have the automatic download of the message body
*
* @return A bool value
*/
- (NSNumber*) downloadBody;
/**
* A bool value preference if the account have the automatic download of the message Attachments
*
* @return A bool value
*/
- (NSNumber*) downloadAttachments;
/**
* A bool value preference if the account have the import contacts at start
*
* @return A bool value
*/
- (NSNumber*) importContacts;
/**
* A bool value preference if the account is the default replier
*
* @return A bool value
*/
- (NSNumber*) defaultReplier;
/**
* A bool value preference if the account is Right Text Lanaguage
*
* @return A bool value
*/
- (NSNumber*) rtl;
/**
* The account mail
*
* @return the mail account
*/
- (NSString*) mail;
/**
* The account name
*
* @return the name of the account
*/
- (NSString*) name;
/**
* Is tha path where the account files are stored
*
* @return the account path
*/
- (NSString*) path;
/**
* Is string of the file name
*
* @return the file name
*/
- (NSString*) notifySound;
/**
* the profile icon image
*
* @return The icon image
*/
- (NSImage*) profileIcon;
/**
* The aliases array
*
* @return the aliases array of AMPAlias
*/
- (NSMutableArray*) aliases;
/**
* The signatures name array
*
* @return the signatures array of AMPSignature
*/
- (NSMutableArray*) signatures;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPAddress.h
================================================
//
// AMPAddress.h
// AirMail
//
// Created by Joe on 11/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
#import "AMPObject.h"
@interface AMPAddress : AMPObject
{
}
/**
* The name of the contact
*
* @return The name of the contact
*/
- (NSString*) name;
/**
* The contact mail
*
* @return The mail address
*/
- (NSString*) mail;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPAlias.h
================================================
//
// AMPAlias.h
// AMPluginFramework
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@class AMPAccount;
@class AMPProvider;
#import "AMPObject.h"
@interface AMPAlias : AMPObject
{
}
/**
* The provider of the alias
*
* @return The provider of the alias
*/
- (AMPProvider*) provider;
/**
* The account of the alias
*
* @return The account of the alias
*/
- (AMPAccount*) account;
/**
* The alias name
*
* @return The alias name
*/
- (NSString*) name;
/**
* The alias mail
*
* @return The alias mail
*/
- (NSString*) mail;
/**
* The unique identifier
*
* @return The unique identifier
*/
- (NSNumber*) idx;
/**
* A boolean if is the default sender
*
* @return A boolean if is the default sender
*/
- (NSNumber*) defaultSender;
/**
* A boolean if have a custom SMTP
*
* @return A boolean if have a custom SMTP
*/
- (NSNumber*) customSmtp;
/**
* A boolean if the alias copy the mail in the sent folder
*
* @return A boolean
*/
- (NSNumber*) copySent;
/**
* A boolean if is the default replier
*
* @return A boolean if is the default replier
*/
- (NSNumber*) defaultReplier;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPAttachment.h
================================================
//
// AMPAttachment.h
// AirMail
//
// Created by Joe on 11/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
#import "AMPObject.h"
@interface AMPAttachment : AMPObject
{
}
/**
* The attachment file Path
*
* @return The attachment file path
*/
- (NSString*) filePath;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPCallBack.h
================================================
//
// AMPCallBack.h
// AMPluginFramework
//
// Created by Joe on 18/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@class AMPAccount;
@class AMPMessage;
@class AMPFolder;
@class AMPComposerInfo;
@interface AMPCallBack : NSObject
{
id callback;
}
+(AMPCallBack*)shared;
/**
* Open a window to read the message
*
* @param messages the message to read
*/
- (void) OpenReaderMessages:(NSArray*)messages;
/**
* Reply message action, it will open a composer for each message passed
*
* @param messages the message to reply
*/
- (void) ReplyMessages:(NSArray*)messages;
/**
* Mark as read action, it will mark as read the messages passed
*
* @param messages the message to mark
*/
- (void) MarkAsReadMessages:(NSArray*)messages;
/**
* Move Message action, it will move the messages to the folder
*
* @param messages the messages to move
* @param folder the folder where to move
*/
- (void) MoveMessages:(NSArray*)messages folder:(AMPFolder*)folder;
/**
* Copy Message action, it will copy the messages to the folder
*
* @param messages the messages to copy
* @param folder the folder where to copy
*/
- (void) CopyMessages:(NSArray*)messages folder:(AMPFolder*)folder;
/**
* Forward message action, it will open a composer for each message passed
*
* @param messages the message to forward
*/
- (void) ForwardMessages:(NSArray*)messages;
/**
* Trash message action, it will move to trash all the messages passed
*
* @param messages the message to trash
*/
- (void) TrashMessages:(NSArray*)messages;
/**
* Archive message action, it will archive all the messages passed
*
* @param messages the message to reply
*/
- (void) ArchiveMessages:(NSArray*)messages;
/**
* Return the current selected messages in the message list
*/
- (NSArray*) SelectedMessages;
/**
* The accounts list of Airmail
*/
- (NSArray*) Accounts;
/**
* Folders of an account
*
* @param account the account owner of the folders
*
* @return the folders
*/
- (NSArray*) Folders:(AMPAccount*)account;
/**
* the ordered folders (hierarchy) for an account. the standard folders are
* all grouoed in the first positions of the array
*
* @param account the account owner of the folders
*
* @return the ordered folders
*/
- (NSArray*) OrderedFoldersWithStandardFirst:(AMPAccount*)account;
/**
* The image for a message
*
* @param message the message owner of the image
*
* @return the image
*/
- (NSImage*) MessageImage:(AMPMessage*)message;
- (NSNumber*) Beta_Store_Status;
- (void) ChangePluginStatus:(NSString*)plugin_id status:(NSNumber*)status;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPComposerInfo.h
================================================
//
// AMPComposerInfo.h
// AMPluginFramework
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
#import
@class AMPMessage;
@class AMPlugin;
@interface AMPComposerInfo : NSObject
{
NSObject *back;
}
/**
* the local message created by the composer
*/
@property (strong) AMPMessage *localMessage;
/**
* the reply message in the case of a reply
*/
@property (strong) AMPMessage *replyMessage;
/**
* type is (amp_mailcomposertype)
*/
@property (strong) NSNumber *type;
/**
* the composer mode (amp_composertype)
*/
@property (strong) NSNumber *mode;
/**
* The web view of the composer
*/
@property (weak) WebView *webView;
/**
* The original represented object passed by the plugin in the menu item
*/
@property (strong) NSObject *representedObject;
/**
* All the plugins views in the composer
*/
@property (weak) NSDictionary *composerViews;
/**
* Get the composer button for the input plugin
*/
- (NSArray*) composerBtn:(AMPlugin*)plugin;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPFolder.h
================================================
//
// AMPFolder.h
// AMPluginFramework
//
// Created by Joe on 18/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@class AMPAccount;
#import "AMPObject.h"
@interface AMPFolder : AMPObject
{
}
/**
* The account of the folder
*
* @return The account of the folder
*/
- (AMPAccount*) account;
/**
* The parent folder of the current folder
*
* @return The parent folder of the current folder
*/
- (AMPFolder*) parentFolder;
/**
* The subfolder folder of the current folder
*
* @return an array of the subfolder
*/
- (NSArray*) subFolders;
/**
* Unique identifier of the object
*
* @return Unique identifier of the object
*/
- (NSNumber*) idx;
/**
* An integer for the folder type amp_foldertype
*
* @return An integer for the folder type amp_foldertype
*/
- (NSNumber*) standardFolderid;
/**
* A bool value if the folder is completly fetched
*
* @return A bool value if the folder is completly fetched
*/
- (NSNumber*) fetched;
/**
* The indentation level of the folder
*
* @return The indentation level of the folder
*/
- (NSNumber*) indent;
/**
* The order position of the folder
*
* @return The order position of the folder
*/
- (NSNumber*) position;
/**
* The message Count
*
* @return The message Count
*/
- (NSNumber*) count;
/**
* The messages Unread Count for that folder
*
* @return The messages Unread Count for that folder
*/
- (NSNumber*) unreadCount;
/**
* A bool value if the folder is enabled or not (not used)
*
* @return A bool value if the folder is enabled or not (not used)
*/
- (NSNumber*) disabled;
/**
* A bool value if the folder is hided
*
* @return A bool value if the folder is hidden
*/
- (NSNumber*) hided;
/**
* A bool value if the folder is selectable, IMAP only
*
* @return A bool value if the folder is selectable
*/
- (NSNumber*) selectable;
/**
* A bool value if the folder is a local Folder, like MUTE
*
* @return A bool value if the folder is a local Folder
*/
- (NSNumber*) localTag;
/**
* The path name of the folder /folder/folder or .folder.folder
*
* @return The path name of the folder
*/
- (NSString*) name;
/**
* The name of the folder EXCHANGE Only
*
* @return The name of the folder
*/
- (NSString*) displayName;
/**
* The localised name of the folder
*
* @return The name of the folder
*/
- (NSString*) cleanedName;
/**
* The unique id of the Exchange Folder
*
* @return The id
*/
- (NSString*) uniqueIdx;
/**
* The sync state of the Exchange folder
*
* @return A String of the sync state
*/
- (NSString*) syncState;
/**
* A bool indicating that the folder have a custom color
*
* @return A bool value
*/
- (NSNumber*) colorTheme;
/**
* The custom color of the folder
*
* @return The folder color
*/
- (id) colorCustom;
/**
* The date of the last folder update
*
* @return The date
*/
- (NSDate*) lastUpdate;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPGroup.h
================================================
//
// AMPGroup.h
// AirMail
//
// Created by Joe on 11/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
#import "AMPObject.h"
@interface AMPGroup : AMPObject
{
}
/**
* The contacts group name
*
* @return The contacts group name
*/
- (NSString*) name;
/**
* An array of AMPAddress
*
* @return An array of AMPAddress
*/
- (NSMutableArray*) addresses;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOAbstractMessage.h
================================================
//
// AMPAbstractMessage.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
#import "AMPObject.h"
@class AMPMCOMessageHeader;
@class AMPMCOAbstractPart;
@interface AMPMCOAbstractMessage : AMPObject
/** Header of the message. */
- (AMPMCOMessageHeader*) header;
/** Returns the part with the given Content-ID.*/
- (AMPMCOAbstractPart *) partForContentID:(NSString *)contentID;
/** Returns the part with the given unique identifier.*/
- (AMPMCOAbstractPart *) partForUniqueID:(NSString *)uniqueID;
/** All attachments in the message.
It will return an array of MCOIMAPPart for MCOIMAPMessage.
It will return an array of MCOAttachment for MCOMessageParser.
It will return an array of MCOAttachment for MCOMessageBuilder. */
- (NSArray * /* MCOAbstractPart */) attachments;
/** All image attachments included inline in the message through cid: URLs.
It will return an array of MCOIMAPPart for MCOIMAPMessage.
It will return an array of MCOAttachment for MCOMessageParser.
It will return an array of MCOAttachment for MCOMessageBuilder. */
- (NSArray * /* MCOAbstractPart */) htmlInlineAttachments;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOAbstractMessagePart.h
================================================
//
// AMPMCOAbstractMessagePart.h
// AMPluginFramework
//
// Created by Gio on 13/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import "AMPMCOAbstractPart.h"
@class AMPMCOMessageHeader;
@interface AMPMCOAbstractMessagePart : AMPMCOAbstractPart
// Returns the header of the embedded message.
-(AMPMCOMessageHeader *) header;
// Returns the main part of the embedded message. It can be MCOAbstractPart, MCOAbstractMultipart
// or a MCOAbstractMessagePart.
-(AMPMCOAbstractPart *) mainPart;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOAbstractMultipart.h
================================================
//
// AMPMCOAbstractMultipart.h
// AMPluginFramework
//
// Created by Gio on 13/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import "AMPMCOAbstractPart.h"
@interface AMPMCOAbstractMultipart : AMPMCOAbstractPart
/** Returns the subparts of that multipart.*/
-(NSArray*) /* MCOAbstractPart */ parts;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOAbstractPart.h
================================================
//
// AMPAbstractPart.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
#import "AMPObject.h"
typedef enum {
// Used for a single part.
// The part will be a MCOAbstractPart.
AMPMCOPartTypeSingle,
// Used for a message part (MIME type: message/rfc822).
// The part will be a MCOAbstractMessagePart.
// It's when a message is sent as attachment of an other message.
AMPMCOPartTypeMessage,
// Used for a multipart, multipart/mixed.
// The part will be a MCOAbstractMultipart.
AMPMCOPartTypeMultipartMixed,
// Used for a multipart, multipart/related.
// The part will be a MCOAbstractMultipart.
AMPMCOPartTypeMultipartRelated,
// Used for a multipart, multipart/alternative.
// The part will be a MCOAbstractMultipart.
AMPMCOPartTypeMultipartAlternative,
// Used for a multipart, multipart/signed.
// The part will be a MCOAbstractMultipart.
AMPMCOPartTypeMultipartSigned,
// Used for a multipart, multipart/encrypted.
// The part will be a MCOAbstractMultipart.
AMPMCOPartTypeMultipartEncrypted,
} AMPMCOPartType;
@interface AMPMCOAbstractPart : AMPObject
/** Returns type of the part (single / message part / multipart/mixed,
multipart/related, multipart/alternative). See MCOPartType.*/
-(AMPMCOPartType) partType;
/** Returns filename of the part.*/
-(NSString*) filename;
/** Returns MIME type of the part. For example application/data.*/
-(NSString*) mimeType;
/** Returns charset of the part in case it's a text single part.*/
-(NSString*) charset;
/** Returns the unique ID generated for this part.
It's a unique identifier that's created when the object is created manually
or created by the parser.*/
-(NSString*) uniqueID;
/** Returns the value of the Content-ID field of the part.*/
-(NSString*) contentID;
/** Returns the value of the Content-Location field of the part.*/
-(NSString*) contentLocation;
/** Returns the value of the Content-Description field of the part.*/
-(NSString*) contentDescription;
/** Returns whether the part is an explicit inline attachment.*/
-(BOOL) inlineAttachment;
/** Returns the part with the given Content-ID among this part and its subparts.*/
- (AMPMCOAbstractPart *) partForContentID:(NSString *)contentID;
/** Returns the part with the given unique identifier among this part and its subparts.*/
- (AMPMCOAbstractPart *) partForUniqueID:(NSString *)uniqueID;
/** Returns a string representation of the data according to charset.*/
- (NSString *) decodedStringForData:(NSData *)data;
/** Returns all parts for a mime type*/
- (NSArray*) PartsForMime:(NSString*)mimeIn;
/** Returns all parts.*/
- (NSArray*) AllParts;
//Added out of mailcore
+ (AMPMCOAbstractPart*) partForMailCorePart:(id)part;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOAddress.h
================================================
//
// AMPMCOAddress.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
#import "AMPObject.h"
@interface AMPMCOAddress : AMPObject
/** Creates an address with a display name and a mailbox.
Example: [MCOAddress addressWithDisplayName:@"DINH Viêt Hoà" mailbox:@"hoa@etpan.org"] */
+ (AMPMCOAddress *) addressWithDisplayName:(NSString *)displayName
mailbox:(NSString *)mailbox;
/** Creates an address with only a mailbox.
Example: [MCOAddress addressWithMailbox:@"hoa@etpan.org"]*/
+ (AMPMCOAddress *) addressWithMailbox:(NSString *)mailbox;
/** Creates an address with a RFC822 string.
Example: [MCOAddress addressWithRFC822String:@"DINH Vi=C3=AAt Ho=C3=A0 "]*/
+ (AMPMCOAddress *) addressWithRFC822String:(NSString *)RFC822String;
/** Creates an address with a non-MIME-encoded RFC822 string.
Example: [MCOAddress addressWithRFC822String:@"DINH Viêt Hoà "]*/
+ (AMPMCOAddress *) addressWithNonEncodedRFC822String:(NSString *)nonEncodedRFC822String;
/**
Returns an NSArray of MCOAddress objects that contain the parsed
forms of the RFC822 encoded addresses.
For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 " ]*/
+ (NSArray *) addressesWithRFC822String:(NSString *)string;
/**
Returns an NSArray of MCOAddress objects that contain the parsed
forms of non-encoded RFC822 addresses.
For example: @[ "DINH Viêt Hoà " ]*/
+ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string;
/** Returns the display name of the address.*/
-(NSString*) displayName;
/** Returns the mailbox of the address.*/
-(NSString*) mailbox;
/** Returns the RFC822 encoding of the address.
For example: "DINH Vi=C3=AAt Ho=C3=A0 "*/
- (NSString *) RFC822String;
/** Returns the non-MIME-encoded RFC822 encoding of the address.
For example: "DINH Viêt Hoà "*/
- (NSString *) nonEncodedRFC822String;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOAttachment.h
================================================
//
// AMPMCOAttachment.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import "AMPMCOAbstractPart.h"
@interface AMPMCOAttachment : AMPMCOAbstractPart
/** Returns a MIME type for a filename.*/
+ (NSString *) mimeTypeForFilename:(NSString *)filename;
/** Returns a file attachment with the content of the given file.*/
+ (AMPMCOAttachment *) attachmentWithContentsOfFile:(NSString *)filename;
/** Returns a file attachment with the given data and filename.*/
+ (AMPMCOAttachment *) attachmentWithData:(NSData *)data filename:(NSString *)filename;
/** Returns a part with an HTML content.*/
+ (AMPMCOAttachment *) attachmentWithHTMLString:(NSString *)htmlString;
/** Returns a part with a RFC 822 messsage attachment.*/
+ (AMPMCOAttachment *) attachmentWithRFC822Message:(NSData *)messageData;
/** Returns a part with an plain text content.*/
+ (AMPMCOAttachment *) attachmentWithText:(NSString *)text;
/** Returns a part with an plain text content with mime type*/
+ (AMPMCOAttachment *) attachmentWithText:(NSString *)text mimeType:(NSString*)contentType;
/** Decoded data of the part.*/
- (NSData*) data;
/** Returns string representation according to charset*/
- (NSString *) decodedString;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOMessageBuilder.h
================================================
//
// AMPMCOMessageBuilder.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import "AMPMCOAbstractMessage.h"
@class AMPMCOAttachment;
@interface AMPMCOMessageBuilder : AMPMCOAbstractMessage
/** Main HTML content of the message.*/
-(NSString*) htmlBody;
/** Plain text content of the message.*/
-(NSString*) textBody;
/** List of file attachments.*/
-(NSArray*) /* MCOAttachment */ attachments;
/** List of related file attachments (included as cid: link in the HTML part).*/
-(NSArray*) /* MCOAttachment */ relatedAttachments;
/** Prefix for the boundary identifier. Default value is nil.*/
-(NSString*) boundaryPrefix;
/** Add an attachment.*/
- (void) addAttachment:(AMPMCOAttachment *)attachment;
/** Add a related attachment.*/
- (void) addRelatedAttachment:(AMPMCOAttachment *)attachment;
/** RFC 822 formatted message.*/
- (NSData *) data;
/** HTML rendering of the body of the message to be displayed in a web view.*/
- (NSString *) htmlBodyRendering;
/** Text rendering of the message.*/
- (NSString *) plainTextRendering;
/** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up.
This method can be used to generate the summary of the message.*/
- (NSString *) plainTextBodyRendering;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOMessageHeader.h
================================================
//
// AMPMessageHeader.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
#import "AMPObject.h"
@class AMPMCOAddress;
@interface AMPMCOMessageHeader : AMPObject
@property BOOL generatedMessageID;
/** Message-ID field.*/
-(NSString*) messageID;
/** References field. It's an array of message-ids.*/
-(NSArray*) /* NSString */ references;
/** In-Reply-To field. It's an array of message-ids.*/
-(NSArray*) /* NSString */ inReplyTo;
/** Date field: sent date of the message.*/
-(NSDate*) date;
/** Received date: received date of the message.*/
-(NSDate*) receivedDate;
/** Sender field.*/
-(AMPMCOAddress*) sender;
/** From field: address of the sender of the message.*/
-(AMPMCOAddress*) from;
/** To field: recipient of the message. It's an array of MCOAddress.*/
-(NSArray*) /* MCOAddress */ to;
/** Cc field: cc recipient of the message. It's an array of MCOAddress.*/
-(NSArray*) /* MCOAddress */ cc;
/** Bcc field: bcc recipient of the message. It's an array of MCOAddress.*/
-(NSArray*) /* MCOAddress */ bcc;
/** Reply-To field. It's an array of MCOAddress.*/
-(NSArray*) /* MCOAddress */ replyTo;
/** Subject of the message.*/
-(NSString*) subject;
/** User-Agent.*/
-(NSString*) userAgent;
/** Adds a custom header.*/
- (void)addHeaderValue:(NSString *)value forName:(NSString *)name;
/** Remove a given custom header.*/
- (void)removeHeaderForName:(NSString *)name;
/** Returns the value of a given custom header.*/
- (NSString *)headerValueForName:(NSString *)name;
/** Returns an array with the names of all custom headers.*/
- (NSArray * /* NSString */)allHeadersNames;
/** Extracted subject (also remove square brackets).*/
- (NSString *) extractedSubject;
/** Extracted subject (don't remove square brackets).*/
- (NSString *) partialExtractedSubject;
/** Fill the header using the given RFC 822 data.*/
- (void) importHeadersData:(NSData *)data;
/** Returns a header that can be used as a base for a reply message.*/
- (AMPMCOMessageHeader *) replyHeaderWithExcludedRecipients:(NSArray *)excludedRecipients;
/** Returns a header that can be used as a base for a reply all message.*/
- (AMPMCOMessageHeader *) replyAllHeaderWithExcludedRecipients:(NSArray *)excludedRecipients;
/** Returns a header that can be used as a base for a forward message.*/
- (AMPMCOMessageHeader *) forwardHeader;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOMessageParser.h
================================================
//
// AMPMessageParser.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 12/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
#import "AMPMCOAbstractMessage.h"
@class AMPMCOAbstractPart;
//@class AMPMCOAbstractMessage;
@interface AMPMCOMessageParser : AMPMCOAbstractMessage
/** returns a parsed message from the given RFC 822 data.*/
+ (AMPMCOMessageParser *) messageParserWithData:(NSData *)data;
/** It's the main part of the message. It can be MCOMessagePart, MCOMultipart or MCOAttachment.*/
- (AMPMCOAbstractPart *) mainPart;
/** data of the RFC 822 formatted message. It's the input of the parser.*/
- (NSData *) data;
/** HTML rendering of the body of the message to be displayed in a web view.*/
- (NSString *) htmlBodyRendering;
/** Text rendering of the message.*/
- (NSString *) plainTextRendering;
/** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up.
This method can be used to generate the summary of the message.*/
- (NSString *) plainTextBodyRendering;
- (NSString *) plainBody;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOMessagePart.h
================================================
//
// AMPMCOMessagePart.h
// AMPluginFramework
//
// Created by Gio on 13/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import "AMPMCOAbstractMessagePart.h"
@interface AMPMCOMessagePart : AMPMCOAbstractMessagePart
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMCOMultiPart.h
================================================
//
// AMPMCOMultiPart.h
// AMPluginFramework
//
// Created by Gio on 13/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
#import "AMPMCOAbstractMultipart.h"
@interface AMPMCOMultiPart : AMPMCOAbstractMultipart
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMenuAction.h
================================================
//
// AMPMenuAction.h
// AMPluginFramework
//
// Created by Joe on 18/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@interface AMPMenuAction : NSObject
{
}
/**
* The objec passed by the plugin in the represented object menu item
*/
@property (strong) NSObject *representedObject;
/**
* An array og AMPMessages involved in the action
*/
@property (strong) NSArray *messages;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPMessage.h
================================================
//
// AMPMessage.h
// AirMail
//
// Created by Joe on 11/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
#import "AMPObject.h"
@class AMPAccount;
@class AMPAddress;
@class AMPComposerInfo;
@interface AMPMessage : AMPObject
{
}
/**
* The account name
*
* @return The Account Name
*/
- (AMPAccount*) account;
/**
* The email address of the sender
*
* @return The email address
*/
- (AMPAddress*) from;
/**
* Unique identifier of the message in Airmail
*
* @return the Unique identifier
*/
- (NSNumber*) idx;
/**
* The local flags number
*
* @return the number of the local flag
*/
- (NSNumber*) localflags;
/**
* The thread count number
*
* @return the number of the thread count
*/
- (NSNumber*) threadCount;
/**
* The Xpriority value
*
* @return the Xpriority value
*/
- (NSNumber*) xPriority;
/**
* The subject of the message
*
* @return the messag subject vlue
*/
- (NSString*) subject;
/**
* the message ID of th RFC Message
*
* @return the message ID
*/
- (NSString*) messageId;
/**
* The HMTL body of the message
*
* @return The string with the HTML
*/
- (NSString*) htmlBody;
/**
* The Plain Text body of the message
*
* @return The string with the Plain text
*/
- (NSString*) plainBody;
/**
* The message excerpt
*
* @return the plain text excerpt
*/
- (NSString*) excerpt;
/**
* The message date
*
* @return The message date
*/
- (NSDate*) date;
/**
* The attachments array of AMPAttachment model
*
* @return The attachment array
*/
- (NSArray*) attachments;
/**
* The message references (message id) for a conversation
*
* @return an array of strings
*/
- (NSArray*) references;
/**
* The message in reply to (message id) for a conversation
*
* @return an array of strings
*/
- (NSArray*) inReplyTo;
/**
* The message TO field
*
* @return an array of AMPAddress or AMPGroup
*/
- (NSArray*) to;
/**
* The message CC field
*
* @return an array of AMPAddress or AMPGroup
*/
- (NSArray*) cc;
/**
* The message BCC field
*
* @return an array of AMPAddress or AMPGroup
*/
- (NSArray*) bcc;
/**
* The message replyTO field
*
* @return an array of AMPAddress or AMPGroup
*/
- (NSArray*) replyTo;
/**
* The message rfc
*
* @return the full rfc of the message
*/
- (NSData*) rfcData;
/**
* A dictionary,the key is the folder idx, the objec is an AMPUidFlag (uid and flag) for the folder
* a message can belogn to multiple folders with different uids/flags
*
* @return a dictionary
*/
- (NSDictionary*) folderUids;
/**
* The composer that has generated the message in the case of a send
*
* @return a the composer info
*/
- (AMPComposerInfo*) composerInfo;
/**
* The encypted status fo the message
*
* @return an encypted based on amp_encryption_type
*/
- (NSNumber*) encrypted;
/**
* Get the mails in the local message
*/
-(NSArray*) GetMails;
/**
* Get a dictionary with to,cc,bcc as keys and an array of mails for each entry
*/
-(NSDictionary*) GetMailsMaps;
/**
* Get a unique url for a message
*/
- (NSString*) urlformessage;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPObject.h
================================================
//
// AMPObject.h
// AMPluginFramework
//
// Created by Joe on 19/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@interface AMPObject : NSObject
{
}
/**
* The Airmail object. is the base object used to create the AMP models
*
* @return the AM object
*/
- (id) object;
- (id) initWithObject:(NSObject*)obj;
/**
* Simple method to call selectors on the AM object
*
* @param selector the AM selector
* @param object the AM object
*
* @return an id with the populated property
*/
- (id) callSelector:(SEL)selector;
- (id) callSelector:(SEL)selector obj:(id)object;
- (id) callSelector:(SEL)selector obj:(id)object obj:(id)object2;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPProvider.h
================================================
//
// AMPProvider.h
// AMPluginFramework
//
// Created by Joe on 16/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
#import "AMPObject.h"
@interface AMPProvider : AMPObject
{
}
/**
* An integer for the provider type (see amp_provderType enum)
*
* @return a a number with the value
*/
-(NSNumber*) key;
/**
* The provider name, gmail,aol,...
*
* @return The provider name
*/
-(NSString*) name;
/**
* The provider domain, gmail.com, aol.com ...
*
* @return The provider domain
*/
-(NSString*) domain;
/**
* The provider mail user@domain.com
*
* @return The provider mail
*/
-(NSString*) mail;
/**
* The provider username the user add in account settings
*
* @return The provider username
*/
-(NSString*) userName;
-(NSString*) descriptionName;
/**
* The receiving server imap.domain.com, pop.domain.com
*
* @return The receiver server
*/
-(NSString*) rServer;
/**
* The receiving user user@domain.com or user
*
* @return The receiving user
*/
-(NSString*) rUser;
/**
* The receiving authentication type NONE,PLAIN,LOGIN,CRAM-MD5,GSSAPI,DIGEST-MD5,SRP,NTLM,KERBEROS_V4
*
* @return The receiving authentication
*/
-(NSString*) rAuthType;
/**
* The Exchange endpoint https://domain.com/EWS/Exchange.asmx
*
* @return The Exchange endpoint
*/
-(NSString*) endPoint;
/**
* The receiving port 993, 143, ...
*
* @return The receiving port
*/
-(NSNumber*) rPort;
/**
* TLS connection value: 0 clear connection, 1 Start TLS, 2 TLS.
*
* @return TLS connection value
*/
-(NSNumber*) rTls;
/**
* Sending Server smtp.domain.com ...
*
* @return Sending Server
*/
-(NSString*) sServer;
/**
* The sending user user@domain.com or user
*
* @return The sending user
*/
-(NSString*) sUser;
/**
* The sending authentication type type PLAIN,LOGIN,CRAM-MD5,GSSAPI,DIGEST-MD5,NTLM,KERBEROS_V4
*
* @return The sending authentication type
*/
-(NSString*) sAuthType;
/**
* The sending port 587, 25, ...
*
* @return The sending port
*/
-(NSNumber*) sPort;
/**
* A boolean for the sending authentication if NO user and password are not used
*
* @return A boolean for the sending authentication
*/
-(NSNumber*) sAuth;
/**
* TLS connection value: 0 clear connection, 1 Start TLS, 2 TLS.
*
* @return TLS connection value
*/
-(NSNumber*) sTls;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPSendResult.h
================================================
//
// AMPSendResult.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 18/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
@interface AMPSendResult : NSObject
{
}
/**
* the result of the sending (encrypt/sign) type amp_send_result
*/
@property NSInteger result;
/**
* the result of the sending (encrypt/sign)
*/
@property (strong) NSString *rfc;
/**
* the error of the sending (encrypt/sign)
*/
@property (strong) NSString *err;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPSignature.h
================================================
//
// AMPSignature.h
// AMPluginFramework
//
// Created by Joe on 17/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@class AMPAccount;
#import "AMPObject.h"
@interface AMPSignature : AMPObject
{
}
/**
* The Account of the signature
*
* @return the account
*/
-(AMPAccount*) account;
/**
* Unique identifier of the object
*
* @return unique identifier
*/
-(NSNumber*) idx;
/**
* A boolean if the signature is the default one
*
* @return A boolean
*/
-(NSNumber*) defaultSign;
/**
* The HTML of the signature
*
* @return HTML String
*/
-(NSString*) html;
/**
* the mail of the signature
*
* @return the mailof the signature
*/
-(NSString*) mail;
/**
* The name of the signature
*
* @return The name of the signature
*/
-(NSString*) name;
/**
* An array of the attachments file paths
*
* @return An array of the attachments file paths
*/
-(NSArray*) attachments;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPSignatureVerify.h
================================================
//
// AMPSignatureVerify.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 17/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
@interface AMPSignatureVerify : NSObject
{
}
/**
* the result of the verify of type amp_verify_signature
*/
@property (assign) NSInteger signatureVerify;
/**
* the array of the mime parts to remove
*/
@property (strong) NSArray *mimetoRemove;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPUidFlag.h
================================================
//
// AMPUidFlag.h
// AMPluginFramework
//
// Created by Joe on 19/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@interface AMPUidFlag : NSObject
{
}
/**
* the uid of the message for a folder
*/
@property NSInteger uid;
/**
* the flags of the message for a folder (amp_flags)
*/
@property NSInteger flags;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPView.h
================================================
//
// PluginView.h
// AirmailCss
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
@class AMPlugin;
@interface AMPView : NSView
{
}
@property (weak) AMPlugin *plugin;
- (id)initWithFrame:(NSRect)frame plugin:(AMPlugin*)pluginIn;
/**
* When the view is displayed on the Plugin selection in the preference section
*/
- (void) RenderView;
/**
* When all plugin is reloaded
*/
- (void) ReloadView;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPlugin.h
================================================
//
// AMPlugin.h
// AirMail
//
// Created by Joe on 11/11/13.
// Copyright (c) 2013 Joe. All rights reserved.
//
#import
@class AMPAccount;
@class AMPMessage;
@class AMPView;
@class AMPComposerInfo;
@class AMPMCOMessageParser;
@class AMPMCOMessageBuilder;
@class AMPSignatureVerify;
@class AMPSendResult;
@interface AMPlugin : NSObject
{
}
/**
* The plugin data path
*/
@property (strong) NSString *dataPath;
/**
* The plugin bundle
*/
@property (strong) NSBundle *bundle;
/**
* The plugin preferences
*/
@property (strong) NSMutableDictionary *preferences;
/**
* The plugin view (in plugin prefernece of AM)
*/
@property (strong) AMPView *myView;
- (id)initWithbundle:(NSBundle*)bundleIn path:(NSString*)pathIn;
/**
* The Load is called int the plugin init
*
* @return Boolean if NO the plugin will not be loaded
*/
- (BOOL) Load;
//Must Have
/**
* The view to show in the AM preference (must override)
*
* @return the view
*/
- (AMPView*) pluginview;
/**
* The plugin name (must override)
*
* @return the name
*/
- (NSString*) nametext;
/**
* A short description of the plugin (must override)
*
* @return the description
*/
- (NSString*) descriptiontext;
/**
* The plugin author (must override)
*
* @return The author
*/
- (NSString*) authortext;
/**
* The plugin version (from bundle)
*
* @return plugin version
*/
- (NSString*) versiontext;
/**
* The plugin support link (must override)
*
* @return support link
*/
- (NSString*) supportlink;
/**
* The plugin icon (must override)
*
* @return icon
*/
- (NSImage*) icon;
//Logs
/**
* Log an error
*
* @param desc text for the log
*/
- (void) LogError:(NSString*)desc;
/**
* Trace log for debug
*
* @param desc text for the log
*/
- (void) LogTrace:(NSString*)desc;
//Events
/**
* Called when the plugin is enabled
*/
- (void) Enable;
/**
* Called when the plugin is disabled
*/
- (void) Disable;
/**
* Called when the plugin is set to invalid state
*/
- (void) Invalid;
/**
* Called when the user decide to reload the plugin
*/
- (void) Reload;
//Utilities
/**
* load an image from the plugin bundle
*
* @return the image
*/
- (NSImage*) loadImage:(NSString*)imageName;
/**
* the suggested path for saving data
*
* @return the path
*/
- (NSString*) suggestedpath;
/**
* The plugin bundle identifier
*
* @return the identifier
*/
- (NSString*) identifier;
/**
* A method to save a preference (key,value) in a plist
* in the suggested path folder
*
* @return Yes if successful
*/
- (BOOL) SavePreferences;
/**
* The path of the preference plist
*
* @return the path
*/
- (NSString*) preferencesPath;
/**
* A list of the files under the plugin data folder (suggested path)
*
* @return an array of paths
*/
- (NSArray*) suggestedpathContents;
/**
* A list of the files under the plugin bundle resources
*
* @return an array of paths
*/
- (NSArray*) bundlepathContents;
//Account / Folders
/**
* All Accounts of Airmail
*
* @return an array of AMPAccount
*/
- (NSArray*) Accounts;
/**
* All the folders for an account
*
* @param ampacc the account of the requested folders
*
* @return an array of AMPFolder
*/
- (NSArray*) Folders:(AMPAccount*)ampacc;
/**
* All the folders for an account standard folders(inbox,starred,...) first
*
* @param ampacc the account of the requested folders
*
* @return an array of AMPFolder
*/
- (NSArray*) OrderedFoldersWithStandardFirst:(AMPAccount*)ampacc;
#pragma mark - Composer
/**
* Get the html from a message to render in the composer
* Unique methods are called only one time from AM, if more than one plugin
* support Unique methods only one of them (randomly) will be used
*
* @param info the message to render
*
* @return the html to render
*/
- (NSString*) ampUniqueComposerRenderHtml:(AMPComposerInfo*)info;
/**
* Get the html for the new created composer
*
* @param info of the current composer
*
* @return the html to render
*/
- (NSString*) ampStackComposerRenderHtmlFromHtml:(NSString*)html composerInfo:(AMPComposerInfo*)info;
/**
* The menu item that AM will add in the composer
*
* @return the menu item
*/
- (id) ampMenuComposerItem:(AMPComposerInfo*)info;
/**
* Called to add a button on the composer
*
* @param info of the current composer
*
* @return the button to show
*/
- (NSArray*) ampPileComposerView:(AMPComposerInfo *)info;
/**
* Called on a recipients change in the composer
*
* @param info of the current composer
*
* @return void
*/
- (NSNumber*) ampPileChangedRecipients:(AMPComposerInfo*)info;
#pragma mark - Render BodyView
/**
* Get the html from a message to render in the bodyview
* Unique methods are called only one time from AM, if more than one plugin
* support Unique methods only one of them (randomly) will be used
*
* @param message the message to render
*
* @return info of the current composer
*/
- (NSString*) ampUniqueMessageRender:(AMPMessage*)message;
/**
* Get the html from the html that AM create from a message, to render in the
* bodyview. Stack methods can be queued, so AM will call all the plugins with
* a stack method in a random order.
*
* @param html the html to process
*
* @return the html to render
*/
- (NSString*) ampStackMessageRenderFromHtml:(NSString*)html message:(AMPMessage*)message;
/**
* Get the a message and create an array of NSView to render in the bodyview
*
* @param message the message to render
*
* @return the array of views to render
*/
- (NSArray*) ampPileMessageView:(AMPMessage*)message;
#pragma mark - Notify
/**
* Called after the standard AM notify. Is called for each message that AM will notify in the notification center
*
* @param message the message to notify
*
* @return a number with a boolean YES/NO
*/
- (NSNumber*) ampQueueNotify:(AMPMessage*)message;
#pragma mark - Action
/**
* The menu item that AM will add to the message menu
*
* @param messages the selected messages when the item is activated
*
* @return the menu item
*/
- (id) ampMenuActionItem:(NSArray*)messages;
#pragma mark - Rule
/**
* Called as rule action
*
* @param message the message filtered by the rule condition
*
* @return the Number for a bool if the rule is applied to the message
*/
- (NSNumber*) ampRuleActionItem:(AMPMessage*)message;
#pragma mark - Crypto
/**
* Called to let AM know if the message is encrypted
*
* @param the parser of the rfc to analyze
*
* @return a Number with the amp_encryption_type
*/
- (NSNumber*) ampPileIsEncrypted:(AMPMCOMessageParser*)parser;
/**
* Called to decrypt the message
*
* @param the message
*
* @return the decrypted rfc data to render
*/
- (NSData*) ampStackDecrypt:(AMPMessage*)message;
/**
* Called to verify the signature of the message
*
* @param the message
*
* @return a Number with the amp_verify_signature value
*/
- (AMPSignatureVerify*) ampPileVerifySignature:(AMPMessage*)message;
#pragma mark - Send
/**
* Called to before to send a mail
*
* @param the builder of the rfc to change
*
* @return the builder of the rfc to send
*/
- (AMPSendResult*) ampStackSendRfc:(NSString*)rfc composer:(AMPComposerInfo*)info;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/AMPluginFramework.h
================================================
//
// AMPluginFramework.h
// AMPluginFramework
//
// Created by Joe on 12/11/13.
// Copyright (c) 2013 Bloop. All rights reserved.
//
#import
#import "AMPlugin.h"
//Objects
#import "AMPObject.h"
#import "AMPAccount.h"
#import "AMPAddress.h"
#import "AMPGroup.h"
#import "AMPMessage.h"
#import "AMPProvider.h"
#import "AMPAttachment.h"
#import "AMPAlias.h"
#import "AMPSignature.h"
#import "AMPFolder.h"
//Utility
#import "AMPCallBack.h"
#import "AMPUidFlag.h"
#import "AMPComposerInfo.h"
#import "AMPMenuAction.h"
#import "AMPView.h"
#import "AMPSignatureVerify.h"
#import "AMPSendResult.h"
//Mailcore
#import "AMPMCOAddress.h"
#import "AMPMCOAttachment.h"
#import "AMPMCOAbstractPart.h"
#import "AMPMCOMultiPart.h"
#import "AMPMCOAbstractMultipart.h"
#import "AMPMCOMessagePart.h"
#import "AMPMCOAbstractMessagePart.h"
#import "AMPMCOMessageHeader.h"
#import "AMPMCOAbstractMessage.h"
#import "AMPMCOMessageParser.h"
#import "AMPMCOMessageBuilder.h"
//Categories
#import "NSScanner+Utility.h"
#import "NSData+AMPBase64.h"
enum amp_message_localflags {
AMP_FLAG1 = 1,
AMP_FLAG2 = 2,
AMP_FLAG3 = 3,
AMP_FLAG4 = 4,
AMP_FLAG5 = 5,
AMP_FLAG6 = 6,
AMP_FLAG7 = 7,
};
enum amp_provderType {
AMP_PROVIDER_GMAIL = 0,
AMP_PROVIDER_ICLOUD = 1,
AMP_PROVIDER_YAHOO = 2,
AMP_PROVIDER_AOL = 3,
AMP_PROVIDER_YAHOOJP = 5,
AMP_PROVIDER_OUTLOOK = 6,
//other imap here
AMP_PROVIDER_GENERICIMAP = 10,
AMP_PROVIDER_GENERICPOP3 = 100,
//all pop here
AMP_PROVIDER_HOTMAIL = 101,
AMP_PROVIDER_GENERICEXCHANGE = 200,
AMP_PROVIDER_GENERICLOCAL = 300
};
enum amp_encryption_type {
AMP_ENCRYPTED_NONE = 0,
AMP_ENCRYPTED_SIGNED = 1 << 0,
AMP_ENCRYPTED = 1 << 1,
};
enum amp_send_result {
AMP_SEND_RESULT_NONE = 0,
AMP_SEND_RESULT_FAIL = 1 << 0,
AMP_SEND_RESULT_SUCCESS = 1 << 1,
};
enum amp_verify_signature {
AMP_SIGNED_NONE = 0,
AMP_SIGNED_FAILS = 1 << 0,
AMP_SIGNED_SUCCESS = 1 << 1,
};
enum amp_composertype {
AMP_COMPOSER_RICHTEXT,
AMP_COMPOSER_PLAINTEXT,
AMP_COMPOSER_MARKDOWNTEXT
};
enum amp_mailcomposertype {
AMP_COMPOSER_NEW = 0,
AMP_COMPOSER_REPLY = 1,
AMP_COMPOSER_REPLYALL = 2,
AMP_COMPOSER_FORWARD = 3,
AMP_COMPOSER_EDITOR = 4,
AMP_COMPOSER_NEWFORFILE = 5,
AMP_COMPOSER_MAILTO = 6,
AMP_COMPOSER_QUICKREPLY = 7,
AMP_COMPOSER_SENDAGAIN = 8,
AMP_COMPOSER_SCRIPT = 9,
AMP_COMPOSER_REDIRECT = 10,
};
enum amp_foldertype {
AMP_STANDARDFOLDER = 0,
AMP_INBOX = 1,
AMP_STARRED = 2,
AMP_IMPORTANT = 3,
AMP_DRAFTS = 4,
AMP_SENTMAIL = 5,
AMP_ALLMAIL = 6,
AMP_TRASH = 7,
AMP_SPAM = 8,
AMP_ARCHIVE = 9,
AMP_NOTES = 10,
AMP_TODO = 11,
AMP_MEMO = 12,
AMP_DONE = 13,
AMP_AIRMAIL = 14,
AMP_LOCAL = 51,
AMP_SENDING = 52,
AMP_UNREAD = 53,
AMP_TODAY = 54,
//YESTERDAY = 54,
AMP_SEARCH = 55,
AMP_ALLVIRTUAL = 56,
AMP_LOCALSENT = 57,
AMP_MUTE = 101
};
enum amp_flags {
AMP_FlagNone = 0,
AMP_FlagAnswered = 1 << 0,
AMP_FlagSeen = 1 << 1,
AMP_FlagFlagged = 1 << 2,
AMP_FlagDeleted = 1 << 3,
AMP_FlagDraft = 1 << 4,
AMP_FlagMDNSent = 1 << 5,
AMP_FlagForwarded = 1 << 6,
AMP_FlagSubmitPending = 1 << 7,
AMP_FlagSubmitted = 1 << 8,
};
extern NSString * const amp_enabledDisabledAccount;
@interface AMPluginFramework : NSObject
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/NSData+AMPBase64.h
================================================
//
// NSData+AMPBase64.h
// AMPluginFramework
//
// Created by Giovanni Simonicca on 17/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
@interface NSData (AMPBase64)
//void *NewBase64Decode(
// const char *inputBuffer,
// size_t length,
// size_t *outputLength);
//
//char *NewBase64Encode(
// const void *inputBuffer,
// size_t length,
// bool separateLines,
// size_t *outputLength);
+ (NSData *)ampDataFromBase64String:(NSString *)aString;
- (NSString *)ampBase64EncodedString;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Headers/NSScanner+Utility.h
================================================
//
// NSScanner+SmimeUtility.h
// AMPSmime
//
// Created by Gio on 15/04/14.
// Copyright (c) 2014 Bloop. All rights reserved.
//
#import
@interface NSScanner (Utility)
- (unichar) currentCharacter;
- (unichar) previousCharacter;
- (BOOL) scanNext;
- (BOOL) scanNext:(NSUInteger)n;
- (BOOL) scanNext:(NSUInteger)next inString:(NSString**)string;
- (BOOL) nextCharacter:(unichar*)charx;
- (BOOL) nextString:(NSString*)string;
- (BOOL) nextCharacters:(NSUInteger)n inString:(NSString**)string;
- (BOOL) scanUpAndScan:(NSString*)str intoString:(NSString**)string;
@end
================================================
FILE: AMPluginFramework.framework/Versions/A/Resources/Info.plist
================================================
BuildMachineOSBuild
18A391
CFBundleDevelopmentRegion
English
CFBundleExecutable
AMPluginFramework
CFBundleIdentifier
com.airmail.framework
CFBundleInfoDictionaryVersion
6.0
CFBundleName
AMPluginFramework
CFBundlePackageType
FMWK
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleSupportedPlatforms
MacOSX
CFBundleVersion
1
DTCompiler
com.apple.compilers.llvm.clang.1_0
DTPlatformBuild
10O23u
DTPlatformVersion
GM
DTSDKBuild
18A384
DTSDKName
macosx10.14
DTXcode
1010
DTXcodeBuild
10O23u
NSHumanReadableCopyright
Copyright © 2013 Bloop. All rights reserved.
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: README.md
================================================

Airmail Plugin Framework (AMPF) 1.0
============================
The AMPF provides the API necessary to develop a plugin for Airmail.
Why a Plug-In Framework?
============================
The implementation of a plugin is necessary to inherit from the AMPF/AMPlugin class and to override the request methods (see Class Documentation)
The framework is an extended part of Airmail.
[API Call List](https://github.com/Airmail/Airmail-Plug-In-Framework/wiki/AMPF-Calls)
Samples
============================
The bundle inluiced few sample plugins that show some API of the framework.
[AMPlug Composer Template SDK Sample ](http://github.com/Airmail/Airmail-Plug-In-Framework/wiki/AMPlug-Composer-Template-SDK-Sample)
[AMPlug Message Style SDK Sample](http://github.com/Airmail/Airmail-Plug-In-Framework/wiki/AMPlug-Message-Style-SDK-Sample)
[AMPlug Simple Notifier SDK Sample](http://github.com/Airmail/Airmail-Plug-In-Framework/wiki/AMPlug-Simple-Notifier-SDK-Sample)
[AMPlug Translate SDK Sample](http://github.com/Airmail/Airmail-Plug-In-Framework/wiki/AMPlug-Translate-SDK-Sample)
[AMPlug Campaign Monitor](https://github.com/Airmail/CampaignMonitor-AMPlug)
[AMPlug MailChimp](https://github.com/Airmail/Mailchimp-AMPlug)
[AMPlug Wunderlist](https://github.com/Airmail/Wunderlist-AMPlug)
[AMPlug Todoist](https://github.com/Airmail/Todoist-AMPlug)
How to install
============================
You need to add a reference to the AMPF in your plugin project in order to use the requested classes. After you build your plugin, copy the bundle in the appropriate directory.
`~Library/Containers/it.bloop.airmail/Data/Library/Application Support/Airmail/General/Plugins`
`~Library/Containers/it.bloop.airmail.beta8/Data/Library/Application Support/Airmail/General/Plugins`
More Docs
============================
[- Wiki](https://github.com/Airmail/Airmail-Plug-In-Framework/wiki)
[- Class documentation](http://sdk.airmailapp.com)
[](http://sdk.airmailapp.com/)
Support
============================
[- Feedback](http://airmail.tenderapp.com)