Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
PasswordPDE.m
/* |
File: PasswordPDE.m |
Abstract: Implementation of a slightly more advanced PDE that implements |
new functionality in Leopard while also being compatible with Tiger. |
Version: 1.0 |
Disclaimer: IMPORTANT: This Apple software is supplied to you by |
Apple Inc. ("Apple") in consideration of your agreement to the |
following terms, and your use, installation, modification or |
redistribution of this Apple software constitutes acceptance of these |
terms. If you do not agree with these terms, please do not use, |
install, modify or redistribute this Apple software. |
In consideration of your agreement to abide by the following terms, and |
subject to these terms, Apple grants you a personal, non-exclusive |
license, under Apple's copyrights in this original Apple software (the |
"Apple Software"), to use, reproduce, modify and redistribute the Apple |
Software, with or without modifications, in source and/or binary forms; |
provided that if you redistribute the Apple Software in its entirety and |
without modifications, you must retain this notice and the following |
text and disclaimers in all such redistributions of the Apple Software. |
Neither the name, trademarks, service marks or logos of Apple Inc. |
may be used to endorse or promote products derived from the Apple |
Software without specific prior written permission from Apple. Except |
as expressly stated in this notice, no other rights or licenses, express |
or implied, are granted by Apple herein, including but not limited to |
any patent rights that may be infringed by your derivative works or by |
other works in which the Apple Software may be incorporated. |
The Apple Software is provided by Apple on an "AS IS" basis. APPLE |
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION |
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS |
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND |
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS. |
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, |
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED |
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), |
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE |
POSSIBILITY OF SUCH DAMAGE. |
Copyright (C) 2007 Apple Inc. All Rights Reserved. |
*/ |
#import <Print/PMPrintingDialogExtensions.h> |
#import "PasswordPDE.h" |
#import "PDEChoice.h" |
#import "PDELogging.h" |
// Keys to look up localized data for the UI |
static NSString* kPasswordPanelNameKey = @"AuthPanel"; |
// PDE Kind definition |
static NSString* kPasswordKindID = @"com.apple.samplecode.OutputBins2.PasswordKind"; |
static NSString* kAuthUsernameKey = @"com.apple.samplecode.OutputBins2.Username"; |
static NSString* kAuthPasswordKey = @"com.apple.samplecode.OutputBins2.Password"; |
@implementation PasswordPDE |
- (id)initWithCallback:(PDEPluginCallback*)callback andBundle:(NSBundle*)bundle; |
{ |
PDEProlog(@"initWithCallback:(%@, %p) andBundle:(%@ %p)", callback, callback, bundle, bundle); |
self = [super init]; |
// init instance variables |
thePDEName = nil; |
pdePluginCallbackObject = [ callback retain ]; |
pluginBundle = [ bundle retain ]; |
// ensures that our username & password starts fresh when this print panel is loaded. |
[self restoreValuesAndReturnError:nil]; |
PDEEpilog(@"initWithCallback:=id(self)"); |
return self; |
} |
/* The dealloc method is called on object deallocation when garbage collection is not in effect. |
Therefore this is the place to release objects that we've allocated or retained. |
*/ |
- (void)dealloc |
{ |
[pdePluginCallbackObject release]; |
[thePDEName release]; |
[pdeView release]; |
[super dealloc]; |
} |
/* The finalize method is only needed when you have resources or data that |
needs to be released when garbage collection is in effect. Since the NSObjects |
represented by our instance variables are garbage collected, there is no |
need to release them in the finalize method. Since this code example has no |
other resources that need to be deallocated when garbage collection is in effect, |
there is no need for a finalize method in this code. |
If your code needs to explicitly deallocate resources that are not garbage |
collected even when garbage collection is in place, remove the ifdef here and add |
your needed deallocations prior to calling the superclass'es finalize. In general |
however, it is NOT correct to simply migrate such code from your -dealloc method |
directly to -finalize, as the timing of -finalize is non-deterministic |
All of our objects are NSObjects, and thus will be garbage collected automatically |
for us, therefore we don't need to do anything here. |
*/ |
#if 0 |
- (void)finalize |
{ |
// Release your resources that are not garbage collected. |
// ... |
// Then finalize the superclass. |
[super finalize]; |
} |
#endif |
// return the NSView for this PDE |
- (NSView*)panelView |
{ |
PDEProlog(@"panelView:"); |
if (pdeView == NULL) { |
[NSBundle loadNibNamed:@"PasswordPDE" owner:self]; |
} |
PDEEpilog(@"panelView:=NSView(%@, %p)", pdeView, pdeView); |
return pdeView; |
} |
// Return the localized name for this PDE. This will be used as its title in the |
// menu of printing panes. |
- (NSString*)panelName |
{ |
PDEProlog(@"panelName:"); |
if (thePDEName == NULL) { |
thePDEName = [[pluginBundle localizedStringForKey:kPasswordPanelNameKey value:nil table:nil] retain]; |
} |
PDEEpilog(@"panelName:=NSString(%@)", thePDEName); |
return thePDEName; |
} |
// return the kind ID for this PDE |
- (NSString*)panelKind |
{ |
PDEProlog(@"panelKind:"); |
PDEEpilog(@"panelKind:=NSString(%@)", kPasswordKindID); |
return (NSString*)kPasswordKindID; |
} |
// return an NSArray of PPD option keywords supported by this PDE |
// This PDE doesn't support any options, so we return nil. |
- (NSArray *)supportedPPDOptionKeys |
{ |
PDEProlog(@"supportedPPDOptionKeys:"); |
PDEEpilog(@"supportedPPDOptionKeys:=NSArray(nil)"); |
return nil; |
} |
// the PDE panel is about to be shown |
-(void)willShow |
{ |
PDEProlog(@"willShow:"); |
PDEEpilog(@"willShow:=void"); |
} |
// Checks the print settings to verify that the print destination is one that |
// we are interested in restricting. |
-(BOOL)authenticateDestination |
{ |
PMDestinationType destination; |
BOOL authenticate = NO; // Assume that we don't need to verify if we can't determine the print destination. |
PMPrintSession session = [pdePluginCallbackObject printSession]; |
// The typecast avoids a conflict between -[NSPrintInfo printSettings] and |
// -[NSObject(PDEPlugInCallbackProtocol) printSettings]. |
PMPrintSettings settings = (PMPrintSettings)[pdePluginCallbackObject printSettings]; |
OSStatus err = PMSessionGetDestinationType(session, settings, &destination); |
if(err == noErr) |
{ |
// Require authentication if we are going to printer or preview (as preview can print directly) |
// This also covers the case where the user cancels the print operation. |
authenticate = (destination == kPMDestinationPrinter) || (destination == kPMDestinationPreview); |
} |
return authenticate; |
} |
-(BOOL)validateAndAlert:(BOOL)mustPass |
{ |
if([self authenticateDestination]) |
{ |
NSString * username = [usernameView stringValue]; |
NSString * password = [passwordView stringValue]; |
bool valid = ([username length] != 0) && ([password length] != 0); |
NSInteger ret = NSOKButton; |
if(!valid) |
{ |
NSString * title = ([username length] != 0) ? @"Missing Password" : ([password length] == 0) ? @"Missing Username and Password" : @"Missing Username"; |
ret = NSRunAlertPanel(title, @"In order to print to this printer, you must enter both a username and a password", @"OK", mustPass ? nil : @"Later", nil); |
} |
return valid || (ret == NSCancelButton); |
} |
return YES; |
} |
// the PDE panel is about to be hidden |
-(BOOL)shouldHide |
{ |
PDEProlog(@"shouldHide:"); |
BOOL hide = [self validateAndAlert:NO]; |
PDEEpilog(@"shouldHide:=BOOL(%s)", hide ? "YES" : "NO"); |
return hide; |
} |
// This method will be called to ask you if printing should occur |
// This is your opportunity to prevent printing from happening |
// Returning YES will cause printing to continue, returning NO will stop it. |
// Remember, this is only called on Mac OS X 10.5 or later, so you will not |
// be able to stop the print job using this method on Mac OS X 10.4. |
-(BOOL)shouldPrint |
{ |
PDEProlog(@"shouldPrint:"); |
BOOL print = [self validateAndAlert:YES]; |
PDEEpilog(@"shouldPrint:=BOOL(%s)", print ? "YES" : "NO"); |
return print; |
} |
// This method enables you to catch the help button and determine |
// the default print panel help should be shown or not. |
// Returning YES will display the default help, returning NO will supress it |
// allowing you to show your own help. |
-(BOOL)shouldShowHelp |
{ |
OSStatus err; |
// the log macro is a no-op on release builds |
// so we mark 'err' unused so we avoid the warning |
#pragma unused(err) |
PDEProlog(@"shouldShowHelp:"); |
PDELog(@"Opening Help Book"); |
CFStringRef helpbook = CFSTR("OutputBinsPDE2Help"); |
err = AHGotoPage(helpbook, NULL, NULL); |
PDELog(@"Result %i attempting to open %@", err, helpbook); |
PDEEpilog(@"shouldShowHelp:=BOOL(%s)", "NO"); |
return NO; |
} |
// read the new settings values and update our internal PDE's settings accordingly |
- (BOOL)restoreValuesAndReturnError:(NSError **)error |
{ |
PDEProlog(@"restoreValuesAndReturnError:(%p)", error); |
// Remove any values that currently exist for username & password to ensure that |
// a later user can't print with the previous users's credentials. |
// The typecast avoids a conflict between -[NSPrintInfo printSettings] and |
// -[NSObject(PDEPlugInCallbackProtocol) printSettings]. |
PMPrintSettings settings = (PMPrintSettings)[pdePluginCallbackObject printSettings]; |
PMPrintSettingsSetValue(settings, (CFStringRef)kAuthUsernameKey, NULL, false); |
PMPrintSettingsSetValue(settings, (CFStringRef)kAuthPasswordKey, NULL, false); |
PDEEpilog(@"restoreValuesAndReturnError:=BOOL(YES)"); |
return YES; |
} |
// set UI/stored values to the print settings |
- (BOOL)saveValuesAndReturnError:(NSError **)error |
{ |
PDEProlog(@"saveValuesAndReturnError:(%p)", error); |
// Save the username & password to the print settings. Presumably you would have a CUPS |
// prefilter, port monitor or backend that inspected or transmitted these values |
// before allowing printing. Also, it is unlikely that you would want to send |
// the password, or possibly the username, in the clear as is done here. |
// The typecast avoids a conflict between -[NSPrintInfo printSettings] and |
// -[NSObject(PDEPlugInCallbackProtocol) printSettings]. |
PMPrintSettings settings = (PMPrintSettings)[pdePluginCallbackObject printSettings]; |
PMPrintSettingsSetValue(settings, (CFStringRef)kAuthUsernameKey, [usernameView stringValue], false); |
PMPrintSettingsSetValue(settings, (CFStringRef)kAuthPasswordKey, [passwordView stringValue], false); |
PDEEpilog(@"saveValuesAndReturnError:=BOOL(YES)"); |
return YES; |
} |
#if 0 |
#warning This is debug code to show you the username and password. |
// On 10.4 it appears that stringValue == nil if the view has no string |
// This one liner just makes sure the returned string is non-nil |
// so that we don't get an exception adding it to the dictionary. |
NSString* EmptyIfNil(NSString *str) { return str == nil ? @"" : str; } |
static NSString* kAuthUsernameSummaryKey = @"UsernameSummary"; |
static NSString* kAuthPasswordSummaryKey = @"PasswordSummary"; |
-(NSDictionary *)summaryInfo |
{ |
PDEProlog(@"summaryInfo:"); |
NSMutableDictionary *summaryInfoDict = [NSMutableDictionary dictionaryWithCapacity:2]; |
// It is unlikely that you would want to display anything in the summary for an authorization print panel |
// but this is useful debugging information. |
[summaryInfoDict setObject:EmptyIfNil([usernameView stringValue]) forKey:[pluginBundle localizedStringForKey:kAuthUsernameSummaryKey value:nil table:nil]]; |
[summaryInfoDict setObject:EmptyIfNil([passwordView stringValue]) forKey:[pluginBundle localizedStringForKey:kAuthPasswordSummaryKey value:nil table:nil]]; |
PDEEpilog(@"summaryInfo:=NSDictionary(%@, %p)", summaryInfoDict, summaryInfoDict); |
return summaryInfoDict; |
} |
#endif |
@end |
Copyright © 2008 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2008-02-08