Qual o nível de segurança do seu sistema?

Constantemente me deparo com esse questionamento por algum cliente e, confesso, ainda hesito um pouco na hora de responder. A primeira coisa que me vem à cabeça é: ”O sistema possui um Sistema de Segurança Sayajin Nível 3“. Acredito que a maioria dos cliente se dariam por satisfeitos. Além disso de que adiantaria ficar cuspindo várias siglas e jargões como: XSS, Força Bruta, SQL Injection, etc.

Quanto mais demoro para responder, mais desconfiados ficam os clientes e isso gera ainda mais dúvidas.

Software Livre é outro termo que levanta muitas suspeitas. Muita gente acha que se o código está aberto fica mais fácil para pessoas mal intencionadas descobrirem falhas mas não entendem que o inverso também se aplica. E o fato de o código estar aberto para todos incrementarem amplia o número de revisores e, consequentemente, da qualidade do software.

Escala de Segurança

O problema é que não existe uma escala de segurança para sistemas web. Sei que seria complicado pois deveria levar em conta: servidor, sistema operacional e o fator humano entre outros; mas acredito que essa escala se faça necessária para facilitar o diálogo com clientes leigos e até conduzir o desenvolvimento de novos sistemas.

No que tange os sistemas web, talvez um primeiro passo seja pensar em divisões de nível baseado nas falhas que esse sistema trata, como sanitizar as consultas antes de processá-las no banco. Em seguida, avaliar boas práticas de programação empregadas, por exemplo: não usar variáveis globais.

Cada nível possuiria uma lista de critérios a serem atendidos que ficariam cada vez mais complexos à medida que fosse subindo de nível. Dessa forma teríamos um valor concreto da categoria em que o sistema se encontra.

O Custo da Segurança

Certa vez um cliente disse que queria um site 100% seguro. Pensei em dizer que ninguém se daria ao trabalho de hackear seu site mas acho que isso iria atingir em cheio o seu ego. Ao invés disso, me limitei a chutar um valor e prazo para implementação da solução de acordo com o que ele queria, que ultrapassavam sua estimativa de orçamento e cronograma. Isso foi o suficiente para fazê-lo mudar de idéia.

Um site deve ser tão seguro quanto precisa ser. Esse é outra forma de enxergar uma escala de segurança, entendendo que a implementação de cada nível requer um investimento maior, não só para o desenvolvimento mas para compra de certificados, alocação de recurso e por aí vai.

Nada é Completamente Seguro

Não existe segurança absoluta, mas dizer isso a seu cliente pode significar a perda de um contrato para uma empresa que diz ter um sistema impenetrável.

Mais uma vez uma escala de segurança mostra sua importância. Deixaria claro para usuários inexperientes o nível de segurança de um sistema e nos permitira fazer comparações com os seus concorrentes.

No mais, quer segurança? Coloque seu site em um pendrive criptografado, com senha, dentro de um cofre, debaixo da sua cama… bem longe da internet.

Plugin: MM Chat

A algum tempo atrás trabalhei num plugin para chat que acabou nem sendo colocado em funcionamento. Para não haver desperdício, resolvi disponibilizá-lo para download, caso exista algum interessado.

Instalação

  1. Faça o upload do plugin ‘mm-chat’ para o diretório ‘/wp-content/plugins/’ do WordPress;
  2. Ative o plugin;
  3. Arraste o widget ‘Chat’ para qualquer sidebar

Configuração

Um novo menu aparecerá em ‘Configurações > Chat’, onde será possível configurar o limite e caracteres de cada mensagem e intervalo das atualizações de: mensagens e usuários.

Utilização

Para iniciar uma conversa, faça o login no site, vá para a página onde o widget está, clique no nome da pessoa com quem você quer conversar. Cada usuário tem uma janela própria que pode ser movida para qualquer canto da tela (jQuery UI – Dialog).

Caso alguém te mande uma mensagem, a janela de dialogo abrirá automáticamente, além de manter um breve histórico das conversas anteriores.

Caso você não queira mais receber mensagens de um determinado usuário, basta clicar no cadeado ao lado do nome do mesmo.

Download

MM Chat

Template para subcategorias

As últimas versões do WordPress melhoraram muito a hierarquia de templates, possibilitando criar modelos usando slug de tags ou categorias (category-noticias.php), nome dos autores (author-marcelo.php), tipos de arquivos (image.php) e até criar templates para tipos de posts (single-evento.php archive-evento.php).

Uma coisa da qual sinto falta no WordPress é a possibilidade de criar um template para subcategorias. Dessa forma podemos dividir o site em áreas com cores específicas ou com sidebares diferenciados, por exemplo.

Para resolver esse problema, existe uma função do que recupera as subcategorias de uma dada categoria (get_term_children) e as retorna em um array. Com isso podemos usar a template tag is_category passando esse array como parâmetro.

Por fim basta condicionar o carregamento dos templates no arquivo category.php:

if( is_category( 1 ) or is_category( get_term_children( 1, 'category' ) ) )
  include( 'category-noticias.php' );
elseif( is_category( 2 ) or is_category( get_term_children( 2, 'category' ) ) )
  include( 'category-eventos.php' );
else
  include( 'category-default.php' ); 

Assim para a categoria 1 e suas respectivas filhas, será usado o template category-noticias.php, para a categoria 2 e suas respectivas filhas será usado o template category-eventos.php e para as demais categorias, será usado o template category-default.php.

Para manter o código limpo, é recomendável que o template category.php tenha apenas as condições e os includes dos arquivos corretos, se você pretende manter o código padrão do template da categoria nesse arquivo, lembre-se de deixá-lo dentro da condição else.

Download

category

Plugin: Widget Custom Loop

Existe uma rotina na montagem dos conteúdos dos tema para WordPress já que é sempre um loop que carrega o conteúdo dos posts e páginas. Quando trabalhamos com sites grandes com várias colunas de informação a variação nesse loop se dá quase sempre por categorias – uma coluna mostra os posts da categoria x enquanto outra coluna mostra os posts da categoria y. A maioria das alterações era na estrutura html desses loops, então porque não automatizar esse processo?

custom-loopTentando facilitar as coisas eu criei o plugin Widget Custom Loop, que se trata de um widget que permite a definição do loop e personalização de sua estrutura.

Instalação

  1. Faça o upload do plugin ‘widget-custom-loop’ para o diretório ‘wp-content/plugins/’ do WordPress;
  2. Ative o plugin.

Utilização

Na páginda de widgets deverá aparecer o widget ‘Custom Loop’. Arraste o widget para o sidebar desejado e configure de acordo com suas necessidades.

Por padrão, caso o campo ‘Loop’ seja deixado em branco o plugin monta um loop automático. Esse modelo de loop automático é definido através da opção ‘loop_model’, caso o tema queira definir um modelo de loop, basta salvar esse modelo na opção ‘loop_model’, por exemplo:

update_option( ‘loop_model’, ‘<h3>{title}</h3>{excerpt}’ );

Dessa forma, sempre que o ‘Custom Loop’ for adicionado em algum sidebar, ele seguirá esse modelo por padrão.

Download

Widget Custom Loop

WordPress é CMS

Esse post era pra ser uma resposta a um comentário que recebi no post ‘Migrando Conteúdo do Drupal para WordPress‘ que escrevi, mas acabou ficando muito grande e se tornou um post. Minha intensão intenção não é denegrir a imagem do Drupal, só quero derrubar alguns mitos que existem em relação ao WordPress quando comparado a outros CMS’s – nesse caso o Drupal.

Já trabalhei desenvolvendo temas e plugins para os dois CMS’s e minha experiência com o WordPress foi muito mais simples e satisfatória.

WordPress é para Blog

O argumento de WordPress ser para blogs já não cola mais, no Showcase do WordPress, vocês encontram vários exemplos de portais, vitrines e sites que não tem nenhum traço de blog (não que isso seja algo ruim) em seu visual. O fato é: você faz o que quer com o WordPress.

É verdade que existem milhões de blogs no ar que utilizam o WordPress, mas isso não significa que o WordPress só sirva para blogs. A explicação mais adequada para sua popularização se deve a sua simplicidade, facilidade de uso, facilidade de personalização, facilidade de ampliação e integração com outros sistemas. O WordPress diminui a dependencia que os usuários finais têm com os técnicos de informática pois ele é intuitivo, muitos usuários sequer precisam de treinamento para começar a publicar conteúdo.

Também vejo milhares de temas de blogs desenvolvidos para WordPress mas em muitos casos esses temas sequer foram desenvolvidos por programadores, foram designers que se aventuraram no mundo dos códigos e tiveram êxito, o que também é algo positivo pois prova como é tranquilo desenvolver um tema para o WordPress.

WordPress não é ‘completo’

Outra comparação errônea é pensar que determinado CMS é mais completo que outro. O termo ‘completo’ é muito relativo, de que adianta um CMS oferecer trinta recursos se você utiliza apenas quatro ou cinco. Os vinte e cinco recursos restantes acabam por complicar o uso da ferramenta e piorar a sua performance. O WordPress oferece um sistema mais enxuto com possibilidades de expansão (plugins), assim você consegue manter apenas o que é necessário para você.

Quanto ao uso de plugins, a instalação básica do Drupal já ativa por padrão vários plugins para as tarefas mais básicas que um CMS poderia oferecer, como: upload de imagens, comentários e taxonomia. Esses recursos são integrados ao WordPress o que fornece mais segurança e facilita a manutenção da plataforma.

Quem ainda tiver dúvidas da qualidade do WordPress como CMS, talvez não saiba que o WordPress foi eleito o CMS do ano em 2009 pela Info.

Conclusão

Enfim, eu penso que não há nada que outros CMS’s façam que o WordPress não possa fazer mas, com certeza, não é qualquer um que pode fazer.

Migrando conteúdo do Drupal para o WordPress

Da necessidade de migrar o conteúdo do Drupal para o WordPress, surgiu o plugin para o Drupal chamado ‘Drupal to WordPress’. Durante o desenvolvimento desse plugin tive a oportunidade de conhecer um pouco mais sobre o Drupal e ficarei grato se nunca mais precisar trabalhar com ele.

A instalação básica do Drupal gera 47 tabelas e isso dificulta muito o trabalho de migração dos conteúdos. Entendo que isso torne o sistema mais ‘completo’, mas fico pensando em quantas instalações do Drupal realmente utilizam todas essas tabelas. Acredito ser muito mais interessante um sistema enxuto com possibilidades de expansão e é por isso que gosto tanto do WordPress.

Portanto, aos usuário de Drupal que quiserem experimentar algo novo, heis a chance!

Descrição

Esse plugin recupera o conteúdo dos nodes, comentários e anexos do Drupal, qualquer outro conteúdo inserido através de plugin não é recuperado. Ele separa os tipos de nodes em categorias no WordPress já que as categorias no Drupal não são obrigatórias.

Instalação

  1. baixe o plugin;
  2. descompacte-o no diretório ‘sites/all/modules/’ ou ‘sites/nome-do-seu-site/modules/’;
  3. vá para ‘Administer › Site building › Modules’;
  4. marque o módulo ‘Drupal to WordPress’;
  5. salve as configurações.

Modo de usar

Backup

Após a instalação deverá aparecer um novo item no menu chamado ‘Drupal to WordPress’, basta clicar nele para baixar o arquivo de migração. Caso o item do menu não apareça, você pode digitar o endereço do seu site em Drupal seguido de ‘drupal_to_wordpress’, por exemplo: http://www.meusite.com/drupal_to_wordpress

Restauração

  1. faça o login no WordPress;
  2. vá para ‘Ferramentas › Importar’;
  3. selecione o item ‘WordPress’;
  4. faça o upload do arquivo de backup;
  5. informe o nome dos autores;
  6. marque a opção ‘baixar e importar arquivos anexos’ para copiar os arquivos do Drupal;
  7. clique em enviar.

Download

Criando Meta Boxes

Na versão 2.7 o WordPress estreiou as meta boxes, que são aquelas caixinhas arrastáveis que estão presente no dashboard, na área de edição de posts e páginas além de outros locais na área administrativa do WordPress.

Muitas vezes, na criação de plugins que interajem com os posts ou páginas, é necessário adicionar um novo campo à area de edição. Afim de manter a formatação do WordPress, a criação de uma meta box é o caminho mais limpo e fácil. Também é possível adicionar as metaboxes as páginas dos seus plugins, mas é uma tarefa um pouco mais complicada, então vamos deixar para outro artigo.

add_meta_box($id, $title, $callback, $page, $context=’advanced’, $priority=’default’, $callback_args=null);

Essa função é a responssável por adicionar a meta box a uma determinada página. O $id é o identificador único para o HTML, é com esse identificador que o WordPress manipulará sua metabox. Já o $title é o título da metabox, $callback é a sua função que ficará responssável pelo carregamento do conteúdo dentro da metabox e $page é a página onde a sua metabox será carregada (‘page’, ‘post’, ‘link’, etc). Os outros parâmetros são opcionais: $context define o local da página onde sua metabox será carregada por padrão (‘normal’, ‘advanced’, ‘side’) enquanto $priority diz o posicionamento padrão da metabox dentro do $context (‘high’ ou ‘low’), e por fim $callback_args que permite a passagem de argumentos à metabox.

Por exemplo, para criar uma metabox que mostre uma frase de incentivo (não consegui pensar em algo mais simples e útil) na parte de cima do sidebar da tela de edição de posts, ficaria assim:

add_meta_box('incentivador', 'Incentivador', 'incentive_me', 'post', 'side', 'high');

Não se esqueça de criar a função ‘incentive_me’ em seu plugin.

Agora só falta adicionar um gancho para a chamada da metabox:

add_action('do_meta_boxes', 'incentivador_metabox');

Onde ‘incentivador_metabox’ é a função que conterá o seu add_meta_box.

O código final ficaria assim:

<?php
/*
Plugin Name: MetaBox: Incentivador
Description: Mostra uma frase
Version: 0.1
Author: Marcelo Mesquita
Author URI: http://www.marcelomesquita.com/
*/

add_action('do_meta_boxes', 'incentivador_metabox');

function incentivador_metabox()
{
    add_meta_box('incentivador', 'Incentivador', 'incentive_me', 'post', 'side', 'high');
}

function incentive_me()
{
    $frases = array(
        'Você consegue!',
        'Faça seu melhor!',
        'Tudo é possível!'
    );

    print $frases[rand(0, 3)];
}
?>

Para saber mais acesse a Referência da Função add_meta_box

Criando Widgets para o WordPress 2.8

Como todos já devem saber, foi lançada a versão 2.8 do WordPress e entre as principais melhorias está novo sistema de widgets. A interface do usuário está muito mais simples de utilizar, todos os widgets e sidebares ficam listados, basta arrastar um widget para o sidebar desejado e pronto! O WordPress salva automaticamente o sidebar, além disso os widgets já são multiplicáveis então não é mais necessário ficar regulando a divisão deles ou utilizar plugins que façam a duplicação.

Mas a melhoria não foi só na interface com o usuário, a criação dos widgets também ficou muito mais simples, o WordPress disponibiliza uma classe com todo o código bruto para o funcionamento dos widgets sobrando para o desenvolvedor apenas algumas funções específicas.

A API dos Widgets do WordPress fornece um modelo para a criação dos widgets:

class My_Widget extends WP_Widget {
	function My_Widget() {
		// widget actual processes
	}

	function widget($args, $instance) {
		// outputs the content of the widget
	}

	function update($new_instance, $old_instance) {
		// processes widget options to be saved
	}

	function form($instance) {
		// outputs the options form on admin
	}
}
register_widget('My_Widget');

Explicando rapidamente, nesse modelo você cria uma classe ‘My_Widget’ filha de uma classe ‘WP_Widget’ que é a classe fornecida pelo WordPress contendo o código bruto, restando ao desenvolvedor a definição dos métodos:

My_Widget()

O construtor deve sempre ter o mesmo nome da classe ou se chamar __construct (depende da versão do PHP). No construtor são definidos o id, o nome, a descrição, e outras informações relativas ao widget.

widget($args, $instance)

Esse método define a forma como o widget é apresentado no tema. O parêmetro $args é um array contendo a formatação da estrutura do widget como: tags de abertura e fechamento do widget e do título do widget além do nome e id do widget.

O conteúdo dessa função não muda muito em relação ao modelo anterior dos widgets que era chamado pelo ‘register_sidebar_widget’, a única diferença é que o conteúdo da função, antes carregado do banco, agora vem todo no array $instance.

form($instance)

O médoto form representa a inteface administrativa do widget, onde é feita a configuração do mesmo, sua definição não é obrigatória.

Esse método é o espelho da função chamada pelo ‘register_widget_control’, mas aqui fica somente a estrutura do formulário. Assim como o método ‘widget’, aqui os dados não precisam mais serem carregados do banco, o array $instance traz todos os dados. O que notei de diferente na montagem do formulário foram apenas as nomeclaturas dos campos, agora tendo que ser feita da seguinte forma:

<input type="text" id="<?php print $this->get_field_id('nome-do-campo'); ?>" name="<?php print $this->get_field_name('nome-do-campo); ?>" value="<?php print $instance['nome-do-campo']; ?>" />

update($new_instance, $old_instance)

Também não é necessária a definição do método update. É esse método que realiza o processamento dos dados antes de salva-los no banco. O parâmetro $new_instance contém os dados novos (os que acabaram de ser informados) enquanto o $old_instance contém os dados antigos, para o caso de ser necessário fazer uma comparação.

Após o processamento dos dados, um array com os dados finais deverá ser retornado.

Não pretendo explicar novamente a lógica de criação de um widget, portanto vou simplesmente refazer o widget ‘Posts Mais Quentes’ nesse novo modelo e caso tenham dúvidas, consultem o post Opções de Widgets.

<?php
/*
Plugin Name: Widget: Posts mais quentes
Description: Lista posts mais comentados
Version: 0.3
Author: Marcelo Mesquita
Author URI: http://www.marcelomesquita.com/
*/

// Posts Mais Quentes
class Widget_Posts_Mais_Quentes extends WP_Widget
{
	function Widget_Posts_Mais_Quentes()
	{
		$this->WP_Widget('posts_mais_quentes', 'Posts Mais Quentes');
	}

	function widget($args, $instance)
	{
		global $wpdb;

		// Valor padrão, caso nada tenha sido informado
		if(empty($instance['quantidade'])) $instance['quantidade'] = "5";
		// Recuperando os posts
		$hot_posts = $wpdb->get_results("SELECT ID, post_title, comment_count FROM {$wpdb->posts} WHERE post_status = 'publish' ORDER BY comment_count DESC LIMIT {$instance['quantidade']}");

		if(empty($hot_posts))
			return false;

		// Usando o modelo de widgets do tema
		print $args['before_widget'];
		print $args['before_title'] . $instance['titulo'] . $args['after_title'];
		print "<ul>";
		// Listando os posts mais quentes
		foreach($hot_posts as $hot_post)
			print "<li><a href='" . get_permalink($hot_post->ID) . "'>{$hot_post->post_title} ({$hot_post->comment_count})</a></li>";
		print "</ul>";
		print $args['after_widget'];
	}

	function update($new_instance, $old_instance)
	{
		return $new_instance;
	}

	function form($instance)
	{
		?>
			<p>
				<label for="<?php print $this->get_field_id('titulo'); ?>">Título:</label>
				<input type="text" id="<?php print $this->get_field_id('titulo'); ?>" name="<?php print $this->get_field_name('titulo'); ?>" maxlength="26" value="<?php print $instance['titulo']; ?>" class="widefat" />
				<label for="<?php print $this->get_field_id('quantidade'); ?>">Quantidade:</label>
				<input type="text" id="<?php print $this->get_field_id('quantidade'); ?>" name="<?php print $this->get_field_name('quantidade'); ?>" maxlength="2" value="<?php print $instance['quantidade']; ?>" class="widefat" />
			</p>
		<?php
	}
}
// register widget
add_action('widgets_init', create_function('', 'return register_widget("Widget_Posts_Mais_Quentes");'));

Boa sorte!

Minhas impressões sobre o BuddyPress

Estive trabalhando no projeto Cultura Digital e não tem sido uma tarefa fácil. Grande parte da dificuldade que estamos tendo é atribuída ao BuddyPress. Ele não parece ter sido desenvolvido para o WordPress, suas tabelas e códigos (tanto interface quanto programação) não seguem um padrão semelhante ao do WordPress (“Code is Poetry”).

Banco de Dados

Me espantei na primeira vez que resolvi analisar a estrutura de dados do BuddyPress; vinte e uma tabelas novas criadas! A instalação original do WP utiliza apenas dez tabelas, a do WPMU necessita de dezesete, por que diabos o BP precisaria de vinte e uma só pra ele, resultando em trinta e oito no total (BP + WPMU).

Após gerar o modelo de dados do BP pude ter uma visão mais ampla da bobagem que haviam feito:

Nomeclatura das tabelas

Nomes como ‘wp_bp_acivity_user_activity’, ‘wp_bp_acivity_user_activity_cached’, ‘bp_messages_messages’ ou ‘bp_messages_threads’ já eram em si um quebra-cabeça a ser decifrado.

Normalização das tabelas

Ao começar a trabalhar com as tabelas não pude deixar de notar a quantidade de campos ‘user_id’ espalhados por tabelas, de alguma forma, conectadas. O caso mais claro foi o das tabelas ‘bp_activity_user_activity’ e ‘bp_activity_user_activity_cached’ que já são ligados através do campo ‘item_id’ mas ambas possuem os campo ‘user_id’.

Outro caso que me fez perder alguns cabelos foi o da tabela ‘bp_messages_threads’ que apenas mantém a ligação das mensagens que são respostas a outras mensagens. Isso poderia ser feito simplesmente criando um auto-relacionamento na tabela ‘bp_messages_messages’.

Dados redundantes

Acredito que o pior de tudo foi descobrir que algumas tabelas criadas pelo BuddyPress nem precisavam existir, pois serviam para armazenar informações que podiam ser armazenadas nas tabelas do WordPress.

Destaco o conjunto de tabelas ‘bp_xprofile_fields’ e ‘bp_xprofile_data’ que server para adicionar novos campos ao perfil do usuário. Para passar uma idéia, uma única tabela do WordPress substitui essas duas do BuddyPress, o plugin Register Plus é um exemplo de como isso pode ser feito. O único motivo, que vejo para que o BuddyPress tenha feito essa separação, seria para obter ganhos em performance, mas o fato de existir um campo para cada dado me fez pensar que a performance estaria equilibrada já que na tabela ‘usermeta’ esses dados poderiam estar em forma de array e, assim, ocupariam um campo apenas.

Também não gostei da forma como o BuddyPress trata as atividades. Apesar das atividades do site serem o conjunto das atividades de cada usuário, os dados ficam duplicados em diferentes tabelas. Por exemplo: Ao alterar meu perfil uma nova atividade é cadastrada na tabela ‘bp_activity_user_activity’ e depois a mesma informação é cadastrada na tabela ‘bp_activity_sitewide’.

Codificação

A codificação também ficou a desejar.

Funções engessadas

Diferente do WordPress onde as ‘template tags’ (funções que auxiliam a montagem do tema) praticamente não interferem na forma como o html é montado, no BuddyPress algumas ‘template tags’ carregam muito lixo e apresentam um visual pré-definido. Isso dificulta a personalização do tema pois força a alteração dos arquivos do BuddyPress para atingir um resultado esperado.

Por exemplo: a função que carrega os dados do perfil (xprofile_get_profile) monta uma tabela zebrada (uma linha clara outra escura), apenas com os dados informados e adiciona link a cada item. Mas a zebra que o BP monta é baseada nos dados que estão no banco, então se eu tiver deixado algum campo vazio a tabela acaba pulando uma cor deixando duas linhas claras e uma escura ou algo parecido. Se eu quiser corrigir essa zebra ou retirar os links dos dados eu precisarei criar uma função do zero para não ter que ‘hackear’ o BP.

Mistura de tema com plugin

Os temas são muito dependentes de funções definidas nos plugins. Essa questão é mais ou menos a mesma citada no item acima, imagine tentar criar uma nova função apenas para recuperar os membros ou pense na dor de cabeça que é ficar alternando entre plugins e tema para entender como tal trecho de código é montado.

Conclusão

O BuddyPress tem muito a evoluir antes de se tornar um sistema confiável, acredito que o principal é voltar os esforços para deixá-lo mais compatível com o seu hospedeiro, o WordPress. Assim poderá haver uma maior compatibilidade entre os plugins e temas, além de diminuir a curva de aprendizado para os desenvolvedores que já trabalham com o WordPress, o que, na minha opinião, poderá resultar em um impulso na comunidade BuddyPress.