Skip to content
Permalink
Browse files
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.
  • Loading branch information
Michael Heins authored and dmoagx committed May 19, 2017
1 parent 43926b0 commit 0116bce
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 8 deletions.
@@ -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;
@@ -343,6 +343,74 @@ - (NSString *)dataToHexString
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.
*/
@@ -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 @@ - (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableCol
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 @@ - (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableCol

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];
@@ -273,13 +273,6 @@ - (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn
// 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]) {

0 comments on commit 0116bce

Please sign in to comment.