#import "PGPfrontEnd.h"

@implementation PGPfrontEnd

- init
{
    [super init];
    cryptor = [[Cryptor alloc] init];
    return self;
}


- (void)dealloc
{
    [cryptor release];
    [super dealloc];
    return;
}


- (void)encrypt:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:ENCRYPT options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)decrypt:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:DECRYPT options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)decryptInWindow:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:DECRYPT options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    [cryptor showOutput:self];
    *error = nil;
    return;
}


- (void)encryptAndSign:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    NSMutableArray *optionArray;

    optionArray = [NSMutableArray arrayWithObject:@"-s"];
    [self filterPasteboard:ENCRYPT options:optionArray pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)checkSig:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:CHECKSIG options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)clearSign:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:CLEARSIGN options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)detachedSig:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:DETACHEDSIG options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    [cryptor showOutput:self];
    *error = nil;
    return;
}



- (void)encryptFiles:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboardFiles:ENCRYPT options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)decryptFiles:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboardFiles:DECRYPT options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)encryptIDEA:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboard:ENCRYPT_IDEA options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


- (void)encryptFilesIDEA:(NSPasteboard *)pboard userData:(NSString *)inData error:(NSString **)error
{
    [self filterPasteboardFiles:ENCRYPT_IDEA options:nil pasteBoard:pboard];
    [cryptor showStatus:self];
    *error = nil;
    return;
}


/* Filters a pasteboard selection through PGP, */
/*  it encrypts or decrypts depending on the   */
/*  value of filterMode                        */

- (void)filterPasteboard:(int)filterMode options:(NSMutableArray *)options pasteBoard:(NSPasteboard *)pboard
{
    NSArray *types;
    NSString *pgpInString,*pgpOutString;
    NSData *pgpIn,*pgpOut;
    char *pgpInBuf,*pgpOutBuf;
    int pgpInLength,pgpOutLength;

    if(!options)
	options = [[[NSMutableArray alloc] init] autorelease];
    
    types = [pboard types];
    if(![types containsObject:NSStringPboardType]) {
	NSLog(@"NXPGP: Pasteboard couldn't give selection");
	return;
    }

    /* Get input NSString */
    pgpInString = [pboard stringForType:NSStringPboardType];
    if(!pgpInString) {
	NSLog(@"NXPGP: Pasteboard couldn't give selection data");
	return;
    }

    /* Turn NSString into NSData */
    pgpInBuf = (char *)[pgpInString cString];
    pgpInLength = strlen(pgpInBuf);

    pgpIn = [NSData dataWithBytes:pgpInBuf length:pgpInLength];

    /* Process the input data */
    pgpOut = [[cryptor runpgp:filterMode options:options data:pgpIn] retain];

    /* Check for errors */
    if(!pgpOut) {
	NSLog(@"PGP cancelled out");
	return;
    }

    if([pgpOut length] == 0) {
	NSLog(@"PGP error resulted in null output\n");
	[pgpOut release];
	return;
    }

    /* Convert back to NSString */
    pgpOutLength = [pgpOut length];
    pgpOutBuf = malloc(pgpOutLength+1);
    [pgpOut getBytes:pgpOutBuf length:pgpOutLength];
    pgpOutBuf[pgpOutLength] = '\0';

    pgpOutString = [NSString stringWithCString:pgpOutBuf];
    [pgpOut release];
    free(pgpOutBuf);
		    
    types = [NSArray arrayWithObject:NSStringPboardType];
    [pboard declareTypes:types owner:nil];
    [pboard setString:pgpOutString forType:NSStringPboardType];

    return;
}


/* Filters a list of files or directories from    */
/* the pasteboard through PGP.  It encrypts or    */
/* decrypts depending on the value of filterMode  */

- (void)filterPasteboardFiles:(int)filterMode options:(NSMutableArray *)options pasteBoard:(NSPasteboard *)pboard
{
    NSArray *pasteboardNames;
    NSMutableArray *fileNames;
    NSArray *types;
    int iname;

    fileNames = [[NSMutableArray alloc] init];

    if(!options)
	options = [[[NSMutableArray alloc] init] autorelease];
    
    types = [pboard types];
    if(![types containsObject:NSFilenamesPboardType]) {
	NSLog(@"NXPGP: Pasteboard couldn't give Filename selection");
	return;
    }

    pasteboardNames = [pboard propertyListForType:NSFilenamesPboardType];
    if(!pasteboardNames) {
	NSLog(@"NXPGP: Pasteboard couldn't give Filename data");
	return;
    }

    /* Turn all directory names into an array of all the */
    /* filenames in the subdirectory tree                */
    for(iname=0; iname<[pasteboardNames count]; iname++) {
	NSString *currentName;
        BOOL isDir;

	isDir = NO;
	currentName = [pasteboardNames objectAtIndex:iname];
        [[NSFileManager defaultManager] fileExistsAtPath:currentName isDirectory:&isDir];
	if(isDir) {
	    NSArray *subDirNames;
	    NSString *fullName;
	    int isubname;

	    subDirNames = [[NSFileManager defaultManager] subpathsAtPath:currentName];
	    for(isubname=0; isubname<[subDirNames count]; isubname++) {
		fullName = [currentName stringByAppendingPathComponent:
			    [subDirNames objectAtIndex:isubname]];

		[fileNames addObject:fullName];
	    }
	}
	else [fileNames addObject:currentName];
    }

    for(iname=0; iname<[fileNames count]; iname++)
      NSLog([NSString stringWithFormat:@"   %@",[fileNames objectAtIndex:iname]]);

    [self filterPGPFiles:fileNames mode:filterMode options:options];
    return;
}


/* Filters an array of files (ONLY FILES!)   */
/* through PGP.  It encrypts or  decrypts    */
/* depending on the value of filterMode      */

- (void)filterPGPFiles:(NSMutableArray *)fileArray mode:(int)filterMode options:(NSMutableArray *)options
{
    NSPanel *infoPanel;
    NSData *pgpIn,*pgpOut;
    NSTextField *fileTextField;
    int ifile;

    infoPanel = encryptInfoPanel;
    fileTextField = encryptFileTextField;

    switch(filterMode) {
      case ENCRYPT:
      case ENCRYPT_IDEA:
	infoPanel = encryptInfoPanel;
	fileTextField = encryptFileTextField;
	break;

      case DECRYPT:
	infoPanel = decryptInfoPanel;
	fileTextField = decryptFileTextField;
	break;
    }
	
	
    for(ifile=0; ifile<[fileArray count]; ifile++) {
	NSString *oldFile,*newFile;
	int result;

	oldFile = [fileArray objectAtIndex:ifile];

	[fileTextField setStringValue:oldFile];
	[infoPanel display];
        [infoPanel flushWindow];
	[infoPanel makeKeyAndOrderFront:self];

	pgpIn = [NSData dataWithContentsOfFile:oldFile];
	pgpOut = [[cryptor runpgp:filterMode options:options data:pgpIn] retain];

	/* Check for errors */
	if(!pgpOut) {
	    NSLog(@"NXPGP: PGP cancelled out");
	    [infoPanel orderOut:self];
	    [cryptor clearRecipient:self];
	    [cryptor clearIdeaPhrase:self];
	    [cryptor clearDecryptPhrase:self];
	    return;
	}

	if([pgpOut length] == 0) {
	    NSLog(@"PGP error resulted in null output\n");
	    [infoPanel orderOut:self];
	    [cryptor clearRecipient:self];
	    [cryptor clearIdeaPhrase:self];
	    [cryptor clearDecryptPhrase:self];
	    [pgpOut release];
	    return;
	}

	/* Write back to file */
	switch(filterMode) {

	  case ENCRYPT:
	  case ENCRYPT_IDEA:
	    newFile = [oldFile stringByAppendingString:@".pgp"];
	    if([[NSFileManager defaultManager] fileExistsAtPath:newFile]) {
		result = NSRunAlertPanel([NSString stringWithFormat:@"File %@ Exists",newFile],
					 @"Over Write Existing File?",@"Yes",@"No",0);
		switch(result) {
		  case NSAlertDefaultReturn:
		    [pgpOut writeToFile:newFile atomically:NO];
		    break;
		  default:
		    break;
		}
	    }
	    else
	      [pgpOut writeToFile:newFile atomically:NO];
	      
	    break;

	  case DECRYPT:
	    newFile = [oldFile stringByDeletingPathExtension];
	    if([[NSFileManager defaultManager] fileExistsAtPath:newFile]) {
		result = NSRunAlertPanel([NSString stringWithFormat:@"File %@ Exists",newFile],
					 @"Over Write Existing File?",@"Yes",@"No",0);
		switch(result) {
		  case NSAlertDefaultReturn:
		    [pgpOut writeToFile:newFile atomically:NO];
		    break;
		  default:
		    break;
		}
	    }
	    else
	      [pgpOut writeToFile:newFile atomically:NO];
	      
	    break;
	    
	  default:
	    break;
	}

	[pgpOut release];
    }

    [infoPanel orderOut:self];
    [cryptor clearRecipient:self];
    [cryptor clearIdeaPhrase:self];
    [cryptor clearDecryptPhrase:self];

    return;
}



- showStatus:sender
{
    [cryptor showStatus:self];
    return self;
}


- showOutput:sender
{
    [cryptor showOutput:self];
    return self;
}


/******************  NSApplication Delegate Routines *************************/

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    [NSApp setServicesProvider:self];
    return;
}


- (BOOL)application:(NSApplication *)anApp openFile:(NSString *)aFile
{
    NSData *pgpIn,*pgpOut;
    NSMutableArray *options;
    NSString *newFile;
    int result;

    [decryptFileTextField setStringValue:aFile];
    [decryptInfoPanel display];
    [decryptInfoPanel flushWindow];
    [decryptInfoPanel makeKeyAndOrderFront:self];

    options = [[[NSMutableArray alloc] init] autorelease];
    pgpIn = [NSData dataWithContentsOfFile:aFile];
    pgpOut = [[cryptor runpgp:DECRYPT options:options data:pgpIn] retain];

    /* Check for errors */
    if(!pgpOut) {
	NSLog(@"NXPGP: PGP cancelled out");
	[decryptInfoPanel orderOut:self];
	[cryptor clearIdeaPhrase:self];
	[cryptor clearDecryptPhrase:self];
	return NO;
    }

    if([pgpOut length] == 0) {
	NSLog(@"PGP error resulted in null output\n");
	[decryptInfoPanel orderOut:self];
	[cryptor clearIdeaPhrase:self];
	[cryptor clearDecryptPhrase:self];
	[pgpOut release];
	return NO;
    }
    
    /* Write back to file */
    newFile = [aFile stringByDeletingPathExtension];
    if([[NSFileManager defaultManager] fileExistsAtPath:newFile]) {
	result = NSRunAlertPanel([NSString stringWithFormat:@"File %@ Exists",newFile],
				 @"Over Write Existing File?",@"Yes",@"No",0);
	switch(result) {
	  case NSAlertDefaultReturn:
	    [pgpOut writeToFile:newFile atomically:NO];
	    break;
	  default:
	    break;
	}
    }
    else
      [pgpOut writeToFile:newFile atomically:NO];

    [pgpOut release];
    
    [decryptInfoPanel orderOut:self];
    [cryptor clearIdeaPhrase:self];
    [cryptor clearDecryptPhrase:self];

    return YES;
}




#if 0
/****************************  Cryptor Test Routines *************************/
- encryptTest:sender
{
    NSMutableArray *options;
    NSData *pgpIn,*pgpOut;

    options = [[NSMutableArray alloc] init];

    pgpIn = [NSData dataWithContentsOfFile:@"/junk/tmp/dumpgp.c"];
    pgpOut = [cryptor runpgp:ENCRYPT options:options data:pgpIn];

    [pgpOut writeToFile:@"/tmp/pgpOutput.pgp" atomically:NO];

    return self;
}

- encryptSignTest:sender
{
    NSMutableArray *options;
    NSData *pgpIn,*pgpOut;

    options = [[NSMutableArray alloc] initWithObjects:@"-s", nil];

    pgpIn = [NSData dataWithContentsOfFile:@"/junk/tmp/dumpgp.c"];
    pgpOut = [cryptor runpgp:ENCRYPT options:options data:pgpIn];

    [pgpOut writeToFile:@"/tmp/pgpOutput.pgp" atomically:NO];

    return self;
}

- checkSigTest:sender
{
    NSMutableArray *options;
    NSData *pgpIn,*pgpOut;

    options = [[NSMutableArray alloc] init];
    pgpIn = [NSData dataWithContentsOfFile:@"/junk/tmp/dumpgp.c.clearsign"];
    pgpOut = [cryptor runpgp:CHECKSIG options:options data:pgpIn];

    return self;
}


- decryptTest:sender
{
    NSMutableArray *options;
    NSData *pgpIn,*pgpOut;

    options = [[NSMutableArray alloc] init];
    pgpIn = [NSData dataWithContentsOfFile:@"/junk/tmp/dumpgp.c.new.pgp"];
    pgpOut = [cryptor runpgp:DECRYPT options:options data:pgpIn];

    return self;
}


- clearSignTest:sender
{
    NSMutableArray *options;
    NSData *pgpIn,*pgpOut;

    options = [[NSMutableArray alloc] init];
    pgpIn = [NSData dataWithContentsOfFile:@"/junk/tmp/dumpgp.c"];
    pgpOut = [cryptor runpgp:CLEARSIGN options:options data:pgpIn];

    return self;
}



- detachedSigTest:sender
{
    NSMutableArray *options;
    NSData *pgpIn,*pgpOut;

    options = [[NSMutableArray alloc] init];
    pgpIn = [NSData dataWithContentsOfFile:@"/junk/tmp/dumpgp.c"];
    pgpOut = [cryptor runpgp:DETACHEDSIG options:options data:pgpIn];

    return self;
}
#endif

@end

	     
