#!/usr/bin/php
<?php
/**
 * Script shell para gerenciar as senhas de acesso de um usuário de forma segura
 * utilizando como base de dados, um arquivo texto simples
 *
 *
 * PHP version 5
 *
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @author          Thiago Paes - mrprompt at gmail dot com
 * @filesource      senha.php
 * @copyright        Copyright 2008, Thiago Paes
 * @link            http://www.thiagopaes.com.br/phpSenha/
 * @version            $Revision: 0.2 $
 * @license            http://www.opensource.org/licenses/mit-license.php The MIT License
 *
 */
ini_set ("display_errors"false);

define ("ARQ_SENHAS"$_ENV["HOME"] .'/.senhas_list');
define ("MD5_USER",   md5($_ENV['USER']) );

$arg1 = ( isset($argv[1]) ? $argv[1] : null );
$base basename($_SERVER['SCRIPT_FILENAME']);

// Tentando carregar a classse Console_Color
if ( !include_once('Console/Color.php') ) {
    print (
"Você precisa da classe Console_Color, tente: pear install Console_Color\n");
    exit;
}

// Tentando carregar a classse Console_Table
if ( !include_once('Console/Table.php') ) {
    print (
"Você precisa da classe Console_Table, tente: pear install Console_Table\n");
    exit;
}

// Cria o banco de dados de senhas caso este não exista
if ( !file_exists(ARQ_SENHAS) ) {
    
file_put_contents(ARQ_SENHASnull);
}

/**
 * Criptografa uma string
 *
 * @param string $enc_text="Texto Criptografado"
 * @param string $password="chave criptográfica"
 * @return string
 */
function str_encrypt($plain_text$password)
{
    return 
base64_encode($plain_text.$password);
}

/**
 * Decriptografa uma string
 *
 * @param string $enc_text="Texto Criptografado"
 * @param string $password="chave criptográfica"
 * @return string
 */
function str_decrypt($enc_text$password)
{
    
$passLength strlen($password);
    
$strdecode  base64_decode($enc_text);
    
$plain_text substr($strdecode0, -$passLength);

    return 
$plain_text;
}

/**
 * Ajuda
 * 
 * Exibe a ajuda
 */
function ajuda ()
{
    global 
$base;
    
    print 
Console_Color::convert("%_{$base}%n é um script shell para facilitar a administração de várias contas de acesso.\n");
    print 
Console_Color::convert("%_Uso:%n {$base} <opções>\n\n");
    print 
Console_Color::convert("Opções:\n");
    print 
Console_Color::convert("%_ajuda%n\t\t\t\tExibe esta ajuda\n");
    print 
Console_Color::convert("%_listar%n\t\t\t\tLista as senhas cadastradas\n");
    print 
Console_Color::convert("%_buscar%n %ycritério%n\t\t\tBusca por registros que coincidam com o critério\n");
    print 
Console_Color::convert("%_adicionar%n %yalias usuário senha%n\tInsere um novo cadastro de senha\n");
    print 
Console_Color::convert("%_apagar%n %yID%n\t\t\tRemove um registro%n\n");
    print 
Console_Color::convert("%_atualizar%n %yID alias usuáro senha%n\tAtualiza um registro%n\n");
}

/**
 * Atualizar
 *
 * Atualiza um registro
 */
function atualizar ()
{
    global 
$base;
    
    
$args       func_get_args();
    
$args       $args[0];
    
$linha      $args[2];
    
$alias      $args[3];
    
$usuario    $args[4];
    
$senha      $args[5];
    
$erro       false;

    if ( !
preg_match("/[[:digit:]]/"$linha) ) {
        
$erro true;
    }

    if ( !
preg_match("/[[:alnum:]]/"$alias) ) {
        
$erro true;
    }

    if ( !
preg_match("/[[:alnum:]]/"$usuario) ) {
        
$erro true;
    }

    if ( !
preg_match("/[[:alnum:]]/"$senha) ) {
        
$erro true;
    }

    if ( !
$erro ) {
        
$fp fopen("php://stdin""r");
        
        print 
Console_Color::convert("%r%_Continuar atualização do registro [s/n] ?%n ");

        
$confirmacao fgets($fp100);

        if ( 
preg_match('/(s|S)/'$confirmacao) ) {
            
$senhaCript     str_encrypt($senhaMD5_USER);
            
$novoRegistro   "{$alias};{$usuario};{$senhaCript}";

            
passthru("sed -i '{$linha}s/.*/{$novoRegistro}/g' "ARQ_SENHAS);
            
passthru("{$_SERVER['SCRIPT_FILENAME']} listar");

            print 
Console_Color::convert("%r%_Registro atualizado%n\n");
        }
        
        
fclose($fp);
    } else {
        print 
Console_Color::convert("Uso: {$base} atualizar %_ID alias usuario senha%n\n");
    }
}

/**
 * Apagar
 *
 * Remove um registro da base
 */
function apagar ()
{
    global 
$base;
    
    
$args func_get_args();
    
$args $args[0];

    if ( isset (
$args[2]) ) {
        
$fp fopen("php://stdin""r");
        
        print 
Console_Color::convert("%r%_Continuar exclusão do registro [s/n] ?%n ");

        
$confirmacao fgets($fp100);

        if ( 
preg_match('/(s|S)/'$confirmacao) ) {
            
passthru("sed -i {$args[2]}d "ARQ_SENHAS);
            
passthru("{$_SERVER['SCRIPT_FILENAME']} listar");

            print 
Console_Color::convert("%r%_Excluído%n\n");
        }

        
fclose($fp);
    } else {
        print 
Console_Color::convert("Uso: {$base} {$arg1} %_ID%n\n");
    }
}

/**
 * Adicionar
 *
 * Adiciona um novo registro na base de dados, criptografando a senha do usuário
 */
function adicionar ()
{
    global 
$base;
    
    
$args       func_get_args();
    
$args       $args[0];
    
$alias      $args[2];
    
$usuario    $args[3];
    
$senha      $args[4];
    
$erro       false;

    if ( !
preg_match("/[[:alnum:]]/"$alias) ) {
        
$erro true;
    }

    if ( !
preg_match("/[[:alnum:]]/"$usuario) ) {
        
$erro true;
    }

    if ( !
preg_match("/[[:alnum:]]/"$senha) ) {
        
$erro true;
    }

    if ( !
$erro ) {
        
$senhaCript str_encrypt($senhaMD5_USER);

        
file_put_contents(ARQ_SENHAS"{$alias};{$usuario};{$senhaCript}\n"FILE_APPEND|FILE_TEXT);

        print 
Console_Color::convert("%_{$alias}%n adicionado\n");

        
passthru("{$_SERVER['SCRIPT_FILENAME']} listar");
    } else {
        print 
Console_Color::convert("Uso: {$base} adicionar %_alias usuario senha%n\n");
    }
}

/**
 * Buscar
 * 
 * Busca por ocorrências que coincidam com o filtro informado pelo usuário
 */
function buscar ()
{
    global 
$base;
    
    
$args func_get_args();
    
$args $args[0];

    if ( isset (
$args[2]) ) {
        print 
Console_Color::convert("Buscando por %_{$args[2]}%n\n");

        
$ocorrencias0;
        
$linhaAtual 0;
        
$arquivocsv fopen (ARQ_SENHAS'r');

        while ( 
$linha fgetcsv ($arquivocsvnull";""\"") ) {
            
$linhaAtual++;

            if ( 
preg_match("/$args[2]/i"$linha[0]) ) {
                
$senhaCript str_decrypt($linha[2], MD5_USER);

                print 
Console_Color::convert("%_ID:%n {$linhaAtual}\n");
                print 
Console_Color::convert("%_Alias:%n {$linha[0]}\n");
                print 
Console_Color::convert("%_Usuário:%n {$linha[1]}\n");
                print 
Console_Color::convert("%_Senha:%n {$senhaCript}\n");
                print 
"==============================================\n";

                
$ocorrencias++;
            }
        }

        
fclose($arquivocsv);

        print 
Console_Color::convert("Encontrada(s) %_{$ocorrencias}%n ocorrência(s)\n");
    } else {
        print 
Console_Color::convert("Uso: {$base} buscar %_buscar%n\n");
    }
}

/**
 * Listar
 * 
 * Lista todos os registros da base de dados
 */
function listar ()
{
    global 
$base;

    
$tabela     = new Console_Table();
    
$args       func_get_args();
    
$args       $args[0];
    
$linhaAtual 0;
    
$arquivocsv fopen (ARQ_SENHAS'r');

    while ( 
$linha fgetcsv ($arquivocsvnull";""\"") ) {
        
$linhaAtual++;

        
$tabela->addRow( array($linhaAtual$linha[0], $linha[1], str_decrypt($linha[2], MD5_USER) ) );
    }

    
fclose($arquivocsv);

    
$tabela->setHeaders( array ("ID""Alias""Usuário""Senha") );

    print 
$tabela->getTable();
}

// executando caso a função exista, senão exibe uma ajuda mínima
if ( function_exists($arg1) ) {
    
$arg1($argv);
} else {
    
// Função padrão, com instruções de uso
    
print Console_Color::convert("%_{$base}%n é um script shell para facilitar a administração de várias contas de acesso.\n");
    print 
Console_Color::convert("%_Uso:%n");
    print 
Console_Color::convert("\t{$base} <opções> [<parâmetros>]\n");
    print 
Console_Color::convert("\t{$base} ajuda\n\n");
}
?>