Um manifestohttp://www.manifesto.blog.brArtigos de Um manifestoTue, 09 Feb 2010 05:30:36 +0000Yoomp.compt-brTroca de mensagens com criptografia em Java, usando AES.http://feeds.yoomp.com/36/379653/trocademensagenscomcriptografiaemjavausandoaesThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/379653/trocademensagenscomcriptografiaemjavausandoaesLogo deveria haver uma forma de criptografia disponível [...]]]>Logo deveria haver uma forma de criptografia disponível tanto no servidor como nos clientes, inicialmente um serviço em Java e o cliente seria no Android (depois outros surgiriam), com isso tem quer ser usado um algorítimo de chave simétrica, que permitisse recuperar a mensagem original de posse da chave de criptografia usada. Obviamente deveria ser um mecanismo eficiente.

Escolhi o AES por acreditar ser o padrão ideal atualmente, "lançado" em 2001 entrou em estudo pelo governo dos EUA e hoje é o seu padrão para troca de documentos, incluindo os "tops". Usando mesmo uma chave de apenas 128bits seria extremamente seguro, a chave pode ser de 128bits, 192bits ou 256bits.

Se você está desenvolvendo em Java EE 5 ou no Android (Ou qualquer Java 6, acredito eu, mas não confirmei), ambos já possuem a implementação deste algoritmo, caso a plataforma não possua você pode usar a implementação do Bouncy Castle, geralmente basta o Provider do bcprov-jdk16-*.jar .

O primeiro passo para a criptografia é definir uma chave, ela pode ser gerada automaticamente pelos mecanismos do sistema:

public byte[] key() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey key = keyGen.generateKey();
return key.getEncoded();
}

Esse método retorna o array de bytes de uma chave de 128bits, podemos usar 256bits mas esse algorismo nem sempre está disponível ou requer configurações especificas do JRE.

A criptografia trabalha com valores em Hexadecimal, assim a chave também usa valores em hexa, você pode criar uma chave com um array de hexas do tamanho que deseja da chave, uma chave de 128bits são 8 bytes (128/16), assim:

byte[] key = { 0x0f, 0xad, 0x54, 0x12, 0x00, 0xaf , 0x34, 0xff }

Em posse de uma chave de criptografia basta aplica-la a uma engine de criptografia, junto dos bytes da mensagem a ser encriptada, com o seguinte método:

public byte[] encode(byte[] input, byte[] key) throws NoSuchAlgorithmException, 
InvalidKeyException, IllegalBlockSizeException,
BadPaddingException, NoSuchPaddingException {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(input);
return encrypted;
}

Detalhe para o "AES/ECB/NoPadding" , isso usa o algoritmo AES e não faz o padding da mensagem.

Por trabalhar em hexadecimal, o algoritmo trabalha com blocos de 16 bytes, então a mensagem(seus bytes) devem ter uma tamanho múltiplo de 16 para não haver erros de "BadPaddingException: pad block corrupted, para isso podemos usar os seguintes métodos, que preenchem os espaços que faltam até formar o tamanho necessário com "null":

public String nullPadString(String original) {
StringBuffer output = new StringBuffer(original);
int remain = output.length() % 16;
if (remain != 0) {
remain = 16 - remain;
for (int i = 0; i < remain; i++) {
output.append((char) 0);
}
}
return output.toString();
}

Então podemos encriptar uma mensagem assim:

String mensagem = "Hello World!";
byte[] enc = encode(nullPadString(mensagem).getBytes(), key);

Para descriptografar a mensagem não tem mistério, basta o seguinte método:

public byte[] decode(byte[] input, byte[] key) throws NoSuchAlgorithmException, 
InvalidKeyException, IllegalBlockSizeException,
BadPaddingException, NoSuchPaddingException {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(input);
return decrypted;
}

A única diferença é o parâmetro passado ao Cipher, para de descriptografar.

Agora que podemos criptografar e decodificar as mensagens, precisamos garantir seu formato ao ser enviado via HTTP/HTTPS.

Novamente, como trabalhamos com Hexadecimal, ele não é simplesmente convertido para String, não sem perda, e a conversão de volta também traria riscos, ainda mais se for em plataformas diferentes.

Precisa-se então converter esses valores hexadecimais para uma representação "por extenso" destes, e que possa ser transformado de volta, e podemos alcançar isto com os seguintes métodos:

public String fromHex(byte[] hex) {
StringBuffer sb = new StringBuffer();
for (int i=0; i < hex.length; i++) {
sb.append( Integer.toString( ( hex[i] & 0xff ) + 0x100, 16).substring( 1 ) );
}
return sb.toString();
}

public byte[] toHex(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

Então para enviar uma mensagem podemos proceder da seguinte forma (contando que ambos possuem a mesma chave):

String mensagem = "Hello World!";
byte[] enc = encode(nullPadString(mensagem).getBytes(), key);
String msgParaEnviar = fromHex(enc);

Enviamos então via http a string msgParaEnviar, e ao recebe-la procedemos a decodificação:

byte[] msgEnc = toHex(msgRecebida);
byte[] msg = decode(msgEnc,key);
String mensagem = new String(msg).trim();

Assim temos a mensagem nas duas pontas, o trim é necessário devido ao "padding".

Veja o código da Classe de Criptografia que uso.

]]>
PHPDocumentor: Documentaçã de API em PHPhttp://feeds.yoomp.com/36/377734/phpdocumentordocumentadeapiemphpThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/377734/phpdocumentordocumentadeapiemphpOutra parte importante em um projeto, principalmente se está tratando de pacotes públicos e frameworks, é uma documentação completa. Mas documentar é um saco.

Parte da documentação incluí a API de classes, com os pacotes, cla [...]]]>Outra parte importante em um projeto, principalmente se está tratando de pacotes públicos e frameworks, é uma documentação completa. Mas documentar é um saco.

Parte da documentação incluí a API de classes, com os pacotes, classes, métodos e suas descrições. O padrão para documentação destes são o docblocks, ou phpdoc, que são comentários no código, sobre a classe, propriedade ou método, e possuem descrição e tags padrões para completar a documentação.

< ?php

/**
* Class Foo
*
* This class implements a hello speaker
* @package hello
*/
class Foo {
/**
* this is some useless var
*/
private $bar ;

/**
* Says hello to provided name
* @param string $name this is the name to be said
* @return Foo
*/
public function hello($name="world") {
echo "Hello, ".ucfirst($name)."!";
return $this
}
}

Esses comentários comuns são mais fáceis de escrever durante o desenvolvimento, e acrescentam muito a documentação. O padrão permite descriçoes muito mais complexas que isso, mas na maior parte das vezes não é necessário.

Agora que esses comentários estão em seu lugar basta usar uma ferramenta para transformar o código em documentação de verdade, pronto para ir online e estar disponível para consulta.

O PhpDocumentor é extremamente fácil de usar e instalar, e gera documentações razoáveis. Ele possui bastante opções de formato de saída (html, pdf, xml...) e templates, mas vou fazer só o básico aqui.

Para instalar o PhpDocumentor você pode usar o PEAR ( se você não conhece, está perdendo muito), basta rodar o comando a seguir:

# pear install PhpDocumentor

Se tudo correr bem você pode agora transformar seu código em documentação com a linha a seguir:

$ phpdoc -t docs -o HTML:default:eathli -d src

Nesse caso a documentação será salva na pasta docs, no formato HTML usando o template earthli, através dos arquivos da pasta src.

Basta apontar seu navegador para a pasta docs e navegar na documentação agora.

 

Documentação em PHP
 

 

Confira mais opções comentários, anotações e tudo mais no Manual do PhpDocumentor.

]]>
Testes Unitários em PHP com simpletesthttp://feeds.yoomp.com/36/377599/testesunitriosemphpcomsimpletestThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/377599/testesunitriosemphpcomsimpletestTestes automatizados são parte importante do desenvolvimento de software, apesar de ser a mais demorada prática a se aceitar, é a que mais traz benefícios. O seu uso deve ser simples, e por isso é bom o uso de um framework prático para [...]]]>Testes automatizados são parte importante do desenvolvimento de software, apesar de ser a mais demorada prática a se aceitar, é a que mais traz benefícios. O seu uso deve ser simples, e por isso é bom o uso de um framework prático para tal.

No começo escrevi scripts de testes "na mão" mesmo, com ifs e elses, mas, apesar de ser melhor que nada, não é nada prático se comparado ao uso de um bom framework. Então tentei usar o phpunit uma vez, mas achei mais complexo que o necessário, então parti para o simpletest.

O simpletest é realmente simples, basta fazer o download do pacote e descompacta-lo na sua pasta de testes, e em seguida é só escrever sua suite de testes.

Uma suite de testes é escrita da seguinte forma:


< ?php

include_once 'simplestest/autorun.php';

class AllTests extends TestSuite {
function allTests() {
$this->TestSuite("Meus testes");
$this->addTestCase(new MeuCasoDeTests1);
$this->addTestCase(new MeuCasoDeTests2);
}
}

?>

E cada caso de teste se define da sequinte forma:


< ?php

include_once 'simpletest/autorun.php';

class MeuCasoDeTests1 extends UnitTestCase {
function testFoo() {
$this->assertEqual("foo","foo");
}
function testBar() {
$this->assertEqual("foo","bar");
}
}
?>

Cada função no caso de teste iniciada por "test" será executada na ordem declarada, e o cada "assert" é um teste. Existem vários "asserts" disponíveis.

Basta acessar pelo browser a url do caso de testes ou da suite de testes e ter certeza de testar tudo, para garantir a qualidade do software.

]]>
Programando fora da zona de conforto: Programação Funcional e NoSQLhttp://feeds.yoomp.com/36/376610/programandoforadazonadeconfortoprogramaofuncionalenosqlThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/376610/programandoforadazonadeconfortoprogramaofuncionalenosqlMais alguns links da série de programação funcional, e também adcionar o NoSQL a lista, banco da dados não relacionais para resolver o problema da escalabilidade.

  • Mais alguns links da série de programação funcional, e também adcionar o NoSQL a lista, banco da dados não relacionais para resolver o problema da escalabilidade.

     Divarta-se. 

    ]]>Linux em um pendrive: Debian e Enlightenment (E17) persistente.http://feeds.yoomp.com/36/376046/linuxemumpendrivedebianeenlightenmente17persistenteThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/376046/linuxemumpendrivedebianeenlightenmente17persistenteHistória

     

    Enlightenment E17Enlightenment E17
     

     

    Além de já ter usado o Linux em um pendrive com o DSL, que é uma das distros que melhor se adaptam ao estilo, é fácil hoje instalar outras distros semelhantes, como o Slax, o SliTaz (muito bom) e o TinyCore(abandonei o DSL por este), com seus 10MBs.

    A boa noticia é que hoje é bem mais fácil rodar um linux a partir de um pendrive, temos o projeto pendrive linux, com vários distros preparadas para tal, e o unetbootin para configurar e ?bootar? qualquer ISO a partir de um pendrive.

    Parti então para as distros completas: Ubuntu e Debian. O Ubuntu eu não gosto, acho um desktop muito fraco. O Debian iniciei com o projeto do Debian Live, oficial, mas este se baseia na versão estável, então está muito antigo nos pacotes. Mas como o debian é o debian era possível reconstruir o Debian live em qualquer versão, com o Debian Live Helper, mas também dava muito trabalho e demorava muito.

    Foi ai que pensei em ficar com as minimalistas, entre o TinyCore e o SliTaz. Não fiquei com o SliTaz por que me parecia pacotes muito antigos, em especial o kernel, já o TinyCore eu fiquei com preguiça mesmo, afinal ainda seria muito parecido com o DSL.

    Ai eu esbarrei no Elive. Na verdade já paquerava o Enlightenment tem um bom tempo, mas E16 não é tão interessante, e o E17 envolvia muitas gambiarras, e as versão ?fáceis? de instalar não estavam muito legais.

    Uma boa opção me pareceu usar o Elive, baseado no debian, que já vem configurado com tudo de bom e melhor do Enlightenment de desenvolvimento, por isso resolvi testa-lo.

    Como fazer

     

    Unetbootin com E17 ELIve
     

     

    Primeiro instale o Unetbootin, que está presente na maioria das distribuições modernas:

    # aptitude install unetbootin

    Executando-o como root, o unetbootin já existem diversas distros prontas, ele mesmo se encarrega de baixar a ISO configurar o pendrive e torná-lo bootável com o syslinux.

    Você pode também fazer o Download da ISO do ELive você mesmo(eu fiz assim), e seleciona-la no unetbootin, e então é só seguir e iniciar o processo, não tem mistério nenhum.

    O passo seguinte, após o unetbootin dizer que terminou, é configurar um arquivo para que o Elive salve as alterações. Você precisa primeiro criar um arquivo para ser a ?partição? da persistencia:

    # dd if=/dev/zero of=elive-rw bs=1M count=1024

    O valor do count diz o tamanho do arquivo em megabytes, veja quanto resta no pendrive e quanto você quer usar, no exemplo vai ter 1GB (mais ou menos).

    Em seguida formate-o como ext3, apenas confirme:

    # mkfs.ext3 elive-rw

    Agora pode copiar o arquivo elive-rw para a raiz do pendrive, e editar o arquivo de boot ?syslinux.cfg? nessa mesma raiz. No linha append da entrada padrão adcione ?persistent=elive-rw? e salve.

    Basta desmontar o pendrive e rebootar o computador com a BIOS configurada para carregar apartir do pendrive e curtir no ambiente. Trate-o como um netbook, pois o espaço é pouco.

    Um detalhe importante, que me atrapalhou a testar o elive antes, é que ele não roda no Qemu(e KVM) por algum motivo, mas funciona no VirtualBox e VMWare, eu acredito.

    Agora posso carregar meu lindo ambiente de programação para todo canto, combinado com controle de versão, e impressionar todo mundo com como o linux pode ser bonito :D

    ]]>
    Compartilhando internet pela rede sem fio no linuxhttp://feeds.yoomp.com/36/371737/compartilhandointernetpelaredesemfionolinuxThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/371737/compartilhandointernetpelaredesemfionolinux
    Aqui vou explicar como configurar seu computador/notebook como hotspot wifi, para compartilhar a internet na rede sem fio, com o mínimo de "segurança" [...]]]>

    Aqui vou explicar como configurar seu computador/notebook como hotspot wifi, para compartilhar a internet na rede sem fio, com o mínimo de "segurança" WEP apenas.

    O Primeiro passo é saber qual a interface que chega a conexão com a internet, no geral se é internet discada, 3G ou se usa o pppoe a interface é ppp0, se a internet chega roteada pela rede é a mesma da interface de rede, eth0 ou outro. Aqui uso internet móvel 3G, então conecta em ppp0.

    Temos então que mascarar o encaminhamento de pacotes dessa interface por um nat, usando as regras do iptables. Carregue o módulo de nat, definir a regra e ativar o encaminhamento no sistema, com os seguintes comandos:

    # modprobe iptable_nat
    # iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
    # echo 1 > /proc/sys/net/ipv4/ip_forward

    O próximo passo é configurar a rede wifi, com os seguintes comandos:

    # ifconfig wlan0 down
    # ifconfig wlan0 192.168.0.1 netmask 255.255.255.0 broadcast 192.168.0.255
    # ifconfig wlan0 up

    Em seguida definimos as caracteristicas da rede sem fio, definindo o nome, o modo ad-hoc, a chave de encriptação e para apenas aceitar com encriptação, os comandos:
    # iwconfig wlan0 essid "acer"
    # iwconfig wlan0 mode ad-hoc
    # iwconfig wlan0 key 's:diogo'
    # iwconfig wlan0 key restricted

    Para os clientes receberem as configurações devidas você precisará agir como cliente dhcp (ou configurar manualmente a rede nos clientes), você pode instalar o servidor com o seguinte comando:

    # aptitude install dhcp3-server

    Para configurar o servidor, edite o arquivo /etc/dhcp3/dhcpd.conf, conforme:

    ddns-update-style ad-hoc;
    option domain-name "home.org";
    option domain-name-servers 208.67.222.222, 208.67.220.220;
    default-lease-time 600;
    max-lease-time 7200;
    authoritative;
    log-facility local7;
    subnet 192.168.0.0 netmask 255.255.255.0 {
    range 192.168.0.10 192.168.0.254;
    option routers 192.168.0.1;
    option broadcast-address 192.168.0.255;
    }

    Com o dhcp configurado, basta ativa-lo na interface da rede sem fio.

    # dhcp3d wlan0

    Agora os clientes podem se conctar a sua rede e navegar na sua internet. Você pode tentar configurar outro meio mais seguro que WEP, mas eu não sei ainda :P e definir regras no dhcp e iptables limitando os MACs e IPs, mas isso fica para próxima.]]>
    Downgrade de versão no Debianhttp://feeds.yoomp.com/36/369748/downgradedeversonodebianThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/369748/downgradedeversonodebianSabe, sou um feliz usuário de Linux. Mesmo tendo um hardware complico, isso melhorou com o tempo.

    A história deste post está [...]]]>Sabe, sou um feliz usuário de Linux. Mesmo tendo um hardware complico, isso melhorou com o tempo.

    A história deste post está no primeiro link.

    Vou explicar aqui o simples passo-a-passo para fazer o downgrade de versão do debian, sem reinstalar o sistema ou fazer algo mais complicado que o apt-get costumeiro. Se você usa o debian, sabe que pode fazer isso com a consciencia limpa.

    O debian tem um sistema de "pinning" para o apt, que permite, entre outras coisas, definir preferencias de versões de pacotes, e vamos usar isso para fazer o downgrade, já que por padrão o apt escolhe os pacotes mais novos.

    Primeiro devemos acertar os repositórios desejados, eu estou voltando do unstable(Sid) para o testing(Squeeze), então meu /etc/apt/sources.list ficou assim:

    # deb ftp://ftp.br.debian.org/debian/ unstable main contrib non-free 
    # deb ftp://ftp.br.debian.org/debian-multimedia/ unstable main

    #deb ftp://security.debian.org/ testing/updates main contrib non-free
    deb ftp://ftp.br.debian.org/debian/ testing main contrib non-free
    deb ftp://ftp.br.debian.org/debian-multimedia/ testing main

    #deb http://apt.wicd.net/ sid extras

    Eu apenas comentei os "unstable" e adcionei as linhas do "testing".

    Agora vamos configurar o tal "pin", para editar suas preferências do apt e dpkg você pode editar o arquivo /etc/apt/preferences, ou criar um arquivo em /etc/apt/preferences.d/ para cada configuração, no caso para o downgrade para o testing, fiz um assim:

    X-comment: Force downgrade to testing.
    Package: *
    Pin: release a=testing
    Pin-Priority: 1100

    Veja que facilmente podemos criar outros, para escolher versões especificas de cada pacote, bastando acerta o "pin-priority" para isso.

    Após configurado, basta atualizas a lista de pacotes e instala-los:

    # dselect update
    # aptitude dist-upgrade

    E Pronto, seu sistema está "atualizado", é só reiniciar o X, se não mudou o Kernel nem precisa reiniciar. Se você acha que mudou muitos módulos do kernel em uso pode fazer um "depmod" e depois um "modprobe" nos módulos desejados.

    Seja feliz com seu sistema "novo" :)

    ]]>
    Introdução a linguagem Lua, você vai querer aprender também.http://feeds.yoomp.com/36/363143/introduoalinguagemluavocvaiquereraprendertambmThu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/363143/introduoalinguagemluavocvaiquereraprendertambmEm busca de uma programação poliglota, e entender as vantagens da cada linguagem oferece, iniciei meus estudos na linguagem Lua.

    Histórico 

     Lua é uma [...]]]>Em busca de uma programação poliglota, e entender as vantagens da cada linguagem oferece, iniciei meus estudos na linguagem Lua.

    Histórico 

     Lua é uma linguagem de extensão, criada nos laboratórios da PUC-RJ, com o objetivo de ser simples de ser embarcada. Isso é, ele é extremamente pequena, sucinta, de sintaxe simples, esta presente praticamente em qualquer sistema. É uma verdadeira "write once, run everywhere"(bem mais que java). O pacote de Lua, com documentação, código fonte e exemplos tem cerca de 800KBs, apenas o runtime compilado(no linux) tem 150KBs. São 1700 linhas de código C portável, o mesmo código compila em várias plataformas.  

    Roda em Unix, Linux, Windows, e em várias plataformas embarcadas, como celulares e setop boxes, robôs entre outros. Pode ser incluída em qualquer aplicação feita em outra linguagem , com quase nenhum overhead. Para ter melhor noção, um interpretador Lua completo em puro Java (tanto J2ME quanto J2SE), tem cerca de 150KBs. É usada como linguagem de extensão em produtos da Adobe, roda no Android, esta no Ginga (da TVDigital), e é muito usada em Jogos, como o sempre citado World of Warcraft.

    E por que não fazer tudo em Lua então? Lua foi pensada em extensão de aplicativos, então a biblioteca básica é bem limitada, não possui as milhares de funções para tudo como teria em Java ou PHP ou Ruby ou Python ou Outra. Seus 150KBs incluem apenas o necessário, muito tem disponível em módulos externos, como os do LuaRocks. Embora seja possível para certas aplicações, mas não é foco.

    Enfim, vendido o peixe de Lua. Agora é demonstrar, afinal ?Show me the code?.

    Exemplos 

    Primeiro o essencial, lua é Imperativo, tem funções como cidadão de primeira classe(ah, deu para entender) e tudo é armazenado em tabelas. Tabelas são como arrays, mas são tabelas, depois eu explico. É tipagem dinamica, essencialmente não é orientada a objetos(pode ser simulado), possui escopo e é modular. Vamos ao exemplo.  

      -- rss.test.lua

    local xml = dofile("xml.lua")
    local sample = "<?xml ?><channel><rss><title>Lua Rock!</title>"
    sample = sample .. "<item><title>Item 1</title></item>"
    sample = sample .. "<item><title>Item 2</title></item>"
    sample = sample .. "</rss></channel>";
    local rss = xml.parse_rss(sample)
    assert(rss[1].title == "Item 1","Invalid Item 1 title")
    assert(rss[2].title == "Item 2","Invalid Item 2 title")
    print("rss tests ok")

    Esse simples exemplo é o arquivo de testes de uma biblioteca de parser de rss que uso. O uso do modificador "local" indica o escopo mais fechado possível dessa variável. O não uso de "local" implica numa variável "global", visível em toda a aplicação.  

    A função "dofile" carrega um arquivo (como se fosse um include), esse arquivo carregado pode retornar uma ou mais variáveis, no caso o xml.lua me retorna uma tabela.

    A chamada de função é normal, no caso o xml é uma tabela, e um dos seus índices (parse_rss) é uma função que recebe um argumento e retorna uma tabela.

      Fato interessante sobre tabelas em Lua, é que os índices numéricos começam em 1, e não em 0 como estamos acostumados.

      Em "rss[1].title", eu pego o item de índice 1(o primeiro), da tabela "rss" e o item de índice title dentro desta. No "assert" eu garanto que a expressão retorne True, do contrário levanto o erro no segundo argumento. 

      O arquivo de rss é assim: 

      -- rss.lua
    local xml = dofile("utils/xml.lua")
    xml.parse_rss = function (str)
    local rss = {};
    local t = xml.parse(str)
    local channel = t[2][1]
    for k,v in pairs(channel) do
    local label = v['label']
    if label == "item" then
    local item = {}
    for k,v in pairs(v) do
    local label = v['label']
    if label and v[1] then
    item[label] = v[1]
    end -- if label and value
    end --for pairs in v
    table.insert(rss,item)
    end -- if is item
    end -- for item in channel
    return rss
    end
    return xml

     

    Novamente eu carrego um parser xml externo, e na tabela xml eu adcione um índice, o parse_rss. Nesse índice eu ligo uma função, que recebe um argumento. Veja que não tem tipo fixo, eu poderia usar assert para garantir o tipo.

    Eu defino então a variável ?rss? como uma tabela vazia. Então faço um loop for nos itens retornados pelo parser xml. A função ?pairs? retorna as chaves (k) e os valores(v) de uma tabela.

    Temos então um IF padrão, nova tabela e mais um for. Então eu uso o ?insert?, ?table?, que é uma tabela embutida no core do lua. E retorno o RSS, o arquivo então retorna a tabela com as funções.

    O parser XML é deveras grande, não vale a pena passa-lo aqui, e isso tudo foi apenas para dar um visão geral na estrutura da sintaxe da linguagem. Vamos agora no passo-a-passo de verdade.

    Tutorial 

    Em Lua, funções são objetos de primeira classe, então podemos por exemplo ter funções ?curried?, como no exemplo abaixo:

      -- curry.lua

    function soma(n)
    return function(n2)
    return n + n2
    end
    end

    local f2 = soma(2)
    local soma2e3 = f2(3)
    assert(soma2e3 == 5)

     

    Podemos levar um pouco alem:

      
    -- curry.lua
    local somador = function(n)
    local soma = n
    function f(n2)
    if type(n2) == "number" then
    soma = soma + n2
    return f
    else
    return soma
    end
    end
    return f
    end

    local total = somador (1) (2) (3) ()
    print(total)

    local somador = function (itens)
    assert(type(itens) == "table")
    local soma = 0;
    for k,v in pairs(itens) do
    soma = soma + v
    end
    return soma, #itens
    end

    local total,n = somador {
    1,2,3
    }
    print(total,n)

    local somador = function(```)
    local soma = 0;
    for k,v in pairs(arg)do
    if type(k) == "number" then
    soma = soma + v
    end
    end
    return soma
    end

    local total = somador(1,2,3)
    print(total)

     

    São as várias formas de fazer a mesma coisa, veja no penúltimo somador uma característica legal, uma função pode retornar mais de uma variável.

    Agora que você conhece como fazer funções, loops e condicionais, vamos tratar das tais tabelas.

      --tabelas.lua
    local tab = {
    "um","dois",
    x="3",
    y=function() return "hello" end
    }
    table.insert(tab,"cinco")
    table.remove(tab,2)
    local final = table.concat(tab," , ") -- apenas numéricos
    print(tab[1], tab[2], tab["x"],tab.y,tab["y"](),tab[5],final)

     

    Entendeu?

    A ultima parte que quero tratar nesse texto é sobre coroutines, que são as ?threads? do lua, incluído no core da linguagem, exemplo geral:

      --co.lua
    local hello = coroutine.create(function(name)
    print ("hello "..name)
    end)


    coroutine.resume(hello,"diogo")

    local hello2 = coroutine.create(function(name)
    repeat
    print("hello you, "..name)
    name = coroutine.yield(name)
    until not type(name) == "string"
    end)

    local h2 = coroutine.resume(hello2,"diogo")
    local h3 = coroutine.resume(hello2,"diego")
    local h3 = coroutine.resume(hello2)
    local h4 = coroutine.resume(hello2)

     

    Acho que com esses exemplo já dá para decidir se quer ou não aprender Lua. Caso queira, o melhor lugar é a wiki da documentação de lua.

      Termino com um exemplo de uso real, uma função que realiza uma busca na wikipedia e retorna o resultado, o JSON eu achei na internet, e o http usa o Lua Socket, o wikipedia.lua.  

    ]]>
    Game Over: Linux ganhou no Acer 5050!http://feeds.yoomp.com/36/361100/gameoverlinuxganhounoacer5050Thu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/361100/gameoverlinuxganhounoacer5050Eu tenho um hardware complicado. Meu notebook é um acer 5050 e sempre deu trabalho Linux, mas firme e forte segui com minha saga de suporta-lo 100 [...]]]>Eu tenho um hardware complicado. Meu notebook é um acer 5050 e sempre deu trabalho Linux, mas firme e forte segui com minha saga de suporta-lo 100% no pinguim.

    E a pouco tempo essa saga chegou no fim, e é Game Over, com vitória para o usuário, vitória do pinguim!

    Basta um kernel recente e o Linux funciona no Acer 5050. Sem truques, sem mágica, sem compilações complicadas com parametros sinistros, agora quando eu quiser atualizar o  kernel, o farei sem medo.

    Muito obrigado ao desenvolvedores do Kernel Linux. Tux #win. 

    ]]>
    O Shouter e o TwitterFlow2http://feeds.yoomp.com/36/359984/oshoutereotwitterflow2Thu, 01 Jan 1970 00:33:29 +0000http://feeds.yoomp.com/36/359984/oshoutereotwitterflow2Como disse, o importante é programar. Então como bom nerd e tentando manter o ânimo com projetos pessoais, estou sempre com proje [...]]]>Como disse, o importante é programar. Então como bom nerd e tentando manter o ânimo com projetos pessoais, estou sempre com projetinhos.

    Semana passada consegui licenciar com o SHOUTCast(tm) Radio para (re)lançar o Shouter. O Shouter é um player que permite navegar entre as estações de radio online do SHOUTCast(tm) Radio , salvar suas favoritas e ouvi-la, é claro.

    Foi um projeto curto, em 2 dias já estava funcional, mais 2 dias estava redondo. Mas demorou quase um mês para licenciar, fora encher de coisas a interface. Mas, enfim, saiu.

    E têm também o TwitterFlow, já havia feito o cliente para twitter, mas estava muito insatisfeito com o resultado. Então depois de um tempo resolvi fazer um do zero, ai começou na quinta-feira 3 de setembro o TwitterFlow2, do zero, com o grande diferencial de usar OAuth.

    Também já esta online, apesar de estar propenso a muitos erros ainda, e têm bastante o que acertar, mas estou satisfeito com o resultado.

    Enfim, é isso. Estou precisando voltar mais ao PHP...

    ]]>