Revision: 2911
          http://skim-app.svn.sourceforge.net/skim-app/?rev=2911&view=rev
Author:   hofman
Date:     2007-09-12 12:05:23 -0700 (Wed, 12 Sep 2007)

Log Message:
-----------
Save password in keychain, after showing an alert when a password was entered 
successfully. Use a hack: override a method of the private PDFDisplayView class.

Modified Paths:
--------------
    trunk/SKDocument.h
    trunk/SKPDFView.m
    trunk/Skim.xcodeproj/project.pbxproj

Modified: trunk/SKDocument.h
===================================================================
--- trunk/SKDocument.h  2007-09-12 16:35:19 UTC (rev 2910)
+++ trunk/SKDocument.h  2007-09-12 19:05:23 UTC (rev 2911)
@@ -105,6 +105,8 @@
 - (NSString *)notesFDFString;
 - (NSString *)notesFDFStringForFile:(NSString *)filename;
 
+- (NSArray *)fileIDStrings;
+
 - (NSDictionary *)currentDocumentSetup;
 
 - (SKPDFSynchronizer *)synchronizer;

Modified: trunk/SKPDFView.m
===================================================================
--- trunk/SKPDFView.m   2007-09-12 16:35:19 UTC (rev 2910)
+++ trunk/SKPDFView.m   2007-09-12 19:05:23 UTC (rev 2911)
@@ -56,6 +56,8 @@
 #import <Carbon/Carbon.h>
 #import "NSGeometry_SKExtensions.h"
 #import "SKTypeSelectHelper.h"
+#import "OBUtilities.h"
+#import <Security/Security.h>
 
 NSString *SKPDFViewToolModeChangedNotification = 
@"SKPDFViewToolModeChangedNotification";
 NSString *SKPDFViewAnnotationModeChangedNotification = 
@"SKPDFViewAnnotationModeChangedNotification";
@@ -115,6 +117,8 @@
 - (NSCursor *)cursorForEvent:(NSEvent *)theEvent;
 - (void)updateCursor;
 
+- (void)tryToUnlockDocument:(PDFDocument *)document;
+
 @end
 
 #pragma mark -
@@ -449,6 +453,8 @@
 #pragma mark Accessors
 
 - (void)setDocument:(PDFDocument *)document {
+    if ([document isLocked] && [[NSUserDefaults standardUserDefaults] 
boolForKey:@"SKDisableSavingPassword"] == NO)
+        [self tryToUnlockDocument:document];
     [readingBar release];
     readingBar = nil;
     selectionRect = NSZeroRect;
@@ -3678,6 +3684,26 @@
     [[self cursorForEvent:event] set];
 }
 
+- (void)tryToUnlockDocument:(PDFDocument *)document {
+    NSArray *fileIDStrings = [(SKDocument *)[[[self window] windowController] 
document] fileIDStrings];
+    NSString *fileIDString = [fileIDStrings count] ? [fileIDStrings 
objectAtIndex:0] : nil;
+    if (fileIDString) {
+        const char *serviceName = [[NSString stringWithFormat:@"Skim - %@", 
fileIDString] UTF8String];
+        const char *userName = [NSUserName() UTF8String];
+        void *passwordData = NULL;
+        UInt32 passwordLength = 0;
+        NSData *data = nil;
+        NSString *password = nil;
+        OSErr err = SecKeychainFindGenericPassword(NULL, strlen(serviceName), 
serviceName, strlen(userName), userName, &passwordLength, &passwordData, NULL);
+        if (err == noErr) {
+            data = [NSData dataWithBytes:passwordData length:passwordLength];
+            SecKeychainItemFreeContent(NULL, passwordData);
+            password = [[[NSString alloc] initWithData:data 
encoding:NSUTF8StringEncoding] autorelease];
+            [document unlockWithPassword:password];
+        }
+    }
+}
+
 @end
 
 #pragma mark Core Graphics extension
@@ -3760,3 +3786,77 @@
 
 @end
 
+#pragma mark -
+
[EMAIL PROTECTED] PDFDisplayView : NSView
+- (void)passwordEntered:(id)sender;
[EMAIL PROTECTED]
+
[EMAIL PROTECTED] PDFDisplayView (SKExtensions)
+- (void)replacementPasswordEntered:(id)sender;
+- (void)savePasswordInKeychain:(NSString *)password;
[EMAIL PROTECTED]
+
[EMAIL PROTECTED] PDFDisplayView (SKExtensions)
+
+static IMP originalPasswordEntered = NULL;
+
++ (void)load {
+    if ([self instancesRespondToSelector:@selector(passwordEntered:)])
+        originalPasswordEntered = 
OBReplaceMethodImplementationWithSelector(self, @selector(passwordEntered:), 
@selector(replacementPasswordEntered:));
+}
+
+- (void)replacementPasswordEntered:(id)sender {
+    originalPasswordEntered(self, _cmd, sender);
+    if ([[NSUserDefaults standardUserDefaults] 
boolForKey:@"SKDisableSavingPassword"] == NO) {
+        SKDocument *document = [[[self window] windowController] document];
+        if ([document isKindOfClass:[SKDocument class]] && [[document 
pdfDocument] isLocked] == NO)
+            [self savePasswordInKeychain:[sender stringValue]];
+    }
+}
+
+- (void)savePasswordInKeychain:(NSString *)password {
+    SKDocument *document = [[[self window] windowController] document];
+    NSArray *fileIDStrings = [document fileIDStrings];
+    NSString *fileIDString = [fileIDStrings count] ? [fileIDStrings 
objectAtIndex:0] : nil;
+    if (fileIDString) {
+        NSAlert *alert = [NSAlert alertWithMessageText:[NSString 
stringWithFormat:NSLocalizedString(@"Remember Password?", @"Message in alert 
dialog")]
+                                         
defaultButton:NSLocalizedString(@"Yes", @"Button title")
+                                       
alternateButton:NSLocalizedString(@"No", @"Button title")
+                                           otherButton:nil
+                             informativeTextWithFormat:NSLocalizedString(@"Do 
you want to save this password in your Keychain?", @"Informative text in alert 
dialog")];
+        if ([alert runModal] == NSAlertDefaultReturn) {
+            const char *userNameCString = [NSUserName() UTF8String];
+            const char *nameCString = [[NSString stringWithFormat:@"Skim - 
%@", fileIDString] UTF8String];
+            
+            OSStatus err;
+            SecKeychainItemRef itemRef = NULL;    
+            const void *passwordData = NULL;
+            UInt32 passwordLength = 0;
+            
+            // first see if the password exists in the keychain
+            err = SecKeychainFindGenericPassword(NULL, strlen(nameCString), 
nameCString, strlen(userNameCString), userNameCString, &passwordLength, (void 
**)&passwordData, &itemRef);
+            
+            if(err == noErr){
+                // password was on keychain, so flush the buffer and then 
modify the keychain
+                SecKeychainItemFreeContent(NULL, (void *)passwordData);
+                passwordData = NULL;
+                
+                passwordData = [password UTF8String];
+                SecKeychainAttribute attrs[] = {
+                    { kSecAccountItemAttr, strlen(userNameCString), (char 
*)userNameCString },
+                    { kSecServiceItemAttr, strlen(nameCString), (char 
*)nameCString } };
+                const SecKeychainAttributeList attributes = { sizeof(attrs) / 
sizeof(attrs[0]), attrs };
+                
+                err = SecKeychainItemModifyAttributesAndData(itemRef, 
&attributes, strlen(passwordData), passwordData);
+            } else if(err == errSecItemNotFound){
+                // password not on keychain, so add it
+                passwordData = [password UTF8String];
+                err = SecKeychainAddGenericPassword(NULL, strlen(nameCString), 
nameCString, strlen(userNameCString), userNameCString, strlen(passwordData), 
passwordData, &itemRef);    
+            } else 
+                NSLog(@"Error %d occurred setting password", err);
+        }
+    }
+}
+
[EMAIL PROTECTED]

Modified: trunk/Skim.xcodeproj/project.pbxproj
===================================================================
--- trunk/Skim.xcodeproj/project.pbxproj        2007-09-12 16:35:19 UTC (rev 
2910)
+++ trunk/Skim.xcodeproj/project.pbxproj        2007-09-12 19:05:23 UTC (rev 
2911)
@@ -150,6 +150,7 @@
                CE9C423C0B8B5633004AD8CF /* PreferenceWindow.nib in Resources 
*/ = {isa = PBXBuildFile; fileRef = CE9C42360B8B5633004AD8CF /* 
PreferenceWindow.nib */; };
                CE9DC2EA0B9F131900D64F28 /* ToolbarHighlightNote.tiff in 
Resources */ = {isa = PBXBuildFile; fileRef = CE9DC2E80B9F131800D64F28 /* 
ToolbarHighlightNote.tiff */; };
                CEA182280C92E3300061A6D4 /* NSData_SKExtensions.m in Sources */ 
= {isa = PBXBuildFile; fileRef = CEA182260C92E3300061A6D4 /* 
NSData_SKExtensions.m */; };
+               CEA1CD1B0C9864470061A6D4 /* Security.framework in Frameworks */ 
= {isa = PBXBuildFile; fileRef = CEA1CCE60C9864470061A6D4 /* Security.framework 
*/; };
                CEA575CE0B9206E60003D2E7 /* SKNoteOutlineView.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CEA575CD0B9206E60003D2E7 /* SKNoteOutlineView.m 
*/; };
                CEA575E50B9207B80003D2E7 /* SKThumbnailTableView.m in Sources 
*/ = {isa = PBXBuildFile; fileRef = CEA575E40B9207B80003D2E7 /* 
SKThumbnailTableView.m */; };
                CEA575FD0B9208B60003D2E7 /* SKTocOutlineView.m in Sources */ = 
{isa = PBXBuildFile; fileRef = CEA575FC0B9208B60003D2E7 /* SKTocOutlineView.m 
*/; };
@@ -531,6 +532,7 @@
                CE9DC2E80B9F131800D64F28 /* ToolbarHighlightNote.tiff */ = {isa 
= PBXFileReference; lastKnownFileType = image.tiff; name = 
ToolbarHighlightNote.tiff; path = Images/ToolbarHighlightNote.tiff; sourceTree 
= "<group>"; };
                CEA182250C92E3300061A6D4 /* NSData_SKExtensions.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
NSData_SKExtensions.h; sourceTree = "<group>"; };
                CEA182260C92E3300061A6D4 /* NSData_SKExtensions.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= NSData_SKExtensions.m; sourceTree = "<group>"; };
+               CEA1CCE60C9864470061A6D4 /* Security.framework */ = {isa = 
PBXFileReference; lastKnownFileType = wrapper.framework; name = 
Security.framework; path = /System/Library/Frameworks/Security.framework; 
sourceTree = "<absolute>"; };
                CEA575CC0B9206E60003D2E7 /* SKNoteOutlineView.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
SKNoteOutlineView.h; sourceTree = "<group>"; };
                CEA575CD0B9206E60003D2E7 /* SKNoteOutlineView.m */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path 
= SKNoteOutlineView.m; sourceTree = "<group>"; };
                CEA575E30B9207B80003D2E7 /* SKThumbnailTableView.h */ = {isa = 
PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = 
SKThumbnailTableView.h; sourceTree = "<group>"; };
@@ -644,6 +646,7 @@
                                CE2BD83E0BD4132B00A5F4DB /* Sparkle.framework 
in Frameworks */,
                                CE5F43730BF8A3410069D89C /* IOKit.framework in 
Frameworks */,
                                CE1ADB280C4BC6DE00071840 /* OpenGL.framework in 
Frameworks */,
+                               CEA1CD1B0C9864470061A6D4 /* Security.framework 
in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
@@ -662,6 +665,7 @@
                1058C7A6FEA54F5311CA2CBB /* Linked Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               CEA1CCE60C9864470061A6D4 /* Security.framework 
*/,
                                1058C7A7FEA54F5311CA2CBB /* Cocoa.framework */,
                                F98E24BE0B702D9400914AF0 /* Carbon.framework */,
                                455989F70B2662FF00E5419B /* Quartz.framework */,


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Skim-app-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/skim-app-commit

Reply via email to