Skip to content

Nova lista do Ubuntu-PR, agora no Launchpad

08-Sep-08

Com a última migração dos servidores da Ubuntu-BR, as antigas listas estaduais que ficavam sob o domínio listas.ubuntubrasil.org acabaram sendo desativadas. Portanto, seguindo o exemplo do Lício, que recriou a Ubuntu-MG no launchpad, estamos recriando também no launchpad, a antiga lista do Ubuntu-PR.

Portanto, se você ainda não participa do Ubuntu-PR no Launchpad, junte-se a nós! E para aqueles que já fazem parte do grupo, acessem suas contas e se cadastrem na lista pelo seguinte endereço:

https://launchpad.net/people/+<seu-login>/+editemails

Nos vemos na lista! :)

Scataplaft!

02-Sep-08

Outro post falando sobre o Google Chrome, mas este daqui é apenas para chamar a atenção para um trecho que eu achei “engraçado” no texto da Google Blogoscoped.

(Google could, for instance, release browser features that benefit their sites more than most other sites… as can Microsoft with Internet Explorer)

Fonte: http://blogoscoped.com/archive/2008-09-01-n47.html

Em um texto onde o Google diz que está jogando o mais limpo possível, o comentário acima (pelo menos para mim) parece ser mais uma espécie de “tapa com luva de pilica” do que qualquer outra coisa. :)

Implementação de singleton em PHP

28-Aug-08

Durante uma discussão hoje na lista php-especialistas, eu criei um protótipo para a implementação do padrão Singleton, mas que (na minha opinião) acabou ficando bem legal… Então, para não desperdiçar o trabalho e movimentar um pouco o blog, segue o código abaixo:


<?php
abstract class Singleton {
    static private $instance = array();

    final static public function instance($module) {
        if (!class_exists($module))
            throw new Exception("Module '{$module}' not found.");
        $module = strtolower($module);
        if (!isset(self::$instance[$module]))
            self::$instance[$module] = new $module;
        return self::$instance[$module];
    }
}
?>

Quer saber como ela funciona!? Essa classe abstrata, portanto não pode ser instanciada, funciona da seguitne forma: sempre que você quiser que uma determinada classe siga ao padrão Singleton, basta chama-la sempre através da classe acima, como segue:


<?php
require_once 'Singleton.php';

class ClassA {
    public $valueA = null;
}   

class ClassB {
    public $valueB = null;
} 

try {
    $objA1 = Singleton::instance('ClassA');
    $objA2 = Singleton::instance('ClassA');
    $objA1->valueA = 'ClassA instance 1';
    echo $objA2->valueA . "\n";

    $objB1 = Singleton::instance('ClassB');
    $objB2 = Singleton::instance('ClassB');
    $objB1->valueB = 'ClassB instance 1';
    echo $objB2->valueB . "\n";

    $objC1 = Singleton::instance('ClassC'); // exception!
} catch (Exception $ex) {
    echo "<b>Singleton Error:</b> {$ex->getMessage()}";
}
?>

E o resultado do código acima é:

ClassA instance 1
ClassB instance 1
Singleton Error: Module 'ClassC' not found.

E é isso ae, espero que esse código seja útil para mais alugém. :)

UPDATE1: Definido o método Singleton::instance como final, assim ele não poderá ser alterado por nenhuma classe que extenda a classe Singleton.

UPDATE2: Na versão 5.3 do PHP, foi introduzida uma funcionalidade chamada de Late static binding que faz com que possamos criar (sem nenhuma artimanha-extravagante) uma classe Singleton, onde todas as classes que a extenderem serão Singleton também. Algo parecido com o código abaixo.


<?php
require_once 'Singleton.php';

abstract class Singleton {
    static private $__CLASS__ = __CLASS__;
    static private $instance = null;

    final static public function instance() {
        if (static::$instance == null)
            static::$instance = new static::$__CLASS__;
        return static::$instance;
    }
}
?>

E nessa caso, a implementação fica algo mais ou menos parecido com:


<?php
class ClassA extends Singleton {
    // Singleton implementation
    static private $__CLASS__ = __CLASS__;
    static private $instance = null;

    prublic $value = null;
}

$objA1 = ClassA::instance();
$objA2 = ClassA::instance();
$objA1->value = 'ClassA instance 1';
echo $objA2->value . "\n";
?>

Nessa versão 5.3, ainda dará para usar os namespaces organizando um pouco melhor essa estrutura. :)

O planeta está de volta!

27-Aug-08

Aeee! O Planeta Ubuntu-BR está de volta…


afurlan@beterraba:~$ ping planeta.ubuntu-br.org
PING planeta.ubuntu-br.org (91.189.94.191) 56(84) bytes of data.
64 bytes from neodymium.canonical.com (91.189.94.191): icmp_seq=1 ttl=43 time=347 ms
64 bytes from neodymium.canonical.com (91.189.94.191): icmp_seq=2 ttl=43 time=362 ms
64 bytes from neodymium.canonical.com (91.189.94.191): icmp_seq=3 ttl=43 time=353 ms

--- planeta.ubuntu-br.org ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 347.647/354.583/362.456/6.120 ms

Servidor novo, engine nova, tema novo… Enfim, parabéns ao pessoal do Ubuntu-BR por todo o esforço. :)

Dia dos pais

11-Aug-08

#!/usr/bin/env python
# -*- coding: utf-8 -*-

class Arthur:
    pass
class Bianca:
    pass
class Eduarda(Arthur, Bianca):
    pass

Feliz dia dos pais para todos que, assim como eu, tem a felicidade de poder comemorar este dia! :)
No mais as coisas estão corridas e eu pra variar, sem tempo para escrever no blog… Infelizmente.

Instalando o flash player 10 beta 2

09-Jul-08

Essa semana foi lançada a nova versão beta do Flash Player 10 que promete acabar com o problema das aplicações transparentes.

Como todo bom nerds curioso, tentei instalar a nova versão no meu computador para dar uma olhada no que ela trazia de bom, mas infelizmente, o instalador que vem junto com o pacote da Adobe não funcionou e eu acabei tendo que fazer a instalação manualmente mesmo… Apesar de não ser nada complicado, vou colocar aqui os passos que tomei para fazer a instalação, pois quem sabe possa ajudar mais alguém que esteja passando pelo mesmo problema. :)

Então vamos começar fazendo o download da versão para linux e descompactando:


$ wget http://download.macromedia.com/pub/labs/flashplayer10/flashplayer10_install_linux_070208.tar.gz
$ tar xvzf flashplayer10_install_linux_070208.tar.gz

Será criado um diretório chamado install_flash_player_10_linux que contém os seguintes arquivos:


$ ls install_flash_player_10_linux
flashplayer-installer  libflashplayer.so

O primeiro deles, flashplayer-installer, é o instalador da Adobe e o segundo, libflashplayer.so, é a biblioteca do flash mesmo. Antes de instalar, vamos fazer um backup da versão atual da biblioteca:


$ sudo cp /usr/lib/flashplugin-nonfree/libflashplayer.so /usr/lib/flashplugin-nonfree/libflashplayer9.so

E então vamos tentar (apesar de não ter funcionado comigo) instalar através do flashplayer-installer, existente no próprio pacote. Se você quiser que a instalação funcione para todos os usuários da máquina, execute:


$ cd install_flash_player_10_linux
$ sudo ./flashplayer-installer

Caso contrário, se você é um cara egoísta e quer que a nova versão funcione só para o seu usuário, faça:


$ cd install_flash_player_10_linux
$ ./flashplayer-installer

Como eu sou o único usuário deste meu computador, tentei instalar o player para todos os usuários da máquina mas como já foi dito, o instalador não funcionou comigo e apresentou o seguinte problema:


$ cd install_flash_player_10_linux
$ sudo ./flashplayer-installer
...
Please enter the installation path of the Mozilla, Netscape,
or Opera browser (i.e., /usr/lib/mozilla): /usr/lib/mozilla

WARNING: Please enter a valid installation path.

Please enter the installation path of the Mozilla, Netscape,
or Opera browser (i.e., /usr/lib/mozilla): /usr/lib/mozilla

WARNING: Please enter a valid installation path.

Please enter the installation path of the Mozilla, Netscape,
or Opera browser (i.e., /usr/lib/mozilla):
...

Não sei porque o instalador não reconheceu o diretório que ele mesmo recomenda, que existe e, principalmente, que é o diretório de instalação do Mozilla. Se esse erro aconteceu com você também, vamos partir para a instalação manual, que é mais simples que os passos anteriores… Para instalar a biblioteca manualmente, execute:


$ cd install_flash_player_10_linux
$ sudo cp libflashplayer.so /usr/lib/flashplugin-nonfree/

E agora você já está com a nova versão do flash player instalada! Para conferir, feche o firefox e então execute:


$ firefox "about:plugins" &

Você vai encontrar:

File name: libflashplayer.so
Shockwave Flash 10.0.0 d525

Mas e sobre o novo player!? Pois é, ele resolveu o problema das transparências porém acabou ficando mais pesado que a versão anterior… Ainda é uma release beta, então provavelmente a versão final estará um pouco melhor!

E você, já instalou a nova versão!? O que achou?

UPDATE1: Seguindo os comentários do Agail e Mitzgitari usando o diretório /usr/lib/firefox-3.0 a instalação ocorre normalmente.
UPDATE2: Assim como reportado pelo Wildner a nova versão do flash continua não funcionando para plataforma 64bits do linux.

Caçando erros de sintaxe em sistemas PHP

06-Jun-08

Como o PHP não é uma linguagem compilada, grande parte dos bugs de um sistema só são percebidos (e corrigidos) em ambiente de produção. Isso acontece principalmente se você mantém um sistema grande, pois se torna difícil validar todos os arquivos que são enviados para ambiente produção em cada nova release.

Porém, usando o PHP CLI (Command Line Interface) você consegue validar a sintaxe de um sistema inteiro de uma forma simples, fácil e rápida. Se você ainda não tem o PHP CLI instalado, você pode instalá-lo no Ubuntu (ou Debian) da seguinte forma:


$ sudo aptitude install php5-cli

Pronto, agora você tem acesso ao PHP via linha de comando:


$ php -r 'echo "Hello World!";'
Hello World!

Aproveite também dar uma olhada em todas as opções do PHP CLI porque ele tem bastante coisa legal e que podem ser muito úteis em vários casos. Uma dessas opções é o validador de sintaxe, ou seja, a opção -l.

Veja o exemplo de um arquivo sem problemas de sintaxe:


$ nl helloworld.php
     1  <?php
     2  echo 'Hello ';
     3  echo 'World!';
     4  ?>
$ php -l helloworld.php
No syntax errors detected in helloworld.php

E agora o mesmo arquivo com erros de sintaxe


$ nl helloworld.php
     1  <?php
     2  echo 'Hello '   // erro de sintaxe, faltando um ";" aqui
     3  echo 'World!';
     4  ?>
$ php -l helloworld.php

Parse error: syntax error, unexpected T_ECHO, expecting ',' or ';' in helloworld.php on line 3
Errors parsing helloworld.php

Agora você pode usar um pouco de bash junto com essa opção de checagem de sintaxe para validar todo o seu sistema PHP de uma só vez, como mostrado a seguir


$ find /var/www/meu-site -name *.php -exec php5 -l {} ";"

Claro que isso não garante que não hajam erros de lógica no seu sistema, mas encontrar e corrigir todos os erros de sintaxe antes de enviar o código para o cliente já um grande passo. É possível ainda criar um script muito mais elaborado do que o comando mostado acima, mas a idéia desse post era só mostrar o conceito mesmo.

É isso ae, abraços.

Por essa eu não esperava…

04-Jun-08

Agora eu realmente fiquei impressionado com o Google, por essa eu realmente não esperava! Acho que uma imagem vale mais do que mil palavras, então segue abaixo:

Google e o \"dedo do meio\"

Quer ver também? Tá ae.

E caso você tenha ficado em dúvida… Sim, era exatamente esta a figura que eu estava procurando, um dedo do meio. :)

Analogias às propagandas da Microsoft na Linux Magazine

13-May-08

Eu estava debatendo hoje com o meu amigo Marcos Miklos no GTalk a respeito das propagandas da Microsoft na Revista Linux Magazine. Na opinião dele isso está completamente errado, uma vez que a Microsoft não apóia/pratica o Software Livre, e portanto a Linux Magazine não deveria permitir esse tipo de coisa… Eu não concordei e contra-argumentei:

Nesse caso é diferente, é como você entrar na torcida do Flamengo e dizer que o Vasco é o melhor… Não vai adiantar nada! Você só vai perder tempo (e dinheiro, no caso deles) e ainda correr um grande risco de ser enxovalhado. Deixa eles lá, financiando o linux, nem que seja somente a revista… é bom para a gente.

E então eis que surge a pérola:

Imagina você comprando uma Playboy, uma revista para homens, com mulheres nuas, e vendo uma propaganda da G Magazine com um homem mostrando o bilau e dizendo: “Venha para o lado rosa da força, é muito mais legal”.

Hahaha… Simplesmente sensacional a analogia!

Depois ele me disse que essa discussão já estava rolando há algum tempo na Comunidade Linux Brasil e que esse comentário foi feito pelo Gabriel Pnordico. Leiam a discussão porque vale a pena, está bem engraçada! Depois lendo o tópico na íntegra eu encontrei outra pérola como:

É como se você tivesse uma namorada e ela usasse uma camiseta dizendo que ama o padeiro da esquina

dita pelo Lord Heizel.

Django, download e o problema no Internet Explorer 7

09-May-08

Há pouco tempo atrás eu postei aqui no blog como forçar o download de arquivos com Django.

Na época eu havia testado o sistema em todos os navegadores que estavam ao meu alcance (Firefox, Iceweasel, Opera, Epiphany, IE6 e IE7) porém mesmo assim não precisou de muito tempo em ambiente de produção para me contactarem dizendo que o sistema não estava funcionando no IE7 (ué, como assim!? mas eu tinha testado isso!).

Testei novamente e então descobri que na verdade ele funcionava e não funcionava. Hm, ok… mas como assim!? Na verdade ele funcionava perfeitamente no IE7 do Windows 2003 Server, mas não funcionava em nenhum outro e eu dei o azar (ou sorte) de testar justamente nele… no Windows 2003 Server. Nos Windows com problemas (pleonasmo?) o erro que ocorria era o seguinte:

Internet Explorer was not able to open this Internet site.
The requested site is either unavailable or cannot be found. Please try again later.

Ok, um erro muito explicativo… Então vamos ao Google! Depois de muito procurar no Google sem encontrar nenhuma solução, um colega de empresa decidiu comparar os headers de uma aplicação escrita em .NET e que funcionava em qualquer IE, com os headers gerados pela minha aplicação. Chegamos a conclusão de que o problema estava no campo Vary, que aparecia nos headers do Django mas não existia no header da aplicação .NET.

A primeira idéia foi remover o campo manualmente, antes de retornar o response da página:


from django.http import HttpResponse, Http404
from os import path
import mimetypes

def index(request, file=''):
    abspath = path.join('/your/absolute/path', file)
    if not (file and path.exists(abspath)):
        raise Http404()
    mimetype, encoding = mimetypes.guess_type(abspath)
    if mimetype is None:
        mimetype = 'application/force-download'
    response = HttpResponse(open(abspath, 'r').read())
    response['Content-Disposition'] = 'attachment; filename=%s' % file
    response['Content-Type'] = mimetype
    response['Content-Length'] = str(path.getsize(abspath))
    del response['Vary']
    return response

* As linhas em negritos são as linhas que foram alteradas na solução inicial.

Mas não funcionou… O campo Vary continuava aparecendo e com o mesmo valor de antes. Lendo um pouco de documentação, descobrimos que essa diretiva não pode ser alterada diretamente no header da página e também qual era a forma correta de remover esse campo:


from django.views.decorators.cache import cache_control
from django.http import HttpResponse, Http404
from os import path
import mimetypes

@cache_control(private=True)
def index(request, file=''):
    abspath = path.join('/your/absolute/path', file)
    if not (file and path.exists(abspath)):
        raise Http404()
    mimetype, encoding = mimetypes.guess_type(abspath)
    if mimetype is None:
        mimetype = 'application/force-download'
    response = HttpResponse(open(abspath, 'r').read())
    response['Content-Disposition'] = 'attachment; filename=%s' % file
    response['Content-Type'] = mimetype
    response['Content-Length'] = str(path.getsize(abspath))
    return response

* As linhas em negritos são as linhas que foram alteradas na solução inicial.

Ok, agora sim! Tudo funcionando direitinho e em todos os (pseudo-)navegadores!

Como eu não achei nada na internet que ligasse esse problema aos campos Vary do header, acredito que esse post possa ajudar alguém mais que esteja passando pelo menos problema! :)

UPDATE: Em alguns casos a conexão terminava antes de ter baixado todo o arquivo. Esse é um problema do servidor, e para corrigi-lo basta definir a diretiva EnableSendfile do Apache como On. Com essa configuração, também houve uma melhora significativa na taxa de download do servidor (pelo menos no meu caso).