Embora a gravação em uma extensão PHP não seja particularmente onerosa, SWIG simplificará mais a tarefa, muito pela automatização do trabalho necessário para unir PHP e o código C ou C++. Com uma descrição da função apresentada — seu nome e seus argumentos formais — SWIG gera um wrapper para formar uma ponte entre PHP e o código de baixo nível.
SWIG tem alguns pré-requisitos. As versões mais recentes solicitam PHP V5. É preciso também ter um compilador C/C++, como o GNU Compiler Collection (GCC), e uma cópia do Module Development Kit (MDK) para PHP. Especificamente, é preciso ter os arquivos de cabeçalho associados à sua instalação de PHP. Caso utilize Ubuntu Linux® ou uma variação de Debian e instale PHP V5 a partir de um repositório de pacote, você poderá geralmente adicionar o MDK usando Advanced Packaging Tool (APT). Por exemplo, no kernel Ubuntu 9.10, digite apt-get install sudo apt-get install --install-recommends --yes php5-dev.
No fim de 2009, a release mais recente de SWIG era a V1.3.40 (consulte Recursos). Faça o download de tarball (um arquivo TAR compactado por gzip), descompacte-o, configure o código do sistema e crie e instale o software. (Para encontrar todas as opções de configuração, execute ./configure --help). A Listagem 1 apresenta os comandos para download, descompactação e instalação de SWIG.
Listagem 1. Download, descompactação e instalação de SWIG
$ wget http://prdownloads.sourceforge.net/swig/swig-1.3.40.tar.gz $ tar xzf swig-1.3.40.tar.gz $ cd swig-1.3.40 $ ./configure $ make $ sudo make install $ which swig /usr/local/bin/swig |
Vamos criar uma extensão para criptografar e decriptografar mensagens com a biblioteca mcrypt do Linux. PHP oferece uma biblioteca mcrypt, mas ela é um pouco mais do que um aglomerado muito fino sobre os pontos de entrada de C da biblioteca. Aqui, vamos criar dois métodos bem mais sucintos: um para criptografar uma cadeia de caracteres e outro para decriptografá-la.
Em Ubuntu e seus semelhantes, é possível instalar as bibliotecas mcrypt pertinentes e os arquivos de cabeçalho com APT: $ sudo apt-get install libmcrypt-dev libmcrypt4 mcrypt libmhash2.
Se preferir criar do zero ou se a sua distribuição não tiver mcrypt, você poderá fazer o download do código de origem de sua página inicial (consulte Recursos). O utilitário mcrypt, que substitui crypt, também depende de libmhash, que deve ser criado antes da compilação de mcrypt. A Listagem 2 mostra o código para a criação de libmhash.
Listagem 2. Criando
libmhash
$ # libmhash
$ wget http://sourceforge.net/projects/mhash/files/mhash/0.9.9.9/\
mhash-0.9.9.9.tar.bz2/download
$ tar xfj mhash-0.9.9.9.tar.bz2
$ cd mhash-0.9.9.9
$ ./configure
$ make
$ sudo make install
# libmcrypt
$ wget ftp://mcrypt.hellug.gr/pub/crypto/mcrypt/libmcrypt/\
libmcrypt-2.5.7.tar.gz
$ tar xfz libmcrypt-2.5.7.tar.gz
$ cd libmcrypt-2.5.7
$ ./configure
$ make
$ sudo make install
$ # mcrypt
$ wget wget http://sourceforge.net/projects/mcrypt/files/MCrypt/2.6.8/\
mcrypt-2.6.8.tar.gz/download
$ tar xfz mcrypt-2.6.8.tar.gz
$ cd mcrypt-2.6.8
$ ./configure
$ make
$ sudo make install
|
Em seguida, crie o código C para a extensão. As funções interessantes no código são encode() e decode(), na parte inferior da Listagem 3. Ambas têm dois argumentos formais — uma cadeia de caracteres e uma contagem — e as duas funções retornam uma cadeia de caracteres. A primeira criptografa uma cadeia de caracteres com texto simples, retornando sua codificação; a última decriptografa uma cadeia de caracteres codificada e retorna texto simples. As cadeias de caracteres podem ter qualquer extensão.
O código usa o algoritmo Data Encryption Standard-Electronic Codebook (DES-ECB). A chave secreta pode ser qualquer cadeia de caracteres de oito caracteres e é mostrada como 12345678 somente para fins de demonstração. Se estiver trocando mensagens criptografadas com outra parte, obtenha a chave da parte ou crie uma nova chave e a compartilhe. (O algoritmo de criptografia é independente de arquitetura e linguagem.) Entretanto, tanto o remetente quanto o destinatário devem saber a chave secreta.
Listagem 3. O código C para a extensão PHP
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mcrypt.h>
char *encode( char *string, int length );
char *decode( char *string, int length );
MCRYPT start() {
MCRYPT td = mcrypt_module_open( "des", NULL, "ecb", NULL );
if ( td == MCRYPT_FAILED ) {
return( MCRYPT_FAILED );
}
if ( mcrypt_enc_self_test( td ) != 0 ) {
return( MCRYPT_FAILED );
}
int i;
char *IV;
int iv_size = mcrypt_enc_get_iv_size( td );
if ( iv_size != 0 ) {
IV = calloc( 1, iv_size );
for ( i = 0; i < iv_size; i++ ) {
IV[ i ] = rand();
}
}
int keysize = mcrypt_enc_get_key_size( td );
char *key = calloc( 1, keysize );
memcpy(key, "12345678", keysize);
i = mcrypt_generic_init ( td, key, keysize, IV );
if ( i < 0 ) {
mcrypt_perror( i );
exit(1);
}
return( td );
}
void end( MCRYPT td ) {
mcrypt_generic_deinit( td );
mcrypt_module_close( td );
}
#define B64_DEF_LINE_SIZE 72
#define B64_MIN_LINE_SIZE 4
/*
** encode 3 8-bit binary bytes as 4 '6-bit' characters
*/
void encodeblock( unsigned char in[3], unsigned char out[4], int len ) {
static const char
cb64[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
out[0] = cb64[ in[0] >> 2 ];
out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? cb64[
((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? cb64[ in[2] & 0x3f ] : '=');
}
char *base64encode( char *input, int size ) {
int i, x, len;
unsigned char in[3], out[4];
char *target = calloc( 1, ( ( size + 2 ) / 3 ) * 4 + 1 );
char *t = target;
for ( x = 0; x < size; ) {
len = 0;
for( i = 0; i < 3; i++ ) {
if ( x < size ) {
len++;
in[i] = input[x++];
}
else {
in[i] = 0;
}
}
if( len ) {
encodeblock( in, out, len );
for( i = 0; i < 4; i++ ) {
*t++ = out[i];
}
}
}
return( target );
}
char *encode( char *string, int length ) {
MCRYPT td = start();
int blocksize = mcrypt_enc_get_block_size( td );
int cryptsize = ( ( length + blocksize - 1 ) / blocksize ) * blocksize;
char *target = calloc( 1, cryptsize );
memcpy( target, string, length );
if ( mcrypt_generic( td, target, cryptsize ) != 0 ) {
fprintf( stderr, "Code failing" );
}
end( td );
char* result = base64encode( target, cryptsize );
free( target );
return result;
}
char *decode( char *string, int length ) {
MCRYPT td = start();
int blocksize = mcrypt_enc_get_block_size( td );
char *block_buffer = calloc( 1, blocksize );
int decryptlength = (length + blocksize - 1) / blocksize * blocksize;
char *target = calloc( 1, decryptlength );
memcpy(target, string, length);
mdecrypt_generic( td, target, decryptlength );
end( td );
free(block_buffer);
return( target );
}
|
Copie e cole o código da Listagem 3 em um novo arquivo denominado secret.c. Sua próxima tarefa é descrever a API da extensão usando a própria sintaxe de SWIG.
Neste ponto do desenvolvimento, é possível criar manualmente uma extensão com base em secret.c. SWIG, entretanto, faz o trabalho pesado para você — com uma quantidade minúscula de pseudocódigo. A Listagem 4 mostra secret.i, um modelo de SWIG para a nova extensão.
Listagem 4. secret.i
%module secret
%{
extern char *encode( char *string, int length );
extern char *decode( char *string, int length );
%}
extern char *encode( char *string, int length );
extern char *decode( char *string, int length );
|
Um almanaque completo de sintaxe e opções de SWIG vai além do escopo deste artigo. É possível encontrar documentação completa on-line (consulte Recursos). Resumidamente, o arquivo SWIG declara o nome da extensão na linha 1. O restante do arquivo declara os pontos de entrada. É isso. A compilação requer poucas etapas: a primeira etapa gera o wrapper para o seu código: $ swig -php secret.i.
SWIG transforma secret.i em secret_wrap.c. As próximas etapas criam e vinculam o código do wrapper, sua extensão e a biblioteca mcrypt. Certifique-se de criar cada arquivo de origem C com a opção -fpic, que gera código independente de posição adequado para uma biblioteca compartilhada.
$ cc -fpic -c secret.c
$ gcc `php-config --includes` -fpic -c secret_wrap.c
$ gcc -shared *.o -o secret.so -lmcrypt
$ sudo cp secret.so `php-config --extension-dir`
|
Os dois primeiros comandos criam a origem C. O terceiro comando cria a extensão PHP. A opção -lmcrypt determina as chamadas na extensão com pontos de entrada na biblioteca mcrypt. O quarto comando coloca a nova extensão PHP no diretório correto para que ela possa ser carregada por PHP.
A etapa final antes de escrever o código PHP é carregar a extensão. Abra o arquivo php.ini apropriado — para Apache ou para a variante de linha de comando de PHP — e adicione uma linha: extension=secret.so.
Se não tiver certeza de qual arquivo php.ini editar, você poderá consultar o próprio PHP. Crie esse programa de três linhas e o execute usando o navegador ou o interpretador interativo:
<?php
phpinfo();
?>
|
Procure uma linha que começa com Loaded Configuration File. Por exemplo, na plataforma de teste usada para criar este artigo, o programa gerou a saída Loaded Configuration File => /etc/php5/cli/php.ini. Consequentemente, o arquivo a ser editado é /etc/php5/cli/php.ini.
Com uma nova extensão brilhante em mãos, agora é possível escrever PHP. A Listagem 5 mostra code.php.
Listagem 5. code.php.
<?php
include("secret.php");
$string = "Double secret probation";
$base64encode = secret::encode($string, strlen($string));
$base64decode = base64_decode($base64encode);
$decode = secret::decode( $base64decode, strlen($base64decode));
echo $decode . "\n";
?>
|
A linha 1 carrega a extensão. A linha 4 codifica a cadeia de caracteres Double secret probation e usa Base64 para transformar a cadeia de caracteres criptografada em caracteres imprimíveis que podem ser transmitidos facilmente por e-mail, digamos. A linha 5 mostra a codificação Base64 para gerar caracteres brutos, e a linha 6 decriptografa uma mensagem secreta para o texto original.
Considerando que você salve o código em coder.php e tem instalado a biblioteca mcrypt no seu sistema em /usr/local/lib, é possível executar o código de exemplo com o comando PHP CLI:
$ LD_LIBRARY_PATH=/usr/local/lib php ./code.php
Double secret probation
|
SWIG é uma excelente forma de reutilizar o código existente. Finalize suas bibliotecas C ou C++ com SWIG e integre o resultado ao seu próximo aplicativo de sistema ou Web. Melhor ainda, SWIG pode gerar wrappers para outras linguagens de script também, exatamente do mesmo arquivo .i. Escreva sua extensão apenas uma vez e a compartilhe com PHP, Perl, Python, Ruby e outros desenvolvedores.
Aprender
-
Saiba mais sobre o gerador de extensão SWIG no site do SWIG.
-
Veja a documentação do SWIG e encontre artigos e tutoriais para tornar o SWIG ainda mais fácil. O projeto também mantém vários wikis.
-
PHP.net é o recurso central dos desenvolvedores de PHP.
-
Consulte a "Lista de leituras recomendadas em PHP."
-
Navegue por todo o conteúdo PHP do developerWorks.
-
Siga o developerWorks no Twitter.
-
Expanda suas habilidades em PHP consultando os recursos de projetos em PHP do IBM developerWorks.
-
Para ouvir entrevistas e discussões interessantes para desenvolvedores de software, consulte os podcasts do developerWorks.
-
Usando um banco de dados com PHP? Consulte Zend Core para IBM, um ambiente de desenvolvimento e produção PHP perfeito, inovador e fácil de instalar que suporta IBM DB2 V9.
-
A comunidade My developerWorks é um exemplo de comunidade geral de sucesso que abrange uma ampla gama de tópicos.
-
Mantenha-se atualizado com os eventos e webcasts técnicos do developerWorks.
-
Consulte as próximas conferências, feiras, webcasts e outros Eventos em todo o mundo que sejam de interesse dos desenvolvedores IBM de software livre.
-
Visite a Zona de software livre do developerWorks para obter informações abrangentes sobre procedimentos, ferramentas e atualizações de projetos que simplificam o desenvolvimento de tecnologias de software livre e a utilização destas com produtos IBM; e não deixe de passar pelos nossos artigos e tutoriais mais populares.
-
Assista e aprenda sobre a IBM e as tecnologias e funções de produtos de software livre com as demos on demand do developerWorks grátis.
Obter produtos e tecnologias
-
Faça o download do SWIG de seu site do projeto.
-
Faça o download do código de origem da biblioteca
mcrypt. -
Inove em seu próximo projeto de desenvolvimento de software livre com o software de avaliação da IBM, disponível para download ou em DVD.
- Faça download das versões de avaliação de produtos IBM ou explore as avaliações on-line no IBM SOA Sandbox e utilize as ferramentas de desenvolvimento de aplicativos e produtos de middleware do DB2®, Lotus®, Rational®, Tivoli® e WebSphere®.
Discutir
-
Participe dos blogs developerWorks e envolva-se na comunidade do developerWorks.
-
Participe do Fórum PHP developerWorks: Desenvolvendo aplicativos PHP com produtos IBM Information Management (DB2, IDS).

Martin Streicher é desenvolvedor autônomo de Ruby on Rails e o editor-chefe anterior da Linux Magazine. Martin é Mestre em Ciência da Computação pela Purdue University e faz programação de sistemas do tipo UNIX desde 1986. Ele coleciona arte e brinquedos.