//
//  Util.m
//  CyTV
//
//  Created by Andreas Junghans on Sat May 08 2004.
//  Copyright (c) 2004-2005 Andreas Junghans. All rights reserved.
//

#import "Util.h"
#import <Security/Authorization.h>
#import <sys/wait.h>

@implementation Util

+ (int)findPortStartingWith:(int)startPort {
    int port;
    NSSocketPort *socketPort;
    for (port = startPort; port <= 65535; ++port) {
        socketPort = [[NSSocketPort alloc] initWithTCPPort:(unsigned short)port];
        [socketPort release];
        if (socketPort != nil) {
            return port;
        }
    }
    return 0;
}

+ (int)findPortStartingWith:(int)startPort excluding:(int)excludedPort {
    int port;
    NSSocketPort *socketPort;
    for (port = startPort; port <= 65535; ++port) {
        if (port != excludedPort) {
            socketPort = [[NSSocketPort alloc] initWithTCPPort:(unsigned short)port];
            [socketPort release];
            if (socketPort != nil) {
                return port;
            }
        }
    }
    return 0;
}

+ (NSString*)getCyTVLogPath {
    return [@"~/Library/Logs/CyTV" stringByExpandingTildeInPath];
}

+ (NSString*)getCyTVSupportPath {
    return [@"~/Library/Application Support/CyTV" stringByExpandingTildeInPath];
}

+ (NSString *)quoteForShell:(NSString *)input {
    NSArray *parts = [input componentsSeparatedByString:@"'"];
    NSString *result = @"'";
    int i;
    for (i = 0; i < [parts count]; ++i) {
        result = [result stringByAppendingString:[parts objectAtIndex:i]];
        if (i < ([parts count] - 1)) {
            result = [result stringByAppendingString:@"'\"'\"'"];
        }
    }
    return [result stringByAppendingString:@"'"];
}

+ (NSString *)shell:(NSString *)command {
    NSTask *task = [[NSTask alloc] init];
    [task setLaunchPath:@"/bin/sh"];
    [task setArguments:[NSArray arrayWithObjects:@"-c", command, nil]];
    NSPipe *stdIn = [NSPipe pipe];
    NSFileHandle *writeHandle = [stdIn fileHandleForWriting];
    NSPipe *stdOut = [NSPipe pipe];
    NSFileHandle *readHandle = [stdOut fileHandleForReading];
    [task setStandardInput:stdIn];
    [task setStandardOutput:stdOut];
    [task launch];
    //const char* commandBytes = [command UTF8String];
    //[writeHandle writeData:[NSData dataWithBytes:commandBytes length:strlen(commandBytes)]];
    [writeHandle closeFile];
    NSData *resultData = [readHandle readDataToEndOfFile];
    NSString *result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
    [readHandle closeFile];
    [task waitUntilExit];
    [result autorelease];
    int terminationResult = [task terminationStatus];
    if (terminationResult != 0) {
        [NSException raise:@"ShellCallFailedException" format:@"Shell call failed with exit status %d",
         terminationResult];
    }
    return result;
}

+ (NSString *)adminShell:(NSString *)command {
    NSString *retVal = nil;
    
    AuthorizationRef authRef;
    OSStatus err = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
     kAuthorizationFlagDefaults, &authRef);   
    if (err != noErr) {
        [NSException raise:@"AuthorizationCreateError" format:@"Could not create an authorization."];
    }
    char *commandBytes = (char *)[command UTF8String];
    char *myArguments[] = {"-c", commandBytes, NULL};
    FILE *commPipe;
    err = AuthorizationExecuteWithPrivileges(authRef, "/bin/sh",
           kAuthorizationFlagDefaults, myArguments, &commPipe);
    if (err == noErr) {
        char buffer[1025];
        size_t bytesRead = fread(buffer, 1, 1024, commPipe);
        buffer[bytesRead] = '\0';
        retVal = [NSString stringWithUTF8String:buffer];
        fclose(commPipe);
    }
    int status;
    wait(&status);
    AuthorizationFree(authRef, kAuthorizationFlagDefaults);
    if (err != noErr) {
        [NSException raise:@"AuthorizationExecuteError" format:@"Could not execute the privileged command."];
    }

    return retVal;
}

@end
