Posts Tagged ‘classes’

Classe, WebService e RSS para rastreamento de encomendas nos Correios em PHP

abril 10th, 2010

Olá, depois de meses sem escrever estou voltando com uma classe muito útil e simples que nunca vi em lugar nenhum. É uma classe para rastrear encomendas nos correios que eu escrevi em PHP, que retorna um vetor com cada modificação de status lá.

Vamos direto ao ponto, confira o exemplo:

http://ferrari.eti.br/correios/samples/class.php

E para deixar a brincadeira mais divertida, fiz também um webservice com suporte a Json (padrão), phpserialize, XML e um modo dump, para visualização:

http://ferrari.eti.br/correios/webservice/?q=PB151832535BR
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&f=dump
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&f=serial
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&f=xml
e claro, para quem usa Ajax:
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&callback=minhaFuncJs

Disponibilizei tanto a classe quanto o código do webservice (que tem suporte a caching!) “de grátis” e com licença BSD no github:

http://github.com/caferrari/correios/

*UPDATE* Adicionado um gerador de RSS, assim é possível usar o proprio agregador para fazer o tracking!

http://ferrari.eti.br/correios/rss/?PB151832535BR

e em homenagem aos atendentes de telemarketing: Estarei esperando forks e colaborações para a classe, além de comentários!.

Até a próxima.

Autenticação de Usuários no Vórtice PHP

outubro 9th, 2009

Nesse post vou explicar como adicionar autenticação de usuários no @vorticephp, como base para o sistema vamos utilizar o exemplo que já vem com o framework.

Script de BD:

CREATE TABLE IF NOT EXISTS orgaos (
id int(11) NOT NULL AUTO_INCREMENT,
sigla varchar(50) collate utf8_unicode_ci NOT NULL,
nome varchar(150) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY  (id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8
 
CREATE TABLE IF NOT EXISTS usuarios (
id int(10) UNSIGNED NOT NULL,
nome varchar(50) NOT NULL,
email varchar(60) NOT NULL,
senha char(32) NOT NULL,
PRIMARY KEY  (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO usuarios (nome, email, senha) VALUES('Administrador', 'adm@ferrari.eti.br', md5('123'));

eu criei essa tabela com esse usuario e senha no database que já vem configurado no framework para vocês testarem localmente. Você pode configurar a conexão com o seu próprio banco de dados no arquivo app/app.php

Para iniciar vamos criar o objeto do usuário em: app/model/Usuario.php e codificar:

<?php
class Usuario{
	public function __construct($id=0, $nome='', $email='', $senha=''){
		$this->id = $id;
		$this->nome = $nome;
		$this->email = $email;
		$this->senha = $senha;
	}
}

agora que temos o objeto, vamos criar um DAO para realizar operações, crie o arquivo app/model/UsuarioDAO.php e segue o código:

<?php
class UsuarioDAO{
	public function getByEmail($email){
		$sql = "SELECT * FROM usuarios WHERE email='$email'";
		return Database::getInstance()->queryOne($sql);
	}
}

vamos para o controller de usuários, crie o arquivo app/controller/UsuarioController.php e segue o codigo inicial:

<?php
class UsuarioController extends Controller{
	public function login(){
 
	}
}

Dai a gente cria o nosso formulário de login, edite app/view/usuario/login.php:

<h2>Login</h2>
<fieldset>
	<form method="post">
		<p><label>E-mail:</label><input type="text" name="email" /></p>
		<p><label>Senha:</label><input type="password" name="senha" /></p>
		<p><input type="submit" value="Logar!" /></p>
	</form>
</fieldset>

Agora com o form criado, vamos editar a action login do controller Usuario, volte e edite o arquivo app/controller/UsuarioController.php:

<?php
class UsuarioController extends Controller{
	public function login(){
		// se um formulario foi postado
		if (post){
			// pega as variáveis do post
			$email = addslashes(p('email'));
			$senha = md5(p('senha'));
 
			// seleciona o usuario, armazena na variavel $u
			// e ainda verifica se o usuario existe
			if ($u = UsuarioDAO::getByEmail($email)){
				// verifica se a senha digitada combina com
				// a que está no BD
				if ($u->senha == $senha){
					// remove a senha do objeto
					$u->senha = null;
					// grava a session
					Session::set("u", $u);
					// Cria mensagem de sucesso e redireciona para o index
					Post::setSucesso("Olá {$u->nome}, você está logado", new Link(""));
				}else
					// Retorna erro
					Post::setErros("Senha incorreta!");
			}else
				// Retorna erro
				Post::setErros("e-mail não encontrado!");
		}
	}
}

Para ficar bonita a url vamos criar um route para esta action, edite o arquivo app/routes.php e adicione:

Route::add("^login$", "usuario:login");

Agora o formulário de login já está funcionando, vamos fazer o sistema obrigar o usuario estar logado para fazer qualquer coisa no sistema, para isso edite o arquivo app/controller/MasterController.php, como queremos que para todo o sistema sejá necessário o login, vamos adicionar um construtor nessa classe com o seguinte código:

function __construct(){
	// se a session "u" não existir, criar uma com um usuario vazio
	if (!Session::get("u")) Session::set("u", new Usuario());
 
	// Se a session u tiver um objeto vazio..
	// e o controller/action forem diferentes dos de login
	if (Session::get("u")->id == 0 && controller != 'usuario' && action != 'login'){
		// redireciona para a tela de login
		redirect(new Link("login"));
	}
}

Bom, com isso já deve estar tudo funcionando de forma eficiente e simples. Qualquer dúvida ou sugestão mande sem hexitar.

Criando Tweets pelo PHP

março 4th, 2009

Sou responsável por um site de notícias e hoje precisei criar um meio de que quando uma notícia for inserida no site, ser criado automaticamente um tweet no twitter lincando para ela, a solução foi essa classe abaixo:

class Tweet{
	var $user;
	var $pass;
	var $json = false;
 
	function __construct($user, $pass, $texto=false){
		$this-&gt;user = $user;
		$this-&gt;pass = $pass;
		if ($texto) $this-&gt;send($texto);
	}
 
	private function testTweet($texto, $match){
		foreach ($match as $m){
			$url = $m[0];
			if (ereg("^www", $url)) $url = "http://$url";
			if (strlen($url) &gt; 19) $url = str_repeat("x", 19);
			$texto = str_replace($m[0], $url, $texto);
		}
		$texto = ereg_replace("http://(x{19,})", "\\1", $texto);
		if (strlen($texto) &gt; 140) return false;
		return true;
	}
 
	public function makeUrl($url){
		if (ereg("^www", $url)) $url = "http://$url";
		if (strlen($url) &lt;= 19) return $url;
		$url = "http://migre.me/atalho/" . urlencode($url);
		$ch = curl_init();
		curl_setopt_array($ch, array(
			CURLOPT_URL =&gt; $url,
			CURLOPT_RETURNTRANSFER =&gt; true
		));
		$o = curl_exec($ch);
		ereg ("value=\"(http://migre.me/[a-zA-Z0-9/:]+)\"", $o, $mat);
		return $mat[1];
	}
 
	public function send($texto){
		if (function_exists("curl_init")){
			// Localiza as URLs
			preg_match_all("/((https?:\/\/)|(www))([a-zA-Z0-9\/:%&amp;\?\.=\-\+]+)/", $texto, $match, PREG_SET_ORDER );
 
			// Testa se o tamanho do twitter é aceitavel
			if (!$this-&gt;testTweet($texto, $match)) throw new Exception ("Postagem muito longa!");
 
			// Cria as URLs finais
			foreach ($match as $m) $texto = str_replace($m[0], $this-&gt;makeUrl($m[0]), $texto);
			$texto = str_replace("http://http://", "http://", $texto);
 
			// Testa novamente pelo comprimento do tweet
			if (strlen($texto) &gt; 140) throw new Exception ("Postagem muito longa!");
 
			// Envia o tweet
			$ch = curl_init();
			curl_setopt_array($ch, array(
				CURLOPT_URL =&gt; "http://twitter.com/statuses/update.json",
				CURLOPT_HTTPHEADER =&gt; array('Expect:'),
				CURLOPT_POST =&gt; 1,
				CURLOPT_POSTFIELDS =&gt; array("status" =&gt; "{$texto}"),
				CURLOPT_HTTPAUTH =&gt; CURLAUTH_ANY,
				CURLOPT_RETURNTRANSFER =&gt; true,
				CURLOPT_USERPWD =&gt; "{$this-&gt;user}:{$this-&gt;pass}")
			);
			return $this-&gt;json = curl_exec($ch);
		}
		return $this-&gt;json = false;
	}
}
 
$tmp = new Tweet("username", "password");
echo $tmp-&gt;send("Eu não gosto das URLs do site da Microsoft: http://search.microsoft.com/results.aspx?form=MSHOME&amp;setlang=en-us&amp;q=office+templates&amp;mkt=en-US");

Ela faz a análise do seu texto e converte as URLs, caso necessário, para um formato resumido usando o migre.me e caso passe os 140 caracteres uma exception é jogada.

Operador XOR no PHP

maio 21st, 2008

Há alguns meses estava precisando criar uma classe de criptografia e quando eu fui desenvolver eu não encontrei nenhuma criptografia veloz o suficiente, até que o Luan me mostrou uma excelente utilização para o XOR. Este operador é muito parecido com o OR, porém a sua leitura é: “OU um OU outro” e não “UM ou OUTRO” como o OR. Confira a tabela abaixo exemplificando:

false ^ false = false
false ^ true = true
true ^ true = false
true ^ false = true

Legal não? só é verdadeiro se os valores forem diferentes.

Como exemplo vamos pegar 2 valores binários, como sendo uma chave e um valor:

valor: "11010110"
chave: "10011101"

Vamos operar cada bit usando o XOR, isso irá resultar o binário “encriptado”

11010110 ^ (valor)
10011101 = (chave)
01001011    (valor encriptado)

Na terceira linha obtivemos o valor encriptado, só para demonstrar, vamos usar esse valor encriptado e dar um XOR com a chave novamente.

01001011 ^ (valor encriptado)
10011101 = (chave)
11010110   (valor novamente)

Não precisa de mais exemplos certo? é uma forma fraca, porém muito veloz de gerar criptografia, e perfeita para usarmos em coisas simples, como a criptografia de URL’s e Salts

Mas não pense que programar isso é complexo, o PHP permite que façamos esse processo usando dois caracteres.

"a" ^ "b" = "?", logo
"?" ^ "b" = "a"

Com isso vou mostrar uma classe de criptografia extremamente simples:

class Crypt {
    static $chave = "xy";
    static function StringXor($a,$b) {
        if ($a=='') return '';
        $retorno = ""; $i = strlen($a)-1; $j = strlen($b);
        do{
            $retorno .= ($a{$i} ^ $b{$i % $j});
        }while ($i--);
        return strrev($retorno);
    }
    static function Encrypt($string) {
        return base64_encode(Crypt::StringXor($string, Crypt::$chave));
    }
    static function Decrypt($string) {
        return Crypt::StringXor(base64_decode($string), Crypt::$chave);
    }
}

O que essa classe faz basicamente é percorrer as strings da chave e do valor passado, calculando para cada caractere o seu valor encriptado, e ao final é codificado usando-se base64 para que não fique com caracteres inválidos na string.

Um exemplo:

texto = "andre"
chave = "xy"
resultado:
a ^ x
n ^ y
d ^ x
r ^ y
e ^ x

Código php:

$a = Crypt::Encrypt("andre");
echo "Encriptado:";
$b = Crypt::Decrypt($a);
echo "Decriptado: $b";

Saída:

Encriptado: GRccCx0=
Decriptado: andre

é isso, testem, entendam e qualquer coisa pergunte.