You are on page 1of 44

editorial

ndice
3 4 16 37 40 42 notcias tema de capa a programar tecnologias eventos internet

24 meses e a histria de um projecto...


Era uma vez uma comunidade jovem de programao, bastante jovem. Os seus criadores e primeiros membros no eram gurus nem profissionais e muito menos leets . No entanto, no seio desta emanava o desejo de inovar e criar, duas palavras desde h muito apresentadas como a verdadeira matria-prima para os alicerces do edifcio do desenvolvimento deste pas. Da proveio a revista PROGRAMAR Coordenador Adjunto desde a 4 edio, actualmente o Coordenador da Revista Programar. Entrou em 2007 no curso de Engenharia Informtica e de Computadores, no IST.

equipa PROGRAMAR administrao


Rui Maia David Pintassilgo

Miguel Pais

coordenador
Miguel Pais

coordenador adjunto
Joel Ramos

A ideia surgiu, finalmente, como todas surgem, brilhantemente, por David Pintassilgo, e o final de 2005 acabou agitado e no menos atribulado em longas discusses e questes existenciais. Ser que possvel, que conseguimos, que queremos ou sequer podemos? De facto queramos, podamos e conseguiramos, s precisvamos de algum que nos mostrasse tal, um pequeno condensador que na sua descarga poria toda a mquina a trabalhar. Srgio Matias assim nos apresentou quase do nada a 1 edio, uma compilao de alguns tutoriais e artigos espalhados pelo frum, e todos ns admirmos e contemplmos: era de facto possvel! Torna-se interessante constatar que o nosso projecto, apesar de tudo o que de bom dele proveio, no nada do outro mundo, mas apenas um pequeno esboo do que uma comunidade pode fazer quando motivada. Porque no h ento mais projectos destes? Porque que a revista PROGRAMAR a ningum veio fazer concorrncia quando foi lanada? Porque no ousam mais os annimos da web o trabalho sem proveito vista, mas consequentemente tambm o sentimento de gratificao pelo que foi feito, que acaba por ser aplaudido? A verdade que preciso coragem, a mesma que necessria quando tudo parece escurecer depois da ideia brilhante ter surgido mas j se encontra nublada por incertezas e medos de trabalho sem proveito e intil. Que prevalea ento a conscincia de que grandes projectos no necessitam de turbos nem nitros, mas apenas de uma mente sonhadora e um pequeno condensador. Rapidamente continumos, a alegria do j feito levando a melhor organizao, e a revista prosperou com Srgio Santos a coordenar. 9 Edies passaram-se e a renovao trouxe-me a coordenador. Acompanhando a revista e colaborando desde a 1 edio devo dizer que passmos por maus bocados que at agora soubemos superar, no por sermos os melhores, muito profissionais ou sabedores, mas sim porque os nossos utilizadores, redactores e colaboradores assim o permitiram. E enquanto o fizerem, continuaremos. 2 Anos de Revista Programar, parabns!

editor

Pedro Abreu

redaco

Ciro Cardoso Fbio Correia Gaspar Brogueira Joo Brando Joo Rodrigues Mrio Pereira Paulo Cabral

colaboradores
David Ferreira Jos Fontainhas Pedro Teixeira

contacto

revistaprogramar @portugal-a-programar.org

website

www.revista-programar.info

<2>

notcias

15 Semana Informtica

Os estudantes da Licenciatura em Engenharia Informtica e de Computdores (LEIC) do Insituto Superior Tcnico, em colaborao com o Departamento de Engenharia Informtica (DEI) e o Ncleo Estudantil de Informtica do I.S.T. (NEIIST), tm vindo a organizar anualmente, desde 1993, a Semana Informtica do Instituto Superior Tcnico. Este ano, a 15 Semana Informtica ter lugar de 10 a 14 de Maro. O evento tem como principais objectivos a divulgao e debate relativamente s notcias no mercado das Tecnologias de Informao que marcam a realidade nacional e internacional e as prprias TI, em geral, que esto cada vez mais presentes no nosso dia-a-dia. A Semana Informtica ter um ciclo de apresentao e debate, onde iro ser apresentados diversos projectos de pesquisa, desenvolvimento e Cincia de Computadores em geral. Uma exposio de tecnologia de computadores, onde novos produtos e tecnologias na rea das TI estaro expostos, e o LEIC Jovem, um evento dedicado a estudantes do Ensino Secundrio que procura divulgar informao sobre Cincia de Computadores e Sistemas de Informao, sero ainda outras atraces de relevo nesta Semana Informtica. Quanto aos oradores convidados, o evento deste ano contar com presena do professor Professor Andrew Tanenbaum, Raymond Chen (Microsoft) e Shiki Okasaka (Google). Resta acrescentar que o evento gratuito e aberto a todos os interessados.

PJ alerta compradores online


Para evitar que os casos de burla online continuem a aumentar, a Polcia Judiciria lanou um alerta pblico onde indica quais os principais cuidados que o consumidor deve ter quando compra atravs da Internet. Tendo em conta que os utilizadores no tm contacto pessoal com os vendedores dos produtos, nem conseguem ver os bens que querem adquirir ao vivo, a PJ frisa que os consumidores devero optar sempre por uma loja segura, certificada, recomendada ou que represente electronicamente um espao comercial que exista fisicamente. H ainda que verificar em todos os casos se o site possui os dados essenciais da loja para que, caso seja necessrio, o utilizador entre em contacto com a marca. As autoridades recomendam ainda que o utilizador digite sempre o endereo para o site respectivo ao invs de clicar numa ligao fornecida, evitando assim o reencaminhamento para destinos falsos ou indesejveis. Por fim, os consumidores devem evitar divulgar dados pessoais e de contas bancrias e devero confirmar se o produto adquirido, quando entregue, corresponde ao que foi encomendado e se os valores cobrados esto certos.

Microsoft reduz preo do Windows Vista


Desde 1 de Maro, o Windows Vista pode ser adquirido a um preo cerca de 40% inferior ao preo anterior. De forma a fomentar o uso e promover uma maior adeso dos utilizadores a este sistema operativo, a Microsoft reduziu o seu preo a nvel mundial. Esta reduo afectou toda a gama de verses do produto para particulares - as edies Windows Vista Home Basic, Windows Vista Home Premium e Windows Ultimate, assim como a actualizao Windows Vista SP1 introduzida no incio de Fevereiro.

<3>

tema de capa

? representa zero ou uma ocorrncia de algo.

Assinaturas Digitais XML

O seguinte XML descreve uma assinatura segundo a especificao W3C, de acordo com as regras descritas. <Signature ID?> <SignedInfo> <CanonicalizationMethod/> <SignatureMethod/> (<Reference URI?> (<Transforms>)? <DigestMethod> <DigestValue> </Reference>)+ </SignedInfo> <SignatureValue> (<KeyInfo>)? (Object ID?)* </Signature>

Desde a sua normalizao pelo W3C, a linguagem XML tem vindo a ser adoptada por um nmero crescente de produtores de software como formato base para os documentos utilizados pelas aplicaes que desenvolvem. O crescendo de utilizao de documentos neste formato revelou o interesse em definir mecanismos que lhes permitissem aportar as caractersticas de segurana (origem, no-repdio e integridade) adequadas a cenrios de utilizao mais exigentes. Para colmatar essa lacuna, o W3C definiu posteriormente a norma XMLDSIG. Neste artigo vamos-nos debruar essencialmente no desenvolvimento em C# de uma pequena API para assinar digitalmente documentos XML.

Dissecando a especificao XMLDSIG


O elemento Signature o construtor primrio da assinatura, de acordo com a especificao W3C. A assinatura pode ser envelop ou enveloped pela informao que est a ser assinada, ou por outro lado pode referenciar informao que no consta do ficheiro XML, e neste caso ser uma assinatura detached. As assinaturas detached so muito teis para assinar ficheiros externos ao XML, relembro que no existe qualquer limitao sobre o que se est a assinar.

Introduo e Enquadramento
De acordo com o RFC2828 uma assinatura digital define-se como sendo um valor calculado com um algoritmo criptogrfico e anexado ao objecto de dados de tal forma que se possa usar essa assinatura para verificar a autenticidade e integridade dos dados. A forma de funcionamento de uma assinatura digital XML extremamente fivel. Respeitando escrupulosamente a terceira regra fundamental da criptografia, a integridade, a assinatura no s assegura que a pessoa que assinou o documento de facto quem se espera, como tambm que o mesmo se manteve inalterado em todo o seu percurso digital at ao momento em que chegou ao destinatrio. Relembrando noes bsicas de criptografia assimtrica, uma mensagem cifrada com uma chave pblica apenas pode ser decifrada com a correspondente chave privada.

- Etapas de uma assinatura


SignedInfo O elemento SignedInfo representa a informao que est actualmente assinada. Esta informao processada sequencialmente por vrias etapas no processo de assinatura. Canonicalization O elemento CanonicalizationMethod contm o algoritmo que foi usado para canonizar/estruturar a informao, numa forma comum reconhecida por todos os intervenientes no processo. Este processo extremamente importante. A canonizao pode definir regras como a definio de um standard para o EOF, remoo de comentrios ou outra qualquer manipulao de um documento assinado que possamos necessitar.
Reference/Transform

Percebendo o W3C XML Digital Signature


A especificao XML responsvel pela definio da informao que usada na verificao de certificados digitais. Assinaturas digitais em XML so representadas pelo elemento XML Signature que contm uma estrutura com as seguintes regras: * representa zero ou mais ocorrncias de algo. + representa uma ou mais ocorrncias de algo.

<4>

tema de capa

O elemento Reference identifica o recurso que vai ser assinado e os algoritmos para processar a informao. Estes algoritmos esto enunciados no elemento Transform e podem incluir operaes de Canonizao, encoding/decoding, compresso, ou at XPATH ou transformaes XSLT. O elemento Reference pode conter vrios elementos Transform. Nota: O elemento Reference contm um atributo opcional URI . A incluso de um URI numa assinatura opcional se a assinatura possuir apenas um elemento Reference.
DigestMethod/DigestValue

Enveloping: O documento e a assinatura esto contidos num envelope XML. <signature> <document> ...</document> </signature>

Relembrar Conceitos
Antes de focar a fase de implementao, necessrio rever alguns aspectos importantes da criptografia, bem como certos aspectos organizacionais presentes no sistema operativo Windows. Comecemos pela Criptografia

O elemento DigestMethod representa o algoritmo aplicado informao aps passar pelo processo de transformao, gerando um valor nico representado pelo elemento DigestValue. O DigestValue uma aplicao ao resultado dos processos de Canonizao e transformao, sem qualquer referncia directa informao a ser assinada. KeyInfo O elemento KeyInfo opcional e pode conter a assinatura pblica do autor para permitir a verificao da autenticidade do documento automtica.

Certificados Digitais
Um certificado digital um arquivo de computador que contm um conjunto de informaes referentes entidade para o qual o certificado foi emitido (seja uma empresa, pessoa fsica ou computador), mais a chave pblica referente e a chave privada que acredita-se ser de posse unicamente da entidade especificada no certificado.

- A anatomia de um certificado X.509


Um certificado padro X.509 contm os seguintes campos: Verso - Contem a verso do certificado X.509, actualmente verso 3 Nmero de srie - Todo certificado possui um, no globalmente nico, mas nico no mbito de uma AC, ac LCRs usam o nmero de serie para apontar quais certificados se encontram revogados. Tipo de algoritmo - Contem um identificador do algoritmo criptogrfico usado pela AC para assinar o certificado juntamente com o tipo de funo de hash criptogrfica usada no certificado Nome do titular - Nome da entidade para o qual o certificado foi emitido Nome do emitente - Autoridade Certificadora que emitiu/assinou o certificado Perodo de validade - Mostra o perodo de validade do certificado no formato No antes e No depois (Ex. No antes de 05/03/2006 - 14:35:02 No depois de 05/03/2007 14:03:20) Informaes de chave pblica da entidade

- Tipos de assinaturas XMLDSIG


As assinaturas XMLDSIG podem ser aplicadas em trs formas bsicas: Detached : O documento XML a ser assinado e a assinatura esto em dois ficheiros distintos, sendo que esta tem uma referncia (URI) ao documento que se prope a assinar.

<signature> ... </signature>

Enveloped: O documento XML e a assinatura surgem no mesmo ficheiro de uma forma sequencial.

<document> <signature> ...</signature> </document>

<5>

tema de capa

Algoritmo de chave pblica Chave pblica Assinatura da AC - A garantia que a AC prov sobre a veracidade das informaes contidas neste certificado de acordo com as polticas da AC Identificador da chave do titular - uma extenso do X.509 que possui um identificador numrico para a chave pblica contida neste certificado, especialmente til para que programas de computador possam se referir a ela Identificador da chave do emitente - A mesma ideia mencionada anteriormente, s que se referindo a chave pblica da AC que emitiu o certificado Atributos ou extenses - A vasta maioria dos certificados X.509 possui campos chamados extenses (OID) que provem algumas Informaes extra, como registos adicionais do titular e do emitente, especificaes de propsito do certificado, etc.

Len Adleman, que inventaram este algoritmo at data (2005), a mais bem-sucedida implementao de sistemas de chaves assimtricas, e fundamenta-se em Teorias Clssicas dos Nmeros. considerado dos mais seguros. Foi tambm o primeiro algoritmo a possibilitar cifra e assinatura digital, uma das grandes inovaes em criptografia de chave pblica.

KeyStore
Uma KeyStore uma base de dados de chaves. As chaves privadas numa KeyStore possuem uma cadeia de certificados associada, que possibilita a autenticao correspondente chave pblica. Uma KeyStore tambm possui certificados de entidades confiveis. O Sistema operativo Windows possui uma KeyStore prpria, onde so armazenados todos os certificados instalados. Existem tambm uma API embebida no Sistema Operativo que permite fazer a ponte entre SmarCards com certificados digitais, desde que o hardware possua um leitor de smartcards.

Criptografia de chave pblica


A criptografia de chave pblica ou criptografia assimtrica um mtodo de criptografia que utiliza um par de chaves: uma chave pblica e uma chave privada. A chave pblica distribuda livremente para todos os correspondentes via email ou outras formas, enquanto a chave privada deve ser conhecida apenas pelo seu dono. Num algoritmo de criptografia assimtrica, uma mensagem cifrada com a chave pblica pode somente ser decifrada pela sua chave privada correspondente. Do mesmo modo, uma mensagem cifrada com a chave privada pode somente ser decifrada pela sua chave pblica correspondente. Os algoritmos de chave pblica podem ser utilizados para autenticidade e confidencialidade. Para confidencialidade, a chave pblica usada para cifrar mensagens, com isso apenas o dono da chave privada pode decifr-la. Para autenticidade, a chave privada usada para cifrar mensagens, com isso garante-se que apenas o dono da chave privada poderia ter cifrado a mensagem que foi decifrada com a chave pblica.

Programming, Programming, Program...


Requisitos
Para Prosseguir necessrio termos instalado no nosso computador uma licena do Windows XP ou superior, com a Framework .NET v2.0. Ajuda possurmos tambm uma licena do Visual Studio 2005, se bem que no obrigatrio pois existem alternativas OpenSource bastante completas na WWW.

Gerao de um Certificado Digital


Vamos gerar um ficheiro PKCS#12. Um ficheiro PKCS12 um formato que permite o armazenamento de chaves privadas juntamente com o certificado de chave pblica, protegidos por uma palavra-chave. Este ficheiro servir de base para os testes que vamos produzir ao longo do desenvolvimento. No obrigatria a gerao deste ficheiro. Podemos criar em RunTime um certificado e exportar as respectivas chaves pblicas e privadas. Este passo apenas um exerccio didctico.

RSA
RSA um algoritmo de cifra de dados, que deve o seu nome a trs professores do Instituto MIT (fundadores da actual empresa RSA Data Security, Inc.), Ron Rivest, Adi Shamir e

- Criao das chaves


makecert.exe -sv MyKey.pvk -n CN=P@P MyKey.cer

<6>

tema de capa

Ser-vos- pedida uma palavra-chave para a criao da chave privada.

{ get { return m_rsa; } } #endregion #region Constructors

- Criao do PKCS#12
pvk2pfx.exe -pvk MyKey.pvk -spc MyKey.cer -pfx cert.pfx -po pwd

Este aplicativo permite criar o ficheiro cert.pfx , protegido pela password pwd.

Classe KeyManager.cs
A classe KeyManager.cs servir de ponte para a gerao/carregamento de chaves publicas/privadas/Certificados, usando RSA. bastante simples alterar a classe para podermos usar tambm o DSA, mas deixo isso vossa curiosidade e investigao. tambm possvel interligar esta classe com a KeyStore do Windows ou simplesmente gerar uma chave pblica/privada e export-las para XML. using System; using System.Collections.Generic; using System.Text; #region Crypt using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certif icates; #endregion namespace AsynXmlCrypt { public sealed class KeyManager { public static int KeySize = 1024; // Tamanho da chave #region Private Properties private RSACryptoServiceProvider m_rsa = null; // Provider RSA #endregion #region Public Properties public RSACryptoServiceProvider KeyProvider // Propriedade que exporta o provider

// Inicializa o Provider com uma chave de tamanho igual KeySize public KeyManager(){ m_rsa = new RSACryptoServiceProvider (KeySize); }

// Inicializa o Provider com um ficheiro public KeyManager(string filename) { m_rsa = new RSACryptoServiceProvider (KeySize); _loadKey(m_rsa, filename); } // Inicializa o Provider com um ficheiro XML de chave public e um ficheiro XML de chave privada public KeyManager(string publicKeyFilename, string privateKeyFilename) { m_rsa = new RSACryptoServiceProvider (KeySize); LoadPublicKeyFromXmlFile (publicKeyFilen ame); LoadPrivateKeyFromXmlFile (privateKeyFil ename); } // Inicializa o Provider com um certificado public KeyManager(X509Certificate2 certificate) { if (certificate == null) throw new Exceptions.KeyManagerException("certifi cate not initialized" );

<7>

tema de capa

if (certificate.HasPrivateKey) m_rsa = certificate.PrivateKey as RSACryptoServiceProvider; else throw new Exceptions.KeyManagerException("certifi cate does not contains the PrivateKey "); }

false, Encoding.UTF8)) { sw.WriteLine(Key); sw.Close(); } } #endregion #region LOAD // Carrega uma chave privada de um ficheiro XML public void LoadPrivateKeyFromXmlFile (string filename) { _loadKey(m_rsa, filename); } // Carrega uma chave publica de um ficheiro XML public void LoadPublicKeyFromXmlFile (string filename) { _loadKey(m_rsa, filename); } private void _loadKey(RSACryptoServiceProvider rsa, string filename) { if (rsa == null) throw new Exceptions.ServiceProviderException ("Se rvice Provider NULL Exception" ); if (!System.IO.File.Exists(filename)) throw new System.IO.FileNotFoundException (filenam e); using (System.IO.StreamReader sr = new System.IO.StreamReader(filename, Encoding.UTF8)) { string Key = sr.ReadToEnd(); sr.Close(); rsa.FromXmlString(Key); }

#endregion #region SAVE // Exporta a chave privada para um ficheiro XML public void SavePrivateKeyToXmlFile( string filename, bool overwrite) { _saveKey(m_rsa, filename,overwrite , true); } // Exporta a chave publica para um ficheiro XML public void SavePublicKeyToXmlFile(string filename, bool overwrite) { _saveKey(m_rsa, filename,overwrite , false); } private void _saveKey(RSACryptoServiceProvider rsa, string filename, bool overwrite, bool privateKey){ if (rsa == null) throw new Exceptions.ServiceProviderException("Se rvice Provider NULL Exception"); if (System.IO.File.Exists(filename) && !overwrite) return; string Key = rsa.ToXmlString(privateKey); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filename,

<8>

tema de capa

} #endregion } }

Como se pode verificar pela anlise do cdigo fonte, auxiliados pela classe que construmos, a gerao de um par de chaves passa a ser de codificao simples/trivial.

- Lendo um certificado PKCS#12


O seguinte exemplo ilustra a forma de carregar um certificado PKCS#12 para posteriormente assinar documentos. Podemos tentar carregar o certificado gerado previamente no ponto Gerao de um Certificado Digital.

Utilizaes da classe KeyManager.cs - Gerando um par de chaves


O seguinte exemplo ilustra a forma de gerar um par de chaves (1024 bits) para posteriormente assinar documentos. As Chaves so posteriormente guardadas em ficheiros XML. Normalmente no muito usual guardar as chaves em ficheiros XML, mas nada impede a um utilizador, guardar e distribuir a sua chave pblica, para assinatura e verificao. using System; using System.Collections.Generic; using System.Text; #region Crypt using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certif icates; using AsynXmlCrypt; #endregion static class Program{ [STAThread] static void Main() {

using System; using System.Collections.Generic; using System.Text; #region Crypt using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certif icates; using AsynXmlCrypt; #endregion static class Program{ [STAThread] static void Main() { AsynXmlCrypt.KeyManager km = new AsynXmlCrypt.KeyManager( new X509Certificate2 @"c:/cert.pfx", "pwd") ); } }

AsynXmlCrypt.KeyManager.KeySize = 1024; AsynXmlCrypt.KeyManager km = new AsynXmlCrypt.KeyManager(); km.SavePublicKeyToXmlFile (@"c:/Publica. xml",true); km.SavePrivateKeyToXmlFile (@"c:/Privada .xml", true); } }

- Lendo um certificado da KeyStore do Windows


O seguinte exemplo ilustra a forma de carregar um certificado da KeyStore do Windows para posteriormente assinar documentos. O Cdigo genrico e num caso real ser necessrio filtrar o certificado a extrair da KeyStore.

using System; using System.Collections.Generic; using System.Text; #region Crypt

<9>

tema de capa

using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certif icates; using AsynXmlCrypt; #endregion static class Program{ [STAThread] static void Main() { // Store Current User X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); X509Certificate2 cc = null; foreach (X509Certificate2 c in store.Certificates){ // Vai buscar o primeiro cc = c; break; } store.Close(); //Carrega o par de chaves do certificado. AsynXmlCrypt.KeyManager km = new AsynXmlCrypt.KeyManager(cc); } }

using System; using System.Collections.Generic; using System.Text; #region Crypt using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certif icates; using AsynXmlCrypt; #endregion static class Program{ [STAThread] static void Main() { // Leitura do certificado :) AsynXmlCrypt.KeyManager km = new AsynXmlCrypt.KeyManager( new X509Certificate2 @"c:/cert.pfx", "pwd") ); // Leitura de um documento (Test.XML) XmlDocument xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; xmlDoc.Load("./test.xml"); XML // Ok, vamos assinar o documento SignXml(xmlDoc, km);

Numa aplicao real, variantes deste cdigo sero talvez aquelas que faro mais sentido de ser usadas j que normalmente pretendemos usar certificados que estejam instalados no nosso Sistema Operativo.

// Gravar o documento. xmlDoc.Save("./SignedTest.xml"); } public static void SignXml(XmlDocument Doc, AsynXmlCrypt.KeyManager Key) { if (Doc == null) throw new ArgumentException("Empty XML Document Object ?");

Assinar um documento XML


Vamos agora assinar um documento XML usando o certificado Cert.pxf, e recorrendo classe KeyManager.cs .

<10>

tema de capa

if (Key == null) throw new ArgumentException("Empty KeyManager Provider ?"); SignedXml signedXml = new SignedXml(Doc); // Passamos a chave :) signedXml.SigningKey = Key.KeyProvider; // Criamos uma referencia para a assinatura Reference reference = new Reference(); reference.Uri = ""; // Adicionamos uma transformao enveloped referencia. XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform (); reference.AddTransform(env); // Adicionamos a referncia ao objecto SignedXml. signedXml.AddReference(reference); // Assinamos. signedXml.ComputeSignature(); // Extraimos a representao da assinatura em XML XmlElement xmlDigitalSignature = signedXml.GetXml(); // Juntamos a assinatura XML ao documento. Doc.DocumentElement.AppendChild(Doc.Imp ortNode(xmlDigitalSignature, true)); //Et Voil :) } } Com este pedao de cdigo, criamos um documento SignedTest.xml com uma assinatura do tipo Enveloped. O resultado do ficheiro assinado ser algo do gnero

<Signature xmlns= "http://www.w3.org/2000/09/xmldsi g#"> <SignedInfo> <CanonicalizationMethod Algorithm= "http://www.w3.org/TR/2001/RE C-xml-c14n-20010315" /> <SignatureMethod Algorithm= "http://www.w3.org/2000/09/xm ldsig#rsa-sha1" /> <Reference URI= ""> <Transforms> <Transform Algorithm= "http://www.w3.org/2000/09/xm ldsig#enveloped-signature" /> </Transforms> <DigestMethod Algorithm= "http://www.w3.org/2000/09/xm ldsig#sha1" /> <DigestValue> 9H/rQr2Axe9hYTV2n/tCp+ 3UIQ Q=</DigestValue> </Reference> </SignedInfo> <SignatureValue> Mx4psIy9/UY+u8QBJRDrwQW KRaCGz0WOVftyDzAe6WHAFSjMNr7qb2ojq9kdip T8 Oub5q2OQ7mzdSLiiejkrO1VeqM/ 90yEIGI4En6K EB6ArEzw+iq4N1wm6EptcyxXx M9StAOOa9ilWYqR9Tfx3SW1urUIuKYgUitxsONi UHBVaW6HeX51bsXoTF++4ZI+D jiPBjN4HHmr0cbJ6BXk91S27ffZIfp1Qj5nL9on FLUGbR6EFgu2luiRzQbPuM2tP XxyI7GZ8AfHnRJK28ARvBC9oi+O1ej20S79CIV7 gdBxbLbFprozBHAwOEC57YgJc x+YEjSjcO7SBIR1FiUA7pw== </SignatureValu e> </Signature>

A prxima etapa ser a verificao/validao de um documento XML assinado.

Validar um documento assinado


A verificao de um documento previamente assinado uma tarefa relativamente simples. O cdigo fonte inicial (leitura do ficheiro, e chaves) de alguma forma idntico ao do ponto anterior.

<11>

tema de capa

using System; using System.Collections.Generic; using System.Text; #region Crypt using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certif icates; using AsynXmlCrypt; #endregion static class Program{ [STAThread] static void Main() { // Leitura do certificado :) AsynXmlCrypt.KeyManager km = new AsynXmlCrypt.KeyManager( new X509Certificate2 @"c:/cert.pfx", "pwd") ); // Leitura de um documento XML coma respectiva assinatura (SignedTest.XML) XmlDocument xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; xmlDoc.Load("./SignedTest.xml"); // Ok, vamos verificar a validade do ficheiro XML bool result=VerifyXml(xmlDoc, km); if (result) Console.Writeln("Ficheiro Valido!"); else Console.Writeln("Ficheiro Invalido!"); } public static void VerifyXml(XmlDocument Doc, AsynXmlCrypt.KeyManager Key) {

if (Doc == null) throw new ArgumentException("Empty XML Document Object ?"); if (Key == null) throw new ArgumentException("Empty KeyManager Provider ?"); // Instanciao/Inicializao SignedXml signedXml = new SignedXml(Doc); //Neste ponto vamos verificar quantos elementos (ASSINATURAS) possui o ficheiro XML. XmlNodeList nodeList = Doc.GetElementsByTagName("Signature"); //O documento XML no possui nenhuma assinatura!! //Decidimos lanar uma excepo . if (nodeList.Count <= 0){ throw new CryptographicException ("Failed: No Sig was found in the document." ); } //O documento XML possui mais que uma assinatura!! //No contexto actual, no possuimos KnowHow suficiente para tratar esta variante, //pois queremos verificar uma relao de 1 para 1, ou seja, um documento assinado por uma chave. //Decidimos lanar uma excepo . if (nodeList.Count >= 2){ throw new CryptographicException ("Failed: More that one sig was found for the document."); }

//Ok, se chegamos ate aqui, ento estamos prontos para verificar a assinatura. //Carregamos o Elemento XML que contm a assinatura para o respectivo objecto

<12>

tema de capa

//que faz a verificao. Reference(); signedXml.LoadXml((XmlElement)nodeList[ 0]); //Retornamos o resultado da verificao. return signedXml.CheckSignature(Key.KeyProvide r); } } O cdigo fonte anterior genrico e serve para verificar a validade de um documento XML, com uma assinatura (Detached, Enveloped ou Enveloping). Verificamos tambm que necessrio termos na nossa posse a chave pblica (neste exemplo temos ambas, j que passamos o certificado), para verificar a validade do documento. Numa situao real, muitas das vezes no temos acesso chave pblica do autor e mesmo assim temos a necessidade de verificar a validade de um documento. Fazendo um pequeno upgrade ao cdigo de assinar, podemos incluir a nossa chave pblica na assinatura, libertando o nosso cdigo de verificao para uma verso mais light e eficiente.

Reference reference = new reference.Uri = ""; // Adicionamos uma transformao enveloped referencia. XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform(); reference.AddTransform(env); // Adicionamos a referencia ao objecto SignedXml. signedXml.AddReference(reference); //BEGIN UPGRADE //Inserimos a nossa chave pblica na prpria assinatura para posterior verificao. #region KeyInfo KeyInfo keyInfo = new KeyInfo(); keyInfo.AddClause(new RSAKeyValue((RSA)Key.KeyProvider)); signedXml.KeyInfo = keyInfo; #endregion

- Upgrade da assinatura
public static void SignXml(XmlDocument Doc, AsynXmlCrypt.KeyManager Key) { if (Doc == null) throw new ArgumentException("Empty XML Document Object ?"); if (Key == null) throw new ArgumentException("Empty KeyManager Provider ?"); SignedXml signedXml = new SignedXml(Doc); // Passamos a chave :) signedXml.SigningKey = Key.KeyProvider; // Criamos uma referencia para a assinatura

//END UPGRADE // Assinamos. signedXml.ComputeSignature(); // Extraimos a representao da assinatura em XML XmlElement xmlDigitalSignature = signedXml.GetXml(); // Juntamos a assinatura XML ao documento. Doc.DocumentElement.AppendChild(Doc.Imp ortNode(xmlDigitalSignature, true)); //Et Voil :) }

<13>

tema de capa

- Upgrade da funo de verificao


public static void VerifyXml(XmlDocument Doc) { if (Doc == null) throw new ArgumentException("Empty XML Document Object ?"); if (Key == null) throw new ArgumentException("Empty KeyManager Provider ?"); // Instanciao/Inicializao SignedXml signedXml = new SignedXml(Doc); //Neste ponto vamos verificar quantos elementos (ASSINATURAS) possui o ficheiro XML. XmlNodeList nodeList = Doc.GetElementsByTagName("Signature"); //O documento XML no possui nenhuma assinatura!! //Decidimos lanar uma excepo . if (nodeList.Count <= 0){ throw new CryptographicException("Failed: No Sig was found in the document."); } //O documento XML possui mais que uma assinatura!! //No contexto actual, no possuimos KnowHow suficiente para tratar esta variante, //pois queremos verificar uma relao de 1 para 1, ou seja, um documento assinado por uma chave. //Decidimos lanar uma excepo. if (nodeList.Count >= 2){ throw new CryptographicException("Failed: More that one sig was found for the document."); }

//Ok, se chegamos ate aqui, ento estamos prontos para verificar a assinatura. //Carregamos o Elemento XML que contm a assinatura para o respectivo objecto que //faz a verfificao. signedXml.LoadXml((XmlElement)nodeList[ 0]); //BEGIN UPGRADE //Tentamos extrair a chave publica da assinatura embebida. //Se no conseguirmos ento no podemos atestar a //validade do documento retornando FALSO. KeyInfo keyInfo = signedXml.KeyInfo; if (keyInfo.Count == 0) return false ; //END UPGRADE //Retornamos o resultado da verificao com a assinatura embebida. return signedXml.CheckSignature(); }

Assim, e com base neste upgrade, no necessitamos de passar nenhuma chave pblica para verificar a validade de um certo documento XML assinado, como podemos verificar no prximo pedao de cdigo:

static void Main() { // Leitura de um documento XML coma respectiva assinatura (SignedTest.XML) XmlDocument xmlDoc = new XmlDocument(); xmlDoc.PreserveWhitespace = true; xmlDoc.Load("./SignedTest.xml"); // Ok, vamos verificar a

<14>

tema de capa

validade do ficheiro XML bool result=VerifyXml(xmlDoc); if (result) Console.Writeln("Ficheiro Valido!"); else Console.Writeln("Ficheiro Invalido!"); }

Este artigo, embora exiga conceitos mais avanados de criptografia, de certa forma introdutrio e fornece aos leitores boas bases para investigao e desenvolvimento de novas funcionalidades tais como : Mltiplas Assinaturas num documento, assinaturas com TimeStamp, Assinar apenas certos elementos XML, Cifrar/Decifrar Documentos/elementos XML baseado na nossa chave pblica/privada, etc.

Concluses
O XMLDSIG de grande utilidade para a indstria, a sua aplicao passa por as mais variadas reas. Podemos integrar esta tecnologia com as mais diversas reas, tais como, WebServices para garantir a fiabilidade da transmisso de dados, podemos tambm usa-la para criar sistemas de proteco de software, aplica-la na troca de dados entre diferentes entidades que exijam garantias de autenticidade e no repudio da informao(O SAFT-PT por exemplo), Facturao electrnica, etc. As aplicaes so inmeras, e tudo depende da imaginao e criatividade de quem desenvolve, integra e arquitecta sistemas.

Nota: Como este documento um artigo didctico, no estou a fazer o devido tratamento das excepes que podem ocorrer no funcionamento do software, o cdigo aqui desenvolvido no est pronto para deploy em ambientes de produo como devem todos perceber.

Reflexes...
Tenham em ateno que a assinatura refere-se ao documento XML, assim se alterarmos o contedo do documento XML a verificao falhar. Mas se alterarmos o Elemento Signature; Incluirmos dados por exemplo sem alterar o contedo XML que assinamos, o processo de verificao e validao do documento funcionar correctamente. Perguntam os leitores: Mas esta falha no invalida de certa forma a autenticidade do documento? No, porque assinamos um documento (XML DATA). Alm de que, no uma falha, podemos corrigir esta distraco adicionando elementos ao objecto Signature que verifiquem a autenticidade da prpria assinatura.

Bibliografia
http://www.w3.org/TR/xmldsig-core/ http://msdn2.microsoft.com http://www.xml.com/pub/a/2001/08/08/xmldsig.html

Paulo Cabral Engenheiro de Sistemas e Informtica. Tem 10 anos de experincia na rea, estando actualmente inserido num projecto de I&D numa instituio de ensino superior.

Paulo Cabral

<15>

a programar

Introduo ao SOAP

dividido em duas partes, um Header (cabealho) e um Body (corpo). O SOAP Header aparece imediatamente a seguir tag XML que abre o envelope, mas o seu uso opcional.

O SOAP (Simple Object Access Protocol) um protocolo concebido para trocar informao estruturada num ambiente descentralizado. Usa as tecnologias de XML para definir uma estrutura de mensagens extensveis que podem ser trocadas sobre uma variedade de protocolos subjacentes. A estrutura foi projectada para ser independente de qualquer linguagem de programao, modelo ou outra implementao especfica. O SOAP habilita aplicaes-cliente a ligarem-se a servios remotos e invocarem mtodos desses servios. Assim, uma aplicao-cliente pode adicionar um servio disponibilizado na Web, ao seu feature set, localizar o servio SOAP apropriado e invocar o mtodo correcto. Ao contrrio de outras arquitecturas distribudas, como o COM/COM+ e o CORBA, o SOAP meramente um protocolo de comunicao. Para conseguirmos comparar com essas arquitecturas temos que implementar o protocolo SOAP como uma arquitectura distribuda. O SOAP oferece: Mecanismo para definir a unidade de comunicao, Mecanismo para lidar com erros, Mecanismo de extenso que permite evoluo, Mecanismo entre as mensagens SOAP e o HTTP, representar tipos de dados em XML. O SOAP pode ser usado numa variedade de sistemas de mensagens e protocolos. As mensagens SOAP so escritas inteiramente em XML e, portanto, so independentes das linguagens e plataformas. Desta forma, um cliente Java usando SOAP, correndo em Solaris, ou um cliente Perl usando SOAP correndo em Linux, podem ligar-se a um servidor Windows 2000 executando SOAP. O protocolo SOAP representa a essncia da arquitectura de servios na Web, habilitando diversas aplicaes a trocarem dados e servios. Pode ver na figura o pedido SOAP. Este pedido encapsulado dentro de um envelope SOAP (que por sua vez encapsulado dentro do pedido HTTP, assumindo que estamos a usar HTTP como transporte). O envelope SOAP

provvel tambm, caso o Header exista, que se encontre um ou mais Headers que nos vo fornecendo metainformao especifica da aplicao. Essa meta-informao pode conter qualquer coisa, embora a especificao do SOAP use o ID da transaco como exemplo. O SOAP Header: <?xml version= "1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/s oap-envelope" soap:encodingStyle="http://www.w3.org/2 001/12/soap-encoding" > <soap:Header> <m:Trans xmlns:m="http://www.mysite.com/transact ion/" soap:mustUnderstand="1">234</m:Trans> </soap:Header> ... ... </soap:Envelope> O SOAP Body contm os argumentos e os nomes dos mtodos remotos a serem chamados. <?xml version= "1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/s oap-envelope" soap:encodingStyle="http://www.w3.org/2 001/12/soap-encoding" > <soap:Body> <m:GetPrice

<16>

a programar

xmlns:m="http://www.mysite.com/prices"> <m:Item>Apples</m:Item> </m:GetPrice> </soap:Body> </soap:Envelope> Toda a informao serealizada usando XML.. Embora o SOAP use XML, que formato de texto, podem ser usadas estruturas, unions e serem passados parmetros por referncia.

Exemplo de uma transaco SOAP


Neste exemplo temos uma aplicao que efectua um pedido ao servidor do preo de um artigo ( G etStockPrice ) passando o nome do artigo no parmetro StockName. Na resposta enviado o preo do artigo no parmetro Price. O pedido SOAP: POST /InStock HTTP/1.1 Host: www.example.org Content-Type: application/soap+xml; charset=utf-8 Content-Length: nnn <?xml version= "1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/s oap-envelope" soap:encodingStyle="http://www.w3.org/2 001/12/soap-encoding" > <soap:Body xmlns:m= "http://www.example.org/stock" > <m:GetStockPrice> <m:StockName> IBM</m:StockName> </m:GetStockPrice> </soap:Body> </soap:Envelope> A resposta SOAP: HTTP/1.1 200 OK Content-Type: application/soap+xml; charset=utf-8 Content-Length: nnn <?xml version= "1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/s oap-envelope" soap:encodingStyle="http://www.w3.org/2 001/12/soap-encoding" > <soap:Body xmlns:m= "http://www.example.org/stock" > <m:GetStockPriceResponse> <m:Price> 34.5</m:Price> </m:GetStockPriceResponse> </soap:Body> </soap:Envelope>

A sintaxe do SOAP
A sintaxe do SOAP muito simples visto usar como base o XML. As regras mais importantes so: As mensagens SOAP tm que usar o XML Todas as mensagens tm que ter as tags de envelope e de enconding As mensagens no podem ter referncias DTD As mensagens no podem ter instrues de processamento de XML Abaixo podem ver o quo simples a estrutura de uma mensagem SOAP: <?xml version= "1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/s oap-envelope" soap:encodingStyle="http://www.w3.org/2 001/12/soap-encoding" > <soap:Header> ... ... </soap:Header> <soap:Body> ... ... <soap:Fault> ... ... </soap:Fault> </soap:Body> </soap:Envelope>

SOAP e a performance
Devido ao uso de XML, ao contrrio de outros protocolos, a performance do SOAP um pouco afectada pois existe a necessidade de extrair o envelope SOAP e efectuar o parsing do XML.

<17>

a programar

Concluso
Com este artigo pretendeu-se que o leitor fique a perceber, de uma forma superficial, o funcionamento do SOAP. O SOAP no especifica necessidades da informao a ser trocada isso cabe s aplicaes que o usam. O SOAP assim uma plataforma sobre a qual informao especfica de aplicaes pode ser trocada. um standard que permite grande expansibilidade e interoperabilidade entre sistemas. Esta interoperabilidade poder naturalmente estar ameaada se no forem utilizados standards puros SOAP. Nem todos os aspectos foram tratados neste artigo, pelo que se aconselha a pesquisar sobre este assunto.

Ver tambm...
Como forma de comear a explorar o mundo SOAP aconselhada a visualizao da palestra realizada no SAPO CodeBits, disponvel no servio SAPO Vdeos em http://videos.sapo.pt/vTPQgrAU7b7wcBDilQJf

Bibliografia
Kennard Scribner e Mark C. Stiver. Understanding SOAP. Sams Publishing.

Residente no Porto, Joo Brando tem 9 anos de experincia em desenvolvimento de software e em montagem e elaborao de redes de computadores. Ocupa desde Dezembro de 2005 o cargo de Senior Engineer no Software Development Center da Qimonda AG. Tem como principais actividades e responsabilidades o desenvolvimento software e gesto de projectos numa grande variedade de aplicaes na rea web e no web.

Joo Brando

<18>

a programar

maiscula ou por _, representando um objecto que no possvel de nomear.

Programao em Lgica com PROLOG

As estruturas so representadas por:


simbolo_funcional(argumentos)

em que o simbolo_funcional um identificador, e os argumentos so uma lista de termos, que pode ser vazia. Aps concluda a base de conhecimento do programa em PROLOG, esta poder ser consultada. Uma consulta uma interrogao ao sistema, da forma:
?-predicado(argumentos).

PROLOG uma linguagem de programao baseada na lgica simblica, servindo como ferramenta para o desenvolvimento de aplicaes na rea da Inteligncia Artificial. A linguagem PROLOG utilizada em problemas que envolvam objectos e relaes entre eles. de fcil deduo que PROLOG vem de PROgramao em LGica. Em lgica define-se um Teorema e para verificar a sua validade, procura-se regras e factos. Comparativamente lgica, em PROLOG exprime-se factos e relaes entre factos, para inferir solues para os problemas.

A resposta dada a uma consulta, depende da forma como feita a pergunta. Se esta for fechada, ou seja, se no contiver variveis nos argumentos dos predicados, a resposta do sistema ser da forma yes/no. Se a pergunta for aberta, ou seja, se contiver variveis nos argumentos dos predicados, sero listados todos os valores, que unificam com as variveis, formando um facto verdadeiro. A primeira resposta do sistema, corresponde primeira unificao das variveis, que forma um facto verdadeiro. Para pedir ao sistema que mostre outras respostas possveis, utiliza-se o simbolo ; que significa ou. O smbolo ; pede ao PROLOG que procure na base de conhecimento, a partir da ltima soluo retornada, a prxima unificao que satisfaa a consulta (processo designado de back-tracking). Quando no houver mais unificaes verdadeiras para mostar, responde no. A unificao corresponde a uma substituio que instncia um termo, ou seja, uma operao que atribui um valor a um termo. Para a pesquisa de uma resposta a uma consulta, o interpretador de PROLOG, utiliza uma rvore de prova, que uma entidade perfeitamente definida que constitui, por si s, uma prova, intuitivamente evidente, que um tomo consequncia lgica de um programa. O interpretador de PROLOG percorre a rvore de prova com avanos e retrocessos (back-tracking), cada avano est associado a uma transformao (alvo e instanciao) e cada retrocesso est associado anulao dessa transformao. Ser apresentado um exemplo de uma rvore de prova, quando for abordado o tema das listas em PROLOG.

Alguns conceitos
Um facto expressa uma verdade sobre uma relao. Um facto uma relao entre objectos da forma:
relao(objecto1, ... ,objecton)

em que objecto1, ... , objecton, so os argumentos. O nome da relao chamado predicado. Uma relao um conjunto de n-tuplos de objectos. Uma regra expressa uma relao entre factos. As regras so usadas quando se deseja dizer que um facto depende de uma conjuno de outros factos, que tm a forma:
cabea :- corpo.

em que o conector :- significa se. O conjunto de regras e de factos designa-se por base de dados, ou base de conhecimento. Os objectos manipulados em PROLOG so chamados termos, que podem ser tomos ou estruturas. Os tomos podero ser uma de duas coisas: constantes ou variveis. As constantes podem ser: identificadores, que comeam por letras minsculas; Strings entre plicas; ou nmeros inteiros. Ao contrrio de outras linguagens, uma varivel em PROLOG, no representa uma posio de memria, mas sim uma associao a um objecto. Comeam por letra

Um primeiro exemplo
Um dos primeiros exemplos e dos mais interessantes, para quem se inicia na Programao em Lgica fazer a sua rvore genealgica.

<19>

a programar

% A base de conhecimento pai(antonio,jose). pai(antonio,costa). pai(jose,carlos). mae(maria,jose). mae(maria,costa). mae(carla,carlos). casado(antonio,maria). casado(jose,carla). homem(antonio). homem(jose). homem(costa). homem(carlos). mulher(maria). mulher(carla). % Fim da base de conhecimento

progenitor(P,Y), X \= Y. tio(X,Y) :irmao(X,I), progenitor(I,Y). primo(A,B) :progenitor(P1,A), progenitor(P2,B), irmao(P1,P2). sogro(Q,W) :pai(Q,A), casado(A,W). cunhado(A,B) :irmaos(A,I), casado(I,B).

Listas
Uma lista uma estrutura recursiva binria, cujos elementos podem ser tomos ou termos estruturados, inclusive listas. Uma lista ou vazia, no contm nenhum elemento, ou uma estrutura com dois elementos: a cabea e a cauda. Uma possvel representao de uma lista ser: [H|T], em que H representa a cabea da lista e T a cauda da lista. As listas permitem agilizar bastante a resoluo de diversos problemas e sobre elas podem ser escritos os mais diversos predicados:
%Verificar se uma estrutura uma lista lista([]). lista([_H|T]) :- lista(T). %Calcular o tamanho de uma lista tamanho([],0). tamanho([_H|T], N) :tamanho(T,M), N is M+1. %Verificar se um elemento pertence a uma lista membro(H,[H|_T]). membro(X,[_H|T]) :membro(X,T). %Concatenar duas listas: %[2][3,1] => [2,3,1] concatena([],L,L). concatena([H|T],L,[H|L1]) :concatena(T,L,L1). %Inverter uma lista: % [1,2] => [2,1] inverte([],[]). inverte([H|T], L) :-

O facto pai(antnio,jos)., l-se: o indivduo antnio pai do indivduo jos. Para manipular a base de conhecimento anterior, pode escrever-se, entre outros, os seguintes predicados (regras): progenitor(P,F) :- pai(P,F). progenitor(P,F) :- mae(P,F). avo(A,N) :progenitor(A,F), progenitor(F,N). bisavo(BV,BN) :avo(BV,N), progenitor(N,BN). irmao(X,Y):homem(X), progenitor(P,X), progenitor(P,Y), X \= Y. irmaos(X,Y) :progenitor(P,X),

<20>

a programar

inverte(T,T1), concatena(T1,[H],L). Com as Listas, possvel definir outras estruturas de manipulao de dados, como por exemplo, uma pilha (Stack). Uma Stack poder ser vista como uma estrutura do gnero:
Stack = [topo, ..., base] %Empilhar um elemento pop pop(X,[],[X]). pop(X,P,[X|P]). push %Desempilhar o elemento do Topo da Stack push([],[]) :- write(Stack vazia!), !. push([_|T],T).

rvores binrias
Outra estrutura tambm muito usada em PROLOG, so as rvores binrias. A rvore binria vazia poder ser representada pela palavra void. Uma rvore binria no vazia ser representada da seguinte forma:
tree(E, LT, RT)

em que E representa o elemento do n da rvore, LT a sub-rvore esquerda e RT a sub-rvore direita.

%Mostar o elemento do topo mostra([]) :- write(Stack vazia!), !. mostra([X|_]) :- write(Elemento do topo: ), write(X). %Tamanho da Stack %Resume-se a calcular o tamanho de uma lista

Exemplo de uma rvore binria:


tree(3, tree(2, tree(1, void, void), void), tree(6, void, void)).

Manipulao de Listas
No caso de programas que tm de lidar com bases de dados consideravelmente grandes, torna-se til a utilizao de predicados que permitam pesquisar informao na base de dados, destacando-se o predicado findall(?Termos,?Predicados,?Lista), que retorna em Lista, a lista de todos os Termos que esto de acordo com os Predicados, e o predicado setof(?Termo,?Predicados,?Lista), que tem um

<21>

a programar

Tambm sobre esta estrutura, podem ser escritos diversos situados direita do ltimo n uni cado, inclusive, no predicados: sendo percorridos aquando do back-tracking. O

operador cut, pode ser utilizado em diversas situaes:

%Verificar se uma estrutura rvore binria binaryTree(void). binaryTree(tree(_E, LT, RT)) :binaryTree(LT), binaryTree(RT).

uma

Excluso mtua incondicional, em que s dada uma resposta a cada consulta,

Excluso mtua condicional,

cabea:-!,objectivo2,...,objectivon.

%Verificar se um elemento pertence rvore treeMember(X,tree(X,_LT,_RT)). treeMember(X,tree(_,LT,_)) :treeMember(X,LT). treeMember(X,tree(_,_,RT)) :treeMember(X,RT). %Multiplicar todos os elementos da rvore multiplica(void, 1). multiplica(tree(E, LT, RT),N) :multiplica(LT, M), multiplica(RT, P), N is E * M * P. %Passar uma rvore para uma lista em pr-ordem preOrdem(void,[]). preOrdem(tree(E, LT, RT), L) :preOrdem(LT, L1), preOrdem(RT, L2), concatena([E|L1], L2, L).

cabea:-objectivo1,...,!,..., objectivon. Resposta nica,


cabea:-objectivo1,...,objectivon, !

Exemplos: %Implementao de um IF, imagem de C ou JAVA if_then_else(C,_T,E):- C, !, E. if_then_else(_C,_T,E):- E. membroComCut(H,[H|_T]):-!. membroComCut(X,[_H|T]):membroComCut(X,T).

%Substituir um elemento de uma rvore binria por outro elemento subs(_X,_Y,void,void). subs(X,Y,tree(X,LT,RT),tree(Y,A,B)):subs(X,Y,LT,A), subs(X,Y,RT,B). subs(X,Y,tree(Z,LT,RT),tree(Z,A,B)):subs(X,Y,LT,A), subs(X,Y,RT,B).

%Exemplo de consultas, para mostrar a diferena de resultados ?-membro(X,[2,4,6]). X=2; X=4; X=6; no ?-membroComCut(X,[2,4,6]). X=2 yes

Ciclos em PROLOG
Embora a linguagem PROLOG seja totalmente diferente de linguagens como C ou JAVA, igualmente possvel construir ciclos em PROLOG, usando o predicado repeat, que j se encontra pr-definido no PROLOG, da seguinte forma:
repeat. repeat:-repeat.

Cut O operador cut, que se denota por !, in uencia o percurso de pesquisa na rvore de procura. Quando utilizado, numa regra ou consulta, modi ca a rvore de procura, eliminando as uni caes realizadas antes de ser activado. Ou seja, elimina todos os ramos da rvore de procura, que ainda no foram percorridos e que esto

Associado ao repeat pode-se ter o predicado fail, que falha sempre. Um ciclo repeat-fail, executa um predicado P at que uma condio X seja verdadeira. O predicado fail permite forar o back-tracking. Como usar o repeat e o fail? Eis um exemplo:

<22>

a programar

Manipulao de Termos
%Um menu simples menu:repeat, write(1 Opo write(2 Opo write(3 Opo write(Introduza read(Opcao), executa(Opcao), fail.
var(X) -> Sucede se X uma varivel

A. ),nl, B. ),nl, C. ),nl,nl, a opo: ),

novar(X) -> Sucede se X no uma varivel atom(X) -> Sucede se X representa um tomo PROLOG integer(X) -> Sucede se X um inteiro

O predicado repeat permite chamadas iterativas ao write e ao read, at que a condio de sada executa(X), tenha xito.

Estrutura=..Lista -> Converte um elemento composto

numa lista, e vice-versa.

Ciclo FOR
for(X,[X,Z]) :- X =< Z. for(X,[Y,Z]) :W is Y+1, W =< Z, for(X,[W,Z]). ?- for(X,[1,3]), write(X), write( ), fail. 1 2 3 yes

Exemplo: f(a,b)=..L resulta em L=[f,a,b] L=..[f,a,b] resulta em L=f(a,b)


arg(Argumento,Termo,Valor)-> Retorna em Valor o

Argumento do Termo.

functor(Termo,Nome,Aridade)-> Retorna em Nome o

nome do Termo, e em Aridade o nmero de argumentos do Termo.

Depurao
Inicialmente, para compreender como funciona o motor de inferncia do PROLOG e para se ter acesso ao raciocnio do PROLOG, podem-se usar os seguintes predicados:
trace -> Activa a depurao notrace -> Desactiva a depurao

Negao Lgica
Combinando o operador cut e o predicado fail , implementa-se a negao lgica, not(A) :- A, !, fail. not(A). Se A tiver xito, ento not(A) falha; se A falha, ento not(A) tem xito.

Exemplo: trace, %Chama o predicado lista lista([1,2,3]), notrace.

Manipulao de Base de Dados


Os predicados seguintes permitem adicionar ou remover factos de uma base de dados PROLOG. asserta(facto) -> adiciona o facto no nicio da lista de factos assertz(facto) -> adiciona o facto no fim da lista de factos retract(facto) -> remove o facto da base de dados

Acesso a ficheiros
A maioria das vezes, quando se faz um programa, desejvel guardar a informao gerada pela execuo desse programa, para utilizao futura. Em PROLOG, ler e guardar informao em ficheiros algo bastante simples, mas que requer algum cuidado.
%see abre o ficheiro para leitura see(nomeFicheiro.pl), read(X), %seen fecha o ficheiro seen.

<23>

a programar

Aps aberto um ficheiro, para escrita, se ocorrer algum erro de execuo enquanto o ficheiro no for fechado, perder-se todo o contedo do mesmo, pelo que aconselhvel manter sempre actualizado, um backup do ficheiro. Caso se queira ler para a memria, uma base de dados contida num ficheiro, bastaria fazer:

write(qualque coisa),nl, %told fecha o ficheiro told.

Penso que neste artigo foram abordados os tpicos essenciais ao incio do desenvolvimento de programas em PROLOG. Embora seja uma linguagem com sintaxe relativamente fcil, requer muita prtica e bastante raciocnio.
write(Muita Programao e muita Diverso!!!),nl, write(FIM). fim:-

:- initialization(iniciar). iniciar:- [nomeFicheiro].

Para escrever dados num ficheiro, bastar fazer:


%tell abre o ficheiro para escrita tell(nomeFicheiro.pl),

Bibliografia
Sterling, Leon; Shapiro, Ehud; The Art of Prolog; Advanced Programming Techniques; 1994

Estudante na Universidade de vora, no curso de Engenharia Informtica, Gaspar Brogueira dedica o seu tempo ao aperfeioamento dos seus conhecimentos nas linguagens de programao C e JAVA. Tem especial interesse pelas reas da Segurana e Criptogra a.

Gaspar Brogueira

<24>

a programar

como algoritmos clssicos, so frequentemente usados como sub-rotinas em aplicaes mais complexas.

Algoritmia Clssica em C++

Um grupo de algoritmos clssicos que apresenta um vasto domnio de aplicao o dos algoritmos de ordenao. Este grupo de algoritmos apresenta variadas tcnicas que possibilitam a ordenao dos elementos de um array segundo uma determinada lgica (pode-se proceder a uma ordenao de forma ascendente ou descendente). Neste artigo sero apenas abordados dois dos muitos algoritmos de ordenao de arrays: o quicksort (por muitos considerado o melhor algoritmo de ordenao) e o bubblesort.

Breve Introduo Histrica


A linguagem C++ foi desenvolvida durante os anos 80 na Bell Labs, pelo cientista de computao dinamarqus Bjarne Stroustrup. Esta linguagem muitas vezes retratada como uma evoluo da linguagem C. De facto, esta linguagem foi a principal base de desenvolvimento de C++, tanto mais que a primeira verso da nova linguagem tinha o nome de C With Classes, evoluindo mais tarde para C++. Em portugus deve-se pronunciar c mais mais (smysmys) sendo que em ingls esta linguagem pronunciada como cee plus plus (siplspls). As vantagens introduzidas pelo C++ face ao C so indiscutveis. No entanto, e muitas vezes devido ao facto de ser uma linguagem com facilidades de alto nvel, ocorrem erros lgicos (os temidos bugs) difceis de resolver e frequentemente com consequncias trgicas para o computador que est a correr a aplicao. So por isso famosas as duas citaes de Stroustrup acerca das facilidades da sua nova linguagem: C faz com que dar um tiro no p seja fcil; C++ torna isso mais difcil, mas quando ns o fazemos rebenta com a perna toda. Sempre desejei que o meu computador fosse to fcil de usar como o meu telefone. O meu desejo realizou-se. J no sei usar o meu telefone. Nem sempre simples para iniciantes da linguagem ou programadores inexperientes evitar que estes erros aconteam. por esta razo que muitas vezes recomendado um perodo de adaptao sintaxe de C e desenvolvimento de aplicaes nesta linguagem, antes de se dar o salto para o C++.

- BubbleSort
O algoritmo BubbleSort talvez o algoritmo mais simples de se perceber dentro do gnero. A sintaxe que este algoritmo apresenta no necessita de explicaes exaustivas, visto recorrer a aspectos bsicos de programao (ciclos for/while, comparao de diferentes elementos do array, incrementao de uma varivel, etc.). O prprio funcionamento do BubbleSort muito simples: por cada iterao do ciclo, o maior elemento do array (para um determinado intervalo de elementos desse mesmo array) colocado no ndice final previamente estabelecido. Isto conseguido custa de sucessivas comparaes de um elemento do array com o seu elemento seguinte. O seguinte excerto de cdigo ilustra a implementao do Bubblesort: //funo para trocar dois elementos do array (utilizao de referncias para afectao directa) void swap (int& n1, int& n2) { //guardar o valor de n2 int aux = n2; //afectar n2 com o valor de n1 n2 = n1; //afectar n1 com o valor de aux (valor inicial de n2) n1 = aux; } //a funo recebe como argumentos o array a ordenar e o numero mximo de elementos a ordenar void bsort (int v[], int n) { for (int i = n; i > 0; --i) //ciclo responsvel pelas

Algoritmos Clssicos - Ordenao


Existe um alargado conjunto de algoritmos informticos que desempenham um papel quase vital no desenvolvimento de aplicaes coerentes e slidas. Estes algoritmos, conhecidos

<25>

a programar

decrementaes do ndice mximo { for (int j = 0; j < i; ++j) //ciclo responsvel por incrementar os ndices a ordenar { if (v[j] > v[j+1]) //se um elemento maior que o seu elemento seguinte { swap (v[j], v[j+1]); //chamar a funo para trocar dois elementos do array } } } } O primeiro ciclo for o responsvel por decrementar o ndice mximo para as ordenaes. Assim, se se quiser ordenar um array tomando em conta todos os seus elementos, ter de se iniciar a varivel que ir percorrer todos os ndices com o valor do tamanho do array. Depois de serem efectuadas todas as operaes uma primeira vez, tem-se a certeza que o maior elemento do array se encontra no ndice final. Na segunda vez que se iro realizar as operaes de ordenao, no interessa que se tenha em conta todo o array (se assim fosse estariam a ser feitas comparaes desnecessria, ocupando recursos da mquina injustificadamente). Logo, decrementa-se em 1 o ndice mximo. As operaes terminaro quando o ndice mximo for zero, ou seja, quando coincidir com o primeiro ndice (ndice zero). Isto acontece pois um array de um elemento est de certeza ordenado.

void qsort (int v[], int inicio_v, int fim_v) { //afectar os indices que iro percorrer o array com as posies iniciais e finais do array int a = inicio_v, b = fim_v; if (a >= b) return ; //pivot (elemento do meio do array) int pivot = v[(a+b)/2]; do { //ir pesquisando por nmeros que estejam esquerda do pivot e que sejam maiores que este while ( v[a] < pivot) ++a; //incrementar "a" para se ir avanando no array //ir pesquisando por nmeros que estejam direita do pivot e que sejam menores que este while ( v[b] > pivot) --b; //decrementar "b" para se ir regredindo no array if (a <= b) //trocar apenas se a menor ou igual a b { if (v[a] != v[b]) //efectuar trocas apenas se os valores forem diferentes swap (v[a], v[b]); //incrementar "a" e decrementar "b" para se retomar as pesquisas ++a; --b; } } while (a <= b); //quer-se ordenar um sub-array que vai desde o principio do array principal ate antes do pivot. //quando se terminam as pesquisas, "b" representa a posio antes do pivot. qsort (v, inicio_v, b); //quer-se ordenar um sub-array que vai desde a posio seguinte ao

QuickSort
O algoritmo QuickSort (desenvolvido em 1960 pelo cientista Charles Antony Richard Hoare) de longe o algoritmo de ordenao mais usado e considerado pelo maior parte dos programadores como o melhor algoritmo dentro do gnero. Este algoritmo implementa uma soluo para a ordenao de um array baseado no famoso lema da informtica dividir para conquistar. O que basicamente o QuickSort faz ir dividindo o array, atravs da seleco de um pivot (elemento de referncia), e ordenando depois cada parte. Apresenta-se a seguir um exemplo de implementao do QuickSort:

<26>

a programar

pivot at ao fim do array //principal quando se terminam as pesquisas, "a" representa a posio seguinte ao pivot. qsort (v, a, fim_v); } No fundo, este algoritmo pode-se resumir a sucessivas colocaes de valores maiores que o pivot sua direita e de valores menores sua esquerda. No exemplo apresentado, o elemento escolhido como pivot o elemento central de cada parte do array. Esta escolha tem tanto valor como qualquer outra. No entanto, se o array estiver parcialmente ordenado, ela prefervel. Imagine-se o seguinte array (denomine-se o array por v): [1,3,1,2,5,4,3]. Vamos recorrer ao QuickSort para o ordenar: Seleccionar o pivot. Para este caso o pivot ser o elemento contido no ndice 3 (elemento central), que contm o valor 2; Colocar esquerda do pivot s elementos menores que este e direita s elementos maiores. Comeando no princpio do array (pesquisar por elementos maiores ou iguais que o pivot), o elemento de ndice 1 (valor 3) maior que o pivot. Portanto, o elemento do ndice 1 ter de ser trocado; Nota: no exemplo apresentado, elementos iguais ao pivot tanto se podem encontrar esquerda como direita deste. No entanto, se durante a pesquisa de valores maiores ou menores que o pivot for encontrado algum elemento igual ao pivot, este ser tomado para troca. A pesquisa por elementos maiores que o pivot (e que estivessem inicialmente esquerda deste) termina, tomando-se o valor v[1] para troca; Para a pesquisa de valores menores que pivot e que estejam sua direita (inicialmente), comea-se no ndice final do array, com sucessivos decrementos. Como se pode observar, comeando em v[6], o elemento v[3], que o valor 2, igual ao pivot (realce-se que o pivot um valor). Ora, o ciclo while em que feita a pesquisa por valores menores que o pivot, terminar para um valor igual ao pivot. Assim, ser tomado para troca o valor contido em v[3]; Procede-se troca. O valor que se usou para ir percorrendo o array ascendentemente (no exemplo a varivel a) menor que o que se usou para percorrer o array de forma descendente (no exemplo a varivel b). Portanto, a condio a < = b retorna TRUE, entrando-se assim no processo de troca de elementos;

Os elementos no so iguais (v[1] ! = v[3], retorna TRUE), logo todas as condies previstas para a troca esto satisfeitas; Invoca-se a funo de troca (swap()), que se encarregar de trocar os elementos; Depois de trocados os elementos, fica-se com o vector v da seguinte forma: v = [1,2,1,3,5,4,3] Os ndices a e b so, respectivamente, incrementado e decrementado. Retoma-se, portanto, a pesquisa por valores maiores que o pivot em v[2] e a pesquisa por valores menores em v[2]; Durante a pesquisa por valores maiores, conclui-se que o elemento v[3] (contm o valor 3) maior que pivot. Logo, ser tomado para troca; J para as pesquisas por elementos menores que pivot, o elemento v[2] igual que pivot, logo ser tomado para troca; No entanto, a troca no ser efectuada, j que o ndice usado para percorrer o array ascendentemente maior que o usado para percorrer o array descendentemente. Desta forma, no se processa a troca de elementos (a maior que b, logo a condio a b retorna FALSE); O ciclo dowhile tambm terminado, j que a condio de teste deste ciclo a b; Procede-se ento s duas chamadas recursivas funo qsort(), sendo que na primeira chamada ser apenas tomado em conta o sub-array [1,2,1] e na segunda o sub-array [3,5,4,3] (no entanto, para questes de indexao, o array em causa continua a ser o prprio v, sendo que para o segundo sub-array, v[3] representa o primeiro valor 3); Para a primeira parte do array, o pivot ser o valor 2 (v[1]), sendo que se troca v[1] (valor 2) e v[2] (valor 1); Para a segunda parte do array, o pivot ser o valor 5 (v[4]), sendo que a nica troca que se efectua entre v[4] (valor 5) e v[6] (valor 3); Depois destas duas trocas, o array est totalmente ordenado. O algoritmo QuickSort termina quando numa chamada recursiva a qsort(), o parmetro inicio_v for maior ou igual a fim_v. Foi imposta esta condio terminal pois um array de um elemento est de certeza ordenado (se o ndice que

<27>

a programar

representa o incio do array for o mesmo que representa o fim do array, ento est-se na presena de um array de 1 elemento).

os elementos que esto direita do elemento central. Caso o elemento central seja maior, dever proceder-se pesquisa na parte esquerda do array. Se o elemento nunca for encontrado, ento a funo retorna -1, indicando que no array em questo no existe o elemento que se procurava. Exemplo de implementao de pesquisa dicotmica em arrays:

Algoritmos Clssicos Pesquisa em Arrays


Tanto no mundo da programao, como no dia-a-dia, somos confrontados com diversas situaes que requerem a pesquisa de algo num determinado conjunto de elementos, que em princpio tero caractersticas semelhantes ou iguais quilo que se quer encontrar. Um exemplo muito simples, mas ilustrativo deste facto, a situao em que se tem de encontrar um livro de uma disciplina dentro de uma mochila, na qual existem tambm outros materiais escolares (estojos, cadernos, etc.). Em informtica, o conceito e toda a logstica em torno do pesquisar tem assumido um papel preponderante nos ltimos anos. Exemplo disso toda a agitao em torno dos diferentes motores de busca na Internet (Google, Yahoo!, etc.). A prpria programao no foge a esta regra. As pesquisas representam tambm uma operao com importncia chave numa aplicao. Uma maneira de encontrar algo no dia-a-dia poder ser uma pesquisa sequencial aos elementos de um determinado conjunto. Ou seja, verificam-se, um a um, os elementos do conjunto at se encontrar o elemento pretendido. Este processo, apesar de se poder implementar em programao, no de todo o melhor para se encontrar um elemento dentro de um conjunto de dados (por exemplo um array). Neste contexto surge a pesquisa dicotmica, um algoritmo que facilita a procura de um certo elemento dentro de um array.

int search (int v[], int find, int inicio_v, int fim_v) { //se o delimitador esquerda for maior que o da direita if (inicio_v > fim_v) //o elemento no existe no array em causa return -1; //elemento central (ndice central do array) int pivot = (inicio_v+fim_v)/2; if (v[pivot] == find) //se o elemento central for igual ao pretendido return pivot; //indicar o ndice em que se encontrou //se o valor central for maior que o valor a pesquisar if (v[pivot] > find) return search (v, find, inicio_v, pivot-1); //pesquisar na parte esquerda do array //se o valor central for menor else return search (v, find, pivot+1, fim_v); //pesquisar na parte direita do array }

- Pesquisa Dicotmica em Arrays


A pesquisa dicotmica em arrays (tambm muitas vezes referida como pesquisa binria) requer, antes de mais, que o array esteja ordenado. Ou seja, este algoritmo requer que antes da sua execuo seja posto em execuo um algoritmo de ordenao, tal como o QuickSort ou o BubbleSort. Este algoritmo provavelmente um dos mais simples e rpidos de entender dentro do mundo da programao. Este algoritmo prope que se v verificando sucessivamente o elemento central do array (que vai sendo divido em subarrays), fazendo uma comparao entre este e o elemento que se quer encontrar. Se o elemento central for menor que o valor que se deseja encontrar, ento devero analisar-se

A funo que implementa o algoritmo de pesquisa dicotmica em arrays (no exemplo a funo search), recebe como parmetros o array a analisar (varivel v), o valor a encontrar (varivel find), o ndice inicial da parte do array a ser analisada (varivel inicio_v) e o ndice final da parte do array a analisar (varivel fim_v). Esta funo termina quando a condio inicio_v > fim_v retornar TRUE. Pense-se no seguinte: aps vrias chamadas funo search() ocorre nova chamada funo, desta vez

<28>

a programar

com uma parte do array principal que s apresenta um elemento. Neste caso, o pivot que ser escolhido ser esse mesmo elemento. Se o pivot no for igual ao valor que se procura, ento de certeza que o valor que se procurava no existe no array. No entanto, o algoritmo continua a ser executado. S que para ambas as possibilidades que se apresentam (o pivot ser maior que o valor que se procura ou ser menor), o parmetro inicio_v ser maior que fim_v. Se o pivot for maior que o valor que se procura, ento o parmetro formal inicio_v ter o mesmo valor com que iniciou essa chamada funo, sendo que o parmetro formal fim_v ter o valor de pivot 1 (como se trata de uma parte do array que tem apenas um elemento, tanto inicio_v como fim_v tm o mesmo valor que pivot, logo fim_v ser passado na nova chamada funo com um valor menor que inicio_v). O outro caso que pode ocorrer (pivot ter um valor menor que o valor que se procura), o parmetro formal inicio_v ser afectado com o valor de pivot + 1 e o parmetro formal fim_v ter o mesmo valor com que iniciou essa chamada funo (tal como no caso do pivot ser maior que o valor em procura, tambm neste caso fim-v e inicio_v tm o mesmo valor que o valor de pivot). Portanto, faz todo o sentido que quando fim_v for passado com um valor menor que inicio_v o algoritmo cesse, indicando-se que o valor que se procura no estava contido no array (return -1 indica a inexistncia do valor dentro do array).

descobertas de solues muitssimo eficientes a este nvel esto agora reunidas. Os algoritmos implementados em linguagens tradicionais (nomeadamente o OOP, ObjectOriented Programming) esto a comear a ser implementados em sistemas especficos de gesto de dados. um ramo da informtica sobre o qual recaem imensas expectativas.

- Listas Ligadas (apresentao de uma lista simplesmente ligada em anel)


Um dos algoritmos mais famosos para a gesto de dados o que implementa uma estrutura de dados denominada Listas Ligadas. Esta estrutura de dados supera o armazenamento e gesto de dados em arrays na medida em que na altura de se inserir um novo elemento na lista no necessrio alterar a posio dos restantes elementos. Isto acontece pois todos os elementos da lista esto ligados ao seu seguinte (numa variao deste algoritmo mesmo possvel ligar cada elemento ao seu anterior), tal como num comboio, em que as diversas carruagens esto ligadas sequencialmente, construindo a estrutura total. Tambm dentro deste algoritmo existem inmeras variaes, nomeadamente a Lista Simplesmente Ligada, a Lista Simplesmente Ligada em Anel e a Lista Duplamente Ligada. Neste artigo ser apresentada a Lista Simplesmente Ligada em Anel pela sua simplicidade e eficincia nos objectivos a que se prope o algoritmo. Exemplo de implementao de uma simplesmente ligada: class List { struct Node //estrutura que representa o n/celula { int data; //atributo em que ser contida a informaao do n Node* nextNode; //apontador para o n seguinte da lista //construtor que ser invocado para criar cada n da lista Node (int val, Node* next) { data = val; nextNode = next; } //construtor default que ser invocado para construir o n sentinela Node()

Algoritmos Clssicos Gesto de Dados


Nos dias que correm, a gesto de dados atravs de aplicaes informticas um domnio extremamente importante e em que se tem apostado fortemente em termos de desenvolvimento e pesquisa. No por isso de admirar que exista uma variedade to grande de facilidades e algoritmos dentro deste ramo. Desde sempre foi uma necessidade do ser humano ter a informao ordenada da melhor maneira possvel, sendo que as tcnicas usadas para a ordenao dessa informao foram evoluindo e transformando-se ao longo do tempo. E neste aspecto a informtica no foi excepo. Desde que foi lanado o primeiro computador pessoal at data actual, muita coisa se modificou na forma de gesto de dados. Os algoritmos responsveis pela boa gesto de dados forem evoluindo, foram criadas plataformas especficas para gesto de dados (as to famosas aplicaes de gesto de base de dados, tais como Oracle, MySQL, SQL Server, ACCESS, etc.). Como este um ramo em constante transformao prev-se que as inovaes no cessem para j. Mais, dito que as condies para mais evolues e

<29>

a programar

{ nextNode = this; } }; //criao do n que servir de sentinela (invoca o construtor default da estrutura) Node guard; //mtodo auxiliar find() para verificar se um dado valor existe ou no na lista bool find (int val, Node*& prev, Node*& next); public: //mtodo para inserir um novo elemento numa lista bool insert (int val); //mtodo para remover um determinado valor da lista bool remove (int val); //destrutor; elimina todos os ns da memria List(); }; Neste exemplo, o algoritmo implementado atravs do paradigma OOP. Desta forma, consegue-se uma melhor abstraco e sobretudo prima-se em organizao e eficincia. Como foi referido, as listas ligadas representam uma estrutura de dados constituda por clulas/ns, que contm a informao a armazenar e a gerir, estando estes ligados numa forma sequencial. Em termos de programao, os ns da lista so implementados atravs uma estrutura (struct), contendo esta um ou mais atributos para conter informao e um outro atributo que a liga s restantes estruturas da lista. No exemplo, os ns so referenciados pela varivel Node. No exemplo est implementada uma lista em que cada n existe um atributo para conter informao (no caso um valor inteiro) e o atributo nextNode, que do tipo apontador para Node (ir apontador para a estrutura que representa o n seguinte). Node tem tambm dois construtores, um com dois parmetros (responsvel pela criao dos ns normais da lista) e um construtor default (que ser invocada aquando da criao do n sentinela). O construtor com parmetros recebe um valor do tipo inteiro (val), que ser o valor que o novo n conter, e um apontador para Node (nextNode), que representa o n seguinte ao n que ser criado.

A particularidade que esta lista introduz da ligao em anel. A organizao da lista feita desta forma a fim de facilitar os algoritmos de insero e remoo dentro da lista. Este n denominado sentinela (referenciado no exemplo como guard) sempre o primeiro n da lista, sendo que quando a lista est vazia aponta para si mesmo (o n seguinte ao n sentinela o prprio sentinela) e quando no est vazia, o ltimo n aponta para o sentinela (o n seguinte ao ltimo n da lista sempre o sentinela). Este n especial criado atravs da invocao do construtor default. Dentro deste construtor usada a palavra-chave this para afectar o atributo nextNode do n que invoca o construtor (neste caso, o sentinela). Ou seja, o n que invocou o construtor passa a apontar para ele mesmo. Se o cdigo apresentado for posto em execuo, a linha Node guard cria o sentinela, fazendo assim com que seja criado o primeiro n da lista. Desta forma, quando a lista criada tem este aspecto:

Quando forem inseridos valores na lista (os valores inseridos numa lista ficam sempre ordenados de uma forma ascendente), a lista apresenta o seguinte aspecto:

Repare-se na forma que a lista apresenta, com o ltimo n ligado ao sentinela. No exemplo foram apresentados quatro mtodos pertencentes classe List: o mtodo (auxiliar) find, o mtodo insert, remove e o destrutor da classe. O mtodo find usado pelos mtodos de insero e remoo da lista, find e remove respectivamente, a fim de se saber se um dado valor existe ou no dentro da lista (no faria qualquer sentido tentar inserir um valor que j estivesse presente na lista ou remover um valor que nem sequer existia dentro da lista). O mtodo find poderia ser ento programado da seguinte forma:

bool List::find (int val, Node*& prev, Node*& next) { guard.data = val; //truque para evitar a pesquisa infinita

<30>

a programar

//afectar "next" como sendo o n seguinte a sentinela e prev como sendo a prpria sentinela for (next = guard.nextNode, prev = &guard; //cessar a pesquisa pelo elemento apenas quando a informao de "next" for maior ou igual a "val" next->data < val; //por cada iterao afectar "prev" com as caractersticas de "next" e "next" com as do n seguinte prev = next, next = next>nextNode); //retornar TRUE se o valor existir ou FALSE se o valor no existir return next->data == val && next != &guard; }

Assim, se este operando retornar TRUE, o valor encontra-se na lista. No nicio do mtodo, foi afectado guard.val com o valor que se procura (para assim evitar pesquisa infinita). Desta forma, se o valor que se passou como parmetro no existir na lista, e se todos os valores da lista forem menores que o que se procura, next data == val retorna TRUE. Ou seja, indicado que o valor em procura est contido na lista, quando na realidade isso no se passa. Da que se teste se o endereo de memria apontado por next o endereo do n sentinela. Em C++, a condio que traduz este caso next != &guard. Portanto, se esta condio retornar TRUE, j se sabe que o apontador next no est a apontar para o n sentinela, ou seja, no percorreu toda a lista, no encontrando o valor pretendido. O mtodo find retorna TRUE (o valor existe de facto na lista) apenas quando next aponta para um n que contm o valor pretendido e no est apontar para o sentinela. Outro mtodo apresentado no exemplo o mtodo de insero. Exemplo de implementao do mtodo de insero de um novo valor: bool List::insert (int val) { //ns auxiliares para percorrerem a lista Node* next, *prev; if (find (val, prev, next)) //se o elemento j existir na lista return false ; //indicar o insucesso da operao de insero //criar um novo elemento prev->nextNode = new Node (val, next); //indicar o sucesso da operao return true ; } Os ns auxiliares criados dentro deste mtodo (next e prev) so os ns que sero passados por referncia ao mtodo auxiliar find. Sendo passados por referncia, no existe necessidade de retornar estes ns no fim do mtodo find. A expresso dentro do if no mais que uma chamada ao mtodo auxiliar find, recebendo este como parmetros o valor a pesquisar (val) e os ns auxiliares que iro percorrer toda a lista (next e prev). Se este mtodo retornar TRUE,

Este mtodo realiza uma pesquisa por toda a lista para verificar a existncia de um determinado valor. Recebe como parmetros o valor a procurar e dois apontadores para Node passados por referncia (prev e next, que sero afectados directamente, j que so argumentos passados por referncia). O atributo val de guard afectado com a valor a procurar. Esta afectao feita devido forma como a pesquisa realizada: o atributo para conter informao do apontador next vai sendo afectado com os sucessivos valores dos ns que representa, sendo que a pesquisa termina quando next data representar um valor maior que val. Assim, imaginando-se que o valor que se procura no existia na lista e que todos os valores contidos na lista eram menores que o que se procurava, se guard.data no fosse afectado com o valor a pesquisar, a pesquisa nunca teria fim, j que nunca se contrariava a condio next data < val, o que implicaria um ciclo for infinito. Este mtodo retorna TRUE ou FALSE consoante o valor que se procurava exista ou no, respectivamente. O valor de retorno dado pelo valor lgico da expresso next data == val && next != &guard. Dissecando esta expresso, como se trata de um a expresso em que se usa o operador lgico &&, apenas se todos os operandos forem condies verdadeiras, o valor lgico da expresso total TRUE. Caso contrrio (basta que um operando seja falso) a expresso ter o valor lgico FALSE. O primeiro operando retorna TRUE se o valor do atributo next data for igual a val. Ora, se o valor que se procurava estiver inserido na lista, ento quando a pesquisa terminar o apontador next representa o n em que est contido o valor em procura e prev o seu n anterior.

<31>

a programar

ento o valor j existe dentro da lista, logo no faz sentido tentar inseri-lo de novo. Da que se faa return false caso isto se verifique. Se a chamada find (val, prev, next) retornar FALSE, ento o valor ainda no existe na lista, logo pode ser inserido. Portanto, se verificar este retorno por parte de find, a execuo da aplicao passa o controlo if (no atinge return false) e por isso necessrio invocar o construtor para os ns normais da lista. Ora, este construtor recebe dois parmetros: o valor que ser contido pelo n e o n seguinte a este. Como no final da pesquisa o apontador next aponta para o n em que est contido o primeiro valor maior que o que se procura, ento o n seguinte ao n que se pretende criar ser exactamente o n next. Portanto, os parmetros a passar ao construtor esto j definidos. No entanto, ser preciso ligar este n ao seu n antecessor. Da se afectar o atributo nextNode de prev com o novo n que ser criado (prev nextNode = new Node (val, next)). Outro mtodo importante para a implementao de listas o mtodo de remoo. Exemplo de implementao do mtodo de remoo:

Se a chamada ao mtodo auxiliar retornar TRUE, ento necessrio desligar o n da restante lista. Para isso liga-se o n anterior quele que se vai remover ao n seguinte daquele que se vai remover. Em C++ esta operao implementada pela linha prev nextNode = next nextNode (mais uma vez se salienta que no final da pesquisa, se o valor existir dentro da lista, o apontador prev aponta para o n anterior ao que se pretende remover e next representa o prprio n a remover). Para eliminar o n da memria usa-se o operador delete, para assim se libertar o espao de memria ocupado pelo n, sem levantar qualquer problema para a mquina. Finalmente, tambm implementado um destrutor da classe List. Exemplo de implementao do destrutor da classe:

List::List() { //n que ir percorrer a lista Node* actual; while (guard.nextNode != &guard) { //afectar "actual" com as caractersticas do n seguinte sentinela actual = guard.nextNode; //desligar o n da restante lista guard.nextNode = actual>nextNode; //eliminar o n da lista delete actual; } } A funo deste destrutor no mais que a de eliminar da memria todos os ns constituintes da lista. Para isso, vose eliminando os ns seguintes ao sentinela (guard.nextNode). S dever ser feita esta eliminao, obviamente, enquanto a lista no estiver vazia. Ora, a lista estar vazia significa que apenas permanece em memria o n sentinela. Portanto, a lista estar apenas vazia quando o n sentinela tiver como n seguinte ele prprio. Este facto testa-se atravs da condio guard.nextNode != &guard (reala-se o facto de se usar o operador referncia, para que assim se teste o endereo de memria do n seguinte a guard, j que nextNode do tipo apontador para Node). Enquanto a lista no estiver vazia, a operao realizada para eliminar o n da memria idntica realizada no mtodo de remoo. Em primeiro lugar necessrio desligar o n em questo da restante lista. O seu n anterior (que ser o

bool List::remove (int val) { Node* next, *prev; if (!find (val, prev, next)) //se o valor no existir na lista return false ; //indicar o insucesso da operao //desligar o n que continha o valor pretendido da restante lista prev->nextNode = next->nextNode; //libertar o espao de memria ocupado pelo n a eliminar delete next; //indicar o sucesso da operao return true ; }

Tambm o mtodo de remoo recorre ao mtodo auxiliar find para reconhecer se o valor em questo j est ou no contido na lista. Neste caso, indicado o insucesso da operao de remoo se o valor no estiver contido na lista (no faz qualquer sentido remover um valor que nem sequer est contido na lista). Da que se faa return false caso a chamada find (val, prev, next) retorne FALSE (atravs do operador ! nega-se o valor lgico da expresso a avaliar pelo if, daqui que se possa escrever simplesmente ! find (val, prev, next) ).

<32>

a programar

sentinela) passa a ter como n seguinte o n que era seguinte quele que se ir remover. Depois disto, basta simplesmente usar o operador delete, libertando-se assim o espao de memria ocupado pelo n. Para alm dos mtodos apresentados, numa implementao de uma lista simplesmente ligada em anel podem ser implementados outros mtodos. Um mtodo tambm bastante comum de uma lista o mtodo que imprime no console os valores de todos os ns; igualmente frequente a implementao de um mtodo que simplesmente procura por um determinado valor dentro da lista (til em caso do utilizador querer procurar por um valor especfico, sem o intuito de proceder a inseres ou remoes).

leitor tinha j adquiridos conceitos dentro desta linguagem. Aconselha-se ento aos leitores menos familiarizados com esta linguagem que realizem uma pesquisa e aprendizagem mais aprofundadas dos conceitos e temas mais bsicos. Atravs da redaco do presente artigo pretende-se desenvolver o gosto pela algoritmia junto dos leitores. bastante importante contrariar a mentalidade da nova gerao de programadores de que este mundo se cinge aprendizagem de linguagens de programao. Assiste-se, cada dia que passa, a um crescente desprezo pela algoritmia, a qual deveria ser tomada como o elemento mais importante dentro da programao.

Bibliografia
RODRIGUES, Pimenta; PEREIRA, Pedro; SOUSA, Manuela; Programao em C++ - Conceitos Bsicos e Algoritmos; Lisboa; FCA; 7. edio; ISBN 972-722-038-X (1998); http://www.portugal-a-programar.org/forum/index.php/ topic,2167.0.html http://www.portugal-a-programar.org/forum/index.php/ topic,4739.0.html http://pt.wikipedia.org/wiki/C%2B%2B

Concluso
Neste artigo foram apresentados alguns dos algoritmos mais conhecidos dentro do mundo da programao, recorrendo para isso linguagem C++. No entanto, e apesar da breve introduo e de cada exemplo ser acompanhado por descries e explicaes detalhadas, pressupe-se que o

Estudante de 17 anos, Mrio Pereira frequenta o curso de Cincias e Tecnologia, sendo um grande amante do mundo informtico. As suas linguagens preferidas so C++, C# e SQL. Aprendeu aquilo que sabe de programao maioritariamente como autodidacta, tendo um gosto especial por algoritmia e tecnologia das bases de dados.

Mrio Pereira

<33>

a programar

Manipulao de Ficheiros com Ruby

so opcionais, podemos apenas dar o caminho. Em seguida eliminamos o directrio criado com o mtodo rmdir. Podamos utilizar o mtodo delete em detrimento ao mtodo rmdir, pois ambos fazem exactamente o mesmo. A classe dir tambm permite criar Streams a directrios, permitindo desta forma percorrer o contedo de directrios de forma mais flexvel do que usando o mtodo foreach mostrado anteriormente. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dir = Dir.open( "/home/magician/" ) dir.path #=> "/home/magician" dir.tell #=> 0 dir.read #=> "Ficheiro 1" dir.tell #=> 599320 dir.read #=> "Ficheiro 2" dir.rewind dir.close

Neste artigo vamos explorar a linguagem Ruby e os seus recursos para manipulao de ficheiros e directrios bem como as capacidades de Input/Ouput disponveis. Para isso vo ser utilizadas as bibliotecas mais comuns como Dir, File e IO. Embora existam outras mais recentes e com mais recursos esto so as mais comuns, de simples utilizao e que servem para base de bibliotecas mais recentes.

Directrios
Para trabalhar com directrios vamos utilizar a Classe Dir. Esta classe disponibiliza diversos mtodos que permitem aceder e manipular directrios de forma rpida . Vamos comear por ver um exemplo simples, um pequeno script que verifica se o directrio actual o definido pelo programa. Depois de passar para o referido directrio todo o contedo impresso um a um.

1 WORK_DIR = "/home/magician/" 2 3 if Dir.pwd != WORK_DIR 4 Dir.chdir( WORK_DIR ) 5 end 6 7 Dir.foreach( WORK_DIR ) { |nome| puts nome } possvel ainda criar e eliminar directrios de forma muito simples, bastando usar os mtodos mkdir e rmdir que a classe Dir dispe. 1 Dir.mkdir( "/home/magician/Ruby" , 755 ) 2 3 Dir.rmdir( "/home/magician/Ruby" ) O exemplo acima no faz mais do que criar um directrio no caminho dado e com as permisses dadas. Estas permisses

Como podemos ver na linha 1 aberta uma ligao ao directrio. A partir dai podemos, entre outras coisas, percorrer todos os ficheiros e directrios contidos no directrio aberto. O mtodo tell (linha 5 e 9) retorna a localizao do apontador sob forma de inteiro, o mtodo read (linha 7 e 11) retorna sob forma de String a prxima entrada no directrio, retornando nil quando no existirem mais entradas. Por fim o mtodo rewind (linha 13) permite colocar o apontador da stream de novo no inicio e mtodo close (linha 15) fecha a ligao ao directrio.

Ficheiros
Criar um ficheiro no podia ser mais simples - basta utilizar a classe File: 1 file = File.new("exemplo.txt", "w") O exemplo acima cria o ficheiro exemplo.txt e abre o ficheiro em modo de escrita. Vamos agora ver que outros modos de abertura e criao de ficheiros existem. r - Read-Only. Comea no inicio do ficheiro. r+ - Read-Write. Comea no inicio do ficheiro. w - Write-Only. Passa o tamanho do ficheiro a zero ou cria um novo ficheiro para escrita.

<34>

a programar

w+ - Read-Write. Passa o tamanho do ficheiro a zero ou cria um novo ficheiro para escrita e leitura. a - Write-Only. Comea no fim do ficheiro caso este exista, caso contrrio cria o ficheiro para escrita. a+ - Read-Write. Comea no fim do ficheiro caso este exista, caso contrrio cria o ficheiro para escrita e leitura. b - (DOS/WIN only) Binary. Depois de criarmos um ficheiro, podemos precisar de apagar o ficheiro ou at mesmo mudar o nome desse ficheiro. Este processo tambm muito simples, para isso a classe File disponibiliza os mtodos rename e delete que permitem estas operaes. 1 File.new( "exemplo.txt", "w" ) 2 File.rename( "exemplo.txt", "novoExemplo.txt" ) 3 File.delete( "novoExemplo.txt" ) O exemplo acima cria o ficheiro exemplo.txt (linha 1), em seguida o nome do ficheiro modificado de exemplo.txt para novoExemplo.txt (linha 2), por fim o ficheiro eliminado (linha 3). A classe File permite ainda realizar mais algumas operaes teis, como por exemplo verificar se um ficheiro existe, se um directrio, se possvel ler ou escrever no ficheiro, entre outras. Vamos ver alguns exemplos: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 File.exist?( "ficheiro.txt" ) File.file?( "ficheiro.txt" ) File.directory?( "ficheiro.txt" ) File.readable?( "ficheiro.txt" ) File.writable?( "ficheiro.txt" ) File.executable?( "ficheiro.txt" ) File.zero?( "ficheiro.txt" ) File.size( "ficheiro.txt" ) File.size?( "ficheiro.txt" )

escrever no ficheiro e na linha 11 o mtodo executable verifica se o ficheiro ou no executvel. No final do exemplo podemos ver os mtodos zero?, size e size?. O mtodo zero? verifica se o ficheiro tem ou no tamanho igual a zero, os mtodos size e size? fazem exactamente o mesmo que retornar o tamanho do ficheiro em bytes, com a diferena que caso este seja nulo, o primeiro retorna 0 e o segundo nil. Para alm destes mtodos ainda possvel obter mais algumas informaes sobre os ficheiros como por exemplo data de criao, de edio e do ultimo acesso. Vamos por isso ver um exemplo desta funcionalidades. 1 File.ctime( "ficheiro.txt" ) Thu Jan 21 19:55:16 +0000 2008 2 3 File.mtime( "ficheiro.txt" ) Thu Jan 21 19:55:16 +0000 2008 4 5 File.atime( "ficheiro.txt" ) Thu Jan 25 19:55:16 +0000 2008 #=>

#=>

#=>

Como podemos ver, na linha 1 o mtodo ctime retorna uma String como a apresentada acima com a data e hora a que o ficheiro foi criado, o mesmo se passando com os mtodos mtime (linha 3) e atime (linha 5), mas neste caso estes mtodos retornam a informao referente ultima modificao e ao ultimo acesso do ficheiro respectivamente. A classe File tem ainda mais um recurso bastante til que o chmod. Este mtodo permite alterar as permisses de acesso ao ficheiro. As masks para as permisses so as seguintes. r - read w - write x - execute 0700 - rwx para o dono. 0400 - r para o dono. 0200 - w para o dono. 0100 - x para o dono. 0070 - rwx para o grupo. 0040 - r para o grupo. 0020 - w para o grupo. 0010 - x para o grupo. 0007 - rwx para os outros. 0004 - r para os outros. 0002 - w para os outros. 0001 - x para os outros. 4000 - Altera o user ID na execuo. 2000 - Altera o group ID na execuo. 1000 - Salva texto em swap mesmo depois de usar. A utilizao do mtodo chmod muito simples, basta abrir o ficheiro como foi mostrado e executar o mtodo chmod.

O exemplo mostra algumas das mais importantes operaes sobre ficheiros. Na linha 1, o mtodo exist? verifica se o ficheiro existe retornando true ou false, em seguida nas linhas 3 e 5 verificam se o ficheiro dado no path realmente um ficheiro ou se um directrio. Nas linhas 7 e 9 os mtodos readable? e writable? verificam se possvel ler ou

<35>

a programar

1 file = File.new( "ficheiro.txt", "r" ) 2 file.chmod( 0644 ) O exemplo acima d permisso de de leitura de escrita (4 + 2) ao dono e de leitura ao grupo e todos os outros utilizadores.

O exemplo acima abre o ficheiro em modo de leitura e l as trs primeiras linhas do ficheiro. Podamos ainda utilizar o mtodo gets que tem exactamente o mesmo funcionamento, com excepo de que o readline lana uma excepo quando o ficheiro chega ao fim. Para alm de ler tambm possvel escrever para o ficheiro.

Input/Ouput de Ficheiros
Ruby tem ainda mais uma classe muito til, a classe IO. Esta pode ser usada isoladamente ou em conjunto com a classe File, e permite trabalhar com fluxos de input e output. Em seguida vamos ver alguns exemplos da utilizao dos recursos desta classe atravs da classe File. 1 2 3 4 5 6 7 8 src = File.open("exemplo.txt","r") puts src.readline puts src.readline puts src.readline src.flush src.close #=> Linha 1 #=> Linha 2 #=> Linha 3

1 2 3 4 5 6 7 8

dst = File.open("exemplo.txt","w") dst.puts("Linha 1") dst.puts("Linha 2") dst.puts("Linha 3") dst.flush dst.close

Este exemplo utiliza o mtodo puts para escrever no ficheiro de destino, a cada execuo do puts automaticamente inserido um \n, para escrever sem a insero de nova linha podemos utilizar o mtodo putc este mtodo coloca um carcter e cada vez. Assim encerramos o artigo com toda a informao bsica necessria para trabalhar com ficheiros.

API
http://www.ruby-doc.org/core/classes/Dir.html http://www.ruby-doc.org/core/classes/File.html http://www.ruby-doc.org/core/classes/IO.html

Fbio Correia estudante de Engenharia Informtica na Universidade de vora. Partilhando o estudo com a moderao do frum Portugal-a-Programar e a participao na Revista Programar, como um dos redactores mais activos, ainda tem tempo para explorar algumas das suas linguagens preferidas: Java, PHP e a recente D.

Fbio Correia

<36>

tecnologias

Bioinformtica O lado do programador

Java, Python, Perl, C, C++ e C#[1]. Outras linguagens, como por exemplo Ruby, encontram tambm alguns adeptos entre os bioinformticos. Porm, para alm das diferentes escolhas no que toca a linguagens de programao, diferentes implementaes de diferentes estratgias tm um efeito preponderante na eficcia final do programa. Ainda assim, alguns problemas podem partilhar solues ou partilhar de ideias e conceitos que, partida, seriam teis num ou noutro caso isolado.

Reinventar a roda? Problemas e Solues


No seguimento do artigo Introduo Bioinformtica (11 Edio da PROGRAMAR), no qual abordei a existncia desta rea da informtica (e da biologia), passo agora a exemplificar, em termos mais prticos, as ferramentas e tcnicas mais populares, que so diariamente usadas por milhares de cientistas. Relembrando, bioinformtica define-se como o aplicar de tcnicas de matemtica aplicada, informtica, estatstica e inteligncia artificial a problemas concretos de biologia e/ou bioqumica. Entre os problemas mais comuns, temos o alinhamento de sequncias de DNA, a procura de genes (por associao e prvio conhecimento de outros), a assemblagem de genomas, a predio de estruturas de protenas (secundrias, tercirias e quaternrias), bem como outras reas menos moleculares, como a evoluo. Para cada uma destas tarefas h determinadas estratgias a seguir, e, obviamente, uma boa estratgia aplicada a outro problema, resulta provavelmente num desastre em termos de eficcia. A razo mais simples por detrs desta pouca plasticidade de mtodos, o diferente conjunto de requisitos que cada problema assume. Exemplificando; um problema comum em biologia o acesso a bases de dados de diferentes tipos e de diferentes especificaes. Isto resulta numa difcil uniformizao dos dados e, consequentemente, do tipo de mtodos a usar para os obter e tratar. Alm disso, necessrio pouco poder de computao puro para resolver estas tarefas. Interessa mais tirar partido de mtodos que faam boa gesto do trfego na web e que sejam eficientes a faz-lo. Obviamente, uma linguagem como C preterida em relao a outra como Perl. J noutro problema, como a predio de estruturas de protenas, onde milhes de complexos clculos matemticos so efectuados por segundo, j nos interessa tirar o mximo partido do poder de computao disponvel, recorrendo ento a linguagens que nos permitam desprezar operaes suprfluas e canalizar recursos para onde de facto interessam. No de estranhar ento que, ao procurar aplicaes de bioinformtica, se encontrem destas escritas nas mais variadas linguagens, sendo as mais usadas: Em cincia, os resultados so, geralmente, publicados. Nas cincias biomdicas em geral, partilham-se mtodos, ideias, conceitos e resultados, permitindo o avano rpido da investigao, uma vez que, salvo raros casos, h sempre algum que j tocou, nem que seja ao de leve, no problema que temos em mos, e que para ele contribuiu. Esta filosofia de partilha estende-se tambm bioinformtica. Apesar de haver programas cujo cdigo est fechado, h grupos de investigadores que se associaram para facilitar o trabalho na rea, construindo verdadeiros repositrios de cdigo, bem documentado e testado, que permite resolver problemas casuais de forma (quase) instantnea. Um bom exemplo a Open Bioinformatics Foundation. Dela, surgiram vrios projectos filhos, entre os quais o projecto BioPython, o BioPerl e o BioJava. Fora estes, mais famosos e mais maduros, uma pesquisa no google revela vrias comunidades, organizadas por linguagem, que servem de repositrios de cdigo, disponibilizando facilmente, ao utilizador, bibliotecas e mdulos que lhe simplificam o trabalho. Segue-se uma breve lista das que uma pesquisa simples por bio[nome da linguagem] produziu (infelizmente, ou felizmente, parece que ainda no houve alma que se lembrasse de criar um bioassembly!): BioPython www.biopython.org BioPerl www.bioperl.org BioJava www.biojava.org BioC++ - biocpp.sourceforge.net BioRuby www.bioruby.org Pegando numa delas, vamos analisar o potencial prtico deste tipo de abordagem. Escolhi o BioPython porque a com que trabalho e porque cdigo em Python , de facto, legvel e perceptvel mesmo a quem no programa na linguagem.

<37>

tecnologias

Exemplos
Um problema simples, ideal para comear, seria partir de uma sequncia de ADN e obter o respectivo ARN, a molcula que vai servir de molde sntese de uma protena. Lembrando conceitos bsicos de biologia molecular, h quatro tipos de bases (comuns) no ADN, cada uma identificada por uma letra (a inicial): Adenina, Guanina, Timina, Citosina. Para o ARN, troca a Timina pelo Uracilo. Para alm disso, temos que as bases so complementares entre si. Quando se d a reaco de transcrio (ADN ARN), cada base do ADN transcrita numa exacta do ARN: A-U, T-A, C-G, G-C. Podemos ento construir um programa que, dada uma sequncia de ADN, nos devolva a correspondente de ARN. Porm, j no tero pensado nisso antes de ns? De facto, j, e como o processo de transcrio no to linear como o descrevi, j houve quem tenha escrito (e complementado) algoritmos que reproduzem in silico a transcrio (quase) tal como in vivo. Se estivermos a usar Python, basta-nos aceder ao mdulo BioPython e chamar a classe Bio.Tools. O cdigo fica to simples como: (dada uma sequncia my_seq de ADN) from Bio.Tools import Transcribe transcriber = Transcribe.unambiguous_transcriber my_rna_seq = transcriber.transcribe(my_seq) print my_rna_seq Seq('GAUCGAUGGGCCUAUAUAGGAUCGAAAAUCGC', IUPACUnambiguousRNA()) Uma vantagem notvel de usar o mdulo bioPython para uma simples operao de transcrio, quando comparada com a nossa alternativa de escrever o algoritmo mo (que no passar das 5 linhas), a fiabilidade dos resultados. Na verdade, a sequncia my_seq no se trata de uma simples string. Trata-se de um objecto de uma outra classe, Bio.Seq, que verificada, a nvel de integridade biolgica, e que define as operaes que podem ser efectuadas sobre ela. Este simples mecanismo previne, por exemplo, o aplicar do mtodo Transcribe numa sequncia de ARN. Entre as outras classes do BioPython, podemos encontrar cdigo que funciona como parser de vrios formatos. As

diferentes bases de dados espalhadas pela web usam cada uma seu formato. Da, so necessrios diferentes parsers para podermos tratar esta informao. Em vez de os escrevemos ns (que d muito trabalho e complicado, experincia prpria), podemos aceder facilmente a classes que o fazem na perfeio. O exemplo que se segue bem ilustrativo da ilegibilidade de alguns formatos:

gi|6273290|gb|AF191664.1|AF191664 Opuntia clavata rpl16 gene; chloroplast gene for (resto da descrio)... TATACATTAAAGGAGGGGGATGCGGATAAATGGAAAGGC GAAAGAAAGAAAAAAATGAATCTAAATGATATAGGATTC CACTATGTAAGGTCTTTGAATCATATCATAAAAGACAAT GTAATAAA..(resto da sequncia).. Para obter informao de um ficheiro deste gnero (formato FASTA), usamos:

from Bio import Fasta parser = Fasta.RecordParser() file = open("ls_orchid.fasta") iterator = Fasta.Iterator(file, parser) cur_record = iterator.next() dir(cur_record) ['_colwidth', 'sequence', 'title'] Chamando os mtodos title ou sequence, podemos aceder selectivamente a diferentes campos de informao. E assim, poupamos o trabalho de escrevermos ns um parser. Como estes dois breves exemplos, h muitos outros. H classes que importam duas estruturas proteicas de bases de dados e depois fazem a superimposio das duas, permitindo compar-las e discernir semelhanas e diferenas. Por exemplo, na comparao entre duas protenas, uma funcional e outra mutante no-funcional, podemos ver quais os domnios (regies) que podem estar na origem da perca de funo. Outras classes permitem, com one-liners, aceder a bases de dados e delas recuperar

<38>

tecnologias

informao estruturada (tendo previamente definido as variveis search_command, search_database, search_term e return_format): from Bio.WWW import NCBI result_handle = NCBI. query(search, base_de_dados, term = termo_a_pesquisar, doptcmdl = formato(ex. FASTA))

Concluso
Concluindo, vemos que muita da contribuio de um bioinformtico facilitar o trabalho dos outros, seja construindo aplicaes que facilitam o trabalho do cientista de wet-lab (quem realmente trabalha com material biolgico), seja cedendo partes do seu cdigo que aliviam o esforo do cientista de dry-lab (um bioinformtico, portanto). Vemos tambm que, com o surgir dirio de novas bases de dados, novas tcnicas de anlise, novas tecnologias disponveis ao bilogo/bioqumico, h ainda muito trabalho a ser feito. Tal como disse no primeiro artigo sobre bioinformtica, h investigao em informtica para alm dos bits e dos bytes, onde o contributo muitas vezes relevante e visvel. uma questo de procurar, aventurar-se e de, no fundo, ter vontade de aprender.

Bibliografia
[1] Fourment, M., Gillings, M.R., A comparison of common programming languages used in bioinformatics, BMC Bioinformatics (9:82), 2008

Estranhamente, Joo Rodrigues no vem das hostes dos informticos tendo tido o primeiro contacto com a programao no 3 ano do curso. Um descontrado finalista da Licenciatura em Bioqumica em Coimbra, com particular interesse pelas reas da Bioinformtica e da Protemica, entrou para a Revista PROGRAMAR e com o objectivo de mostrar que h mais na informtica para alm de bits e bytes.

Joo Rodrigues

<39>

eventos

Evento Tecnologias Wireless

No passado dia 19 de Fevereiro, decorreu no Hotel Villa Rica em Lisboa, um evento dedicado s Tecnologias de Informao. Este evento gratuito e organizado pela Rumos destinou-se a apresentar as ltimas novidades relativas s tecnologias Wireless nomeadamente o tema da Voice Over Wireless e a Segurana das redes Wireless contando com o apoio da Cisco Systems Portugal e a colaborao da NextiraOne. A primeira apresentao de ttulo Cisco Wirelesss Portfolio Development Manager ficou a cargo do orador Ricardo Santos da Cisco Systems de Portugal. Foi uma apresentao dedicada a trs aspectos sendo eles: a apresentao da Soluo WLAN Cisco, a Mobilidade e Redes Wireless e por fim o Standard 802.11n. O orador focou o Cisco Unified Wireless Network, que uma soluo segura, escalvel e que permite uma grande flexibilidade e liberdade em redes Wireless. E abordou diversos aspectos da mesma. Tambm foram apresentas outras solues bastante interessantes, como o Hybrid Remote Edge AP, que conforme mostrou o orador, permitem terminar o trfico localmente e/ou tunneling back para um controlador central e assegura operao em stand-alone quando o link da WAN est em baixo. Outra soluo para a gesto de RF em tempo real o Radio Resource Management. Ao usarmos o RRM, o controlador que tem ao seu encargo um conjunto de Access Points, ir automaticamente ajustar cada AP de maneira a optimizar a cobertura de rede e a sua disponibilidade. Alm disso o RRM tambm permite fazer um balanceamento dinmico dos clientes, por outras palavras divide o mal pelas aldeias. Ou seja se um AP estiver muito sobrecarregado, o controlador ir sugerir que o cliente se ligue a um AP mais livre. Outra soluo apresentada e para mim foi a que gostei mais a Cisco Spectrum Intelligence Technology. Esta imagem um espectro de um AP com clientes, mostrado pelo orador Ricardo Santos.

At aqui tudo bem, mas como sabemos existem muitas interferncias prejudiciais para redes wireless e um sys adm, tem um trabalho complicado em descobrir o que est a causar o problema, onde est e tambm o que fazer. para isso que o Cisco Spectrum Intelligence Technology serve, para descobrir que aparelho est a causar a interferncia, onde est e o que fazer. O CSIT analisa o espectro e sabe dizer que esta imagem em baixo um espectro de um Micro-ondas.

Mais dois aspectos foram apresentados antes de passarmos para o 802.11n. O primeiro o Cisco Compatible Extensions (CCX) que permite uma interoperabilidade entre os clientes e a Cisco. Da o CCX suportar o 802.11k, r, u, v e w. O segundo aspecto o servio de localizao que conta com Chokepoints, CCX Tags, WiFi & CCX Devices, Wireless Location Appliance e Gesto WCS para saber exactamente onde determinado objecto est ou onde um cliente \ empregado se encontra. Depois foram apresentados alguns Componentes Tcnicos do 802.11n, como o MIMO (MRC, Beam forming, Spatial multiplexing), a utilizao de Canais de 40Mhz, a Agregao de Pacotes (mltiplos pacotes agregados numa transmisso,

<40>

eventos

Block acknowledgements) e o Backward Compatibility (Clientes a/b/g/n no mesmo AP). A utilizao destes aspectos permite melhorar em 5 vezes mais o envio de dados e diminuir em metade os Average Packet Retries. Apesar de no ter sido possvel a apresentao do Voice over Wireless, esta apresentao tambm feita no Porto foi uma abordagem do porqu usar VoIP mas neste caso em redes wireless e como isso possvel. Depois de um coffe break passamos para uma apresentao que particularmente me interessava bastante Segurana em Redes Wireless pelo orador Paulo Baptista da Rumos. Falou-se basicamente do IEEE 802.11: Standards, Ameaas e Solues. Foram apresentados os avanos que tem sido feitos desde o passado em que se usava WEP com uma autenticao fraca e com senhas estticas, passando por umas melhorias com o LEAP da Cisco em que j se usava senhas WEP dinmicas e autenticao usando MS-CHAP modificado. Tambm se utilizou o WPA com encriptao mais forte usando PSK\TKIP e uma autenticao mais forte usando EAP-FAST e PEAP. Actualmente usa-se o WPA2/802.11i em que se usa Wireless IDS, IEEE 802.11i com encriptao AES, autenticao 802.1x e uma gesto dinmica de senhas e o WPA2 com AES. O orador Paulo Baptista mostrou como muitos desses protocolos funcionavam em especial, mostrou algumas consideraes de como implementar o EAP. Resumidamente podemos dizer que as duas opes que podemos usar so o PEAP e o EAP-TLS, sendo a diferena entre elas apenas a politica de autenticao, o PEAP usa Password/OTP e o EAP-TLS usa um certificado digital. Claro que esta diferena vai ter consequncias no overhead do

software do cliente e podemos dizer que isso que ir levar a aplicao de um em detrimento de outro. De seguida o orador Paulo Baptista abordou algumas das ameaas mais comuns a uma rede wireless. Mas tambm mostrou diversas solues de segurana baseadas no CSWS Cisco Secure Wireless Solution. Estas abordavam diversos desafios que uma rede enfrenta. Entre muitas a que mais me chamou ateno foram: Como proteger a rede de utilizao indevida? Como identificar os clientes e ao mesmo tempo proteger a rede de vrus? Se no estou em erro foi nesta parte em que se apresentou uma soluo bastante interessante e que vou resumir brevemente. Um cliente novo chega empresa, liga-se rede, mas feito um scan ao laptop, se existirem falhas de segurana no laptop, a rede apenas deixa que o cliente aceda s pginas web com as respectivas actualizaes. No final o orador Paulo Baptista, mostrou algumas medidas a tomar para tornar a rede mais segura. Por fim o orador Daniel Ferreira da NextiraOne, apresentou um Case Study da aplicao de muitas destas medidas de segurana e no s, a uma situao real. Em resumo foi sem dvida alguma, uma excelente iniciativa tanto da parte da Rumos como da Cisco Systems e a NextiraOne em mostrar e em divulgar estas inovaes e tambm em mostrar o que se faz em Portugal nesta rea. Para mais informaes sobre este evento, visitem o site da Rumos em http://formacao.rumos.pt/noticia.rumos?id=400 Na PTsec, existe um tpico aberto sobre este evento na seco Wireless: http://forums.ptsec.net/index.php?show topic=1379.

Residente em Lisboa, Ciro Cardoso um grande amante do vasto mundo que a informtica em especial a segurana. Est actualmente a trabalhar na prxima etapa do percurso Cisco com a certificao CCNP. Gosta bastante da rea de redes, configurao de protocolos assim como a implementao.

Ciro Cardoso
<41>

internet

Cprogramming
CProgramming um site direccionado s linguagens C e C++. Nele possivel encontrar de tudo um pouco, desde tutoriais, compiladores, blocos de cdigo, at desafios de programao. uma boa ferramenta para quem quiser comear em cada uma destas linguagens.

www.cprogramming.com

Haskell.org
O site oficial da linguagem Haskell. possivel ver documentao de todo o tipo sobre esta linguagem, pesquisar blocos de cdigo, e compiladores. Um site fundamental para quem queira conhecer um bocado mais desta linguagem e do paradigma funcional.

www.haskell.org

Services SAPO
Uma coleco de webservices disponibilizados pelo SAPO.pt, onde se podem destacar a gerao de CAPTCHA, APIs do motor de busca, do sistema de mapas, ou mesmo verificar se h cobertura ADSL num determinado nmero de telefone.

services.sapo.pt

<42>

<43>

Queres participar na Revista PROGRAMAR? Queres integrar este projecto, escrever artigos e ajudar a tornar esta revista num marco da programao nacional? Vai a

www.revista-programar.info
para mais informaes em como participar, ou ento contacta-nos por

@portugal-a-programar.org
Precisamos do apoio de todos para tornar este projecto ainda maior... contamos com a tua ajuda!

revistaprogramar

Equipa PROGRAMAR
Um projecto Portugal-a-Programar.org

You might also like