12 de fevereiro de 2010

Interagindo com Forms HTML em programas Delphi e C++ Builder - parte III

No último post, apresentei um exemplo em que uma página HTML é exibida num programa Delphi, programa este que era capaz de interceptar uma navegação realizada no HTML e controlar os efeitos da navegação. No exemplo, apenas um campo era passado do HTML para o Delphi através de scripts embutidos na página. Agora, pretendo mostrar como capturar a navegação produzida num Form HTML e utilizar todos os campos preenchidos nesse form.

A ideia basica não é muito diferente da apresentada no outro post, já que acionar o botão de submit no Form HTML prepara a URL da mesma maneira que nós preparamos manualmente lá. Tome como exemplo o seguinte Form montado numa página HTML.
<form action="http://event-omega" method="get">
Nome Completo:<input type="text" name="edNome" />
EMail:<input type="text" name="edEmail" />
Detalhes:<textarea name="edDet" />
<input type="image" src="BV_Enviar.jpg" />
</form>

Acionar o botão "submit" nesse Form direciona o navegador à URL informada no parâmetro action da tag FORM. A esta URL são acrescentados os nomes e valores de todos campos existentes no Form - mesmo os escondidos, se houver - , produzindo ao final uma URL com parâmetros similiar à utilizada no post anterior:
http://event-omega/?edNome=nome_informado&edEmail=endere_email&edDet=texto_informado
Mais uma vez, o endereço http://event-omega não existe de fato e serve apenas para marcar posição de maneira que a navegação pode ser detectada corretamente pelo nosso programa. Portanto, o código será bastante parecido com o do post anterior, exceto pelo fato de que agora teremos que extrair mais de um parâmetro da URL - o que pode ser conseguido procurando pelo separador & (E-comercial), conforme pode ser observado na URL no quadro anterior.
if AnsiStartsStr ('http://event-omega/', URL) then
begin
lHtmlVars := TStringList.Create;
try
{ Captura apenas os parâmetros, isto é, o que vem após o sinal de interrogação }
lPos := AnsiPos ('?', URL);
lUrl := AnsiRightStr (URL, Length (URL) - lPos);
ExtractParams(URL, lHtmlVars);
finally
trataForm (lHtmlVars);
FreeAndNil (lHtmlVars);
end;

{ Vou navegar para outra página, cancela esta }
Cancel := true;

{ Navega para a nova página, que informará ao usuário sobre o sucesso de sua operação }
URL := 'file://' + ExtractFilePath (Application.ExeName) + 'bemvindo/BV_Form2.html';
FBrowserForm.Navigate(url);

Aqui eu simplesmente recuperei os parâmetros através de uma função minha (ExtractParams e os exibo num MessageBox. O código da função não é mostrado no quadro mas pode ser encontrado nos fontes para download) do projeto com o exemplo. Eu poderia ter feito um tratamento mais complexo com os parâmetros, incluindo a validação das informações fornecidas pelo usuário e cancelando a navegação se algo não estivesse de acordo com o esperado.

Note que no fim do evento eu redireciono a navegação para uma outra página, que mostrará ao usuário que a operação comandada por ele foi executada com sucesso. Como a URL para a qual estou redirecionando não tem o marcador 'http://event-omega/', eu não preciso verificar no início na operação qual é a página que está sendo tratada - haverá apenas uma que se encaixa no meu marcador. No entanto, em um sistema mais completo envolvendo múltiplas navegações, a verificação de nomes de páginas específicas pode ser obrigatório para evitar comportamentos estranhos.

Um inconveniente nessa abordagem é que os valores dos campos são incluídos na URL com algumas marcações próprias para evitar que a URL se torne inválida. Assim, caracteres em branco são substituídos por símbolos + (mais) e caracteres com acentuação são convertidos para um formato de escape que se inicia com uma % (porcentagem) e contem mais dois caracteres com o código da letra. Há que se tratar manualmente esses valores para obter o texto real entrado pelo usuário.

E se um dos campos do FORM for uma senha que deva ser escondida por razões óbvias ?
Se a navegação estivesse ocorrendo num navegador que exponha a URL numa barra de endereços - como o Internet Explorer, o Firefox e outros navegadores de mercado - isso seria mesmo um problema pois a senha apareceria completamente desprotegida na barra. Mas, no nosso programa a navegação é feita internamente, num modo em que o usuário não sabe tão diretamente qual é a URL onde ele está. Portanto, não haveria um risco de segurança como nos navegadores reais.

Ainda assim, o usuário pode clicar com o botão direito na página e obter esse endereço e, por conseguinte, os nomes e valores de todos os campos. Podemos evitar isso substituindo o método de envio do form HTML de GET para POST. O programa Delphi também terá que ser modificado pois com esse método as informações terão que ser recuperadas no parâmetro PostData do evento OnBeforeNavigate2. Para um exemplo de como obter os dados por este método, veja o site http://delphi.about.com/od/delphitips2007/qt/view_http_post.htm.

O programa de exemplo deste post e o do post anterior foram montados com Delphi 2005 e podem ser baixados aqui.

Mais Informações
Interação com HTML em Delphi - parte I e parte II, HTML FORMs, Download do Exemplo.

4 comentários :

Daniel disse...

posso interagir com o html dessa forma nos navegadores iexplorer, firefox ?

Luís Gustavo Fabbro disse...

Daniel

Este post é sequência de um outro (Interagindo com HTML em programas Delphi e C++ Builder - parte I) em que uso o componente WebBrowser do Delphi. O WebBrowser encapsula chamadas às interfaces do Internet Explorer, isto é, ele carrega o IE e trabalha com ele para enviar e receber as informações desejadas.

Procurei recurso semelhante que usasse o Firefox mas não consegui encontrar.

Leonardo L Procópio disse...

Nesse artigo http://www.hardware.com.br/tutoriais/criando-mini-navegadores/usando-mozilla-vez-ie.html você pode trocar o motor do IE pelo da Mozilla.
Grande abraço!

Luís Gustavo Fabbro disse...

Leonardo

Obrigado por sua contribuição. Não conhecia esse componente - muito interessante ...

Postar um comentário

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.

Observação: somente um membro deste blog pode postar um comentário.