OSDN Git Service

Implement encrypt/decrypt.
[tombo/Tombo.git] / iOS / Tombo / Tombo / Storage.m
index 7ff3c73..23acb2a 100644 (file)
@@ -1,5 +1,6 @@
 #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