Ubuntu 8.10 – veja as novidades

Daqui duas semanas, no final de Outubro, será lançada a nova versão do Ubuntu, a 8.10, batizada de Intrepid Ibex. Segue, abaixo, uma lista de algumas das mais significativas mudanças.

Atualização do GNOME
O ambiente gráfico será atualizado para a versão 2.24 (release notes completo: http://library.gnome.org/misc/release-notes/2.24/)

Conectividade 3G
Entre as novidades da nova versão da distro, encontramos um aperfeiçoamento na utilização e suporte para conexões 3G(claro que não era difícil, mas nada melhor que simplificar ainda mais o processo).

Kernel 2.8.27
Atualização do Kernel do linux usado com várias melhorias e correções.

Conta Guest para visitantes
Se você sempre pensou que poderia haver uma conta default para usuários hóspedes, agora sua idéia passará para o plano real. O novo Ubuntu criará usuários temporários(que por questões de segurança não terão acesso a nenhuma informação de outros usuários cadastrados no sistema nem acesso à escrita na máquina) para utilização de funções básicas e emergenciais no sistema.

Maior segurança para seus dados pessoais
Outra coisa boa na próxima versão Ubuntu é um novo diretório privado(~ / Privado), o qual não será acessado por outros usuários (pois terá permissão chmod 700). E o que o torna melhor ainda: este diretório é criptografado!

Melhoria no gerenciador de pacotes de atualizações
Sabe quando você atualiza todos os seus repositórios e sistema fazendo aquele upgrade que deixa vários pacotes “bagunçados”? Pois é, a nova versão do Ubuntu oferecerá um sistema de limpeza que lhe auxiliará quanto a esta “baguncinha” em seu sistema.

Instalação por pendrive
Imagine que você demorou dias para convencer uma pessoa a usar o Ubuntu devido às vantagens trazidas e, justamente na hora de instalar você esqueceu o CD ou não pôde levá-lo devido ao tamanho! Agora o Ubuntu poderá ser instalado diretamente de um pendrive.

Melhor usabilidade no instalador do sistema
O instalador do Ubuntu, que ainda não havia sido modificado desde a criação do sistema, finalmente será atualizado, recebendo um visual mais prático.

Drivers
Novos drivers serão adicionados(entre eles, os de algumas impressoras, o que para muitos que sofrem como eu utilizando a Lexmark X3470, pode ser quase uma conquista).

Gerenciar as fontes pelo GNOME
Quanto ao “fontconfig” no qual temos de modificar manualmente o arquivo de configuração das fontes, trata-se de ser alterado. Um confortável GUI nos permitirá alterar as nossas configurações de fontes no GNOME. É especialmente útil quando muitos usuários trabalham em um computador.

Abas no Nautilus
Finalmente foi criado um sistema de abas para o Nautilus. Agora poderemos criar divisões para facilitar nossa navegação nos arquivos.

Melhoria na pesquisa do gerenciador de pacotes
Foi implementada uma atualização no Synaptic a qual fará com que suas pesquisas retornem os resultados em um momento. Basta escrever o que você está procurando (por exemplo, “áudio”) e os resultados serão exibidos quase que instantâneamente(e você nem precisa pressionar a tecla Enter)

 

Por curiosidade, segue abaixo o wallpaper oficial da nova versão:

Diminuindo o consumo de banda com html, css e javascript

Estava eu ontem, todo *feliz*, analisando as estatísticas de acesso de uns sites feitos (e hospedados) na empresa pra qual trabalho. Bacana, vendo acessos de browsers, horas de pico, resolução de tela, tráfego de arquivos e…
Perae! 45% do tráfego mensal era de javascript. Num site sem absolutamente nada de ajax ou efeitos ou coisas do gênero.
Encafifei: o quê estaria acontecendo?

Simples: esqueceram de ligar o filtro de compressão gzip para arquivos css/javascript.

Vejo por aí que muita gente não conhece isso, e fica proecupado em tirar todos os tabs e espaços dos arquivos html, css e javascript. Usa aqueles aplicativos que diminuem o código javascript, colocando tudo na mesma linha. E acabam com qualquer tabulação no CSS.
Tudo isso era válido 5 anos atrás. Hoje em dia, existe uma forma mais adequada de fazer diminuir o consumo de banda quando arquivos desse gênero são requisitados.

Explicando como os browsers funcionam: ao fazer uma solicitação de um URL, quando essa chega no servidor de destino, a primeira coisa a acontecer é passar pelo webserver. Esse cara tenta pegar os arquivos requisitados (html, imagens, css, js, etc…) e, em caso de sucesso (status 200) devolve pra quem os requisitou.
*isso tudo é uma simplificação beeem simplificada do fluxo, conforme pode-se ver no diagrama abaixo:

 
Bem, um novo passo nesse fluxo foi adicionado com a evolução tanto dos browsers, quanto dos webservers quanto do protocolo HTTP.
Os browsers hoje em dia, bem como o webserver, têm a capacidade de comprimir e descomprimir dados usando o gzip (como se fosse um .zip). Quando o browser faz uma solicitação de uma URL, ele manda um header com dados referentes à solicitação e a ele mesmo (qual a versão, tipo, etc…). Com isso, o webserver consegue saber se esse browser suporta compressão de arquivos. Se o webserver estiver configurado, ele pode fazer a compressão de arquivos html, css, js, ou de qualquer outro formato de arquivo.

 

Fazendo testes aqui, a diferença de tamanho de arquivo para html/css/js chegou a 90% em alguns casos. Imagine que se você usa algum framework js (a jQuery tem uns 100kB, a Prototype está com 120), a cada requisição de um usuário que não está com esses arquivos no cachê pode ser de 90kB – okey, vamos arredondar para 80kB. Se 100 pessoas acessam por dia, dá 8mB; ou, 240mB por mês.
Agora, imagine num site com milhares de pageviews…

Na net, existem muitos links explicando como configurar o seu webserver (ISS, Apache) para cada tipo de arquivo, como esses aqui:

Compressão de html com o Apache: http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/
Compressão de CSS/js com o Apache: http://blog.joshuaeichorn.com/archives/2007/01/10/compressing-javascript-and-css/
Verificar a taxa de compressão: http://www.gidnetwork.com/tools/gzip-test.php

Enjoy 😉
 

Lumine – um exemplo prático de uso

Nesse post eu falei sobre o Lumine, um framework em PHP para persistência de dados (nos moldes do Hibernate para o Java e o DB_DataObjects do PEAR).
Resolvi dar uma para em uns projetos e realmente experimentar em algo que eu precisava, e me dediquei a abandonar as querys SQL. E funcionou.
Vou, abaixo, mostrar como fazer para persistir os dados postados por um formulário numa tabela de uma base (no caso, MySQL).

Vamos supor que você tenha uma tabela no banco chamada messages com as seguintes colunas:

id – tinyint, chave-primária e autoincrement
name – varchar, 64
email – varchar, 64
msg – varchar, 512
publishDate – date

Como seguinte script, cria-se a tabela:

CREATE TABLE `messages` (
  `id` tinyint(4) NOT NULL auto_increment,
  `name` varchar(64) NOT NULL,
  `email` varchar(64) NOT NULL,
  `msg` varchar(512) NOT NULL,
  `parentId` tinyint(4) NOT NULL,
  `publishDate` date NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

O html que contém o formulário (no caso, um formulário em que um usuário posta o nome, e-mail e uma mensagem) é bem simples e já abordei essa técnica usando a biblioteca prototype (sinta-se livre pra usar qualquer outro framework, ou outra técnica; não influencia no resultado final) em outros posts(aqui e aqui):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Upload de mensagem</title>
<script src="http://www.prototypejs.org/assets/2008/1/25/prototype-1.6.0.2.js"></script>
<script type="text/javascript">
    function upload() {
        $("message").update("<img src=´loader.gif´> aguarde, enviando mensagem...");
        $("form_upload").request({
          onComplete: function(transport){
            if(transport.responseText=="")
                $("form_upload").reset();
                $("message").update("Sua mensagem foi enviada com sucesso... obrigado!");
            }
               
        });
        return false;
    }
</script>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="box">
<h1>Envio de mensagem</h1>
<form action="saveMsg.php" method="post" enctype="application/x-www-form-urlencoded" id="form_upload" onsubmit="return upload();">
    <label for="name">nome:</label><input type="text" id="name" name="name" class="field" /><br /><br />
    <label for="email">e-mail:</label><input type="text" id="email" name="email" class="field" /><br /><br />
    <label for="msg">mensagem:</label><textarea id="msg" name="msg"></textarea><br />
    <input type="submit" value="enviar" class="submitButton" />
    <span id="message"></span>
</form>
<div id="msgs_area"></div>
</div>
</body>
</html>

Agora, o passo mais importante: modelar (exemplo: http://www.hufersil.com.br/documentacao/instanciando) uma classe seguindo a estrutura da sua tabela. No arquivo Message.php eu criei a classe, extendendo a classe do Lumine, mapeando os atributos relativos à tabela.

<?php
class Message extends Lumine_Base{
    protected $_tablename = ´messages´;
    protected $_package   = ´entidades´;
    protected function _initialize() {
        $this->_addField(´id´, ´id´, ´tinyint´, 4, array(´primary´ => true, ´notnull´ => true, ´autoincrement´ => true));
        $this->_addField(´name´, ´name´, ´varchar´, 64, array());
        $this->_addField(´email´, ´email´, ´varchar´, 64, array());
        $this->_addField(´publishDate´, ´publishDate´, ´date´,null , array());
        $this->_addField(´msg´, ´msg´, ´varchar´, 512, array());
        $this->_addField(´parentId´, ´parentId´, ´tinyint´, 4, array(´primary´ => false, ´notnull´ => true, ´autoincrement´ => false));
    }
}
?>

Então, o passo final é criar o arquivo que recebe o post do formulário (no caso, saveMsg.php).
Nesse arquivo, o que fazemos: chamamos a classe Lumine.php (que vem no pacote de instalação do Lumine), configuramos a aplicação (http://www.hufersil.com.br/documentacao/lumine_conf), depois atribuímos os valores recebidos por POST a cada parâmetro enviado pelo formulário (e pegamos a dataa atual para salvar no banco) e, por final, chamamos o método insert() que faz salvar os dados na tabela do banco.
Segue o código:

<?php
require "../lumine/Lumine.php";
require "lumine_config.php";
$cfg = new Lumine_Configuration( $lumineConfig );
require "Message.php";
//cria classe Message
$msg = new Message;
//decodifica os pareâmetros enviados, para evitar problemas com acentuaçãao
foreach ($_POST as $key => $valor ){
   $_POST[$key] = utf8_decode($valor);
}
$msg->name = $_POST["name"];
$msg->email = $_POST["email"];
$msg->msg = $_POST["msg"];
$msg->publishDate=date(DATE_RFC822);
$msg->insert();
?>

Passei batido por alguns detalhes aqui relativos à configuração, mas a documentação oficial é muito boa – e o próprio ato de configurar é algo bem simples para quem está na área de desenvolvimento.
E, olhando assim por cima, parece que há muito trabalho para configurar tudo isso para fazer apenas uma inserção no banco; mas, imaginem só configurar uma vez só, e depois acabar com todas querys de inserts, updates, selects, etc… Muito bom, aprovado!

 

Site oficial: http://www.hufersil.com.br/documentacao/apresentacao

Usando a Prototype – passo 4 – upload de arquivo sem post na tela

Segue abaixo um exemplo de como fazer upload de um arquivo, através de um formulário, sem precisar dar post na página.
Como funciona?
Um form normal de upload de arquivo que tem no onsubmit chamada a função javascript. Essa, por sua vez, cria um iframe em tempo de execução, muda o target do form para esse iframe e faz o upload do form.
O arquivo de destino (nesse caso usei um .php, mas independe de qual linguagem para gerenciar esse upload você quer usar) tem no onload uma chamada à função javascript do parent dele que faz informar na tela que o upload foi efetuado. Trocandando em miúdos, o upload é feito da mesma forma que sempre foi feito, e quando a página é carregada no iframe – é o momento em que o upload do arquivo foi feito e a página processada -, por javascript se faz atualizar a página pai.

Segue abaixo o código das duas páginas, comentado (usei a biblioteca Prototype para ajudar no javascript):

index.htm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Exemplo de upload</title>
<script src="http://www.prototypejs.org/assets/2008/1/25/prototype-1.6.0.2.js"></script>
<script type="text/javascript">
    function upload() {
        //cria um iframe, escondido
        var iframe = new Element("iframe", {name:"target", id:"iframe_upload"});
        //insere na página o iframe
        document.body.insert(iframe);
        //muda o target do form, apontando para o iframe
        $("form_upload").target = iframe.name;
        //mostra a mensagem
        $("message").update("aguarde, enviando arquivo...");
    }
   
    function closeIframe() {
        //atualiza a mensagem
        $("message").update("arquivo enviado com sucesso");
        //apaga o iframe
        $("iframe_upload").remove();
    }
</script>
<style type="text/css">
    iframe {display:none;}
</style>
</head>
<body>
<h1>Exemplo de upload</h1>
<form action="upload.php" method="post" enctype="multipart/form-data" id="form_upload" onsubmit="return upload();">
    <input type="file" name="arquivo" id="arquivo" />
    <input type="submit" value="enviar" />
    <span id="message"></span>
</form>
</body>
</html>

 

upload.php

<?php
//faz todo o processamento necessário no PHP para persistir o arquivo
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Upload - OK</title>
</head>
<!-- chama função javascript da página pai -->
<body onload="parent.closeIframe();">
</body>
</html>

Basicamente, isso é o que a maioria dos sites que têm formulários de upload estão fazendo; é o que chamam, por aí, de upload 2.0. Não sei se concordo muito com o termo usado, mas faz o mesmo efeito.
Vale ressaltar que muitas bibliotecas javascript fazem isso, inclusive com plugins bem maduros. Mas, de qualquer modo, vale a pena saber como funcionam esses plugins, entender qual a dinâmica e o conceito.
Em breve mostro outra forma de fazer upload com barra de progresso – tanto com uma linguagem server-side quanto usando Flash (e Action Script 3).