aboutsummaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorMichael Heins <michael.heins@joltup.com>2017-05-18 08:29:53 -0600
committerMax Lohrmann <dmoagx@users.noreply.github.com>2017-05-19 02:15:30 +0200
commit0116bcecf0b1ebb66be0179a1a8e73670814dee1 (patch)
tree9a85e00a795b1d375a366183503dbd7705fca394 /Source
parent43926b0d48a341335538bb7b368c3fa4a73ddadb (diff)
downloadsequelpro-0116bcecf0b1ebb66be0179a1a8e73670814dee1.tar.gz
sequelpro-0116bcecf0b1ebb66be0179a1a8e73670814dee1.tar.bz2
sequelpro-0116bcecf0b1ebb66be0179a1a8e73670814dee1.zip
Hex edit for binary columns
Implement the ability to edit binary columns as hex data. Check input string for valid hex values; if invalid input, open alert sheet.
Diffstat (limited to 'Source')
-rw-r--r--Source/SPDataAdditions.h1
-rw-r--r--Source/SPDataAdditions.m68
-rw-r--r--Source/SPTableContentDataSource.m29
-rw-r--r--Source/SPTableContentDelegate.m7
4 files changed, 97 insertions, 8 deletions
diff --git a/Source/SPDataAdditions.h b/Source/SPDataAdditions.h
index cd8374f6..49dcd315 100644
--- a/Source/SPDataAdditions.h
+++ b/Source/SPDataAdditions.h
@@ -43,6 +43,7 @@ typedef NS_OPTIONS(NSUInteger, SPLineTerminator) {
- (NSData *)dataEncryptedWithKey:(NSData *)aesKey IV:(NSData *)iv;
- (NSData *)dataDecryptedWithPassword:(NSString *)password;
- (NSData *)dataDecryptedWithKey:(NSData *)key;
++ (NSData *)dataWithHexString: (NSString *)hex;
- (NSData *)compress;
- (NSData *)decompress;
diff --git a/Source/SPDataAdditions.m b/Source/SPDataAdditions.m
index 53d18274..3a35e081 100644
--- a/Source/SPDataAdditions.m
+++ b/Source/SPDataAdditions.m
@@ -343,6 +343,74 @@ uint32_t LimitUInt32(NSUInteger i);
return hexString;
}
+static int hexval( char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+//
+// Interpret a string of hex digits in 'hex' as hex data, and return
+// an NSData representation of the data. Spaces are permitted within
+// the string and an initial '0x' or '0X' will be ignored. If bad input
+// is detected, nil is returned.
+//
++ (NSData *)dataWithHexString: (NSString *)hex
+{
+ int n = (int)(hex.length + 1);
+ if (n <= 1)
+ return nil; // no string or empty string
+ char c, *str = (char *)malloc( n), *d = str, *e;
+ const char *s = hex.UTF8String;
+ //
+ // Copy input while removing spaces and tabs.
+ //
+ do {
+ c = *s++;
+ if (c != ' ' && c != '\t')
+ *d++ = c;
+ } while (c);
+ d = str;
+ if (d[0] == '0' && (d[1] == 'x' || d[1] == 'X')) {
+ d += 2; // bypass initial 0x or 0X
+ }
+ //
+ // Check for non-hex characters
+ //
+ for (e = d; (c = *e); e++) {
+ if (hexval( c) < 0) {
+ break;
+ }
+ }
+ n = (int)(e - d); // n = # of hex digits
+ if (*e) {
+ //
+ // Bad hex char at e. Return empty data. Alternative would be to
+ // convert data up to bad point.
+ //
+ free( str);
+ return nil;
+ }
+ int nbytes = (n % 2) ? (n + 1) / 2 : n / 2;
+ unsigned char *bytes = malloc( nbytes), *b = bytes;
+ if (n % 2) {
+ *b++ = hexval( *d++);
+ }
+ while (d < e) {
+ unsigned char v = (hexval( d[0]) << 4) + hexval( d[1]);
+ *b++ = v;
+ d += 2;
+ }
+ NSData *data = [NSData dataWithBytesNoCopy: bytes length: nbytes freeWhenDone: YES];
+ free( str);
+ return data;
+}
+
/**
* Returns the hex representation of the given data.
*/
diff --git a/Source/SPTableContentDataSource.m b/Source/SPTableContentDataSource.m
index 56e8df71..a005cdce 100644
--- a/Source/SPTableContentDataSource.m
+++ b/Source/SPTableContentDataSource.m
@@ -33,6 +33,7 @@
#import "SPDataStorage.h"
#import "SPCopyTable.h"
#import "SPTablesList.h"
+#import "SPAlertSheets.h"
#import <pthread.h>
#import <SPMySQL/SPMySQL.h>
@@ -177,6 +178,11 @@
return;
}
+ NSInteger columnIndex = [[tableColumn identifier] integerValue];
+ NSDictionary *columnDefinition = [[(id <SPDatabaseContentViewDelegate>)[tableContentView delegate] dataColumnDefinitions] objectAtIndex:columnIndex];
+
+ NSString *columnType = [columnDefinition objectForKey:@"typegrouping"];
+
// Catch editing events in the row and if the row isn't currently being edited,
// start an edit. This allows edits including enum changes to save correctly.
if (isEditingRow && [tableContentView selectedRow] != currentlyEditingRow) {
@@ -192,7 +198,28 @@
NSDictionary *column = NSArrayObjectAtIndex(dataColumns, [[tableColumn identifier] integerValue]);
- if (object) {
+ if ([columnType isEqualToString:@"binary"] && [object isKindOfClass: [NSString class]]) {
+ //
+ // This is a binary object being edited as a hex string. (Is there a better
+ // way to detect this case?)
+ // Convert the string back to binary, checking for errors.
+ //
+ NSData *data = [NSData dataWithHexString: object];
+ if (data) {
+ object = data;
+ [tableValues replaceObjectInRow:rowIndex column:[[tableColumn identifier] integerValue] withObject:object];
+ }
+ else {
+ SPOnewayAlertSheet(
+ NSLocalizedString(@"Error", @"error"),
+ [tableDocumentInstance parentWindow],
+ NSLocalizedString(@"Bad hexadecimal data input.", @"Bad hexadecimal data input.")
+ );
+ return;
+
+ }
+ }
+ else if (object) {
// Restore NULLs if necessary
if ([object isEqualToString:[prefs objectForKey:SPNullValue]] && [[column objectForKey:@"null"] boolValue]) {
object = [NSNull null];
diff --git a/Source/SPTableContentDelegate.m b/Source/SPTableContentDelegate.m
index 186fbfcc..3c437333 100644
--- a/Source/SPTableContentDelegate.m
+++ b/Source/SPTableContentDelegate.m
@@ -273,13 +273,6 @@
// Retrieve the column definition
NSDictionary *columnDefinition = [cqColumnDefinition objectAtIndex:[[tableColumn identifier] integerValue]];
- // TODO: Fix editing of "Display as Hex" columns and remove this (also see above)
- if ([self cellValueIsDisplayedAsHexForColumn:[[tableColumn identifier] integerValue]]) {
- NSBeep();
- [SPTooltip showWithObject:NSLocalizedString(@"Disable \"Display Binary Data as Hex\" in the View menu to edit this field.",@"Temporary : Tooltip shown when trying to edit a binary field in table content view while it is displayed using HEX conversion")];
- return NO;
- }
-
// Open the editing sheet if required
if ([tableContentView shouldUseFieldEditorForRow:rowIndex column:[[tableColumn identifier] integerValue] checkWithLock:NULL]) {