#import "Storage.h"
#import "FileItem.h"
+#import "CryptCore.h"
@implementation Storage
FileItem *item = [FileItem alloc];
item.path = [currentPath stringByAppendingString: f];
item.name = [f stringByDeletingPathExtension];
+
BOOL bDir = NO;
[fileManager fileExistsAtPath:item.path isDirectory:&bDir];
item.isDirectory = bDir;
+
+ if (!bDir) {
+ if ([@"chi" isEqualToString:[f pathExtension]]) {
+ item.isCrypt = YES;
+ }
+ }
+
[result addObject:item];
}
return result;
-(BOOL)isTopDir {
return [currentDirectory isEqualToString:@"/"];
}
+
- (void)saveDataWithBOM:(NSString *)note file:(NSString *)path {
- const char *noteBytes = [note cStringUsingEncoding:NSUTF8StringEncoding];
- NSMutableData *data = [[NSMutableData alloc] initWithLength:strlen(noteBytes) + 3];
+ const char *noteBytes = [note cStringUsingEncoding:NSUTF8StringEncoding];
+ int n = strlen(noteBytes);
+ NSMutableData *data = [[NSMutableData alloc] initWithLength:n + 3];
char *buf = (char *)[data mutableBytes];
- strcpy(buf + 3, noteBytes);
+ memcpy(buf + 3, noteBytes, n);
*(char*)(buf + 0) = 0xEF;
*(char*)(buf + 1) = 0xBB;
*(char*)(buf + 2) = 0xBF;
[data writeToFile:path atomically:YES];
}
-// save note
--(FileItem *)save:(NSString *)note item:(FileItem *)item {
- if (!item) return nil;
-
- // Decide new title.
+- (NSString *)pickupTitle:(NSString *)note {
NSRange r;
r.location = 0;
r.length = 0;
NSRange titleRange = [note lineRangeForRange:r];
NSString *title = [note substringWithRange:titleRange];
+
if ([title characterAtIndex:(title.length - 1)] == '\n') {
title = [title substringToIndex:(title.length - 1)];
}
if (title.length == 0) {
title = @"New document";
}
+ return title;
+}
+
+- (FileItem *)savePlain:(NSString *)note item:(FileItem *)item {
+ if (!item) return nil;
+
+ NSString *title = [self pickupTitle:note];
// If title is changed, rename one.
FileItem *result;
}
// Save note.
-// NSError *error = nil;
-// [note writeToFile:result.path atomically:YES encoding:NSUTF8StringEncoding error:&error];
[self saveDataWithBOM:note file:result.path];
return result;
}
+
+- (FileItem *)saveCrypt:(NSString *)note item:(FileItem *)item password:(NSString *)password {
+ NSString *title = [self pickupTitle:note];
+
+ FileItem *result;
+ if (!item.name || ![title isEqualToString: item.name]) {
+ result = [self decideFileName:title path:item.path];
+
+ if (item.name) {
+ NSError *error = nil;
+ [fileManager moveItemAtPath:item.path toPath:result.path error:&error];
+ }
+ } else {
+ result = item;
+ }
+
+ // Save note.
+ const char *noteBytes = [note cStringUsingEncoding:NSUTF8StringEncoding];
+ int n = strlen(noteBytes);
+ NSMutableData *data = [[NSMutableData alloc] initWithLength:n + 3];
+ char *buf = (char *)[data mutableBytes];
+ memcpy(buf + 3, noteBytes, n);
+ *(char*)(buf + 0) = 0xEF;
+ *(char*)(buf + 1) = 0xBB;
+ *(char*)(buf + 2) = 0xBF;
+
+ NSError *error = nil;
+ NSData *encData = [CryptCore encrypt:password data:data error:&error];
+ if (error) return nil;
+
+ if (![encData writeToFile:result.path atomically:YES]) return nil;
+ return result;
+}
+
// Remove characters which can't use file name from given string.
- (NSString *)removeInvalidFilenameChars:(NSString *)src {
NSString *result = src;
+(NSString *)load:(NSString *)path {
NSData *data = [NSData dataWithContentsOfFile:path];
+ return [Storage trimBOM:data];
+}
+
++(NSString *)trimBOM:(NSData *)data {
const char *header = [data bytes];
if ([data length] > 3 &&
*header == 0xEF && *(header + 1) == 0xBB && *(header + 2) == 0xBF) {
return @"";
}
++ (NSString *)loadCryptFile:(NSString *)path password:(NSString *)password {
+ NSData *encData = [NSData dataWithContentsOfFile:path];
+ NSError *error = nil;
+ NSData *plainData = [CryptCore decrypt:password data:encData error:&error];
+ if (error) return nil;
+
+ return [Storage trimBOM:plainData];
+}
+
+- (FileItem *)encrypt:(NSString *)key item:(FileItem*)item {
+ NSData *plainData = [NSData dataWithContentsOfFile:item.path];
+ NSError *error = nil;
+ NSData *encData = [CryptCore encrypt:key data:plainData error:&error];
+ if (error) return nil;
+
+ NSMutableString *newPath = [[NSMutableString alloc] initWithCapacity:256];
+ [newPath appendString:[item.path stringByDeletingPathExtension]];
+ [newPath appendString:@".chi"];
+
+ FileItem *newItem = [self decideFileName:item.name path:newPath];
+ newItem.isCrypt = YES;
+
+ if (![encData writeToFile:newItem.path atomically:YES]) {
+ return nil;
+ }
+ [fileManager removeItemAtPath:item.path error:&error];
+ return newItem;
+}
+
+- (FileItem *)decrypt:(NSString *)key item:(FileItem*)item {
+ // TODO: implement
+ NSData *encData = [NSData dataWithContentsOfFile:item.path];
+ NSError *error = nil;
+ NSData *plainData = [CryptCore decrypt:key data:encData error:&error];
+ if (error) return nil;
+
+ NSMutableString *newPath = [[NSMutableString alloc] initWithCapacity:256];
+ [newPath appendString:[item.path stringByDeletingPathExtension]];
+ [newPath appendString:@".txt"];
+ FileItem *newItem = [self decideFileName:item.name path:newPath];
+
+ if (![plainData writeToFile:newItem.path atomically:YES]) {
+ return nil;
+ }
+ [fileManager removeItemAtPath:item.path error:&error];
+ return newItem;
+}
+
@end