Skip to content

Commit

Permalink
Added a read-only mode for which privileged files will default to.
Browse files Browse the repository at this point in the history
Fixed a memory leak in [HFFileReference writeBytes.]
Changed key equivalent for overwrite mode to something that doesn't clash.
Fixed it so that character and block devices will not allow you to be in insert mode.
  • Loading branch information
Chris Suter committed Dec 23, 2011
1 parent 5c2327b commit bf32c66
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 598 deletions.
653 changes: 106 additions & 547 deletions English.lproj/MainMenu.xib

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions app/sources/AppDelegate.m
Expand Up @@ -14,8 +14,6 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <xpc/connection.h>
#include <syslog.h>

@implementation AppDelegate

Expand Down
8 changes: 6 additions & 2 deletions app/sources/BaseDataDocument.h
Expand Up @@ -47,7 +47,7 @@ NSString * const BaseDataDocumentDidChangeStringEncodingNotification;
BOOL saveInProgress;

BOOL currentlySettingFont;
BOOL isTransient;
BOOL isTransient;
}

- (void)moveSelectionForwards:(NSMenuItem *)sender;
Expand All @@ -74,7 +74,9 @@ NSString * const BaseDataDocumentDidChangeStringEncodingNotification;
- (IBAction)replaceAll:sender;
- (IBAction)performFindReplaceActionFromSelectedSegment:(id)sender;

- (IBAction)toggleOverwriteMode:sender;
- (IBAction)setOverwriteMode:sender;
- (IBAction)setInsertMode:sender;
- (IBAction)setReadOnlyMode:sender;
- (IBAction)modifyByteGrouping:sender;

- (IBAction)setBookmark:sender;
Expand Down Expand Up @@ -102,4 +104,6 @@ NSString * const BaseDataDocumentDidChangeStringEncodingNotification;
/* Returns a string identifier used as an NSUserDefault prefix for storing the layout for documents of this type. If you return nil, the layout will not be stored. The default is to return the class name. */
+ (NSString *)layoutUserDefaultIdentifier;

- (BOOL)requiresOverwriteMode;

@end
58 changes: 48 additions & 10 deletions app/sources/BaseDataDocument.m
Expand Up @@ -266,11 +266,18 @@ - (NSArray *)runningOperationViews {
/* Return a format string that can take one argument which is the document name. */
- (NSString *)documentWindowTitleFormatString {
NSMutableString *result = [NSMutableString stringWithString:@"%@"]; //format specifier that is replaced with document name

if ([controller inOverwriteMode]) {
[result appendString:@" **OVERWRITE MODE**"];

switch ([controller editMode]) {
case HFInsertMode:
break;
case HFOverwriteMode:
[result appendString:NSLocalizedString(@" **OVERWRITE MODE**", @"Title Suffix")];
break;
case HFReadOnlyMode:
[result appendString:NSLocalizedString(@" **READ-ONLY MODE**", @"Title Suffix")];
break;
}

BOOL hasAppendedProgressMarker = NO;
NSArray *runningViews = [self runningOperationViews];
FOREACH(HFDocumentOperationView *, view, runningViews) {
Expand Down Expand Up @@ -789,10 +796,18 @@ - (BOOL)validateMenuItem:(NSMenuItem *)item {
[item setState:[controller shouldAntialias]];
return YES;
}
else if (action == @selector(toggleOverwriteMode:)) {
[item setState:[controller inOverwriteMode]];
else if (action == @selector(setOverwriteMode:)) {
[item setState:[controller editMode] == HFOverwriteMode];
/* We can toggle overwrite mode only if the controller doesn't require that it be on */
return ! [controller requiresOverwriteMode];
return YES;
}
else if (action == @selector(setInsertMode:)) {
[item setState:[controller editMode] == HFInsertMode];
return ![self requiresOverwriteMode];
}
else if (action == @selector(setReadOnlyMode:)) {
[item setState:[controller editMode] == HFReadOnlyMode];
return YES;
}
else if (action == @selector(modifyByteGrouping:)) {
[item setState:(NSUInteger)[item tag] == [controller bytesPerColumn]];
Expand All @@ -814,7 +829,13 @@ - (BOOL)validateMenuItem:(NSMenuItem *)item {
[item setTitle:newTitle];
return selectedBookmark != NSNotFound;
}
else return [super validateMenuItem:item];
else if (action == @selector(saveDocument:)) {
if ([controller editMode] == HFReadOnlyMode)
return NO;
// Fall through
}

return [super validateMenuItem:item];
}

- (void)finishedAnimation {
Expand Down Expand Up @@ -1603,12 +1624,24 @@ - (IBAction)modifyByteGrouping:sender {
[[NSUserDefaults standardUserDefaults] setInteger:newBytesPerColumn forKey:@"BytesPerColumn"];
}

- (IBAction)toggleOverwriteMode:sender {
- (IBAction)setOverwriteMode:sender {
USE(sender);
[controller setInOverwriteMode:![controller inOverwriteMode]];
[controller setEditMode:HFOverwriteMode];
[self updateDocumentWindowTitle];
}

- (IBAction)setInsertMode:sender {
USE(sender);
[controller setEditMode:HFInsertMode];
[self updateDocumentWindowTitle];
}

- (IBAction)setReadOnlyMode:sender {
USE(sender);
[controller setEditMode:HFReadOnlyMode];
[self updateDocumentWindowTitle];
}

- (void)jumpToBookmarkIndex:(NSInteger)bookmark selecting:(BOOL)select {
if (controller) {
HFRange range = [controller rangeForBookmark:bookmark];
Expand Down Expand Up @@ -1775,4 +1808,9 @@ + (void)prepareForChangeInFileByBreakingFileDependencies:(NSNotification *)note
[allDocuments release];
}

- (BOOL)requiresOverwriteMode
{
return NO;
}

@end
2 changes: 1 addition & 1 deletion app/sources/FileDataDocument.h
Expand Up @@ -8,7 +8,7 @@
#import "BaseDataDocument.h"

@interface FileDataDocument : BaseDataDocument {

BOOL requiresOverwriteMode;
}

@end
19 changes: 15 additions & 4 deletions app/sources/FileDataDocument.m
Expand Up @@ -31,12 +31,23 @@ - (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSEr
[controller setByteArray:byteArray];
result = YES;

// If the file is > 64 MB in size, default to starting in overwrite mode
if ([fileReference length] > 64 * 1024 * 1024)
[controller setInOverwriteMode:YES];

if ([fileReference isPrivileged])
[controller setEditMode:HFReadOnlyMode];
else {
// If the file is > 64 MB in size, default to starting in overwrite mode
if ([fileReference length] > 64 * 1024 * 1024)
[controller setEditMode:HFOverwriteMode];
}
}

requiresOverwriteMode = [fileReference isFixedLength];

return result;
}

- (BOOL)requiresOverwriteMode
{
return requiresOverwriteMode;
}

@end
25 changes: 15 additions & 10 deletions framework/sources/HFController.h
Expand Up @@ -75,6 +75,16 @@ enum
};
typedef NSInteger HFControllerMovementGranularity;

/*! @enum HFEditMode
HFEditMode enumerates the different edit modes that a document might be in.
*/
typedef enum {
HFInsertMode,
HFOverwriteMode,
HFReadOnlyMode,
} HFEditMode;

/*! @class HFController
@brief A central class that acts as the controller layer for HexFiend.framework
Expand Down Expand Up @@ -122,7 +132,7 @@ You create an HFController via <tt>[[HFController alloc] init]</tt>. After that

struct {
unsigned antialias:1;
unsigned overwriteMode:1;
HFEditMode editMode:2;
unsigned editable:1;
unsigned selectable:1;
unsigned selectionInProgress:1;
Expand Down Expand Up @@ -240,18 +250,13 @@ You create an HFController via <tt>[[HFController alloc] init]</tt>. After that
- (NSUInteger)bytesPerColumn;
//@}

/*! @name Overwrite mode
Determines whether text insertion overwrites subsequent text or not. */
/*! @name Edit Mode
Determines what mode we're in, read-only, overwrite or insert. */
//@{

/*! Determines whether this HFController is in overwrite mode or not. */
- (BOOL)inOverwriteMode;

/*! Sets whether we this HFController is in overwrite mode or not. */
- (void)setInOverwriteMode:(BOOL)val;
- (HFEditMode)editMode;

/*! Returns YES if we must be in overwrite mode (because our backing data cannot have its size changed) */
- (BOOL)requiresOverwriteMode;
- (void)setEditMode:(HFEditMode)val;

//@}

Expand Down
45 changes: 26 additions & 19 deletions framework/sources/HFController.m
Expand Up @@ -128,7 +128,7 @@ - (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:font forKey:@"HFFont"];
[coder encodeDouble:lineHeight forKey:@"HFLineHeight"];
[coder encodeBool:_hfflags.antialias forKey:@"HFAntialias"];
[coder encodeBool:_hfflags.overwriteMode forKey:@"HFOverwriteMode"];
[coder encodeInt:_hfflags.editMode forKey:@"HFEditMode"];
[coder encodeBool:_hfflags.editable forKey:@"HFEditable"];
[coder encodeBool:_hfflags.selectable forKey:@"HFSelectable"];
}
Expand All @@ -142,7 +142,14 @@ - (id)initWithCoder:(NSCoder *)coder {
font = [[coder decodeObjectForKey:@"HFFont"] retain];
lineHeight = (CGFloat)[coder decodeDoubleForKey:@"HFLineHeight"];
_hfflags.antialias = [coder decodeBoolForKey:@"HFAntialias"];
_hfflags.overwriteMode = [coder decodeBoolForKey:@"HFOverwriteMode"];

if ([coder containsValueForKey:@"HFEditMode"])
_hfflags.editMode = [coder decodeIntForKey:@"HFEditMode"];
else {
_hfflags.editMode = ([coder decodeBoolForKey:@"HFOverwriteMode"]
? HFOverwriteMode : HFInsertMode);
}

_hfflags.editable = [coder decodeBoolForKey:@"HFEditable"];
_hfflags.selectable = [coder decodeBoolForKey:@"HFSelectable"];
representers = [[coder decodeObjectForKey:@"HFRepresenters"] retain];
Expand Down Expand Up @@ -800,7 +807,7 @@ - (NSUInteger)bytesPerLine {
}

- (BOOL)editable {
return _hfflags.editable && ! [byteArray changesAreLocked];
return _hfflags.editable && ! [byteArray changesAreLocked] && _hfflags.editMode != HFReadOnlyMode;
}

- (void)setEditable:(BOOL)flag {
Expand Down Expand Up @@ -1716,7 +1723,7 @@ - (void)moveToLineBoundaryInDirection:(HFControllerMovementDirection)direction a
}

- (void)deleteSelection {
if ([self inOverwriteMode] || ! [self editable]) {
if ([self editMode] == HFOverwriteMode || ! [self editable]) {
NSBeep();
}
else {
Expand All @@ -1729,7 +1736,7 @@ - (void)replaceByteArray:(HFByteArray *)newArray {
REQUIRE_NOT_NULL(newArray);
EXPECT_CLASS(newArray, HFByteArray);
HFRange entireRange = HFRangeMake(0, [self contentsLength]);
if ([self inOverwriteMode] && [newArray length] != entireRange.length) {
if ([self editMode] == HFOverwriteMode && [newArray length] != entireRange.length) {
NSBeep();
}
else {
Expand All @@ -1743,7 +1750,7 @@ - (BOOL)insertData:(NSData *)data replacingPreviousBytes:(unsigned long long)pre
#if ! NDEBUG
const unsigned long long startLength = [byteArray length];
unsigned long long expectedNewLength;
if ([self inOverwriteMode]) {
if ([self editMode] == HFOverwriteMode) {
expectedNewLength = startLength;
}
else {
Expand All @@ -1766,7 +1773,7 @@ - (BOOL)insertData:(NSData *)data replacingPreviousBytes:(unsigned long long)pre
}

- (BOOL)_insertionModeCoreInsertByteArray:(HFByteArray *)bytesToInsert replacingPreviousBytes:(unsigned long long)previousBytes allowUndoCoalescing:(BOOL)allowUndoCoalescing outNewSingleSelectedRange:(HFRange *)outSelectedRange {
HFASSERT(! [self inOverwriteMode]);
HFASSERT([self editMode] == HFInsertMode);
REQUIRE_NOT_NULL(bytesToInsert);

/* Guard against overflow. If [bytesToInsert length] + [self contentsLength] - previousBytes overflows, then we can't do it */
Expand Down Expand Up @@ -1874,7 +1881,7 @@ - (BOOL)insertByteArray:(HFByteArray *)bytesToInsert replacingPreviousBytes:(uns

BEGIN_TRANSACTION();
unsigned long long beforeLength = [byteArray length];
BOOL inOverwriteMode = [self inOverwriteMode];
BOOL inOverwriteMode = [self editMode] == HFOverwriteMode;
HFRange modificationRange; //either range to remove from selection if in overwrite mode, or range to select if not
BOOL success;
if (inOverwriteMode) {
Expand Down Expand Up @@ -1905,7 +1912,7 @@ - (BOOL)insertByteArray:(HFByteArray *)bytesToInsert replacingPreviousBytes:(uns

- (void)deleteDirection:(HFControllerMovementDirection)direction {
HFASSERT(direction == HFControllerDirectionLeft || direction == HFControllerDirectionRight);
if ([self inOverwriteMode]) {
if ([self editMode] != HFInsertMode) {
NSBeep();
return;
}
Expand Down Expand Up @@ -1936,18 +1943,18 @@ - (void)deleteDirection:(HFControllerMovementDirection)direction {
}
}

- (BOOL)inOverwriteMode {
return _hfflags.overwriteMode;
- (HFEditMode)editMode {
return _hfflags.editMode;
}

- (void)setInOverwriteMode:(BOOL)val {
_hfflags.overwriteMode = val;
// don't allow undo coalescing across switching between overwrite mode
[self _endTypingUndoCoalescingIfActive];
}

- (BOOL)requiresOverwriteMode {
return NO;
- (void)setEditMode:(HFEditMode)val
{
if (val != _hfflags.editMode) {
_hfflags.editMode = val;
// don't allow undo coalescing when switching modes
[self _endTypingUndoCoalescingIfActive];
[self _addPropertyChangeBits:HFControllerEditable];
}
}

+ (BOOL)prepareForChangeInFile:(NSURL *)targetFile fromWritingByteArray:(HFByteArray *)array {
Expand Down
4 changes: 4 additions & 0 deletions framework/sources/HFFileReference.h
Expand Up @@ -25,8 +25,12 @@
mode_t fileMode;
BOOL isWritable;
uint32_t blockSize;
BOOL isPrivileged;
BOOL isFixedLength;
}

@property (readonly) BOOL isPrivileged;
@property (readonly) BOOL isFixedLength;

/*! Open a file for reading and writing at the given path. The permissions mode of any newly created file is 0744. Returns nil if the file could not be opened, in which case the error parameter (if not nil) will be set. */
- initWritableWithPath:(NSString *)path error:(NSError **)error;
Expand Down
10 changes: 8 additions & 2 deletions framework/sources/HFFileReference.m
Expand Up @@ -111,6 +111,8 @@ static BOOL returnFTruncateError(NSError **error) {

@implementation HFFileReference

@synthesize isPrivileged, isFixedLength;

- (void)close { UNIMPLEMENTED_VOID(); }
- (void)readBytes:(unsigned char *)buff length:(NSUInteger)length from:(unsigned long long)offset {USE(buff); USE(length); USE(offset); UNIMPLEMENTED_VOID(); }
- (int)writeBytes:(const unsigned char *)buff length:(NSUInteger)length to:(unsigned long long)offset {USE(buff); USE(length); USE(offset); UNIMPLEMENTED(); }
Expand Down Expand Up @@ -204,7 +206,9 @@ - (BOOL)initSharedWithPath:(NSString *)path error:(NSError **)error {

#ifndef HF_NO_PRIVILEGED_FILE_OPERATIONS
if (fileDescriptor < 0 && errno == EACCES) {
if (![[HFPrivilegedHelperConnection sharedConnection] openFileAtPath:p writable:isWritable fileDescriptor:&fileDescriptor error:error]) {
if ([[HFPrivilegedHelperConnection sharedConnection] openFileAtPath:p writable:isWritable fileDescriptor:&fileDescriptor error:error]) {
isPrivileged = YES;
} else {
fileDescriptor = -1;
errno = EACCES;
}
Expand All @@ -231,7 +235,7 @@ - (BOOL)initSharedWithPath:(NSString *)path error:(NSError **)error {

if (!sb.st_size && (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode))) {
uint64_t blockCount;

if (ioctl(fileDescriptor, DKIOCGETBLOCKSIZE, &blockSize) < 0
|| ioctl(fileDescriptor, DKIOCGETBLOCKCOUNT, &blockCount) < 0) {
int err = errno;
Expand All @@ -241,6 +245,7 @@ - (BOOL)initSharedWithPath:(NSString *)path error:(NSError **)error {
}

fileLength = blockSize * blockCount;
isFixedLength = YES;
}
else {
fileLength = sb.st_size;
Expand Down Expand Up @@ -370,6 +375,7 @@ - (int)writeBytes:(const unsigned char *)buff length:(NSUInteger)length to:(unsi
return errno;
HFASSERT(result == (ssize_t)blockSize);
}
free(tempBuf);

return 0;
}
Expand Down

0 comments on commit bf32c66

Please sign in to comment.