O nosso módulo foi criado no
Lazarus, mas é possível utilizar qualquer linguagem de programação que gere uma aplicação console e que consiga acessar um banco de dados
Firebird.
Abaixo segue o código fonte comentado. Ele foi escrito originalmente em
Delphi 7. Para este artigo, fizemos a conversão do código para funcionar no Lazarus. Ele poderá ser compilado, sem nenhuma mudança, no Windows.
Para compilar:
- Abra o Lazarus: Desenvolvimento → Lazarus
- Depois clique em: File → New
Na tela que abrir, escolha "Console Application" (fica na pasta Projetos).
Será exibida uma tela solicitando o Título e a o nome da Classe da aplicação. Deixe como está e clique em OK.
Apague todo o código exibido na tela do Lazarus. Copie o código abaixo e cole:
// Inicio do código
program fb;
uses
SysUtils, IBConnection, sqldb, classes;
//exibe uma mensagem de erro na saida padrão e uma descrição de uso do programa
procedure gravaLog(texto, caminho : string; log: tStringList);
begin
log.Add(texto);
log.SaveToFile(caminho);
end;
procedure erro(texto : string);
begin
writeln(output, 'Modulo Firebird para squid');
writeln(output, 'Versao 1.0.0');
writeln(output, 'Desenvolvido por Renato Felix de Almeida');
writeln(output, '');
writeln(output, 'Modo de uso:');
writeln(output, paramstr(0) + ' servidor;banco;login;senha;sql;param');
writeln(output, '');
writeln(output, 'Onde:');
writeln(output, 'Servidor = Endereco do servidor de banco de dados');
writeln(output, 'Banco = Endereco do arquivo do banco de dados');
writeln(output, 'login = Usuario do banco de dados');
writeln(output, 'senha = Senha de acesso ao banco de dados');
writeln(output, 'sql = Consulta sql que sera executada no banco de dados');
writeln(output, 'param = Quantidade de parametros enviados para a consulta');
writeln(output, '');
writeln(output, 'Erro encontrado:');
writeln(output, texto);
writeln(output, '');
writeln(output, 'Pressione ENTER para fechar o programa');
readln(texto);
end;
//esta funçao pega um ítem de uma lista separada por um delimitador
function pegarItem(texto, delimitador : string; item : integer) : string;
var i, j, p : integer;
temp : string;
begin
i := 0;
j := 0;
p := 0;
temp := texto + delimitador;
for i := 1 to length(temp) do
begin
p := pos(delimitador, temp);
if j = item
then
begin
result := copy(temp, 1, p - 1);
exit;
end
else
begin
j := j + 1;
temp := copy(temp, p + 1, length(temp));
end;
end;
end;
function HexParaTexto(texto : string) : string;
var i : integer;
caractere : string;
begin
i := 1;
result := '';
while i <= length(texto)
do
begin
if texto[i] = '%' then
begin
caractere := copy(texto, i + 1, 2);
result := result + char(strToIntDef('$' + caractere, 0));
inc(i);
inc(i);
end
else
result := result + texto[i];
inc(i);
end;
end;
var
dados, parametros, servidor, banco, usuario, senha, consulta : string;
i, cont : integer;
sql : TIBConnection;
sqlDados : tSqlQuery;
transacao: TSQLTransaction;
log : tStringList;
caminho : string;
logar : boolean;
begin
//pegar os parametros enviados pela linha de comando do squid
for i := 1 to paramcount do
parametros := parametros + ' ' + paramstr(i);
parametros := trim(parametros);
//separar os parametros para cada variavel
servidor := pegarItem(parametros, ';', 0);
banco := pegarItem(parametros, ';', 1);
usuario := pegarItem(parametros, ';', 2);
senha := pegarItem(parametros, ';', 3);
consulta := pegarItem(parametros, ';', 4);
cont := strToIntDef(pegarItem(parametros, ';', 5), 0);
caminho := pegarItem(parametros, ';', 6);
logar := trim(caminho) <> '';
if logar then log := tStringList.Create;;
if logar then gravaLog(parametros, caminho, log);
//validar os parametros
if (servidor='') then
begin
erro('Servidor de Banco de dados nao foi informado!');
exit;
end;
if (banco='') then
begin
erro('Caminho do Banco de dados nao foi informado!');
exit;
end;
if (usuario='') then
begin
erro('Usuario do Banco de dados nao foi informado!');
exit;
end;
if (senha='') then
begin
erro('Senha do Banco de dados nao foi informada!');
exit;
end;
if (consulta='') then
begin
erro('Consulta sql nao foi informada!');
exit;
end;
if (cont=0) then
begin
erro('Quantidade de parametros nao foi informada!');
exit;
end;
//criar os objetos para acesso a dados e configurar
sql := tIbConnection.Create(nil);
sql.HostName := servidor;
sql.UserName:= usuario;
sql.Password:= senha;
sql.DatabaseName:= banco;
transacao := TSQLTransaction.Create(sql);
transacao.DataBase := sql;
sql.transaction := transacao;
sqlDados := tsqlQuery.Create(sql);
sqlDados.Transaction := transacao;
sqlDados.DataBase := sql;
sqlDados.SQL.Text:= consulta;
//tentar conectar
try
sql.Open;
except
on e: exception do
begin
erro(e.Message);
if logar then gravaLog('Erro ao abrir banco de dados:' + #13 + e.Message, caminho, log);
exit;
end;
end;
//inciar o loop infinito que vai receber os dados do squid
while true do
begin
rewrite(output);
readln(input, dados);
if logar then gravaLog(dados, caminho, log);
//verificar se o squid esta sendo encerrado
if dados = '' then exit;
//pegar os parametros e passar para a consulta
for i := 0 to cont - 1 do
sqlDados.Params[i].AsString:= HexParaTexto(pegarItem(dados, ' ', i));
//tentar executar a consulta
try
sqlDados.Open;
except
on e : exception do
begin
erro(e.Message);
if logar then gravaLog('Erro ao executar consulta:' + #13 + e.Message, caminho, log);
exit;
end;
end;
//verificar se a consulta retornou dados
if sqlDados.IsEmpty then
begin
writeln(output, 'ERR');
if logar then gravaLog('Retornou ERR', caminho, log);
end
else
begin
if logar then gravaLog('Retornou OK', caminho, log);
writeln(output, 'OK');
end;
sqlDados.Close;
closeFile(output);
end;
end.
// Fim do código
Agora clique em: File → Save
Altere o nome do arquivo para "fb.lpr" e salve na pasta
/fontes.
Agora clique em: Run → Build
Será criado o executável na pasta
/fontes.
Abra novamente um terminal em modo root. Vá para a pasta
/fontes:
# cd /fontes
Dê permissão de execução para o
fb:
# chmod 777 fb
Copie o nosso módulo para a pasta
/usr/lib/squid:
# cp fb /usr/lib/squid
Chegou a hora de fazer um teste para ver se o módulo funcionou perfeitamente.
Conforme dito anteriormente, o Squid envia alguns parâmetros iniciais para o programa. No nosso caso os parâmetros serão assim:
# /usr/lib/squid/fb "servidor;banco;usuario;senha;sql;parametros;log"
Onde:
- servidor → O nome ou endereço IP do servidor de banco de dados Firebird. No nosso caso pode ser utilizado o endereço local: 127.0.0.1;
- banco → O caminho para o banco de dados no servidor. No nosso caso é /dados/dados.fdb;
- usuario → O nome do usuário com permissão de acesso ao banco de dados. Estamos utilizando o sysdba, mas será importante, quando for colocar o sistema em produção, criar um usuário apenas para este fim, com suas permissões limitadas;
- senha → A senha do usuário acima;
- sql → O comando sql que será executado para autenticar os usuários. No nosso caso será:
SELECT 1 FROM USUARIO WHERE USUARIO=:USUARIO AND SENHA=:SENHA;
- parametros → A quantidade de parâmetros que o Squid enviará para o módulo. No caso de autenticação serão sempre dois parâmetros. Para controle de acesso, a quantidade de parâmetros pode ser definida no squid.conf;
- log → O endereço do arquivo de log. Este arquivo é interessante para verificarmos algum problema no funcionamento. Vamos utilizar para a autenticação o arquivo /tmp/fb_auth.log e para a validação o arquivo /tmp/fb_acl.log. Caso o arquivo de log não seja informado, ele não será gerado.
A nossa linha de comando vai ficar assim:
# /usr/lib/squid/fb "127.0.0.1;/dados/dados.fdb;sysdba;masterkey;SELECT 1 FROM USUARIO WHERE USUARIO=:USUARIO AND SENHA=:SENHA;2;/tmp/fb_auth.log"
Obs.: Digite (ou copie e cole) esta linha no terminal e pressione enter.
Se acontecer algum erro, ele será exibido aqui. Caso não aconteça nenhum erro, o sistema ficará aguardando que você digite um usuário e senha. Para testar, vamos digitar o usuário
admin e senha
admin.
Digite:
admin admin (lembre que o nome do usuário é
admin e a senha que escolhemos também é
admin).
Ao pressionar ENTER, o sistema irá responder: OK.
Isto significa que o usuário foi autenticado com sucesso. Digite um usuário e senha inválidos. Verifique que o sistema irá responder com ERR, que significa que a autenticação não foi bem sucedida.
Pronto! Nosso módulo já está compilado e funcionando.
Vamos agora configurar o Squid para trabalhar com nosso módulo.