Infra - Linux
Biblioteca VBMcgi: Crie aplicações Web CGI em C++ com acesso ao Bco Interbase/Firebird sem MISTÉRIO
VBMcgi é uma biblioteca multiplataforma para desenvolvimento de aplicações CGI, 100% open-source e muito fácil de ser utilizada. Com este recurso podemo cria aplicações Web usando todo os recursos da linguagem C++ sem misticismo!
por Alessandro de Oliveira FariaIntrodução:
Neste documento, criaremos um CGI que consulta em uma tabela de telefone os numeros solicitados usando os recursos básico do SQL do banco interbase. Após a consulta ser efetuada com sucesso, será gerada uma saída em html, assim permitindo a consulta via web.
Download e instalação:
O download encontra-se no link http://www.vbmcgi.org/VBMcgi_unix_30.zip testado em linux com o compilador gnu C++ 3.2, e também em http://www.vbmcgi.org/VBMcgi_win_30.zip testado em windows com o compilador Microsoft Visual C++ 6 Service Pack 5.
Após o download, crie uma pasta e efetue a descompactação do arquivo obtido, compilação e instalação executando os seguintes comandos:
[root@p233 /]# mkdir lib_cgi [root@p233 /]# cd lib_cgi [root@p233 lib_cgi]# wget http://www.vbmcgi.org/VBMcgi_unix_30.zip [root@p233 lib_cgi]# unzip VBMcgi_unix_30.zip Archive: VBMcgi_unix_30.zip inflating: vbmcgi_global.cpp inflating: vbmcgi_VBMenuHtml.cpp inflating: vbmcgi_VBPageCount.cpp inflating: vbmcgi_VBTableMonth.cpp inflating: make.sh inflating: vbmcgi.so inflating: vblib.h inflating: vbmcgi.h inflating: vbmcgi_VBMenuHtml.h inflating: vbmcgi_VBPageCount.h inflating: vbmcgi_VBTableMonth.h inflating: vblib.cpp inflating: vbmcgi.cpp [root@p233 lib_cgi]# ./make.sh Rebuilding the VBMcgi library 3.0. see http://www.vbmcgi.org compiling static VBMcgi binding static VBMcgi bilding dynamic VBMcgi
Neste momento, acabamos de criar a biblioteca VBMcgi versão estática e dinâmica (libvbmcgi.a e vbmcgi.so). Agora copie estes dois arquivos para um dos diretórios encontrado no arquivo /etc/ld.so.conf ou inclua o path das bibliotecas VBMcgi no arquivo ld.so.conf.
Se você optou em alterar o arquivo ld.so.conf, não esqueça de utilizar o comando ldconfig para atualizar o arquivo ld.so.cache. No meu caso decidi copiar as bibliotecas para o path padrão:
[root@p233 lib_cgi]# cp libvbmcgi.a /usr/local/lib/ [root@p233 lib_cgi]# cp vbmcgi.so /usr/local/lib/
Neste ponto, temos a nossa biblioteca VBMcgi instalada e pronto para ser usada.
Criando o banco de dados:
Não é o objetivo deste tutorial explicar a instalação do banco de dados firebird ou interbase.
A instalação do firebird não tem segredo, pois após o comando rpm, tudo estará devidamente configurado e instalado. Agora se voce deseja instalar o interbase por algum motivo, será encontrado todos os procedimento de instalação deste pacote em http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=180
Segue abaixo o metadata do banco de dados que usaremos neste tutorial. Crie um banco dados com a estrutura abaixo:
SET SQL DIALECT 1; /* CREATE DATABASE "servidor:/servdad/secretaria.gdb" PAGE_SIZE 1024 DEFAULT CHARACTER SET NONE */ /* Table: TELEFONES, Owner: SYSDBA */ CREATE TABLE TELEFONES ( CODIGO INTEGER, NOME VARCHAR(60), DDD VARCHAR(2), TELEFONE VARCHAR(8), TIPO VARCHAR(15) ); /* Index definitions for all user tables */ CREATE INDEX NOME ON TELEFONES(NOME); CREATE GENERATOR SEQ_TELEFONE; SET TERM ^ ; /* Triggers only will work for SQL triggers */ CREATE TRIGGER SEQ_TELEFONE FOR TELEFONES ACTIVE BEFORE INSERT POSITION 0 AS BEGIN NEW.CODIGO = GEN_ID (SEQ_TELEFONE, 1); END ^ COMMIT WORK ^ SET TERM ;^
Volto a mencionar que este tutorial não contempla conceitos básico sobre o banco firebird. Em caso de dúvida na criação do banco, me solicite via e-mail o bco de dados em branco ou consulte na internet como executar a criação do mesmo.
Interface em HTML:
Agora criaremos uma interface em html cujo o objetivo é de enviar para a aplicação CGI, o nome a ser consultado no banco de dados. Após a consulta o CGI irá gerar um o resultado em html. Segue abaixo o código em html:
<body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"> <div id="Layer1">Segue abaixo o resultado visual deste tutorial:
Criando o CGI em C++:
Abaixo encontra-se o código fonte CGI em C++. Em virtude da extensão do código fonte, irei disponibiliza-los para download no fim deste artigo. Para maiores detalhes no aspecto de aprendizado, consulte a documentação do Firebird/Interbase e da biblioteca VBMcgi.
O código abaixo é bem simples. Após receber a variável s_name da interface HTML, O select é executado no banco de dados usando a cláusula where do sql. Concluindo esta operação, o resultado é exibido em html construido pela nossa aplicação.
#include "vbmcgi.h" #include "ibase.h" #include "example.h" #include <fstream> #include <iostream> #include <strstream> using namespace std; #define REGILEN 5 #define NOMELEN 60 #define DDDLEN 2 #define TELEFONELEN 8 #define TIPO 15 #define BUFLEN 512 #define SQL_VARCHAR(len) struct {short vary_length; char vary_string[(len)+1];} int main(void) { VBMcgi cgi; cgi.httpCompleteHeader(); cgi.formDecode(); string mTmpINIstr; char registro[REGILEN + 2]; SQL_VARCHAR(NOMELEN) nome; SQL_VARCHAR(DDDLEN) ddd; SQL_VARCHAR(TELEFONELEN) telefone; SQL_VARCHAR(TIPO) tipo; string mNome; string mDDD; string mTelefone; string mTipo; ISC_QUAD blob_id; isc_blob_handle blob_handle = NULL; short blob_seg_len; char blob_segment[512]; isc_db_handle DB = NULL; isc_tr_handle trans = NULL; long status[20]; isc_stmt_handle stmt = NULL; XSQLDA ISC_FAR * sqlda; long fetch_stat, blob_stat; short flag0 = 0,flag1 = 0; char empdb[128]; char user_name[31]; char password[31]; char sel_str[256]; char ISC_FAR * dpb = NULL, *d, *p, *copy; short dpb_length = 0; long l,sweep_interval = 16384; int grid; string mHTML,mSQL; VBString str_name = cgi.getVarContent("s_name"); strcpy(sel_str,"SELECT codigo as registro,nome,ddd,telefone,tipo FROM telefones "); strcat(sel_str,"WHERE nome LIKE "%"); strcat(sel_str,str_name.c_str() ); strcat(sel_str,"%" ORDER BY nome"); copy = dpb = (char *) malloc(7); p = dpb; *p++ = "\1"; *p++ = isc_dpb_sweep_interval; *p++ = "\4"; l = isc_vax_integer((char ISC_FAR *) &sweep_interval, 4); d = (char *) &l; *p++ = *d++; *p++ = *d++; *p++ = *d++; *p = *d; dpb_length = 7; strcpy(user_name, "SYSDBA"); strcpy(password, "masterkey"); isc_expand_dpb(&dpb, (short ISC_FAR *) &dpb_length, isc_dpb_user_name, user_name, isc_dpb_password, password, NULL); mTmpINIstr = "192.168.0.1:/servdad/secretaria.gdb"; strcpy(empdb,mTmpINIstr.c_str()); if (isc_attach_database(status, 0, empdb, &DB, dpb_length, dpb)) isc_print_status(status); if (isc_start_transaction(status, &trans, 1, &DB, 0, NULL)) { ERREXIT(status, 1) } sqlda = (XSQLDA ISC_FAR *) malloc(XSQLDA_LENGTH(5)); sqlda->sqln = 5; sqlda->sqld = 0; sqlda->version = 1; if (isc_dsql_allocate_statement(status, &DB, &stmt)) { ERREXIT(status, 1) } if (isc_dsql_prepare(status, &trans, &stmt, 0, sel_str, 1, sqlda)) { ERREXIT(status, 1) } sqlda->sqlvar[0].sqldata = (char ISC_FAR *)registro; sqlda->sqlvar[0].sqltype = SQL_TEXT + 1;; sqlda->sqlvar[0].sqlind = &flag0; sqlda->sqlvar[1].sqldata = (char *)&nome; sqlda->sqlvar[1].sqltype = SQL_VARYING + 1; sqlda->sqlvar[1].sqlind = &flag1; sqlda->sqlvar[2].sqldata = (char *)&ddd; sqlda->sqlvar[2].sqltype = SQL_VARYING + 1; sqlda->sqlvar[2].sqlind = &flag1; sqlda->sqlvar[3].sqldata = (char *)&telefone; sqlda->sqlvar[3].sqltype = SQL_VARYING + 1; sqlda->sqlvar[3].sqlind = &flag1; sqlda->sqlvar[4].sqldata = (char *)&tipo; sqlda->sqlvar[4].sqltype = SQL_VARYING + 1; sqlda->sqlvar[4].sqlind = &flag1; if (isc_dsql_execute(status, &trans, &stmt, 1, NULL)) { ERREXIT(status, 1) } std::cout << "<HTML><body>" << std::endl; std::cout<<"<table border="0" width="100%" height="46">"<<std::endl; std::cout<<" <tr>"<<std::endl; std::cout<<" <td align="center" colspan="5" bgcolor="#FF9900"><b>"<<std::endl; std::cout<<" <font color="#FFFFFF" face="Tahoma" size="2">NETi TECNOLOGIA - Agenda Telefonica </font></b></td>"<<std::endl; std::cout<<" </tr>"<<std::endl; std::cout<<" <tr>"<<std::endl; std::cout<<" <td width="6%" align="center"><b><font face="Tahoma" size="1">Registro</font></b></td>"<<std::endl; std::cout<<" <td width="65%" align="center"><b><font face="Tahoma" size="1">Nome</font></b></td>"<<std::endl; std::cout<<" <td width="2%" align="center"><b><font face="Tahoma" size="1">DDD</font></b></td>"<<std::endl; std::cout<<" <td width="12%" align="center"><b><font face="Tahoma" size="1">Telefone</font></b></td>"<<std::endl; std::cout<<" <td width="15%" align="center"><b><font face="Tahoma" size="1">Tipo</font></b></td>"<<std::endl; std::cout<<" <tr>"<<std::endl; grid = 0; while ((fetch_stat = isc_dsql_fetch(status, &stmt, 1, sqlda)) == 0) { registro[sqlda->sqlvar[0].sqllen] = "\0"; mNome = nome.vary_string; if (grid==0) { mHTML = "<TD>"; grid = 1; } else {mHTML = "<TD bgcolor="#FFECC6">"; grid = 0;} std::cout<<mHTML<<"<font face="Tahoma" size="1">"<<registro<<"</font></TD>"<<std::endl; std::cout<<mHTML<<"<font face="Tahoma" size="1">"; printf("%-60.*s ", nome.vary_length, nome.vary_string); std::cout<<"</font></TD>"<<std::endl; std::cout<<mHTML<<"<font face="Tahoma" size="1">"; printf("%-2.*s ", ddd.vary_length, ddd.vary_string); std::cout<<"</font></TD>"<<std::endl; std::cout<<mHTML<<"<font face="Tahoma" size="1">"; printf("%-8.*s ", telefone.vary_length, telefone.vary_string); std::cout<<"</font></TD>"<<std::endl; std::cout<<mHTML<<"<font face="Tahoma" size="1">"; printf("%-15.*s ", tipo.vary_length, tipo.vary_string); std::cout<<"</font></TD><tr>"<<std::endl; } if (fetch_stat != 100L) { ERREXIT(status, 1) } if (isc_dsql_free_statement(status, &stmt, DSQL_close)) { ERREXIT(status, 1) } if (isc_commit_transaction (status, &trans)) { ERREXIT(status, 1) } if (isc_detach_database(status, &DB)) { ERREXIT(status, 1) } free(sqlda); std::cout<<"</table>"<<std::endl; std::cout<<"</body>"<<std::endl; std::cout<<"</HTML>"<<std::endl; return 0; }Para compilarmos o programa, basta executar o seguinte comando abaixo:
[root@p233 cgi]# cg++ sel_usu.cpp -o sel_usu -lvbmcgi -lgds -ldl -lcryptAs bibliotecas a serem utilizadas exceto a vbmcgi, deverão variar de acordo como a versão do banco de dados instalado. Para maiores informações, consulte a documentação.
Após a compilação, devemos copiar os arquivos select.html e logo_tel.jpg (imagem) para o diretório default do apache e o binário sel_usu para o diretório cgi-bin.
Não esqueça de ajustar o caminho do banco de dados no fonte, o IP do servidor e a senha do SYDBA caso não seja masterkey.
Para facilitar a execução deste tutorial, clique aqui para o download dos fontes.
- Login automático com SSH e Automatização da instalação (deploy) e atualização de sites com GitLinux
- Extensão Sun Presentation Minimizer para Broffice.ORGLinux
- Otimização de Desempenho em sistemas GNU/LinuxLinux
- Hardware para sistemas GNU/Linux - Dicas de Desempenho - Parte 3Hardware
- Hardware para sistemas GNU/Linux - Dicas de Desempenho - Parte 2Hardware