Image Image Image Image Image
Scroll to Top

Topo

biblioteca

27

out
2014

Sem Comentários

Em CMS
Wordpress

Por Diogo Teobaldo

Filtro para conteúdo na biblioteca de mídia do WordPress

Em 27, out 2014 | Sem Comentários | Em CMS, Wordpress | Por Diogo Teobaldo

Por: Diogo Teobaldo

 

As vezes pode ser útil filtrar quais conteúdos da biblioteca de mídia de seu site os usuários podem ter acesso. Por isso mostrarei uma maneira pratica e simples de fazer o mesmo.

No caso abaixo, o objetivo era fazer com que os usuários(exceto editores) tivessem acesso apenas a conteúdos vinculados a uma post associado a ele ou que tenha sido enviado por ele.

1º passo – Utilizamos um filtro para ter acesso a query de posts e poder altera-la:

add_filter( 'posts_where', 'attachments_wpquery_where', 10, 2 )

2º passo – Definição da função:

function attachments_wpquery_where( $where ){

3° passo – Devemos obter o id do post para saber quais imagens estão vinculadas ao mesmo, e para isso utilizamos a expressão abaixo:

$id = $_POST['post_id'] ? $_POST['post_id'] : "NULL";

4º passo – Restringimos a função para filtrar apenas conteúdo de usuários que não tenham permissão de editor:

if( is_user_logged_in() && !current_user_can('edit_others_pages'))

5º passo – Checamos se o usuário está utilizando ação de consulta de imagens na biblioteca:

if( isset( $_POST['action'] ) ){
            // library query
            if( $_POST['action'] == 'query-attachments' ){

6º passo – Alterar a query de acordo com nossa necessidade:

$where .= ' AND (post_author=' . get_current_user_id() . ' OR post_parent=' . $id .')';
return $where;

No 6º passo filtramos na cláusula where da query conteúdo do autor logado ou que esteja vinculado ao post que ele está consultando.

O que acontece se o usuário for na biblioteca de mídia devido a essa alteração?
R: Como não haverá id de post na página da biblioteca serão trazidos apenas conteúdo que tenha sido enviado pelo usuário logado no sistema.

Código completo para referência:

add_filter( 'posts_where', 'attachments_wpquery_where', 10, 2 );
function attachments_wpquery_where( $where ){            
    $id = $_POST['post_id'] ? $_POST['post_id'] : "NULL";
    if( is_user_logged_in() && !current_user_can('edit_others_pages')){        
        if( isset( $_POST['action'] ) ){
            // library query
            if( $_POST['action'] == 'query-attachments' ){
                $where .= ' AND (post_author=' . get_current_user_id() . ' OR post_parent=' . $id .')';
            }
        }
    }    
    return $where;
}

Tags | , , , ,

21

maio
2012

Sem Comentários

Em Blog
Código
PHP

Por Allison

Sparks: abrindo novos horizontes para o CodeIgniter

Em 21, maio 2012 | Sem Comentários | Em Blog, Código, PHP | Por Allison

Fonte: Ademir Cristiano Gabardo/IMaster

O assunto não é tão novo assim, mas vem se tornando popular a cada dia e é provável que, daqui a algum tempo, tudo o que você precisar acoplar ao seu framework seja feito pelo sparks.

O CodeIgniter está se popularizando muito desde a mudança da metodologia de atualizações e da aceitação da comunidade internacional de desenvolvedores como parte colaboradora para novas funcionalidades. A velocidade com que o framework cresce e se estrutura vem ganhando proporções mais atraentes para profissionais e empresas desenvolvedoras de software.

Aplicativos que consomem serviços, uso da soluções REST, do SOAP, ORMs, sistemas de templates e, é claro, muitos “módulos” de terceiros fazem parte deste caminho. É possível encontrar bibliotecas para quase tudo, desde autenticação de usuários a templates. Essa evolução trouxe a necessidade de gerenciar a instalação desses módulos. E, com isso, surgiu o sparks.

Mas, então, o que é sparks?

Segundo o website sparks.org, “sparks é um sistema de gestão de pacotes para CodeIgniter que lhe permitirá instalar bibliotecas de alta qualidade em seus aplicativos instantaneamente”.

Que tal entender melhor na prática? Para isso, vamos criar um aplicativo capaz de exibir a sua timeline do Twitter:

1. Comece baixando a última versão do CodeIgniter. Descompacte em um caminho que possa ser acessado pelo seu servidor web. Eu escolhi uma pasta chamada “sparks”. Desse modo, posso acessar em http://localhost/sparks/. Até esse ponto, nada de diferente foi feito e nesse momento você deverá ver a tela de boas vindas do CodeIgniter.

2. Na pasta raíz do seu projeto, crie uma pasta chamada “tools”. Então, vamos seguir os passos encontrados neste artigo.

3. Baixe o arquivo spark-manager.zip aqui.

4. Descompacte o conteúdo do arquivo que você acabou de baixar. Você deverá ter na pasta “tools” um arquivo chamado spark sem nenhuma extensão.

5. Agora será necessário criar uma classe Loader, estendendo a classe Loader do CodeIgniter. Acesse aqui para obter o código fonte; copie-o para o seu editor e salve-o em “applicatton/core” com o nome de arquivo MY_Loader.php.

6. Estamos prontos para começar! Agora vamos utilizar o prompt de comando para obter os sparks seguindo os passos “Get Sparks” aqui.

Abra o seu prompt do DOS (Iniciar->Executar e digite CMD). Navegue até a pasta do projeto. No meu caso, CD C:/Webs/2012/Sparks. Obedeçam ao caminho de acordo com a instalação do seu servidor web. Você deverá ver algo como a tela a seguir:

Obs: Usuários do Linux provavelmente já sabem o que têm que fazer no Terminal.

Então, vamos utilizar o PHP via linha de comando para instalar um spark de exemplo, digitando o seguinte:

php tools\spark install -v1.0.0 example-spark

Embora apresentando um erro, o comando foi executado com sucesso exibindo ao final a mensagem “You´re on Fire!”, indicando que o conteúdo foi baixado e descompactado de acordo com o esperado.

Agora que o sparks “example” foi baixado e adicionado à pasta do projeto, você deverá ver na raíz do projeto uma pasta “sparks” com uma subpasta “example-spark” e a estrutura dos arquivos partindo da versão do spark instalado.

Para testar, abra o controlador e adicione o seguinte código ao método index da classe Welcome (estou presumindo que você não alterou nada além em seu projeto):

public function index(){      $this->load->spark('example-spark/1.0.0');
$this->example_spark->printHello(); }

Se tudo correr bem, ao acessar a URL no navegador, você deverá visualizar algo semelhante à figura a seguir:

Se você chegou até este ponto, tudo foi feito corretamente e poderemos prosseguir para nosso aplicativo.

Obtenha o CURL instalando via sparks com o seguinte comando no prompt:

php tools\spark install –v1.2.1 curl

E você deverá ver algo como a tela a seguir:

O próximo passo será, então, obter o RestClient. Do mesmo modo, digite no prompt de comando:

php tools\spark install –v2.1.0 restclient

Se tudo correr bem, ao final da operação, algo semelhante a tela a seguir será exibido:

Pronto, agora temos CURL e um cliente REST disponíveis, vamos aproveitar e utilizar para obter a timeline do Twitter. Precisamos alterar o método index da classe welcome para o seguinte código fonte:

public function index(){    $this->load->spark('curl/1.2.1');
$this->load->spark('restclient/2.1.0');
// Carregando a biblioteca Rest    $this->load->library('rest');
// Inicializando apontando o servidor do Twitter.
$this->rest->initialize(array('server'=> 'http://twitter.com/'));
// Recebendo os twitters do usuário agabardo, troque para o seu usuário.
$tweets = $this->rest->get('statuses/user_timeline/agabardo.xml');

//Exibindo na tela para propositos de teste.
echo "<pre>";    print_r($tweets);    echo "</pre>";
}

E, se tudo correr bem, você deverá visualizar a array com o conteúdo da sua timeline:

E como diriam meus amigos do Rio Grande: “mais simples que painel de Jipe”! Por isso acredito que muita coisa nova e boa deverá surgir empacotada com sparks.

Se você não tem afinidade com a linha de comando, existem outras alternativas, mas, convenhamos, digitar três ou quatro linhas no prompt do DOS ou terminal do Linux não é assim tão dolorido.

Não funcionou? Baixe os arquivos do projeto aqui.

***

Artigo original disponível em: http://codeigniter.com/news/a_quick_look_at_sparks

Abraços a todos!

Tags | , , ,

12

maio
2012

Sem Comentários

Em Blog
PHP

Por Allison

Criando uma biblioteca para controle de acesso por usuário com CodeIgniter

Em 12, maio 2012 | Sem Comentários | Em Blog, PHP | Por Allison

Fonte: Ademir Cristiano Gabardo/IMasters

As aplicações PHP estão se tornando a cada dia mais complexas. Aplicações de uso comercial, acadêmico e das mais diversas finalidades fazem necessário um controle mais apurado de acesso.

No CodeIgniter, estamos, obrigatoriamente, sempre acessando uma classe e um método de um controlador. Dessa forma, é possível mapear todas as possíveis ações e/ ou caminhos disponíveis em uma aplicação e adicionar o controle de acesso aos métodos que desejamos controlar.

Eu desenvolvi uma biblioteca (library) para controlar o acesso dos usuários. O seu funcionamento se dá da seguinte forma: em uma tabela no banco de dados (sys_metodos), ficam guardados os nomes de classe e os métodos, mapeando todos os possíveis caminhos. Em outra tabela (sys_permissoes), ficam as ids dos usuários com os respectivos métodos a que eles têm acesso. Essa segunda tabela está relacionada à tabela de cadastro de usuários (tb_usuarios).

Figura 01: Estrutura das tabelas necessárias ao sistema de autenticação.

Seria bastante trabalhoso ter que popular a tabela de métodos manualmente, ou criar um Admin para ela. Dessa forma, inclui uma rotina na própria biblioteca, para que quando um método invocado por ela não seja encontrado na tabela sys_metodos, ele seja automaticamente criado. Assim, na primeira vez em que um método for acessado, ninguém terá permissão de acesso, sendo, então, necessário parametrizar o sistema uma única vez no primeiro acesso. Depois pode-se construir uma área de administração para varrer a tabela de métodos e adicionar ou remover as permissões dos usuários.

O CodeIgniter provê uma maneira de checarmos “onde estamos”, ou seja, em que classe e em que método. Para verificar o nome da classe, utilize a seguinte linha de código.

$this->router->class

E para recuperar o nome do método utilize:

$this->router->method

Podemos passar para a biblioteca o caminho completo de onde estamos da seguinte forma:

$this->auth->check_logged($this->router->class , $this->router->method);

Auth é o nome da biblioteca e check_logged é o método que estamos acessando. Como essa biblioteca será acessada em muitas classes e métodos, é preferível carregar no autoload para que ela esteja sempre disponível em qualquer parte da aplicação. Para proteger um método, basta incluir a linha de código:

<?php
class AreaRestrita extends Controller {
function __construct(){
parent::Controller();
}
function index(){
$this->auth->check_logged($this->router->class , $this->router->method);
}
}
?>

Vejamos, então, como fica o código fonte da biblioteca. Salve-o com o nome de arquivo auth.php na pasta system/application/libraries:

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Auth
{
private $ci;
public function __construct(){
$this->ci = &get_instance();
}
 
function check_logged($classe,$metodo)
{
/*
* Criando uma instância do CodeIgniter para poder acessar
* banco de dados, sessionns, models, etc...
*/
$this->CI =& get_instance();
 
/**
* Buscando a classe e metodo da tabela sys_metodos
*/
$array = array('classe' => $classe, 'metodo' => $metodo);
$this->CI->db->where($array);
$query = $this->CI->db->get('sys_metodos');
$result = $query->result();
 
// Se este metodo ainda não existir na tabela sera cadastrado
if(count($result)==0){
$data = array(
'classe' => $classe ,
'metodo' => $metodo ,
'apelido' => $classe .  '/' . $metodo,
'privado' => 1
);
$this->CI->db->insert('sys_metodos', $data);
redirect(base_url(). $classe . '/' . $metodo, 'refresh');
}
//Se ja existir tras as informacoes de publico ou privado
else{
if($result[0]->privado==0){
// Escapa da validacao e mostra o metodo.
return false;
}
else{
// Se for privado, verifica o login
$nome = $this->ci->session->userdata('nome');
$logged_in = $this->ci->session->userdata('logged_in');
$data = $this->ci->session->userdata('data');
$email = $this->ci->session->userdata('email');
$id_usuario =  $this->ci->session->userdata('id_usuario');
 
$id_sys_metodos = $result[0]->id;
 
// Se o usuario estiver logado vai verificar se tem permissao na tabela.
if($nome && $logged_in && $id_usuario){
 
$array = array('id_metodo' => $id_sys_metodos, 'id_usuario' => $id_usuario);
$this->CI->db->where($array);
$query2 = $this->CI->db->get('sys_permissoes');
$result2 = $query2->result();
 
// Se não vier nenhum resultado da consulta, manda para página de
// usuario sem permissão.
if(count($result2)==0){
redirect(base_url().'home/sempermissao', 'refresh');
}
else{
return true;
}
}
// Se não estiver logado, sera redirecionado para o login.
else{
redirect(base_url().'home/login', 'refresh');
}
}
}
}
 
/**
* Método auxiliar para autenticar entradas em menu.
* Não faz parte do plugin como um todo.
*/
function check_menu($classe,$metodo){
$this->CI =& get_instance();
$sql = "SELECT SQL_CACHE
count(sys_permissoes.id) as found
FROM
sys_permissoes
INNER JOIN sys_metodos
ON sys_metodos.id = sys_permissoes.id_metodo
WHERE id_usuario = '" . $this->ci->session->userdata('id_usuario') . "'
AND classe = '" . $classe . "'
AND metodo = '" . $metodo . "'";
$query = $this->CI->db->query($sql);
$result = $query->result();
return $result[0]->found;
}
}

Note que a biblioteca se encarrega de inserir os dados de métodos e classes que ainda não estão cadastrados na tabela sys_metodos.

Quando um usuário tentar acessar uma área do site ou sistema no qual ele não tenha privilégios, ele será redirecionado para uma página específica:

redirect(base_url().'home/sempermissao', 'refresh');
 

E, quando ele não estiver logado, será redirecionado para a página de login:

redirect(base_url().'home/login', 'refresh');

Incluí também um método na biblioteca para checar se o usuário logado no sistema tem permissão para acessar um determinado método de uma classe chamado check_menu. Para utilizar a autenticação no menu, basta checar se o usuário tem permissão para o caminho. Isso pode ser feito diretamente na view do menu:

 
<?php
if($this->auth->check_menu('home','index')==1){
echo "<li><a href='". base_url() ."home'>Home</a></li>";                }
?>

Observe também que na tabela sys_metodos existe um campo chamado privado, que tem por objetivo liberar o acesso de métodos que estejam protegidos; caso você construa um sistema de admin para gerenciar essa tabela, quando um método estiver com o campo privado definido como 1, ele estará com seu acesso restrito somente a usuários com permissão de acesso. Quando estiver ajustado como 0, estará liberado como método público.

Outro detalhe dessa tabela é um “apelido”. Ele é cadastrado em um primeiro momento como classe/método, mas poderá ser alterado para qualquer nome amigável e mais compreensível para os usuários, como, por exemplo, Home/login poderia ser substituído por Acesso à tela de login.

Para autenticar um usuário no sistema, crie um formulário com os campos usuário, cnpj e senha, e aponte para uma classe de sua preferência (eu uso a classe de nome home) com os seguintes métodos:

<?php
class Home extends Controller {
 
function __construct(){
parent::Controller();
$this->load->helper('logs');
$this->load->helper('cookie');
}
 
function index(){
redirect(base_url().'home/login', 'refresh');
}
 
function void(){
$data['js_to_load'] = null;
$this->load->view('libs/html-header',$data);
$this->load->view('libs/menu');
$this->load->view('libs/html-footer');
}
function sempermissao(){
 
echo "<html>";
echo "<title>Acesso Negado</title>";
echo "<body bgcolor='#EEEEEE'>";
echo "    <div style='padding:20px;background-color:#FFCC00;'>";
echo "<h2>Você não tem permissão para acessar esta funcionalidade.</h2>
echo "</div>";
echo "</body>";
echo "</html>";
exit();
}
 
function login(){
$this->load->view('login',$data);
}
 
function dologin(){
$usuario = $this->input->post('usuario');
$cnpj = $this->input->post('cnpj');
$senha = md5($this->input->post('senha'));
 
if($usuario=="" || $cnpj=="" || $this->input->post('senha')==""){
redirect(base_url().'home/login', 'refresh');
exit();
}
 
if(isset($_POST['lembrar'])){
setcookie("usuario", $usuario);
setcookie("cnpj", $cnpj);
setcookie("lembrar", "checked");
}
 
$sql = "SELECT id,cnpj,login,nome,email
FROM tb_usuarios
WHERE login ='" . $usuario . "'
AND cnpj ='" . $cnpj . "'
AND senha ='" . $senha . "'";
 
$query = $this->db->query($sql);
$result = $query->result();
if(count($result)<1){
redirect(base_url().'home/login', 'refresh');
exit();
}
else{
$login = array(
'id_usuario'   =>     $result[0]->id,
'cnpj'   =>     $result[0]->cnpj,
'usuario'   =>     $result[0]->login,
'nome'      =>    $result[0]->nome,
'email'     =>     $result[0]->email,
'logged_in' => TRUE,
'data' => date("d/m/Y h:i:s")
);
 
$data['ip'] = getenv("REMOTE_ADDR");
$data['usuario'] = $result[0]->id;
$this->db->insert('tb_acessos',$data);
 
$this->session->set_userdata($login);
redirect(base_url().'home/void', 'refresh');
}
}
 
function logout()
{
$this->session->sess_destroy();
$this->login();
}
}

Com isso, concluímos nosso sistema de autenticação com controle de nível de acesso por classe e método. Não é exatamente a coisa mais simples do mundo, mas também não é a mais complicada. É importante ressaltar que estou guardando as sessões do codeIgniter no banco de dados. As demais funções de cadastro de usuário e o cadastro de usuários na tabela de permissão devem ser construídos separadamente.

Implementações futuras estão previstas e um inconveniente deste sistema é que, quando você altera um nome de classe ou método, será necessário ajustar a tabela sys_metodos.

Código fonte da biblioteca disponível aqui.

Espero que o artigo lhes tenha sido útil!

Tags | , , ,

10

abr
2012

Sem Comentários

Em Blog
JavaScript

Por Allison

Anunciado o lançamento da jQuery Foundation

Em 10, abr 2012 | Sem Comentários | Em Blog, JavaScript | Por Allison

Fonte: IMasters

Com informações de Linux-Under.org

O Conselho jQuery e o Software Freedom Conservancy anunciaram ontem, dia 07/03, o lançamento da jQuery Foundation. A nova organização independente irá gerenciar todos os assuntos relacionados a jQuery, incluindo os seus projetos.

O Presidente da Fundação será Dave Methvin, que já se pronunciou a respeito e disse que o sistema é a mais popular biblioteca JavaScript. “A criação de uma organização autônoma, será o próximo passo para garantir seu desenvolvimento futuro e beneficiar a todos que utilizam o jQuery”, afirmou.

Methvin também afirmou, que a Fundação anunciará várias iniciativas e conferências, que estão planejadas para serem realizadas em breve. A Fundação jQuery é uma associação comercial sem fins lucrativos, que se dedica a apoiar os diversos projetos da plataforma de mesmo nome (Core, UI e Mobile), fornecendo uma importante documentação e suporte, e ajudando a construir a comunidade jQuery, de forma sólida e com credibilidade.

Tags | , ,

19

mar
2012

Sem Comentários

Em Blog
Código

Por Allison

Otimizando o Django Views com C++

Em 19, mar 2012 | Sem Comentários | Em Blog, Código | Por Allison

Fonte: IMasters

Texto original disponível em: http://www.jeffknupp.com/blog/2012/02/15/optimizing-django-views-with-c-plus-plus/


No meu artigo anterior, esbocei o método que vai sobre o perfil de um aplicativo Django. Utilizei uma view do linkrdr como um exemplo. Ela é responsável por agregar, classificar e ordenar todos os links de feeds de um usuário (RSS, Atom, Twitter, etc). O código a partir do envio da mensagem foi uma implementação simplista e inicial do panorama. Tenho, no entanto, um algoritmo de pontuação muito mais robusto, escrito em Python, que eu planejava utilizar no site.

Você pode ter percebido a palavra “planejado” ali, né? Pois é, o algoritmo se revelou muito lento. Mais do que eu consideraria aceitável. Depois de pensar em várias mudanças arquitetônicas que poderiam ser feitas para resolver o problema, cheguei em uma solução um tanto radical para um desenvolvedor Django: eu implementei a visão em C++.

Sei que nem todo desenvolvedor Django sabe C++ – e não precisa -, mas aqueles que sabem precisam perceber que é uma ferramenta viável quando Python está muito lento. Mas, eventualmente, você pode chegar a um ponto onde não é possível realmente otimizar o seu código Python mais. Neste caso, o perfil mostra que a maioria de seu tempo é gasto em chamadas de bibliotecas Python. Depois de bater nesse ponto, ou você escreve um algoritmo ineficiente ou você tem um problema não adequado para Python.

Quando percebi que tinha atingido esse ponto com o meu código de visão, entrei em pânico. “O que mais há para fazer?”, me perguntava. Então me lembrei de um projeto de trabalho onde havia escrito alguns códigos C++ que fazem interface com o Python. De uma perspectiva técnica, não havia nada me impedindo de implementar alguns aspectos do meu app Django em C++ (além do fato de que ele é torturante para escrever quando se trata do Python). Uma vez que linkrdr é um projeto de uma só pessoa, não existem companheiros que precisam aprender o código. Sendo assim, eu sou livre para implementá-lo como eu desejar.

Configurando

Tendo escrito um código “puro” C++/Python de interoperabilidade Python antes, e não querendo ver Py_XDecRef novamente, decidi usar boost::Python. Para começar, eu me certifiquei de que tinha as bibliotecas mais recentes do Boost e uma versão atualizada de gcc para que eu pudesse usar as características C++ 11, que são de fato muito boas. Depois de construir a versão mais recente da biclioteca boost::python, eu realemnte aprendi a lidar com isso. E ela acabou sendo extremamente fácil.

O boost::python envolve uma série de tipos de dados em Python para você: “object” representa um objeto Python genérico, “lista” é uma lista, e assim por diante. Como o Python é tipado dinamicamente, não há realmente muitos lugares inteiramente dele. “Tudo é um objeto” significa que tudo é um boost::python::object e pode ser acessado desta forma.

Além de wrappers primitivo, o boost fornece um mecanismo claro e conciso para fazer classes e funções C++ visíveis para Python. Eu tinha uma classe simples no código de entrada do nome anterior do meu LinkScore. Era basicamente uma estrutura C com uma lista de objetos e um interger. O código C++ é:

using namespace boost::python;

class LinkScore
{
public:
LinkScore() {}
LinkScore(const object& link, int score) : score_(score)
{
links_.append(link);
}
list links_;
int score_;
};

Se você está pensando que meus data members deveriam ser privados, adivinhem: eu não me importo. Essa é alegria de trabalhar em código que só você vai usar. Você pede escrevê-lo e usá-lo como quiser.

Os detalhes

Enfim, o código com o qual o boost:python pode chamar o Python é:

class_<LinkScore>("LinkScore", init<object, int>())
.def_readwrite("links", &LinkScore::links_)
.def_readwrite("score", &LinkScore::score_);

Realmente, não poderia ser mais simples. A maneira de conseguir isso <Python.h> envolve a definição de uma estrutura com quarenta valores para declarar cada classe. Fiquei feliz em não ter que me preocupar com isso.

O atual código para a minha view é uma função gratuita chamada get_scores. Aqui está um breve trecho:

using namespace boost::python;
using namspace std;

class CompareObject {
public:
bool  operator()(const LinkScore& l, const LinkScore& r) { return l.score_ > r.score_; }
};

list get_scores(object links)
{
object utility = import("links.utility");
set<LinkScore, CompareObject> seen_links;
list python_seen_links;
for (int i = 0; i < len(links); ++i)
{
const object& link = links[i];
LinkScore score = LinkScore(link, score_link (link, links));
auto iter = seen_links.find(score);

if (iter != seen_links.end())
{
// Do stuff
}
else
{
// Do other stuff
}
}
// TODO: Optimize this
for (auto i = seen_links.begin(); i != seen_links.end(); ++i)
{
python_seen_links.append(*i);
}
return python_seen_links;

Se você conhece C++ e Python, é quase como ler um mix dos dois. A descrição acima, no entanto, é válida para o código C++ e é a interface que o Python usa para chamar minha biblioteca de pontuação. Para expor essa função para o Python, tudo que é necessário é def (“get_score”, get_score); dentro de um bloco BOOST_PYTHON_MODULE, que nomeia o módulo a ser importado.

Quando terminei de escrever o código C++, eu o compilei usando o gcc com a ferramenta de biuld bjam da biblicota boots; defini o meu LD_LIBRARY_PATH para captar o libboost_Python.so e liguei uma shell do manage.py (na verdade, um “shell_plus”). Usei o módulo cProfile para comparar a versão do C++ da view com a versão do Python da view. Os resultados foram satisfatórios: um aumento de oito vezes na velocidade com a versão C++.

Para acionar o código C++, eu só precisava ter certeza que o .so gerado estiva em minha PYTHON_PATH. Assim, poderia importá-lo como uma biblioteca normal do Python. Acrescentei-o ao meu views.py e meus testes unitários rodaram. Depois disso, comitei tudo e coloquei o novo código através dos seus passos no servidor de desenvolvimento web. O tempo de resposta melhorou visivelmente, com a view funcionando instantaneamente.

Wrap Up

Sei que esta não é uma opção de otimização disponível para todos, mas é uma opção interessante. O Python é uma linguagem fantástica e o Django é um framework muito bom. No geral, estou bastante contente com os resultados e como foi fácil de implementar. Me absterei de escrever mais código C++ para linkrdr, a menos que seja absolutamente necessário. É bom saber, no entanto, que a opção está lá.

Tags | , , , ,

01

fev
2012

Sem Comentários

Em Blog

Por Allison

jQ.Mobi: um jQuery reescrito e otimizado para dispositivos móveis

Em 01, fev 2012 | Sem Comentários | Em Blog | Por Allison

Fonte: Postado por Abel Avram/traduzido por Eder Ignatowicz/InfoQ

A appMobi lançou o jQ.Mobi, uma versão reescrita e gratuita do jQuery, que compete com o jQuery Mobile no mercado de desenvolvimento web para dispositivos móveis.

O jQ.Mobi é otimizado para HTML5 e dispositivos móveis. Comparado ao jQuery, é mais leve (3KB contra 35KB), três vezes mais rápida em dispositivos Android e 2.2 vezes mais performática no iOS, tudo isso de acordo com testes JSPerf. A sintaxe de programação do jQ.Mobi é idêntica à do jQuery, assim como o desenvolvimento de plugins. O jQ.Mobi contém somente um subconjunto considerado essencial da API do jQuery (segundo a appMobi) e tem por objetivo prover uma experiência idêntica ao usuário, em ambos iOS e Android.

O jQ.Mobi é formado por três componentes:

  • Uma biblioteca de consultas;
  • jQ.Ui: uma biblioteca de interface de usuário para browsers WebKit;
  • jQ.Plugin: suporte a plugins desenvolvidos para browsers WebKit.

Por que alguém criaria um novo framework JavaScript baseado no JQuery dois meses após o lançamento do jQuery Mobile 1.0? A appMobi explica que as raízes do jQuery são baseadas em browsers desktop e como resultado, a versão mobile do framework não seria otimizada e não proporciona uma boa experiência para usuários de dispositivos móveis, especialmente no Android.

Com relação ao jQuery Mobile, Todd Parker, líder do projeto, reconheceu problemas com o jQuery Mobile. A equipe do jQuery anunciou uma versão de correção (1.0.1) em que resolve um grande número de bugs e acrescenta componentes visuais, além de antecipar funcionalidades para as próximas versões.

Uma versão de demonstração foi criada para ilustrar as funcionalidades da biblioteca. Mais detalhes sobre a evolução do projeto podem ser acompanhados no blog do jQ.Mobi.

Tags | , , , , ,

02

dez
2011

Sem Comentários

Em Blog
Java
Testes

Por Allison

Restfuse 1.0.0: uma biblioteca para facilitar testes de integração REST/HTTP

Em 02, dez 2011 | Sem Comentários | Em Blog, Java, Testes | Por Allison

A EclipseSource lançou a primeira versão estável de uma extensão open souce do JUnit para automação de testes de serviços REST/HTTP. O Restfuse é um conjunto de anotações para JUnit que oferece asserções para respostas de requisições HTTP. Tanto chamadas síncronas como assíncronas são suportadas.

O Restfuse já está disponível no Maven Central, então para usá-lo não é necessário nenhum repositório especial:

<dependency>
<groupId>com.restfuse</groupId>
<artifactId>com.eclipsesource.restfuse</artifactId>
<version>1.0.0</version>
</dependency>

Usar a biblioteca para chamadas síncronas é simples e direto:

@RunWith(HttpJUnitRunner.class)
public class RestFuseTest {
@Rule
public Destination destination = new Destination("http://example.com" );

@Context
private Response response; // será injetado depois de cada chamada
@HttpTest(method = Method.GET, path = "/reloadLocalConfiguration" )
public void checkRestfuseOnlineStatus() {
assertOk(response );
String answerBody = response.getBody(String.class);
assertEquals("Expected correct response","done",answerBody);
}
}

O teste acima chama um endereço HTTP de maneira síncrona e então valida se há uma resposta textual (text/plain) contendo a string “done”. Note que a primeira asserção, assertOk, é do Restfuse; ela verifica se o status da resposta HTTP foi 200 OK. A segunda asserção, assertEquals, verifica a igualdade como no JUnit. Embora esteja se supondo que o endereço HTTP vai retornar um texto puro, poderia também ser processado conteúdo em JSON/XML ou de outro tipo, e executar os asserts de maneira estruturada.

O Restfuse também suporta chamadas assíncronas. Uma aplicação clássica disso se dá em operações de longa duração (como o upload de um arquivo extenso), em que o cliente monitora continuamente o servidor para identificar o status atual. No exemplo abaixo, é considerado um endereço do lado servidor que retorna um número entre 0 e 100 e mostra o progresso de alguma operação:

@RunWith( HttpJUnitRunner.class )
public class PollTest1 {

@Rule
public Destination destination = new Destination( "http://example.com" );

@Context
private Response response;

@Context
private PollState pollState;

@HttpTest( method = Method.GET, path = "/progressStatus" )
@Poll( times = 5, interval = 500 )
public void testAsynchronousService() {
if(pollState.getTimes() == 5)
{
String answerBody = response.getBody(String.class);
assertEquals("Expected last response","100",answerBody);
}
}
}

O teste acima chama o mesmo endereço cinco vezes (com um intervalo definido), mas somente a última chamada verifica a resposta HTTP.

Uma característica interessante da interface PollState é a manutenção das respostas anteriores. Isto permite aos asserts sejam feitos sobre o histórico das chamadas:

@RunWith( HttpJUnitRunner.class )
public class PollTest2 {

@Rule
public Destination destination = new Destination( "http://example.com" );

@Context
private Response response;

@Context
private PollState pollState;

@HttpTest( method = Method.GET, path = "/progressStatus" )
@Poll( times = 5, interval = 500 )
public void testAsynchronousService() {
int currentRun = pollState.getTimes();
if(currentRun > 1)
{
String previousProgress = pollState.getResponse(currentRun - 1).getBody(String.class);
String presentProgress = response.getBody(String.class);
assertTrue("Expected some progress",Integer.parseInt(presentProgress) > Integer.parseInt(presentProgress)); //Just for illustration purposes
}
}
}
}

O teste acima verifica se cada resposta tem número superior à resposta anterior. O Restfuse tem uma dependência com o servidor HTTP Jetty e suporta serviços assíncronos que seguem o modelo de Web Hooks. Ao invés de enviar várias requisições ao servidor para verificar o estado de um processo, o cliente cliente faz uma chamada uma única vez e então aguarda por uma resposta iniciada pelo servidor em uma conexão diferente. Aqui está um exemplo usando Restfuse:

 
@RunWith( HttpJUnitRunner.class )
public class RestfuseCalbackTest {

@Rule
public Destination destination = new Destination( "http://example.com" );

@Context
private Response response;

private class TestCallbackResource extends DefaultCallbackResource {

@Override
public Response post( Request request ) {
assertTrue("Expected a quote response", request.getBody(String.class).startsWith("quote:") );
return super.post( request );
}
}

@HttpTest( method = Method.GET, path = "/requestQuote" )
@Callback( port = 9090, path = "/asynchron", resource = TestCallbackResource.class, timeout = 10000 )
public void testMethod() {
assertAccepted( response );
}
}

Este último exemplo conecta-se ao requestQuote e monitora a porta 9090 do cliente. Durante até dez segundos, ele espera uma resposta textual, começando com “quote:”

Para mais informações sobre o Restfuse, visite a wiki do projeto e seu Javadocs. O código-fonte esta hospedado no GitHub.

Fonte: Kostis Kapelonis , traduzido por Jefferson Prestes /InfoQ

Tags | , , , , , , ,

22

nov
2011

Sem Comentários

Em Blog

Por Allison

MySQL 5.5.18 traz correções para problemas de replicação

Em 22, nov 2011 | Sem Comentários | Em Blog | Por Allison

A Oracle disponibilizou o MySQL 5.5.18, a última das atualizações regulares para a versão de produção do banco de dados open source. Na atualização, a Oracle tem marcado uma série de situações inseguras em replicação “statement-based”.

As declarações questionadas fazem referência ao resultado de uma instrução “select”, na qual a ordem não pode ser confiada. Sendo assim, a Oracle aconselha os utilizadores de “logging statement based” a consultar a documentação para obter mais orientações. O problema de replicação em que o master (mestre) podia enviar eventos danificados para os slaves (escravos) relacionados ao disco e ao log binário também foi corrigido.

Outras mudanças incluem melhorias para a biblioteca libedit junto com MySQL, remoção de alocação de memória desnecessária e liberação ao abrir tabelas, além de correções para falhas relacionadas com ARCHIVE e tabelas FEDERATED, e uma possível corrupção com o comando OPTIMIZE TABLE ao usar MyISAM.

Os desenvolvedores também fizeram o possível, em relação à utilização de RPM, para substituir qualquer versão instalada do MySQL com outra da mesma versão da família, por exemplo, quando houver a atualização da versão GPL para a versão comercial.

Todos os detalhes sobre essas mudanças estão disponíveis aqui, e o MySQL 5.5.18 pode ser baixado neste link.

Com informações de Under-Linux

Fonte: IMasters

Tags | , , , , , ,