Posts de November, 2010

[Rafael Biriba] HTML5: Trocando mensagens entre a página e iframes

Saturday, November 27th, 2010

Por questões de segurança e privacidade, os navegadores impedem que haja comunicação entre os conteúdo de diferentes domínios. Ou seja, scripts em diferentes dominios (cross-domain) não podem se interagir.

Na prática seria assim… Já imaginou, se um simples anúncio do google adsense, pudesse controlar a página em que ele foi colocado ? Ele iria alterar o background, trocar titulos na página e bagunçar tudo.

Por isso essa é uma importante funcionalidade nos navegadores, pois evita com que páginas desconhecidas (em domínio diferente) de controlar a página atual em que está visitando.

Com o HTML5, podemos contornar esse problema facilmente. Utilizando o Cross-document messaging, podemos estabelecer comunicação entre páginas e documentos no html, sem se procupar com a origem do domínio. Foi desenvolvido justamente para permitir essa comunicação, sem colocar em risco a segurança da página. (cross-site scripting attacks).

Cross-site messaging funciona apenas no HTML5, e está disponível nas seguintes versões de navegadores:

  • Internet Explorer 8.0+
  • Firefox 3.0+
  • Safari 4.0+
  • Google Chrome 1.0+
  • Opera 9.5+

Vejamos então um exemplo prático:

Digamos que em sua página inicial, você tem o seguinte iframe.

1
<iframe id="exemplo-iframe" src="http://www.exemplo.com/teste.html"></iframe>

Se você quiser mandar o titulo do seu site para o iframe, você precisa usar o cross-document messaging pois ele está em um outro domínio. Veja abaixo como você faria para disparar essa mensagem:

1
2
3
4
<script language="javascript">
var iframe = document.getElementById("exemplo-iframe").contentWindow;
iframe.postMessage("Titulo do Site", "*");
</script>

Na linha 2 é onde obtemos o controle do iframe. Na linha 3 é onde disparamos a mensagem. Note que estamos passando um “*” como segundo argumento do postMessage, o que significa que a mensagem é enviada para todos os domínios. Poderiamos ser mais específicos e disparar apenas para o domínio do iframe (exemplo.com).

Agora, no lado do iframe, só falta receber essa mensagem. Veja abaixo o exemplo do código que o iframe deve carregar:

1
2
3
4
5
6
7
8
<script language="javascript">
function displayMessage(event) {
    var message = event.data;
    alert(message);
    event.source.postMessage("Recebido com sucesso!",  "*");
}
window.addEventListener("message", displayMessage, false);
</script>

Vou começar explicando pela linha 7,  onde é estabelecido o listener, que é responsável por “escutar” as mensagens recebidas e chamar a função displayMessage. Na linha 3, recebemos a mensagem numa variável. Na linha 4 exibimos ela no alert do javascript. Na linha 5, é disparado uma mensagem para o “remetente”, ou seja, podemos enviar uma mensagem para confirmar o recebimento por exemplo.

Lembrando que para que a mensagem enviada na linha 5 seja recebida corretamente pela sua página inicial, você tem que adicionar um listener, da mesma forma que foi feito no iframe. Fazendo assim, é possível fazer trocas de informações entre as páginas de diferentes domínios.

No exemplo acima, qualquer site estaria habilitado em trocar informações com aquela página do iframe (http://www.exemplo.com/teste.html) e dependendo do contexto e de como foi implementado, pode vir a ser uma falha de segurança, portanto, utilize com cuidado.

Google Bookmarks Twitter Yahoo Messenger Orkut Hotmail Google Gmail Delicious Share

Leia também:


[Rafael Biriba] HTML5: Trocando mensagens entre a página e iframes

Saturday, November 27th, 2010

Por questões de segurança e privacidade, os navegadores impedem que haja comunicação entre os conteúdo de diferentes domínios. Ou seja, scripts em diferentes dominios (cross-domain) não podem se interagir.

Na prática seria assim… Já imaginou, se um simples anúncio do google adsense, pudesse controlar a página em que ele foi colocado ? Ele iria alterar o background, trocar titulos na página e bagunçar tudo.

Por isso essa é uma importante funcionalidade nos navegadores, pois evita com que páginas desconhecidas (em domínio diferente) de controlar a página atual em que está visitando.

Com o HTML5, podemos contornar esse problema facilmente. Utilizando o Cross-document messaging, podemos estabelecer comunicação entre páginas e documentos no html, sem se procupar com a origem do domínio. Foi desenvolvido justamente para permitir essa comunicação, sem colocar em risco a segurança da página. (cross-site scripting attacks).

Cross-site messaging funciona apenas no HTML5, e está disponível nas seguintes versões de navegadores:

  • Internet Explorer 8.0+
  • Firefox 3.0+
  • Safari 4.0+
  • Google Chrome 1.0+
  • Opera 9.5+

Vejamos então um exemplo prático:

Digamos que em sua página inicial, você tem o seguinte iframe.

1
<iframe id="exemplo-iframe" src="http://www.exemplo.com/teste.html"></iframe>

Se você quiser mandar o titulo do seu site para o iframe, você precisa usar o cross-document messaging pois ele está em um outro domínio. Veja abaixo como você faria para disparar essa mensagem:

1
2
3
4
<script language="javascript">
var iframe = document.getElementById("exemplo-iframe").contentWindow;
iframe.postMessage("Titulo do Site", "*");
</script>

Na linha 2 é onde obtemos o controle do iframe. Na linha 3 é onde disparamos a mensagem. Note que estamos passando um “*” como segundo argumento do postMessage, o que significa que a mensagem é enviada para todos os domínios. Poderiamos ser mais específicos e disparar apenas para o domínio do iframe (exemplo.com).

Agora, no lado do iframe, só falta receber essa mensagem. Veja abaixo o exemplo do código que o iframe deve carregar:

1
2
3
4
5
6
7
8
<script language="javascript">
function displayMessage(event) {
    var message = event.data;
    alert(message);
    event.source.postMessage("Recebido com sucesso!",  "*");
}
window.addEventListener("message", displayMessage, false);
</script>

Vou começar explicando pela linha 7,  onde é estabelecido o listener, que é responsável por “escutar” as mensagens recebidas e chamar a função displayMessage. Na linha 3, recebemos a mensagem numa variável. Na linha 4 exibimos ela no alert do javascript. Na linha 5, é disparado uma mensagem para o “remetente”, ou seja, podemos enviar uma mensagem para confirmar o recebimento por exemplo.

Lembrando que para que a mensagem enviada na linha 5 seja recebida corretamente pela sua página inicial, você tem que adicionar um listener, da mesma forma que foi feito no iframe. Fazendo assim, é possível fazer trocas de informações entre as páginas de diferentes domínios.

No exemplo acima, qualquer site estaria habilitado em trocar informações com aquela página do iframe (http://www.exemplo.com/teste.html) e dependendo do contexto e de como foi implementado, pode vir a ser uma falha de segurança, portanto, utilize com cuidado.

Google Bookmarks Twitter Yahoo Messenger Orkut Hotmail Google Gmail Delicious Share

Leia também:


[Emerson Macedo] [Caos no Rio - OFF TOPIC] Refletindo sobre valores da vida

Friday, November 26th, 2010

Hoje o Rio de Janeiro viveu um dos capítulos mais feios de sua linda história. Considerada a Cidade Maravilhosa, hoje vimos uma cidade sitiada, com o medo imperando e muita apreensão nas ruas. O motivo de eu escrever esse post sobre o assunto não é diretamente o que aconteceu, mas sim as causas do ocorrido.

A minha história

Pra quem não sabe, eu nasci no suburbio aqui do Rio de Janeiro, mais precisamente no Hospital Albert Swaizer em Realengo e morava num barraco dentro de um beco numa espécie de favela em Padre miguel (atrás da menina de mochila rosa) — As imagens de hoje são muito melhores de quando eu era criança — Lá era uma situação muito difícil, pois a maioria das pessoas era envolvida com alguma coisa errada. Meus Pais se separaram e fui morar na casa dos meus avós com minha tia, que era jovem e trabalhava num emprego modesto. Meu avô trabalhava na companhia de lixo (CONLURB) e minha avó era dona de casa. Essa tia — mãe do coração que me criou — tratou de me tirar daquele ambiente e não mediu esforços para que eu não fosse influenciado por aquele meio. Sempre me deu boa educação (inclusive em casa) e me afastando das amizades erradas. Vários dos meus coleguinhas, que brincavam comigo de bola de gude, pipa, futebol, e outras coisas mais, já morreram ou estão presos. Alguns outros felizmente conseguiram se safar.

Contei essa história apenas pra mostrar que não estou querendo dar uma de entendido, mas eu sei muito bem como funcionam as coias em ambientes desse tipo.

Atacando o problema na Raiz

Após tudo que aconteceu hoje, li muitas mensagens no twitter de manifestação de ódio para com os bandidos, a maioria desejando uma chacina. Veja bem, eu não defendo em hipótese alguma que haja impunidade. Pelo contrário, independente de qualquer coisa, cada cidadão é responsável pelos seus atos e deve responder pelo que faz. O que me incomoda na verdade é que no meu modo de ver as coisas, nossa indignação está sendo direcionada de forma equivocada.

As crianças e a marginalidade

É sabido por todos que cada vez mais os traficantes estão iniciando crianças de 10, 12 anos e por algumas vezes até mais novas para começarem no tráfico. Muitas desssas sequer tiveram a oportunidade de estudar. Muitos bandidos começam oferecendo a essas crianças sexo com mulheres mais velhas, depois drogas e ai a criança já está completamente dominada. Crianças nessa idade ainda não tem a personalidade formada, portanto acho injusto atribuir culpa a uma criança dessas, pois a maioria não tem condições de resistir a esses assédios.

Eu me lembro quando em 2005 eu participada de um trabalho da minha Igreja na favela da coreia, tinha uma criança que aparentava ter uns 8 ou 9 anos de idade, mas já tinha um fuzil pendurado no corpo e ficava sentado numa cadeira de ferro, protegendo o acesso a rua que ficava a casa, onde acontecia a reunião da Igreja. Aquilo sempre me doeu o coração. Era uma situação muito triste. Me lembro que por algumas vezes fui em alguns lugares ali por dentro com meu amigo, que morava e foi criado ali. Geralmente  eu via muitas crianças largadas, sem qualquer assistência, presas fáceis para se tornarem futuros bandidos.

O papel do Estado Brasileiro

Nossos governantes tem falhado miseravelmente há decadas, no que diz respeito a saúde, educação, qualidade de vida, programas sociais, entre outros. O máximo que se vê são os bolsa-isso, bolsa-aquilo, bolsa-etc. Apenas tapando o sol com a peneira.

A cada ano que passa, o ensino público piora mais. Na minha época de infância e adolescência, o nível da escola pública era igual e em alguns casos até melhor que as escolas particulares. Tenho grandes amigos que são testemunha disso. Na geração seguinte a coisa já começou a ficar complicada. Hoje em dia nem se fala.

Sobre a saúde em nem vou perder meu tempo …

Pra piorar, o poder público usa uma estratégia bem conhecida e que sempre deu resultado. Eles criam o problema (falta de condições básicas para todo cidadão), agem em cima do problema (matando) e ainda ganham os aplausos da sociedade (que adora ver bandido morrer), sendo que eles são os principais culpados.

Além disso, não existe no sistema penitênciário brasileiro uma forma de recuperar os bandidos que são presos. É lógico que nem todos querem isso, provavelmente uma minoria, mas certamente é papel do estado oferecer essa oportunidade, até porque não a ofereceu para a maioria dessas pessoas quando ainda eram crianças.

Oportunidade de redenção

É impressionante como nós somos implacáveis com as outras pessoas, mas quando é conosco somos tremendamente generosos. Quando uma pessoa erra, caimos condenando, mas quando erramos sempre temos nossas justificativas e achamos que merecemos outra chance.

Certa vez, assistindo um programa de televisão que debatia o Caso Eloá Cristina, se não me engano o Jornalista Roberto Cabrini, criticando veemente e agredindo com palavras, disse que perguntou ao maniaco do parque: “E se a moça fosse a sua filha?”. Ele recebeu outra pergunta de volta: “E se eu fosse seu filho?”. Cabrini disse que ficou totalmente embaraçado e que isso o fez refletir sobre o quanto agente gosta de pagar o mau com o mau.

Toda pessoa tem direito a uma nova chance. Bandidos deveriam ser presos e deveria existir uma forma de recuperar os que estivessem dispostos a isso (Sinceramente eu não acredio que a pessoa nasça bandido, ou com a índole ruim, etc). Alguns infelizmente não vão querer reabilitação e esses deveriam permancer presos, o que também não acontece, pois após cumprir a pena são soltos, independente de estarem em condições de integrar a sociedade.

Conclusão

Por diversas razões, eu não me surpreendo mais com o desejo de ver sangue que existe em nossa sociedade. Essa falta de amor está prevista na bíblia, meu livro de fé e prática. Sinceramente acho que a tendência infelizmente é piorar, pois o mundo está ficando cada vez mais egoista.

De fato, aqueles que cometem delitos precisam pagar por isso, afinal de contas tudo tem uma consequência. Meu ponto maior é que essas pessoas também são seres humanos e precisam ser tratados como tal. Desejar a morte delas é nos tornar tão ruim ou até pior que essas pessoas.

Hoje em dia vejo muita gente que nunca passou fome na vida ou nasceu em uma família com uma condição boa que olha essas pessoas como se fossem lixo. Não tem a menor noção do que é nascer nessas condições. Por outro lado, vejo pessoas que se gloriam em terem vencido essa situação e crucificam os que não conseguiram. Eu prefiro agradeçer muito a Deus e a minha Tia-Mãe por ter me tirado da convivência e das influências, pois eu poderia ter tido o mesmo destino de alguns coleguinhas de infância, não fossem essas oportunidades.

Indo direto ao ponto, o problema maior está no poder público que não oferece condições básicas iguais para todos os brasileiros. Se fosse assim, ai poderiamos questionar que as escolhas dessas pessoas foram mau feitas. De outra forma, é muita injustiça da nossa parte, principalmente porque a maioria delas foi assediada quando criança.

Pra finalizar, vou falar um pouco do que eu acredito. O mundo tem se esquecido de Deus. Cada vez mais as pessoas só pensam em si próprias, e o exercício do amor ao próximo praticamente não existe.

Então não se esqueça. Somos nós que cuidamos desse mundo. Se ele está assim, cabe a nós muda-lo.

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

[Emerson Macedo] Volta das férias, RubyConf Brasil e um pouco de NodeJS

Tuesday, November 23rd, 2010

No final do mês de outubro e no início do mês de novembro tirei um tempo de férias (todo mundo precisa, rs). Nesse tempo eu evitei ao máximo me envolver com trabalho, mas algumas atividades foram inevitáveis até porque já estavam programadas.

Nos dias 26 e 27 de outubro, participei do RubyConf Brasil e apresentei a palestra “Beyond Ruby With NodeJS”, onde basicamente eu falo sobre a repetição do erro em tentar tornar uma tecnologia boa em uma panaceia. Eu sou um rubista convicto e curto muito a tecnologia, mas como já falei tempos atrás aqui mesno nesse blog, não creio ser Ruby/Rails a bala de prata que tanto procuramos (e certamente não acharemos). Os slides seguem abaixo e em breve o vídeo estará disponível no site do evento.

Beyond Ruby with NodeJS – RubyConf Brasil 2010

Passado alguns dias, lancei o segundo episódio do NodeCasts, um site de screencasts em HD sobre NodeJS. O ritmo ainda está um pouco lento, pois a idéia inicial era fazer um screencast a cada 15 dias, mas acabei percebendo que fazer screencasts bem produzidos e com qualidade, sem pausas estranhas e outros detalhes mais que geram um resultado legal da um bocado de trabalho e não é uma tarefa tão simples. Estou aprimorando o processo de produção pra eu poder lançar um a cada 15 dias sem problemas. Se quiser curtir o episódio 2 ou episódio 1 basta clicar no texto linkado. Os screencasts são todos em inglês e colaboradores para tradução são sempre bem vindos e receberão os devidos créditos.

PS: A partir de hoje o blog retorna das férias :)

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

[Bernardo Heynemann] Python Test Spy Engine – MI7

Sunday, November 21st, 2010

Introduction

MI7 is my new pet project. I grew tired of the other mocking/stubbing/spying engines in Python that never did quite what I expected them to.

I’ve been TDDing for a while now in .Net, Ruby, Python and JavaScript. I’ve got my fair share of experience, so I figured I’d give my 2¢ in this issue.

You can check the project at https://github.com/heynemann/mi7/wiki. It’s got a nice tutorial and is currently in 0.1.1 alpha release.

I’ve got a lot of work to do to make it my main tool for test support, but I’m going to get there. Without further delay, let’s get to it.

Why another Spying Engine?

If you check the MI7 wiki you’ll see that I don’t have anything against any single python test support engine. I just haven’t found one that suits my needs and those needs ONLY. IMHO they all do too much. I want a simple, straightforward, fun to use spying engine.

Don’t get me wrong, but I do not believe in mocking in Python. Or stubbing for that matter. Both are akin to dependency injection, IMHO. It just isn’t pythonic.

Python has been around for a while. In this time, there has been a certain Modus Operandi of doing work. This MO has never included injecting your dependencies around. I figured that’s why I feel the weirdness on the part of the mocking/stubbing/spying tools.

With MI7 I’m trying to interfere as less as possible with your code. Production code should be optimized to be production code, and not changed to accommodate your poor testing tools. In the Ruby community they try HARD to make tests and code as clear as possible, not make code work according to tools. I’m trying to get some of that.

The last point of me doing MI7 is to have some fun, and I’m trying to bake in the library as much of that fun as possible, with the spy agency metaphor. Hope you enjoy as much as I am.

Test Sample

Ok, so I’ll write a test with MI7. It’s pretty simple:

from controllers import MyController
from models import User
@new_mission
@agent.spy(User)
def test_user_is_authenticated():
    agents.User.intercept('is_authenticated') \
               .returns(True)
    agents.User.intercept('username') \
               .as_attribute('Bernardo')
    ctrl = MyController()
    result = ctrl.index()
    assert result == "Welcome Bernardo"

So what’s happening here. I’m telling MI7 to keep an eye in the User model, wherever it may be used. Then I’m instructing the User agent (the agents get their code-name from the target they are spying), to intercept calls to is_authenticated and username and return my values.

Now the controller code:

from models import User
class Controller(object):
    def index(self):
        user = User()
        if user.is_authenticated():
            return "Welcome %s" % user.username
        return "Unauthorized"

As you can see, there's not a single line of code in that controller that says "I'm testable". It's just plain old python coding.

Current Status

Currently MI7 supports intercepting modules and classes and telling agents to intercept methods and attributes and to raise exceptions.

Impersonation (stubbing) may come next. Definitely assertions are coming, like what an agent has seen and such.

Conclusion

I’ll keep going with MI7 development as much as I can, because I believe the Python community needs better testing tools and I’m willing to put extra effort into this.

[Rafael Biriba] Net-SFTP: Calculando o progresso do upload

Thursday, November 18th, 2010

Estou escrevendo esse post, para complementar o post sobre o timeout do net-sftp, onde fiquei devendo essa a solução de calculo do progresso…

Para obter o progresso durante o upload, você precisa usar o callback do método upload! e jogar numa variável os valores do tamanho local e do tamanho do arquivo no destino.

Vejamos um pequeno exemplo, retirado da documentação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'rubygems'
require 'net/sftp'
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
    case event
    when :open then
      # args[0] : file metadata
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
    when :put then
      # args[0] : file metadata
      # args[1] : byte offset in remote file
      # args[2] : data being written (as string)
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
    when :finish then
      puts "all done!"
    end
  end
end

No exemplo acima podemos verificar:

  • Ao abrir a conexão (when open), podemos chamar args[0].size e obter o tamanho total do arquivo
  • Durante a transferência (when put), ao chamar args[1] podemos obter o tamanho do arquivo remoto

Com isso, quando o tamanho total do arquivo for igual ao tamanho do arquivo remoto, então o upload estará terminado (100%). Para obter as porcentagens, basta fazer o cálculo.

Confira no exemplo abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require 'rubygems'
require 'net/sftp'
@total_size = 0
@remote_size = 0
@current_progress = 0
 
def update_sftp_progress
  progress = (@remote_size*100)/@total_size)
  if @current_progress < progress then
    @current_progress = progress
    puts "Uploading: #{@current_progress}%"
  end
end
 
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
 sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
   case event
     when :open then
       @total_size = args[0].size
       puts "Starting upload..."
     when :put then
       @remote_size = args[1]
       update_sftp_progress
     when :finish then
       puts "Finished!"
     end
   end
end

Toda vez que o arquivo no destino for incrementado, o evento (:put) será disparado, chamando o método update_sftp_progress.

Nesse método é feito o cálculo da porcentagem(ver no exemplo acima). Ao invés de imprimir a porcentagem(com puts), você também pode salvar no banco de dados, ou utilizar o valor para fazer uma barra de progresso.

Espero ter ajudado, ;)

Google Bookmarks Twitter Yahoo Messenger Orkut Hotmail Google Gmail Delicious Share

Leia também:


[Rafael Biriba] Net-SFTP: Calculando o progresso do upload

Thursday, November 18th, 2010

Estou escrevendo esse post, para complementar o post sobre o timeout do net-sftp, onde fiquei devendo essa a solução de calculo do progresso…

Para obter o progresso durante o upload, você precisa usar o callback do método upload! e jogar numa variável os valores do tamanho local e do tamanho do arquivo no destino.

Vejamos um pequeno exemplo, retirado da documentação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'rubygems'
require 'net/sftp'
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
    case event
    when :open then
      # args[0] : file metadata
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
    when :put then
      # args[0] : file metadata
      # args[1] : byte offset in remote file
      # args[2] : data being written (as string)
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
    when :finish then
      puts "all done!"
    end
  end
end

No exemplo acima podemos verificar:

  • Ao abrir a conexão (when open), podemos chamar args[0].size e obter o tamanho total do arquivo
  • Durante a transferência (when put), ao chamar args[1] podemos obter o tamanho do arquivo remoto

Com isso, quando o tamanho total do arquivo for igual ao tamanho do arquivo remoto, então o upload estará terminado (100%). Para obter as porcentagens, basta fazer o cálculo.

Confira no exemplo abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require 'rubygems'
require 'net/sftp'
@total_size = 0
@remote_size = 0
@current_progress = 0
 
def update_sftp_progress
  progress = (@remote_size*100)/@total_size)
  if @current_progress < progress then
    @current_progress = progress
    puts "Uploading: #{@current_progress}%"
  end
end
 
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
 sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
   case event
     when :open then
       @total_size = args[0].size
       puts "Starting upload..."
     when :put then
       @remote_size = args[1]
       update_sftp_progress
     when :finish then
       puts "Finished!"
     end
   end
end

Toda vez que o arquivo no destino for incrementado, o evento (:put) será disparado, chamando o método update_sftp_progress.

Nesse método é feito o cálculo da porcentagem(ver no exemplo acima). Ao invés de imprimir a porcentagem(com puts), você também pode salvar no banco de dados, ou utilizar o valor para fazer uma barra de progresso.

Espero ter ajudado, ;)

Google Bookmarks Twitter Yahoo Messenger Orkut Hotmail Google Gmail Delicious Share

Leia também:


[Renan Oliveira] Como melhorar meu resultado de busca usando RDFa ?

Saturday, November 13th, 2010

Anotação semântica

“Esquema específico para geração e uso de metadados, possibilitando novos métodos de acesso a informação”

- Kyriakov, 2003

Nós vivemos procurando formas de melhorar nosso SEO (Search Engine Optimization) para que isso reverta em visitas aos nossos sites,  já algum tempo conheço o RDFa (RDF annotations) que é  uma proposta da W3c para organizar e melhorar o que está escrito em XHTML (Combinando as tags de marcação HTML com regras da XML), deste tempo para cá Google, Yahoo! (leia Search Monkey) aproveitam dessa melhor organização e de novos dados inseridos no XHTML para melhorar a apresentação dos resultados de Busca e melhorando assim o seu ranking já que tal informação está mais clara e objetiva e bem organizada.

Como o google usa o RDFa nos resultados de busca ?

O Google utiliza como padrão para Rich Snippets: RDFa e Microformats.

O Rich Snippets são aqueles resultados diferenciados com Reviews (stars), Events e etc.

Tanto o RDFa quanto o Microformats para o google não faz diferença, ainda. Eu particularmente prefiro o RDFa pois é mantido pelo pessoal da W3 Semantic Web Group.

Exemplos de uso em filmes (IMDb):

O próprio Google da dicas de como usa, segue os links:

Como marcar conteúdo usando RDFa:
http://www.google.com/support/webmasters/bin/answer.py?hl=br&answer=146898

Introducing Rich Snippets: http://googlewebmastercentral.blogspot.com/2009/05/introducing-rich-snippets.html

E agora, o Yahoo! usa o RDFa nos resultados de busca ?

Originalmente, a mesma anotação em RDFa será apresentada de forma parecida tanto no Google, quanto no Yahoo! sendo que no Yahoo a aplicação é um pouco mais vasta como pode ser vista nos links abaixo.

O Yahoo! (Search Monkey) participa de um excelente projeto para organizar os dados com Web Semântica (RDFa), o Projeto Commom Tag.

Exemplos de uso em Eventos:

Excelente explicação de como o Yahoo! captura e utiliza os dados em RDFa, além um ótimo tutorial:

http://developer.search.yahoo.com/start

E como usar essa anotações no Meu Blog? Use o  Zemanta

O Projeto Zemanta começou como um Plugin para o Firefox e com o passar do tempo se tornou um Plugin para Blogs e hoje já é recomendado inclusive pelo WordPress, veja o post.

O Zemanta, funciona com um plugin que sugere notícias relacionadas, links , fotos e tags para organizar o seu conteúdo.  Nessas tags que moram a grande sacada do Zemanta, ele escreve essas informação em RDFa.

Nesse post e nos futuros pretendo continuar usando o Zemanta para anotar os meus conteúdos, falo isso pois a Semantic Web continua crescendo de forma exponencial e poderá surgir um melhor “anotador” , por agora estou muito satisfeito com o uso do mesmo. Você pode ver aqui quais informações o Zemanta nos sugere, Exemplos de Uso.

Existem projetos, bem interessantes, que utilizam o RDFa como padrão:
Facebook – http://rdfa.info/2010/04/22/facebook-adopts-rdfa/
Best Buy – http://www.readwriteweb.com/archives/how_best_buy_is_using_the_semantic_web.php
Newsweek… Drupal….O’relly..

Caso queira saber mais informações, recomendo esses links:

http://www.slideshare.net/lzomatos/anotao-semntica-de-contedo-web-utilizando-microformatos-e-rdfa (PT-Br)

http://www.w3.org/TR/xhtml-rdfa-primer/ (Inglês)

http://www.alistapart.com/articles/introduction-to-rdfa/ (Inglês)

http://ilrt.org/discovery/2001/04/annotations/ (Inglês)

RDFa Basics

[Igor Sobreira] Slides - Desenvolvimento web com Python e Django

Monday, November 8th, 2010

Segue os slides da minha palestra Desenvolvimento web com Python e Django.

Apresentei essa palestra no Jatic, na faculdade Facisa em Campina Grande, PB. E também no CITOS, na faculdade Univem, em Marília, SP.

A maior parte da apresentação fala sobre Django, mas também mostra como funciona o WSGI, as maneiras mais comuns de fazer deployment de aplicações em python hoje em dia, configuração de ambiente usando virtualenv, testes…

Desenvolvimento web com python e django

Veja outras aprensentações minhas no Slideshare.

[Rafael Carício] Cookie SQL Injection - Explorando uma falha de segurança na prática

Sunday, November 7th, 2010

Quando converso com desenvolvedores Web eu percebo que são poucos que têm conhecimento de programação segura para Web. A algum tempo atrás eu trabalhava com Java e tinha/tenho muita preocupação com a questão de segurança. Cheguei até a tentar lecionar um curso de programação segura para Web em Java na uCon Security Conference, porém devido a falta de interesse o curso acabou não acontecendo. Acredito que conhecer, no mínimo, as formas de ataques mais básicas é fundamental para qualquer desenvolvedor Web. Um bom lugar para começar é conhecendo o projeto o Open Web Application Security Project (OWASP). Lá vocês podem encontrar uma vasta gama de informações sobre segurança na Web. Um sub-projeto interessante do OWASP é o que lista as 10 vulnerabilidades mais encontradas na Web.

Como mencionei no post anterior, o código em C que postei para melhorar a performance no acesso de aplicações Django usando o NGINX e Memcached tem uma falha de segurança que permite ataques de SQL Injection. Inicialmente eu pensei em realizar a correção no código e depois postar no blog. Mas depois me ocorreu que eu poderia mostrar como explorar esta falha. Achei que isso poderia ser bastante interessante para vocês verem como funciona esse tipo de ataque.

Bem, olhando o código escrito em C talvez não seja tão evidente a existência da falha. Pois normalmente os ataques de SQL Injection teem uma forma de entrada do código malicioso e saída da informação recolhida dentro do sistema. Normalmente esse problema é encontrado em aplicações Web onde é verificada a informação retornada em algum campo que é apresentado dentro do código HTML. Mas as falhas e aplicações se comportam totalmente diferentes em sistemas diferentes. A criatividade deve entrar em ação para tentar descobrir como interferir no sistema e obter uma resposta com sucesso. Ao analisar o comportamento da aplicação em funcionamento aparentemente não encontramos nenhuma forma de obter um retorno sobre qual o dado que está armazenado. O que conhecemos é o comportamento do sistema. Quando um visitante acessa a aplicação ele pode obter uma resposta da aplicação Web em Django ou do código em C onde existe a evidência de falha. Então sabemos que nossa atenção deve ser em cima de como fazer a requisição ir para o código vulnerável. Assim, lembrando do post anterior, todas as requisições passam pelo código em C onde é feita uma consulta a base de dados pelos dados existentes na sessão do usuário que no Django (e na maioria, se não, todos os tipos de aplicações web) armazena o Session Key no cookie do browser do usuário. O código realiza uma consulta a base de dados sobre a sessão e verifica o tamanho desses dados, caso seja maior que 60 caracteres (que foi o tamanho máximo identificado por mim para uma sessão de usuário não autenticado) a requisição é repassada para o Django e é entendido que o usuário está autenticado. Caso contrário, o usuário não está autenticado e a requisição é retornada a partir dos dados existentes no Memcached. Analisando esse fluxo, podemos perceber que a chave para o ataque é identificar como saber se a requisição vem do código em C ou do Django. E usar isso para obter uma resposta, já que este SQL executado (e que contém a vulnerabilidade) só é usado para isso. Assim procurei e achei a diferença entre as respostas do Django e do código vulnerável. Quando a resposta vem do Django, existe uma variável que aparece no cabeçalho da resposta a requisição HTTP. Ao descobrir isso, eu já sabia quando uma requisição vinha do Django e quando vinha do código em C e sabia que se o resultado retornado depois da execução do código SQL se fosse maior que 60 ele ia passar pra o Django e caso fosse menor ele mesmo iria responder. Assim, eu agora precisava só descobri como usar isso para obter informações sobre o sistema, no caso, informações importantes armazenadas na base de dados.

Primeiro eu precisava escolher que informação eu iria tentar obter, dentro do contexto teria que ser algo que estivesse no banco de dados da aplicação. Eu sei que toda aplicação Django com autenticação tem uma tabela chamada auth_user onde ficam armazenados os usuários, então escolhi atacar essa tabela e obter informações sobre os usuários da aplicação.

Bem, depois de descobrir onde deveria atacar eu precisei imaginar (usar a criatividade para) pensar em como fazer a resposta da execução do SQL ser maior que 60 caso a condição que eu verificasse fosse verdadeira ou falsa. Assim eu poderia usar a informação que a resposta veio do Django ou não para validar o que eu estaria perguntando ao banco de dados.

OFF-Topic: Resolvi ir tomar um banho e ficar pensando sobre como fazer isso. Minhas idéias fluem quando estou tomando banho e é lá onde eu tenho muitas ideias interessantes. Acho que quase todas que já postei ou vou postar neste blog surgiram quando eu estava tomando banho.

No final de todo o processo de pensar testar a avaliar o funcionamento eu escrevi este código. A ideia dele é fazer uma requisição a aplicação usando cada letra do alfabeto ou caractere válido para o campo que eu queria e fazer com que a resposta vá para o Django sempre que eu achar o caractere certo. Assim eu teria que iterar caractere por caractere para descobrir um-por-um. E foi isso que eu fiz.

Este código varre todas as possibilidades sobre cada caractere e vai validando cada entrada. No final podemos obter o nome de um usuário que é staff do sistema. Este mesmo código, sem muitas modificações pode ser usado para obter muitas outras informações. Ai vale a criatividade de cada um. Isso é apenas um exemplo simples.

A criatividade é um fator fundamental a qualquer pessoa que deseja realizar um ataque. Pois cada ataque requer um cuidado ou ação bem especifica. Cada sistema tem um funcionamento e foi implementado de uma forma totalmente diferente. Por isso que dificilmente um ataque que obteve sucesso sobre um sistema vai obter o mesmo sucesso sobre outro. O importante na questão de segurança é entender o fundamento do ataque e não decorar como foi feito. O fato da forma de atacar cada sistema ser diferente leva a que poucas pessoas realizem ou tenham sucesso ao tentar realizar esse tipo de atividade.

Espero que tenham gostado do post e ainda tenho muitas ideias que não postei aqui. Muita coisa ainda está por vir. A interação de vocês por meio de comentários é muito importante para minha motivação a continuar postando coisas aqui. Por isso, escrevam suas opniões, criticas ou elogios tudo isso é sempre bem-vindo.