aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBibiko <bibiko@eva.mpg.de>2009-08-24 11:02:23 +0000
committerBibiko <bibiko@eva.mpg.de>2009-08-24 11:02:23 +0000
commit40880459c66165a264faa561319c996d82613fac (patch)
treea5be30704b5cfb26e9f3a3500a0869c589e0fc82
parentb02932c07c4fdbf5b8c051c5a7218c4c37cf4bf2 (diff)
downloadsequelpro-40880459c66165a264faa561319c996d82613fac.tar.gz
sequelpro-40880459c66165a264faa561319c996d82613fac.tar.bz2
sequelpro-40880459c66165a264faa561319c996d82613fac.zip
• further improvements for open/save spf files
- added encryption code routine - if encrypted ask for password • added to SPDataAdditions dataEn/DecryptedWithPassword: • tiny fixes for cascading new doc windows - never decrease win size less than minSize - large win width detection now gets rid of all connected monitors • updated credits.rtf
-rw-r--r--Interfaces/English.lproj/Credits.rtf16
-rw-r--r--Source/SPDataAdditions.h8
-rw-r--r--Source/SPDataAdditions.m83
-rw-r--r--Source/TableDocument.m146
-rw-r--r--sequel-pro.xcodeproj/project.pbxproj2
5 files changed, 224 insertions, 31 deletions
diff --git a/Interfaces/English.lproj/Credits.rtf b/Interfaces/English.lproj/Credits.rtf
index 817cb6fe..245bd88b 100644
--- a/Interfaces/English.lproj/Credits.rtf
+++ b/Interfaces/English.lproj/Credits.rtf
@@ -1,6 +1,7 @@
-{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf460
+{\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf540
{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\fnil\fcharset128 HiraKakuProN-W3;}
{\colortbl;\red255\green255\blue255;\red25\green25\blue25;\red0\green27\blue199;}
+\vieww9000\viewh8400\viewkind0
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural
\f0\b\fs22 \cf2 Current Developers
@@ -47,6 +48,8 @@ Matt Gemmell\
(MGTemplateEngine)\
Joachim M\'e5rtensson, Allan Odgaard\
(TMDIncrementalPopUp)\
+Ci\'e1ran Walsh, Allan Odgaard\
+(TMDHTMLtip) \
\
\b RegexKitLite
@@ -60,6 +63,17 @@ Joachim M\'e5rtensson, Allan Odgaard\
\
\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural
+\b \cf0 AQDataExtension
+\b0 \
+\pard\pardeftab720\qc
+\cf0 Copyright (c) 2005\
+\pard\pardeftab720\qc
+{\field{\*\fldinst{HYPERLINK "http://aquaticmac.com/cocoa.php"}}{\fldrslt \cf0 Lucas Newman}}\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural
+\cf0 All rights reserved.\
+\
+\pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural
+
\b \cf0 BWToolkitFramework
\b0 \
\pard\pardeftab720\qc
diff --git a/Source/SPDataAdditions.h b/Source/SPDataAdditions.h
index fcf2640c..40bea690 100644
--- a/Source/SPDataAdditions.h
+++ b/Source/SPDataAdditions.h
@@ -26,9 +26,11 @@
@interface NSData (SPDataAdditions)
-- (NSString *) base64EncodingWithLineLength:(unsigned int)lineLength;
-- (NSString *) dataToFormattedHexString;
-- (NSString *) shortStringRepresentationUsingEncoding:(NSStringEncoding)encoding;
+- (NSString *)base64EncodingWithLineLength:(unsigned int)lineLength;
+- (NSString *)dataToFormattedHexString;
+- (NSString *)shortStringRepresentationUsingEncoding:(NSStringEncoding)encoding;
+- (NSData*)dataEncryptedWithPassword:(NSString*)password;
+- (NSData*)dataDecryptedWithPassword:(NSString*)password;
- (NSData *)compress;
- (NSData *)decompress;
diff --git a/Source/SPDataAdditions.m b/Source/SPDataAdditions.m
index edac9baa..1af06f5b 100644
--- a/Source/SPDataAdditions.m
+++ b/Source/SPDataAdditions.m
@@ -4,6 +4,11 @@
// SPDataAdditions.m
// sequel-pro
//
+// dataEncryptedWithPassword and dataDecryptedWithPassword:
+// License: FREEWARE http://aquaticmac.com/cocoa.php
+// Copyright (c) 2005, Lucas Newman
+// All rights reserved.
+//
// Created by Hans-Jörg Bibiko on June 19, 2009
//
// This program is free software; you can redistribute it and/or modify
@@ -24,6 +29,8 @@
#import "SPDataAdditions.h"
#include <zlib.h>
+#include <openssl/aes.h>
+#include <openssl/sha.h>
static char base64encodingTable[64] = {
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
@@ -101,6 +108,82 @@ static char base64encodingTable[64] = {
return base64;
}
+- (NSData*)dataEncryptedWithPassword:(NSString*)password
+{
+ // Create a random 128-bit initialization vector
+ srand(time(NULL));
+ int ivIndex;
+ unsigned char iv[16];
+ for (ivIndex = 0; ivIndex < 16; ivIndex++)
+ iv[ivIndex] = rand() & 0xff;
+
+ // Calculate the 16-byte AES block padding
+ int dataLength = [self length];
+ int paddedLength = dataLength + (32 - (dataLength % 16));
+ int totalLength = paddedLength + 16; // Data plus IV
+
+ // Allocate enough space for the IV + ciphertext
+ unsigned char *encryptedBytes = calloc(1, totalLength);
+ // The first block of the ciphertext buffer is the IV
+ memcpy(encryptedBytes, iv, 16);
+
+ unsigned char *paddedBytes = calloc(1, paddedLength);
+ memcpy(paddedBytes, [self bytes], dataLength);
+
+ // The last 32-bit chunk is the size of the plaintext, which is encrypted with the plaintext
+ int bigIntDataLength = NSSwapHostIntToBig(dataLength);
+ memcpy(paddedBytes + (paddedLength - 4), &bigIntDataLength, 4);
+
+ // Create the key from first 128-bits of the 160-bit password hash
+ unsigned char passwordDigest[20];
+ SHA1((const unsigned char *)[password UTF8String], strlen([password UTF8String]), passwordDigest);
+ AES_KEY aesKey;
+ AES_set_encrypt_key(passwordDigest, 128, &aesKey);
+
+ // AES-128-cbc encrypt the data, filling in the buffer after the IV
+ AES_cbc_encrypt(paddedBytes, encryptedBytes + 16, paddedLength, &aesKey, iv, AES_ENCRYPT);
+ free(paddedBytes);
+
+ return [NSData dataWithBytesNoCopy:encryptedBytes length:totalLength];
+}
+
+- (NSData*)dataDecryptedWithPassword:(NSString*)password
+{
+ // Create the key from the password hash
+ unsigned char passwordDigest[20];
+ SHA1((const unsigned char *)[password UTF8String], strlen([password UTF8String]), passwordDigest);
+
+ // AES-128-cbc decrypt the data
+ AES_KEY aesKey;
+ AES_set_decrypt_key(passwordDigest, 128, &aesKey);
+
+ // Total length = encrypted length + IV
+ int totalLength = [self length];
+ int encryptedLength = totalLength - 16;
+
+ // Take the IV from the first 128-bit block
+ unsigned char iv[16];
+ memcpy(iv, [self bytes], 16);
+
+ // Decrypt the data
+ unsigned char *decryptedBytes = (unsigned char*)malloc(encryptedLength);
+ AES_cbc_encrypt([self bytes] + 16, decryptedBytes, encryptedLength, &aesKey, iv, AES_DECRYPT);
+
+ // If decryption was successful, these blocks will be zeroed
+ if ( *((unsigned int*)decryptedBytes + ((encryptedLength / 4) - 4)) ||
+ *((unsigned int*)decryptedBytes + ((encryptedLength / 4) - 3)) ||
+ *((unsigned int*)decryptedBytes + ((encryptedLength / 4) - 2)) )
+ {
+ return nil;
+ }
+
+ // Get the size of the data from the last 32-bit chunk
+ int bigIntDataLength = *((unsigned int*)decryptedBytes + ((encryptedLength / 4) - 1));
+ int dataLength = NSSwapBigIntToHost(bigIntDataLength);
+
+ return [NSData dataWithBytesNoCopy:decryptedBytes length:dataLength];
+}
+
- (NSData *)decompress
{
if ([self length] == 0) return self;
diff --git a/Source/TableDocument.m b/Source/TableDocument.m
index a6b4caae..2608c47e 100644
--- a/Source/TableDocument.m
+++ b/Source/TableDocument.m
@@ -83,6 +83,7 @@
prefs = [NSUserDefaults standardUserDefaults];
queryEditorInitString = nil;
+ [saveConnectionEncryptString setStringValue:@""];
spf = nil;
@@ -114,12 +115,12 @@
screenFrame = [candidate frame];
previousFrame = [tableWindow frame];
- topLeftPoint = previousFrame.origin;
- if(topLeftPoint.x + previousFrame.size.width > screenFrame.size.width-1) {
+ if(previousFrame.origin.x - screenFrame.origin.x + previousFrame.size.width > screenFrame.size.width-1) {
previousFrame.size.width -= 50;
previousFrame.size.height -= 50;
previousFrame.origin.y += 50;
- [tableWindow setFrame:previousFrame display:YES];
+ if(previousFrame.size.width >= [tableWindow minSize].width && previousFrame.size.height >= [tableWindow minSize].height)
+ [tableWindow setFrame:previousFrame display:YES];
}
}
@@ -170,6 +171,8 @@
NSError *readError = nil;
NSString *convError = nil;
NSPropertyListFormat format;
+ NSString *encryptpw = nil;
+
NSData *pData = [[NSData dataWithContentsOfFile:path options:NSUncachedRead error:&readError] decompress];
spf = [[NSPropertyListSerialization propertyListFromData:pData
mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&convError] retain];
@@ -186,27 +189,65 @@
return;
}
+ // Init Custom Query editor with the stored queries if given
if([spf objectForKey:@"queries"])
[self initQueryEditorWithString:[spf objectForKey:@"queries"]];
- if([spf objectForKey:@"type"])
- [connectionController setType:[[spf objectForKey:@"type"] intValue]];
+ // Clean fields
+ [connectionController setName:@""];
+ [connectionController setUser:@""];
+ [connectionController setHost:@""];
+ [connectionController setPort:@""];
+ [connectionController setSshHost:@""];
+ [connectionController setSshUser:@""];
+ [connectionController setSshPort:@""];
+ [connectionController setDatabase:@""];
+ [connectionController setPassword:@""];
+ [connectionController setSshPassword:@""];
+
+ // NSLog(@"%@", spf);
+
+ // Ask for a password if SPF file passwords were encrypted
+ if([spf objectForKey:@"encrypted"] && [[spf objectForKey:@"encrypted"] intValue] == NSOnState) {
+ NSAlert *alert = [NSAlert alertWithMessageText:NSLocalizedString(@"Connection file is encrypted", @"Connection file is encrypted")
+ defaultButton:@"OK"
+ alternateButton:@"Cancel"
+ otherButton:nil
+ informativeTextWithFormat:NSLocalizedString(@"Please enter the password:",@"Please enter the password")];
+
+ NSTextField *input = [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 220, 24)];
+ [input setStringValue:@""];
+ [alert setAccessoryView:input];
+ [[alert window] setInitialFirstResponder:input];
+ [[alert window] makeFirstResponder:input];
+ [input selectText:[alert window]];
+ NSInteger button = [alert runModal];
+ if (button == NSAlertDefaultReturn) {
+ encryptpw = [input stringValue];
+ [input release];
+ } else {
+ [input release];
+ return;
+ }
+ }
+
+ if([spf objectForKey:@"connectionType"]) {
+ [connectionController setType:[[spf objectForKey:@"connectionType"] intValue]];
+ [connectionController resizeTabViewToConnectionType:[connectionController type] animating:NO];
+ }
+
if([spf objectForKey:@"name"])
[connectionController setName:[spf objectForKey:@"name"]];
if([spf objectForKey:@"user"])
[connectionController setUser:[spf objectForKey:@"user"]];
if([spf objectForKey:@"host"])
[connectionController setHost:[spf objectForKey:@"host"]];
- if([spf objectForKey:@"auth"])
- [connectionController setPassword:[spf objectForKey:@"auth"]];
if([spf objectForKey:@"port"])
[connectionController setPort:[spf objectForKey:@"port"]];
if([spf objectForKey:@"sshHost"])
[connectionController setSshHost:[spf objectForKey:@"sshHost"]];
if([spf objectForKey:@"sshUser"])
[connectionController setSshUser:[spf objectForKey:@"sshUser"]];
- if([spf objectForKey:@"sshAuth"])
- [connectionController setSshPassword:[spf objectForKey:@"sshAuth"]];
if([spf objectForKey:@"sshPort"])
[connectionController setSshPort:[spf objectForKey:@"sshPort"]];
if([spf objectForKey:@"selectedDatabase"])
@@ -215,16 +256,46 @@
// If password are stored in SPF file auto-connect
// otherwise wait for password(s)
if([spf objectForKey:@"auth"]) {
- if([[spf objectForKey:@"type"] intValue] == 2) {
- if(![spf objectForKey:@"sshAuth"])
- return;
+
+ NSString *sauth;
+ if(encryptpw != nil && [spf objectForKey:@"encrypted"] && [[spf objectForKey:@"encrypted"] intValue] == NSOnState)
+ sauth = [[NSString alloc] initWithData:[[spf objectForKey:@"auth"] dataDecryptedWithPassword:encryptpw] encoding:NSUTF8StringEncoding];
+ else
+ sauth = [[NSString alloc] initWithData:[spf objectForKey:@"auth"] encoding:NSUTF8StringEncoding];
+ [connectionController setPassword:sauth];
+ [sauth release];
+
+ if([connectionController type] == SP_CONNECTION_SSHTUNNEL) {
+
+ if(![spf objectForKey:@"sshAuth"]) {
+ [connectionController setSshPassword:@""];
+ [[connectionController valueForKeyPath:@"sshSSHPasswordField"] selectText:self];
+ return;
+ }
+
+ NSString *sshauth;
+ if(encryptpw != nil && [spf objectForKey:@"encrypted"] && [[spf objectForKey:@"encrypted"] intValue] == NSOnState)
+ sshauth = [[NSString alloc] initWithData:[[spf objectForKey:@"auth"] dataDecryptedWithPassword:encryptpw] encoding:NSUTF8StringEncoding];
+ else
+ sshauth = [[NSString alloc] initWithData:[spf objectForKey:@"auth"] encoding:NSUTF8StringEncoding];
+
+ [connectionController setSshPassword:sshauth];
+ [sshauth release];
[connectionController initiateConnection:nil];
- [self performSelector:@selector(restoreSession) withObject:nil afterDelay:0.2];
} else {
+
[connectionController initiateConnection:nil];
+
}
+ } else {
+
+ [connectionController setPassword:@""];
+ [connectionController setSshPassword:@""];
+ [[connectionController valueForKeyPath:@"standardPasswordField"] selectText:self];
+
}
+ encryptpw = nil;
}
@@ -249,22 +320,13 @@
// Select table
[tablesListInstance selectTableAtIndex:[NSNumber numberWithInt:[tables indexOfObject:[spf objectForKey:@"selectedTable"]]]];
+ [[tablesListInstance valueForKeyPath:@"tablesListView"] scrollRowToVisible:[tables indexOfObject:[spf objectForKey:@"selectedTable"]]];
// Set table content details for restore
if([spf objectForKey:@"contentSortCol"])
[tableContentInstance setSortColumnNameToRestore:[spf objectForKey:@"contentSortCol"] isAscending:[[spf objectForKey:@"contentSortCol"] boolValue]];
if([spf objectForKey:@"contentLimitStartPosition"])
[tableContentInstance setLimitStartToRestore:[[spf objectForKey:@"contentLimitStartPosition"] intValue]];
- if([spf objectForKey:@"contentSelectedIndexSet"]) {
- NSMutableIndexSet *anIndexSet = [NSMutableIndexSet indexSet];
- NSArray *items = [spf objectForKey:@"contentSelectedIndexSet"];
- unsigned int i;
- for(i=0; i<[items count]; i++)
- {
- [anIndexSet addIndex:(NSUInteger)NSArrayObjectAtIndex(items, i)];
- }
- [tableContentInstance setSelectedRowIndexesToRestore:anIndexSet];
- }
if([spf objectForKey:@"contentViewport"])
[tableContentInstance setViewportToRestore:NSRectFromString([spf objectForKey:@"contentViewport"])];
if([spf objectForKey:@"contentFilter"])
@@ -296,6 +358,17 @@
}
}
+ if([spf objectForKey:@"contentSelectedIndexSet"]) {
+ NSMutableIndexSet *anIndexSet = [NSMutableIndexSet indexSet];
+ NSArray *items = [spf objectForKey:@"contentSelectedIndexSet"];
+ unsigned int i;
+ for(i=0; i<[items count]; i++)
+ {
+ [anIndexSet addIndex:(NSUInteger)NSArrayObjectAtIndex(items, i)];
+ }
+ [tableContentInstance setSelectedRowIndexesToRestore:anIndexSet];
+ }
+
// dealloc spf data
[spf release];
spf = nil;
@@ -1746,8 +1819,9 @@
// Save current session (open connection windows as SPF file)
// [panel setMessage:NSLocalizedString(@"Save Sequel Pro session", @"Save Sequel Pro session")];
[panel setAllowedFileTypes:[NSArray arrayWithObjects:@"spf", nil]];
- [saveConnectionEncryptString setDelegate:self];
+ // [saveConnectionEncryptString setDelegate:self];
[saveConnectionEncryptString setEnabled:YES];
+ [saveConnectionEncryptString selectText:self];
[saveConnectionEncryptString setStringValue:@""];
[saveConnectionEncryptString setEnabled:NO];
[saveConnectionSavePassword setState:NSOffState];
@@ -1778,9 +1852,10 @@
[saveConnectionEncrypt setEnabled:YES];
if([saveConnectionEncrypt state] == NSOnState) {
[saveConnectionEncryptString setEnabled:YES];
- [saveConnectionEncryptString selectText:nil];
+ [saveConnectionEncryptString selectText:self];
} else {
[saveConnectionEncryptString setEnabled:YES];
+ [saveConnectionEncryptString selectText:self];
[saveConnectionEncryptString setStringValue:@""];
[saveConnectionEncryptString setHidden:YES];
[saveConnectionEncryptString setHidden:NO];
@@ -1789,6 +1864,7 @@
} else {
[saveConnectionEncrypt setEnabled:NO];
[saveConnectionEncryptString setEnabled:YES];
+ [saveConnectionEncryptString selectText:self];
[saveConnectionEncryptString setStringValue:@""];
[saveConnectionEncryptString setHidden:YES];
[saveConnectionEncryptString setHidden:NO];
@@ -1824,8 +1900,13 @@
}
return;
}
+
+ // Save connection and session as SPF file
else if(contextInfo == @"saveSPFfile") {
+ [saveConnectionEncryptString abortEditing];
+ [saveConnectionEncryptString selectText:nil];
+
NSMutableDictionary *spfdata = [NSMutableDictionary dictionary];
NSIndexSet *contentSelectedIndexSet = [tableContentInstance selectedRowIndexes];
@@ -1836,14 +1917,25 @@
[spfdata setObject:[self name] forKey:@"name"];
[spfdata setObject:[self host] forKey:@"host"];
[spfdata setObject:[self user] forKey:@"user"];
- // [spfdata setObject:[connectionController password] forKey:@"auth"];
+
+ if([saveConnectionEncrypt isEnabled])
+ [spfdata setObject:[NSNumber numberWithInt:[saveConnectionEncrypt state]] forKey:@"encrypted"];
[spfdata setObject:[NSNumber numberWithInt:[connectionController type]] forKey:@"connectionType"];
if([connectionController type] == 2) {
[spfdata setObject:[connectionController sshHost] forKey:@"sshHost"];
[spfdata setObject:[connectionController sshUser] forKey:@"sshUser"];
[spfdata setObject:[connectionController sshPort] forKey:@"sshPort"];
- // [spfdata setObject:[connectionController sshPassword] forKey:@"sshAuth"];
+ }
+
+ if([saveConnectionSavePassword state] == NSOnState) {
+ if([saveConnectionEncrypt state] == NSOffState) {
+ [spfdata setObject:[[connectionController password] dataUsingEncoding:NSUTF8StringEncoding] forKey:@"auth"];
+ [spfdata setObject:[[connectionController sshPassword] dataUsingEncoding:NSUTF8StringEncoding] forKey:@"sshAuth"];
+ } else {
+ [spfdata setObject:[[[connectionController password] dataUsingEncoding:NSUTF8StringEncoding] dataEncryptedWithPassword:[saveConnectionEncryptString stringValue]] forKey:@"auth"];
+ [spfdata setObject:[[[connectionController sshPassword] dataUsingEncoding:NSUTF8StringEncoding] dataEncryptedWithPassword:[saveConnectionEncryptString stringValue]] forKey:@"sshAuth"];
+ }
}
if([connectionController port] &&[[connectionController port] length])
diff --git a/sequel-pro.xcodeproj/project.pbxproj b/sequel-pro.xcodeproj/project.pbxproj
index c776e45b..9cd9a4c3 100644
--- a/sequel-pro.xcodeproj/project.pbxproj
+++ b/sequel-pro.xcodeproj/project.pbxproj
@@ -2152,6 +2152,7 @@
LEX_INSERT_LINE_DIRECTIVES = YES;
LEX_SUPPRESS_DEFAULT_RULE = NO;
ONLY_ACTIVE_ARCH = YES;
+ OTHER_LDFLAGS = "-lcrypto";
PREBINDING = NO;
SDKROOT = macosx10.5;
STRIP_INSTALLED_PRODUCT = NO;
@@ -2166,6 +2167,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IBC_NOTICES = NO;
+ OTHER_LDFLAGS = "-lcrypto";
PREBINDING = NO;
SDKROOT = macosx10.5;
};