Arquivo da tag: codigo

Net-SFTP: Calculando o progresso do upload

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, 😉

Share

Net-sftp: Solução para timeout durante o upload

Desenvolvendo um script em ruby para upload de arquivos, utilizando a gem net-sftp, acabei encontrando um problema. A falta de timeout durante a transferência.

Decidi escrever esse post, para compartilhar a minha solução e também receber opniões e outras soluções para o problema. Fiz algo parecido quando escrevi o post sobre o cron de 15 em 15 segundos e obtive resultados bem legais.

Introdução ao problema
A gem net-sftp é bastante utilizada em scripts ruby que requerem alguma transferência de arquivo utilizando uma conexão segura, como por exemplo, upload, download, criação de diretórios e etc… Utilizando a gem net-ssh para estabelecer essa conexão.

Primeiramente, vamor ver um exemplo do problema:

1
2
3
4
5
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")
end

O código acima faz o upload de um arquivo de mais de 400 Mb. Se durante o upload houver um problema na sua conexão, o upload fica “esperando” a rede voltar, o que é um problemão, pois ele trava a execução do script, sem dar nenhum sinal de vida.

De acordo com a documentação do net-sftp, você pode utilizar o método “upload” no lugar de “upload!” para não travar a execução do script. Mas ainda sim o problema continua. Fazendo isso, você vai precisar rodar um loop até que o upload termine. Ou seja, se a conexão cair, o método só vai terminar(e sair do loop) quando a conexão voltar. Então essa opção foi logo descartada.

O problema mesmo só acontece quando há perda de conexão depois que a sessão inicia. (O parâmetro :timeout apenas estabelece o limite de espera para iniciar a sessão e não durante a transferência dos arquivos.)

Se o net-sftp / net-ssh aceitasse a opção “ServerAliveInterval” (Parametro de configuração do ssh), ele iria verificar a conexão durante a transferência e ao alcançar o limite (“ServerAliveCountMax”) seria disparado o timeout. Infelizmente, de acordo com a documentação do net-ssh esses parâmetros não estão disponíveis.

Seguindo com a leitura e busca pela solução na documentação do net-sftp, achei uma possível pista para encontrar a soluçã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

Acima temos um exemplo simples retirado da documentação para o controle do progresso de upload.

Quando o upload inicia, o case recebe o evento “:open” onde podemos obter o tamanho total do arquivo e logo em seguida recebe os eventos “:put” onde é possível verificar  o quanto (em bytes) do arquivo já foi enviado, possibilitando assim a criação da porcentagem do upload.

Como o foco aqui não é mostrar como obter o progresso (posso mostrar isso exclusivamente em outro post calculando o progresso durante o upload), não vou entrar muito em detalhes sobre isso. O que realmente inporta nesses eventos são que durante o upload (:put), ao perder a conexão, nenhum evento é disparado, ou seja, o script não tem como sabe que a conexão caiu e a execução fica travada no upload.

Minha solução:

Depois de todo esse estudo detalhado sobre o problema, comecei a pensar numa possível solução. Eu precisava utilizar alguma coisa que pudesse verificar e dar timeout no upload caso ele parasse de responder/transferir.

Foi então que pesquisei, testei e implementei o rufus-scheduler*,  um agendador de tarefas que roda dentro do script ruby(mas numa outra thread), onde posso definir um intervalo de execução para executar alguma coisa, como se fosse um cron. ( *Sugestão do @vicentemundim )

Então a solução foi: Assim que o upload começar, eu defino um tempo de 10 segundos para ele executar uma tarefa com “raise exception”. Então toda vez que o upload responder ao evento (:put), informando que conseguiu subir mais um trecho do arquivo, eu reseto o tempo de execução da tarefa e defino novamente em 10 segundos. Fazendo isso, quando a conexão cair ou o upload travar por algum motivo, ele vai parar de responder ao evento “:put”, e então a tarefa agendada para 10 segundos vai disparar o raise, interrompendo a execução do script.

Depois de alguns testes, tanto de desempenho quanto de falhas, percebi que essa resolução serviu perfeitamente. Segue o exemplo do código utilizado:

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
29
30
31
32
require 'rubygems'
require 'rufus/scheduler'
require 'net/sftp'
 
@job = nil
@scheduler = Rufus::Scheduler::PlainScheduler.start_new  
def @scheduler.handle_exception (job, exception)
  abort(exception.message)
end
 
def job_scheduler
  @job.unschedule unless @job.nil?
  @job = @scheduler.every "10s" do
    raise "SFTP Connection Lost or upload freezed timeout"
  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
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
      job_scheduler
    when :put then
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
      job_scheduler
    when :finish then
      puts "all done!"
     @job.unschedule unless @job.nil? 
    end
  end
end

Quando o upload inicia (:open) e durante a transferência (:put), ele chama o método job_scheduler que é responsável por resetar a tarefa anterior(se houver) e agendar uma nova com timeout de 10 segundos.

Conforme expliquei acima, se o upload travar, o tempo limite de 10 segundos é alcançado e uma exceção é disparada.

Como o agendador do rufus roda em outra thread, qualquer exceção disparada é capturada e tratada pelo próprio rufus, fazendo com que a execução do script continue. Então, sobrescrevi o método (handle_exception) e ao receber a exceção, gero um abort que irá interromper todo o script.

Infelizmente, são poucos os sites relacionados sobre esse assunto, o que dificultou bastante a busca e o desenvolvimento. Mesmo assim, acredito ter resolvido o problema com uma solução bem razoável.

Já falei em cima, mas vale ressaltar:
“Decidi escrever esse post, para compartilhar a minha solução e também receber opniões e outras soluções para o problema. Fiz algo parecido quando escrevi o post sobre o cron de 15 em 15 segundos e obtive resultados bem legais.”

Estou pensando em tentar solucionar isso direto no código do net-sftp e quem sabe mandar um patch para o autor. De qualquer forma, fico no aguardo de qualquer comentário e/ou soluções melhores.

handle_exception
Share

Feliz ano novo com javascript !

natal-16Primeiramente, gostaria de desejar a todos os leitores e amigos que acompanham meu blog:

Um feliz natal e um próspero ano novo !

Entrando nesse ritmo de natal e ano novo, desenvolvi um pequeno código em javascript para desejar feliz natal e ano novo para os leitores do meu blog.

O código está realmente simples, e pode ser alterado e utilizado aonde quiser… Só não esqueça de deixar sua opnião nos comentários abaixo!

O script funciona da seguinte maneira:
3 variáveis são definidas no inicio:
Data atual (var agora).
Data do ano novo (var anoNovo).
Data máxima de exibição (var anoNovoMax).

O alert com a mensagem será exibida enquanto a data atual estiver dentro do intervalo das outras 2 datas.

Abaixo segue o código:

<script language="JavaScript">
var agora = new Date();
var anoNovo = new Date(2010, 0, 1, 0, 0, 0, 0);
var anoNovoMax = new Date(2010, 0, 1, 23, 59, 59, 0);
if(agora >= anoNovo && agora<anoNovoMax)
{
alert("Feliz ano novo !");
}
</script>

Para implementar no wordpress, é bem simples:
Adicione um Widget de texto em seu wordpress, e sem atribuir um titulo, insira o codigo javascript diretamente no campo de baixo “descrição”. Fazendo isso, o widget não ficará visível, mas o código vai funcionar… 🙂

Para implementar em seu site:
Basta inserir o javascript em sua página.

Dica:
Como o javascript pega a data da máquina do cliente, você corre o risco de pegar a data errada.  Uma solução seria usar o PHP para definir a data, ou seja,  seria a data atual seu servidor. Exemplo:

var agora = new Date(<?php echo date("Y, m, d, H, i, s"); ?>);

Então é isso… Façam bom proveito !

Aqui no blog, já está implementado as mensagens de Feliz Natal e Feliz Ano Novo… Serão exibidas durante todo o dia 25 e 01, respectivamente ! Visitem o Blog e confiram ! 😉

 

Share

PHP: Arquivo de log personalizado

 

PHP: http://www.php.net/
PHP: http://www.php.net/

Semana passada, estive fazendo num pequeno site, uma área de login. Foi então que fiz uma funçãozinha no PHP que gera logs diários dos eventos ocorridos desde o login até o logoff, como por exemplo, ações tomadas pelos usuários na parte administrativa.

Abaixo, vocês poderão conferir o código que utilizei, logicamente adaptado para que fosse publicado aqui.

Os arquivos de log são gerados baseado no dia em que se encontra. Como os arquivos estão em formato .txt, utilizei um prefixo no arquivo, para que o acesso não seja tão óbvio por pessoas desautorizadas.

A função armazena no arquivo a hora da ocorrência, seguido pelo IP da máquina do cliente e a mensagem definida por você.

Vamos então seguir para o código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
 
date_default_timezone_set('America/Sao_Paulo');
 
function Logger($msg){
 
$data = date("d-m-y");
$hora = date("H:i:s");
$ip = $_SERVER['REMOTE_ADDR'];
 
//Nome do arquivo:
$arquivo = "Logger_$data.txt";
 
//Texto a ser impresso no log:
$texto = "[$hora][$ip]> $msg \n";
 
$manipular = fopen("$arquivo", "a+b");
fwrite($manipular, $texto);
fclose($manipular);
 
}
 
?>

Salve o arquivo acima como logger.php

Na linha 3 estou declarando o timezone para São Paulo, mesmo estando no Rio de Janeiro, o horário é o mesmo. Isso serve para configurar a data para minha localidade, já que no meu caso, o servidor se encontra em outro fuso horário.

Nas linhas 7, 8 e 9 estou declarando as variáveis de data, hora e ip da máquina que gerou o log (cliente).

Na linha 12 está o nome do arquivo. Será algo do tipo Logger_19-06-2009.txt (dia-mês-ano). Caso deseje armazenar o log em uma pasta já existente, altere a linha para:
$arquivo = “minhapasta/Logger_$data.txt”;

Na linha 17 está a função de abertura do arquivo.  Passando o “a+” como parâmetro, apenas nos dias que tiver alguma coisa para ser inserida no log, é que o arquivo será criado ou se já existir, escreverá o registro no fim do arquivo. O parâmetro “b” serve para questões de portabilidade ( inserção recomendado no manual do php )

As linhas 18 e 19 manipulam e fecham o arquivo definido na linha 12.

Agora vamos para o código onde vamos utilizar nossa função:

1
2
3
4
5
6
7
8
9
<?php
 
include "logger.php";
 
Logger("Testando a função logger !");
Logger("Como você pode ver, estou logando uma informação !");
Logger("Teste 1, Teste 2, Teste 3!");
 
?>

Salve o arquivo acima como teste.php na mesma página onde se encontra o logger.php.

Pronto. O Script acima gera 3 saídas consecutivas no seu arquivo de log.
Conferindo o resultado:
Nome do arquivo gerado:
Logger_19-06-09.txt

Conteúdo:
[21:57:36][201.7.xxx.xxx]> Testando a função logger !
[21:57:36][201.7.xxx.xxx]> Como você pode ver, estou logando uma informação !
[21:57:36][201.7.xxx.xxx]> Teste 1, Teste 2, Teste 3!

Bom, espero que o script sirva para mais alguém. 🙂

===========================================

Atualização em 13/abril/2011

A leitora Renata nos comentários de hoje (13/04/11) deixou uma dúvida muito boa… Vale a pena editar a matéria e acrescentar a solução dela aqui…

Ela estava encontrando problemas para centralizar os arquivos de log em um só lugar. Ela trabalhava com pastas para organizar seus arquivos, e ao incluir a função logger nos arquivos, fazia com que os logs fossem gravados separadamente em cada pasta.

Por que isso ocorreu ?

Ela estava incluindo a função da maneira correta: include “../logger.php”; mas o problema estava mesmo dentro da função Logger.

Na variável $arquivo, onde definimos o nome do arquivo de log, a função parte do princípio que o arquivo .txt está do lado do arquivo .php que contém a função…

Consideremos o seguinte path de diretórios:

/
/logs/Logger.txt
/logger.php
/folder1/pagina1.php

Ao incluir a função logger de dentro da “pagina1”, chamando a função como a Renata fez (“../logger.php”), faz com que ao definir a variavel $arquivo = “teste.txt” o PHP vai salvar o arquivo dentro da pasta “folder1” pois ele interpreta o codigo a partir daquele contexto.

Para resolver isso, ao entrar na função Logger, voce precisa mudar o contexto da execução para ele salvar o log corretamente na pasta log (independente de onde ela estiver), e no final da função, você precisa voltar o contexto para onde ele estava, para evitar possiveis problemas.

Segue então o novo código que resolve o problema:

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
29
30
31
32
<?php
 
date_default_timezone_set('America/Sao_Paulo');
 
function Logger($msg){
 
//pega o path completo de onde esta executanto
$caminho_atual = getcwd(); 
 
//muda o contexto de execução para a pasta logs
chdir("/home/rafaelbiriba/public_html/logs");
 
$data = date("d-m-y");
$hora = date("H:i:s");
$ip = $_SERVER['REMOTE_ADDR'];
 
//Nome do arquivo:
$arquivo = "Logger_$data.txt";
 
//Texto a ser impresso no log:
$texto = "[$hora][$ip]> $msg \n";
 
$manipular = fopen("$arquivo", "a+b");
fwrite($manipular, $texto);
fclose($manipular);
 
//Volta o contexto de execução para o caminho em que estava antes
chdir($caminho_atual);
 
}
 
?>
Share

WordPress 2.7.1 com Syntax Highlight

Plugin: Wp-Syntax
Plugin: WP-Syntax - No exemplo: Linguagem Ruby

Há bastante tempo estive a procura de um plugin para fazer a “Syntax Highlight” dos meus códigos no blog. Parece algo simples, mas na verdade foi bem difícil de arrumar. Não é só instalar um plugin e utiliza-lo no blog, é bem pior que isso.

Pra começar que esse editor de texto do wordpress, TinyMCE, é cheio de “removedor de tags” (strip tag), o que dificulta e muito a inserção de códigos especiais. Vamos para os problemas e suas soluções:

Primeiramente, o plugin selecionado para o Syntax Highlight foi o: WP-Syntax ( http://wordpress.org/extend/plugins/wp-syntax/ ). Para utiliza-lo basta colocar as tags <pre lang=”” line=”” escaped=””> e depois </pre>.

O escaped por padrão é falso, não sendo necessário colocar. Serve para substituir os elementos codificados em html. Em outras palavras, quando no código tiver elementos como &lt; (>), ou &amp; (&),  estes são transformados automáticamente. Logo abaixo você entenderá a necessidade de colocar o escaped.

O line por padrão é falso, não sendo necessário colocar. Serve para dizer qual a numeração inicial que você deseja.

O lang é o atributo principal, onde definimos qual a linguagem que iremos utilizar, para que seja marcada corretamente. Você pode usar as seguintes linguagens: actionscript, actionscript3, asp, bash, c, cobol, cpp, csharp, css, delphi, html4strict, java, java5, javascriptmysqlperl, php, python, rails, ruby, sql, vim, whois, xml, ( Lista completa em http://wordpress.org/extend/plugins/wp-syntax/other_notes/ )

Porém o editor de texto do wordpress, não permite o atributos na tag pre e com isso seria impossível utilizar o plugin corretamente. Depois de muitas pesquisas e testes, descobri um plugin ótimo que serve justamente para “habilitar” tags e atributos que o editor não permite. Este plugin é o TinyMCE Valid Elements ( http://wordpress.org/extend/plugins/tinymce-valid-elements/ ). Com uma interface de configuração extremamente simples, você pode adicionar um elemento e depois os seus atributos válidos.

Bom, o primeiro problema já está solucionado. Depois de adicionar o elemento pre e os seus atributos line, escaped e lang, vamos escrever nosso primeiro código.

Vá ao editor de HTML do wordpress e adicione <pre lang=”ruby”>class Example</pre> isso criará uma saída colorida para o código ruby sem numeração.

Agora, se você tentar criar uma saída numerada e com várias linhas, encontrará 2 problemas:
1) O editor do wordpress remove as tags <? ?> caso você precise demonstrar um script php, por exemplo.
2) O css do plugin tem alguns parâmetros que distorce um pouco a tabela, fazendo com que ela seja maior do que o necessário.

Veremos isso na prática. Crie o código abaixo no editor HTML do wordpress:

<pre lang=”php” line=”1″>
<?php

echo “Hello World !”;
?>

</pre>

O editor do wordpress remove tudo que estiver dentro das tags <? ?>, então para resolver o problema 1, basta trocar a < por &lt; e > por &gt; , sendo assim o código ficará assim:

<pre lang=”php” line=”1″ escaped=”true”>
&lt;?php

echo “Hello World !”;
?&gt;

</pre>

Conforme eu expliquei acima, foi necessário incluir o escaped=”true” para que os elementos html sejam devidamente transformados. Neste caso para que os elementos < > sejam exibidos corretamente.

A Saída do código acima firá assim:

exemplo-wp-syntax-erro-css

O problema 2 é exatamente o tamanho que a tabela ficou! O css faz a tabela se estender até o fim da página, tornando ela exageradamente grande ! Vamos para a correção:

Abra o arquivo \wp-content\plugins\wp-syntax\wp-syntax.css e faça a seguinte alteração, logo no primeiro elemento .wp-syntax:

.wp_syntax {
color: #100;
background-color: #f9f9f9;
border: 1px solid silver;
margin: 0 0 1.5em 0;
overflow: auto;
}

Os parametros de background-color e border que estão distorcendo a tabela. Basta remover as linhas em negrito OU caso não queira deletar, basta comentar este trecho do código com (/* e */). Ao final salve o arquivo !

Agora ao executar o nosso código de teste, a saída será:

1
2
3
<?php
echo "Hello World !";
?>

Bom, acho que isto é tudo ! Qualquer dúvida é só perguntar ! 😉

Detalhes: Caso você venha atualizar o plugin wp-syntax, o css será substituido pelo padrão. Então você terá que alterar o css toda vez que atualizar o plugin, ou então deixe tabela distorcida mesmo… 🙂

Share

QR Code: Gere com o Google Chart API

Devido à rápida difusão e com vários sites e revistas dando ênfase a esse assunto, na semana passada tive mais de 100 visitas vindas diretamente de buscas sobre Qr code pelo Google.

Então resolvi continuar postando, e dessa vez, como gerar utilizando a ferramenta Chart API do Google.
Você que ainda não conhece esta tecnologia, pode ler mais em: https://rafaelbiriba.com/category/tecnologia/qr-code

A imagem ao lado está sendo gerada pela seguinte URL: ( dividida para uma melhor visualização )

http://chart.apis.google.com/chart?
&chs=150×150
&cht=qr
&chl=https://rafaelbiriba.com
&choe=UTF-8

Recomendo que apenas os valores em negrito/colorido sejam editados para facilitar a exibição. Qualquer alteração nos outros parâmetros, recomendo ler a documentação em http://code.google.com/intl/pt-BR/apis/chart/#qrcodes.

Clique aqui para acessar o link completo do gráfico.

&chs = Dimensões em pixel. De acordo com a documentação do google, a maior dimensão deve ter no máximo 300000 pixel, como por exemplo: 600×500, 300×1000, etc…

&cht = Tipo do gráfico. Neste caso qr

&chl = Conteúdo à ser codificado, lembrando que quanto maior o conteúdo, mais linhas e colunas a imagem vai ter, aumentando o seu tamanho, automaticamente.

&choe = Especifica opcionalmente como será a saída codificada. As opções mais comuns são UTF-8 e ISO-8859-1

Antes de gerar o código QR, considere o tipo de dispositivo a ser usado para a leitura do código. Os melhores leitores de código QR conseguem ler códigos versão 40, dispositivos móveis podem ler somente até a versão 4.

O Google recomenda manter a versão 4, que equivale a cerca de 100 caracteres alfanuméricos no nível de EC padrão.

Linhas e Colunas de um QR code:

  • A versão 1 tem 21 linhas e colunas e pode codificar até 25 caracteres alfanuméricos ( EC = L )
  • A versão 2 tem 25 linhas e colunas e pode codificar até 47 caracteres alfanuméricos ( EC = L )
  • A versão 3 tem 29 linhas e colunas e pode codificar até 77 caracteres alfanuméricos ( EC = L )
  • A versão 4 tem 33 linhas e colunas e pode codificar até 114 caracteres alfanuméricos ( EC = L )
  • A versão 40 tem 177 linhas e colunas e pode codificar até 4,296 caracteres alfanuméricos ( EC = L )

Parâmetro opcional: Correção de erros: ( EC )

&chld = Adicionando esse parâmetro no final da URL para gerar o QR Code, você pode especificar o tipo de correção de erros. Abaixo segue cada uma das opções disponíveis:

L permite que 7% de um código QR seja restaurado
M permite que 15% de um código QR seja restaurado
Q permite que 25% de um código QR seja restaurado
H permite que 30% de um código QR seja restaurado

Clique aqui para acessar o link completo do gráfico com o parâmetro de correção de erros ( EC = H ).

Acessando o link: http://code.google.com/intl/pt-BR/apis/chart/#ec_level_table, é possível analisar a tabela com informações de quantos caracteres podem ser armazenados em cada versão da imagem e com cada um dos nível de correção.

🙂

Share

Ruby: Alternativas para require ‘rubygems’

ruby-logo-justruby

Baseado no comentário de Guilherme Chapiewski encontrado em https://rafaelbiriba.com/2009/04/13/ruby-require-rubygems.html, resolvi postar alternativas para suprir essa necessidade do require ‘rubygems’ e porque é errado utilizá-lo !

Primeiramente, vamos para a pergunta que originou este post:
O que há de errado em utilizar require ‘rubygems’ no meu script ?

Bom, analisando o exemplo que eu dei no post do require rubygems, transcrito logo abaixo, onde se você quiser utilizar o pacote “hpricot”, instalado pelo comando gem install hpricot, o código não irá rodar, retornando um erro referente ao rubygems. Usando o require ‘rubygems’ o problema é resolvido, mas não está correto. O motivo é bem simples. Primeiro vamos ver o código em questão:

require 'hpricot' 
require 'open-uri' 
meuXml = Hpricot.XML(open("http://www.exemplo.com/exemplo.xml"))

Concordam comigo que o código acima, é uma simples aplicação em ruby ? O que eu quero dizer é que você pode instalar o hpricot de várias maneiras diferentes ! Por exemplo, acessando o link: http://wiki.github.com/why/hpricot/installing-hpricot, você pode observar que o Hpricot pode ser instalado sem o Rubygems. Sendo assim, ao usar o require “rubygems” em um máquina que não tem o rubygems instalado, vai dar problema na execução !

Então o que fazer se eu instalei o Hpricot pelo rubygems ? Simples…

Você pode facilmente rodar o seu script incluindo -rubygems na linha de comando, conforme o exemplo abaixo:

ruby -rubygems meu_script.rb

Isso fará rodar o pacote rubygems antes de executar sua aplicação meu_script.rb

Fonte: http://gist.github.com/54177

Bom, então é isso.

Share

Ruby: require ‘rubygems’

ruby-logo-justruby

Essa semana estive escrevendo alguns códigos usando Ruby on Rails, e encontrei um problema, que demorei um pouco para descobrir sua solução, mas no fim se tratava de algo muito simples e lógico.

Ao instalar o Rails e qualquer outro pacote pelo rubygems ( gem install hpricot, por exemplo), para importar esse pacote no código, é necessário importar a biblioteca do rubygems primeiro.

Manual do RubyGems ( http://docs.rubygems.org/read/book/1 ).

Na prática, eu estava utilizando o código abaixo:

require 'hpricot' 
require 'open-uri' 
meuXml = Hpricot.XML(open("http://www.exemplo.com/exemplo.xml"))

Este codigo abre uma URL, captura seu XML e armazena o conteúdo em uma variável ( string ).

Porém, isso só é possível se incluir a biblioteca do rubygems. Verifique o código abaixo, desta vez, funcionando:

require 'rubygems'
require 'hpricot'
require 'open-uri' 
meuXml = Hpricot.XML(open("http://www.exemplo.com/exemplo.xml"))

 

Bom, então é isso !
—————–
Baseado no comentário recebido depois da publicação deste Post, visite também:
https://rafaelbiriba.com/2009/04/29/ruby-require-rubygems-alternativas.html

Share

PHP: Ocultando erros de código

PHP: http://www.php.net/
PHP: http://www.php.net/

É muito comum após concluir todo e desenvolvimento de um projeto PHP, alguns error serem mostrados na tela, como um E_WARNING ou E_NOTICE. Isso pode ocorrer por muitos motivos, como indisponibilidade temporária no acesso ao banco de dados, tempo máximo de execução excedido, dentre outros.

Durante o desenvolvimento é altamente recomendado deixar os erros habilitados, justamente para ser feita a depuração dos mesmos, antes de finalizar o projeto. Depois de concluido, podemos desabilitar os erros, para caso haja uma eventualidade, não fique aparecendo diretamente na tela do usuário / cliente !

Para isso, vamos criar uma página PHP, onde vamos deixar os comandos para habilitar/desabilitar de forma simples e rápida, e vamos incluir a página criada nas páginas em que os erros não deverão ser exibidos. Vamos começar:

[ mostra_erros.php ]
<?php

error_reporting(0);
ini_set(“display_errors”, 0 );

?>

Definimos  de início error_reporting para ser zero, com isso nenhum erro é reportado. Logo em seguida atribuimos ao display_errors o valor zero, poderia ser também true ou false, um e zero, respectivamente. O código acima fará com que o PHP não exiba nenhum tipo de erro na tela. Para exibir todos os erros novamente utilize o código abaixo:
[ mostra_erros.php ]
<?php

error_reporting(E_ALL);
ini_set(“display_errors”, 1 );

?>

Veremos a seguir, algumas outras combinações, para ser exibido somente o erro desejado. Primeiro vamos entender o que cada erro mais comum do PHP quer dizer:
( Definições completas disponíveis no manual PHP.net: )

E_ERROR: Estes indicam erros que não podem ser recuperados, como problemas de alocação de memória. A execução do script é interrompida.
E_WARNING: Avisos em tempo de execução (erros não fatais). A execução do script não é interrompida.
E_PARSE: Erro em tempo de compilação. Erros gerados pelo interpretador.
E_NOTICE: Indica que o script encontrou alguma coisa que pode indicar um erro, mas que também possa acontecer durante a execução normal do script.
E_STRICT: Permite ao PHP sugerir mudanças ao seu código as quais irão assegurar melhor interoperabilidade e compatibilidade futura do seu código.
E_ALL: Todos erros e avisos, como suportado, exceto de nível E_STRICT

Caso você deseje exibir apenas os erros de tipo E_WARNING deve ser usado o seguinte código:

[ mostra_erros.php ]
<?php

error_reporting(E_WARNING);
ini_set(“display_errors”, 1 );

?>

Observe que agora atribuimos ao display_errors o valor 1 ( true ), para reportamos apenas os erros E_WARNING, como definimos na função error_reporting.

Podemos ainda utilizar as seguinte combinações:

[ mostra_erros.php ]
<?php

error_reporting(E_ERROR | E_WARNING | E_PARSE);
ini_set(“display_errors”, 1 );

?>

Desta forma apenas os erros do tipo E_ERROR, E_WARNING e E_PARSE serão exibidos na tela. Uma outra forma seria:

[ mostra_erros.php ]
<?php

error_reporting(E_ALL ^ E_WARNING);
ini_set(“display_errors”, 1 );

?>

Com isso, todos os erros serão mostrados ( E_ALL ), com exceção do E_WARNING.

Já temos nosso arquivo de configuração ( mostra_erros.php ), agora basta chamar o arquivo de configuração nas páginas em que gostaria de alterar a configuração.

<?php

include “mostra_erros.php”;

?>

Adicione a ‘include’ acima no inicio das páginas PHP,  para que seja definido os parametros antes da página ser carregada. Quando precisar depurar algum erro nos códigos, ou acrescentar mais linhas ao código, basta alterar o arquivo mostra_erros.php e habilitar a exibição dos erros conforme foi apresentado nos exemplos acima.

Share