#import "Cryptor.h"

@implementation Cryptor

- init
{
    if(![NSBundle loadNibNamed:@"Cryptor" owner:self]) {
	fprintf(stderr,"Can't load Cryptor.nib\n");
	exit(1);
    }

    statusRange.location = 0;
    statusRange.length = 0;
    
    outputRange.location = 0;
    outputRange.length = 0;
    
    [super init];
    return self;
}


- (NSData *) runpgp:(int)mode options:(NSMutableArray *)lineOpts data:(NSData *)pgpDataIn
{
    NSTask *pgpTask;
    NSPipe *toPGP,*fromPGP,*errPGP;
    NSFileHandle *readHandle,*writeHandle;
    NSFileHandle *errHandle;
    NSData *pgpOutput;
    NSMutableData *pgpError;
    NSString *mainDir;
    NSMutableString *launchPath;
    NSString *recipID,*userID,*passPhrase;
    int  errorLength,outputLength;
    char *errorBuffer,*outputBuffer;
    NSString *errorString,*outputString;

    toPGP = [NSPipe pipe];
    fromPGP = [NSPipe pipe];
    errPGP = [NSPipe pipe];
  
    readHandle = [fromPGP fileHandleForReading];
    writeHandle = [toPGP fileHandleForWriting];
    errHandle = [errPGP fileHandleForReading];

    pgpTask = [[NSTask alloc] init];
    [pgpTask setStandardOutput:fromPGP];
    [pgpTask setStandardInput:toPGP];
    [pgpTask setStandardError:errPGP];

    mainDir = [[NSBundle mainBundle] bundlePath];

    switch (mode) {
      case ENCRYPT:
	[lineOpts addObject:@"+batchmode"];
	[lineOpts addObject:@"+force"];
	[lineOpts addObject:@"+encrypttoself=on"];
	[lineOpts addObject:@"-f"];
	[lineOpts addObject:@"-a"];
	
	if([lineOpts containsObject:@"-s"]) {
	    [self getEncryptAndSignInfo:&recipID userID:&userID passPhrase:&passPhrase];
	    if(!recipID) {
		[pgpTask release];
		return nil;
	    }
	    [lineOpts addObject:@"-z"];
	    [lineOpts addObject:passPhrase];
	    if([userID length] > 0) {
		[lineOpts addObject:@"-u"];
		[lineOpts addObject:userID];
	    }
	    [lineOpts addObject:@"-r"];
	    [lineOpts addObject:recipID];
	}
	else {
	    [self getEncryptInfo:&recipID];
	    if(!recipID) {
		[pgpTask release];
		return nil;
	    }
	    [lineOpts addObject:@"-r"];
	    [lineOpts addObject:recipID];
	}

	launchPath = (NSMutableString *)[mainDir stringByAppendingPathComponent:@"pgpe"];
        if([[NSFileManager defaultManager] isExecutableFileAtPath:launchPath] == NO) {
	    NSLog([NSString stringWithFormat:
		     @"Can't find PGP executable: %s",[launchPath cString]]);
	    return nil;
	}

        [pgpTask setLaunchPath:launchPath];
	[pgpTask setArguments:lineOpts];
	[pgpTask launch];

	[writeHandle writeData:pgpDataIn];
	[writeHandle closeFile];

	break;

      case ENCRYPT_IDEA:
	[lineOpts addObject:@"+batchmode"];
	[lineOpts addObject:@"-f"];
	[lineOpts addObject:@"-c"];
	
	[self getIdeaPhrase:&passPhrase];
	if(!passPhrase) {
	    [pgpTask release];
	    return nil;
	}
	    
	[lineOpts addObject:@"-z"];
	[lineOpts addObject:passPhrase];

	launchPath = (NSMutableString *)[mainDir stringByAppendingPathComponent:@"pgpe"];
        if([[NSFileManager defaultManager] isExecutableFileAtPath:launchPath] == NO) {
	    NSLog([NSString stringWithFormat:
		     @"Can't find PGP executable: %s",[launchPath cString]]);
	    return nil;
	}

        [pgpTask setLaunchPath:launchPath];
	[pgpTask setArguments:lineOpts];
	[pgpTask launch];

	[writeHandle writeData:pgpDataIn];
	[writeHandle closeFile];

	break;

      case DECRYPT:
	[self getDecryptInfo:&passPhrase];
	if(!passPhrase) {
	    [pgpTask release];
	    return nil;
	}
	[lineOpts addObject:@"-z"];
	[lineOpts addObject:passPhrase];

	/*  Don't break here - go on */

      case CHECKSIG:
	[lineOpts addObject:@"+batchmode"];
	[lineOpts addObject:@"+force"];
	[lineOpts addObject:@"-f"];

	launchPath = (NSMutableString *)[mainDir stringByAppendingPathComponent:@"pgpv"];
        if([[NSFileManager defaultManager] isExecutableFileAtPath:launchPath] == NO) {
	    NSLog([NSString stringWithFormat:
		     @"Can't find PGP executable: %s",[launchPath cString]]);
	    return nil;
	}

        [pgpTask setLaunchPath:launchPath];
	[pgpTask setArguments:lineOpts];
	[pgpTask launch];

	[writeHandle writeData:pgpDataIn];
	[writeHandle closeFile];

	break;

      case CLEARSIGN:
	[lineOpts addObject:@"+batchmode"];
	[lineOpts addObject:@"+force"];
	[lineOpts addObject:@"-f"];
	[lineOpts addObject:@"-a"];
	[lineOpts addObject:@"-t"];

	[self getSignatureInfo:&userID passPhrase:&passPhrase];
	if(!passPhrase) {
	    [pgpTask release];
	    return nil;
	}
	[lineOpts addObject:@"-z"];
	[lineOpts addObject:passPhrase];
	if([userID length] > 0) {
	    [lineOpts addObject:@"-u"];
	    [lineOpts addObject:userID];
	}

	launchPath = (NSMutableString *)[mainDir stringByAppendingPathComponent:@"pgps"];
        if([[NSFileManager defaultManager] isExecutableFileAtPath:launchPath] == NO) {
	    NSLog([NSString stringWithFormat:
		     @"Can't find PGP executable: %s",[launchPath cString]]);
	    return nil;
	}

        [pgpTask setLaunchPath:launchPath];
	[pgpTask setArguments:lineOpts];
	[pgpTask launch];

	[writeHandle writeData:pgpDataIn];
	[writeHandle closeFile];

	break;

      case DETACHEDSIG:
	[lineOpts addObject:@"+batchmode"];
	[lineOpts addObject:@"+force"];
	[lineOpts addObject:@"-f"];
	[lineOpts addObject:@"-a"];
	[lineOpts addObject:@"-t"];
	[lineOpts addObject:@"-b"];

	[self getSignatureInfo:&userID passPhrase:&passPhrase];
	if(!passPhrase) {
	    [pgpTask release];
	    return nil;
	}
	[lineOpts addObject:@"-z"];
	[lineOpts addObject:passPhrase];
	if([userID length] > 0) {
	    [lineOpts addObject:@"-u"];
	    [lineOpts addObject:userID];
	}

	launchPath = (NSMutableString *)[mainDir stringByAppendingPathComponent:@"pgps"];
        if([[NSFileManager defaultManager] isExecutableFileAtPath:launchPath] == NO) {
	    NSLog([NSString stringWithFormat:
		     @"Can't find PGP executable: %s",[launchPath cString]]);
	    return nil;
	}

        [pgpTask setLaunchPath:launchPath];
	[pgpTask setArguments:lineOpts];
	[pgpTask launch];

	[writeHandle writeData:pgpDataIn];
	[writeHandle closeFile];

	break;

      default:
	return nil;
    }

    pgpOutput = [readHandle readDataToEndOfFile];
    pgpError = (NSMutableData *)[errHandle readDataToEndOfFile];

    [pgpTask kill];
    [pgpTask release];

    /* Display error/status message in statusTextView */
    errorLength = [pgpError length];
    errorBuffer = (char *)malloc(errorLength+1);
    [pgpError getBytes:errorBuffer];
    errorBuffer[errorLength] = '\0';
    errorString = [NSString stringWithCString:errorBuffer];
    free(errorBuffer);

    [statusTextView setSelectedRange:statusRange];
    [statusTextView insertText:errorString];
    statusRange.length = errorLength;

    [statusTextView display];

    
    /* Display pgp output in OutputTextView */
    outputLength = [pgpOutput length];
    outputBuffer = (char *)malloc(outputLength+1);
    [pgpOutput getBytes:outputBuffer];
    outputBuffer[outputLength] = '\0';
    outputString = [NSString stringWithCString:outputBuffer];
    free(outputBuffer);

    [outputTextView setSelectedRange:outputRange];
    [outputTextView insertText:outputString];
    outputRange.length = outputLength;

    [outputTextView display];

    return pgpOutput;
}

    

- (void)getEncryptAndSignInfo:(NSString **)recip userID:(NSString **)userid
                   passPhrase:(NSString **)phrase 
{
    if(![NSApp runModalForWindow:eAndSPanel]) {
	*recip = nil;
	*userid = nil;
	*phrase = nil;
	[eAndSPanel orderOut:self];
	return;
    }

    [eAndSPanel orderOut:self];
    *recip =  [eAndSencryptToField stringValue];
    *userid = [eAndSsecretIDField stringValue];
    *phrase = [eAndSsecretPhraseField stringValue];

    [eAndSsecretPhraseField setStringValue:[NSString stringWithCString:""]];
    return;
}


- (void)getEncryptInfo:(NSString **)recip
{
    if([[eEncryptToField stringValue] length] <= 0) {
	if(![NSApp runModalForWindow:ePanel]) {
	    *recip = nil;
	    [ePanel orderOut:self];
	    return;
	}
    }
	
    [ePanel orderOut:self];
    *recip =  [eEncryptToField stringValue];
    return;
}


- (void)getIdeaPhrase:(NSString **)phrase
{
    if([[iPhraseField stringValue] length] > 0) {
	*phrase =  [iPhraseField stringValue];
	return;
    }
      
    if(![NSApp runModalForWindow:iPanel]) {
	*phrase = nil;
	[iPanel orderOut:self];
	return;
    }

    [iPanel orderOut:self];
    *phrase =  [iPhraseField stringValue];

    return;
}


- (void)getDecryptInfo:(NSString **)phrase
{
    if([[dPhraseField stringValue] length] > 0) {
	*phrase =  [dPhraseField stringValue];
	return;
    }
      
    if(![NSApp runModalForWindow:dPanel]) {
	*phrase = nil;
	[dPanel orderOut:self];
	return;
    }
    
    [dPanel orderOut:self];
    *phrase =  [dPhraseField stringValue];

    return;
}


- (void)getSignatureInfo:(NSString **)userid passPhrase:(NSString **)phrase
{
    if(![NSApp runModalForWindow:sPanel]) {
	*userid = nil;
	*phrase = nil;
	[sPanel orderOut:self];
	return;
    }
    
    [sPanel orderOut:self];
    *userid = [sigIDField stringValue];
    *phrase =  [sigPhraseField stringValue];

    /* Clear passphrase out of field */
    [sigPhraseField setStringValue:[NSString stringWithCString:""]];
    return;
}


- showStatus:sender
{
    [statusPanel orderFront:self];
    return self;
}


- showOutput:sender
{
    [outputPanel orderFront:self];
    return self;
}


- endPassPhraseSession:sender
{
    [NSApp stopModalWithCode:1];
    return self;
}
    
- cancelModal:sender
{
    [NSApp stopModalWithCode:0];
    return self;
}

- clearIdeaPhrase:sender
{
    [iPhraseField setStringValue:[NSString stringWithCString:""]];
    return self;
}

- clearEandSPhrase:sender
{
    [eAndSsecretPhraseField setStringValue:[NSString stringWithCString:""]];
    return self;
}

- clearDecryptPhrase:sender
{
    [dPhraseField setStringValue:[NSString stringWithCString:""]];
    return self;
}

- clearSignPhrase:sender
{
    [sigPhraseField setStringValue:[NSString stringWithCString:""]];
    return self;
}

- clearRecipient:sender
{
    [eAndSencryptToField setStringValue:@""];
    [eEncryptToField setStringValue:@""];
    return self;
}
    


@end
