API codeigniter

La API esta compuesta por dos librerias: User(se encarga de la autentificación) y Api (que sería el core).

User
User es la libreria encargada de la autenticación. La autenticación se basa en un hash construido por la clave publica y el método al que se llama, y tiene como semilla la clave privada que sólo es conocida por el cliente y el server. La clave pública actúa como identificador de usuario. En este caso he reducido la clase para que sea más entendible.

El hash se genera de la siguiente forma.

hash_hmac("md5",CLAVE_PUBLICA.METODO,CLAVE_PRIVADA)
<?php
class CI_User{

    var $CI;
    var $id = false;
    var $mail = false;
    var $key = array('consumer_public'=>'123','consumer_private'=>'456789');		

    function CI_User() {

        $this->CI = & get_instance();

    }

    function apilogin(){

         if ($this->authapi()) {
           return true;

        } else {

            header('WWW-Authenticate: Basic realm="API eCamina"');
            header('HTTP/1.0 401 Unauthorized');
            echo "Yo can't access. You need auth";
            exit;

        }

    }

    function authapi(){

        if(!isset($_SERVER['PHP_AUTH_USER'])||!isset($_SERVER['PHP_AUTH_PW'])){

           return false;

        }

        $user = $_SERVER['PHP_AUTH_USER'];
        $pass = $_SERVER['PHP_AUTH_PW'];

        if(hash_hmac("md5",$user.$this->CI->uri->segment(2),$this->key['consumer_private']) == $_SERVER['PHP_AUTH_PW']){

            return true;
        }else{
	    return false;
	} 

    }

}

?>

La libreria API recibe los siguientes parametros en la carga:

$list = array('item'=>array('name'=>'roberto','lastanme'=>'Rubio','year'=>'27'),'example'=>array('example'=>'1','example'=>'12125'));

        $config['data'] = $list;
        $config['name'] = MÉTODO;
        $config['error'] = $error;//Boolean;
        $config['type'] = $this->_type(4);//Tipo de los datos a devolver // json o XML.

El array $config es pasado en la carga de la libreria load. A continuación anoto el código de la librería. Básicamente la librería recibe $data que es un array asociativo con los datos a formatear para la salida por pantalla y que depende de los parámetros como type y error. El dato name del array config hace referencia al método que necesitará la autentificación en la librería user.

<?php

defined('BASEPATH') OR exit('No direct script access allowed');

class CI_Api {

    var $data = array();
    var $error = false;
    var $type = 'xml';
    var $typee = array('json', 'xml');
    private $CI;

    function CI_Api($param = false) {
        $data = array();
        $error = true;
        $type = 'xml';
        $name = 'WebService';

        foreach ($param as $key => $val) {

            switch ($key) {
                case 'data': $data = $val;
                    break;
                case 'error': $error = $val;
                    break;
                case 'type': $type = $val;
                    break;
                case 'name': $name = $val;
            }
        }

        $this->name = $name;
        //comprobamos si existe algún error desde la declaración
        $this->error = $error;

        //comprobamos si el array esta vacio
        if (!$this->_set_data($data)) {
            $this->error = true;
        }

        if (!$this->_set_type($type)) {
            $this->error = true;
        }

        if ($this->error) {

            $this->data = array('Error' => 'Error: not found');
        }

        $this->CI = &get_instance();
    }

    function _set_data($value) {

        $ok = false;
        if (count($value) > 0) {
            $this->data = $value;
            $ok = true;
        }

        return $ok;
    }

    //Seteamos el tipò de datos
    function _set_type($value) {

        //comprobamos si el valor esta dentro de los tipos permitidos y guardamos en type
        $ok = false;
        foreach ($this->typee as $t) {
            if ($t == strtolower($value)) {
                $this->type = $value;
                $ok = true;
                break;
            }
        }

        return $ok;
    }

    //devolvemos el error
    function _get_error() {
        return $this->error;
    }

    //devolvemos el tipo pedido
    function _get_type() {
        return $this->type;
    }

    function _get_data() {
        return $this->data;
    }

    function _format() {
        $method = "_get_" . $this->type;
        $this->$method();
    }

    function _get_xml() {

        $xml = new ArrayToXML();
        header('Content-type: text/xml');
        echo $xml->toXml($this->data,$this->name);
    }

    function _get_json() {

        $this->CI->load->library("json");
        header('Content-type: application/json');
        echo json_encode($this->data);
    }

    function get() {

        $this->_format();
    }

}

class ArrayToXML { 

    private $Xml = ''; 

    function __construct() {
    } 

    public function toXml($array, $root = 'data', $numeric_identifier = 'nod'){ 

        $this->Xml .= '<?xml version="1.0" encoding="UTF-8"?>'."\n";
        //$this->Xml .= "<".$root.">\n";
        $this->Xml .= $this->build_xml_tree($array, $numeric_identifier);
        //$this->Xml .= "</".$root.">\n"; 

        return $this->Xml; 

    } 

    public function toXml_echo($array, $root = 'data', $numeric_identifier = 'nod'){ 

        $this->toXml($array, $root, $numeric_identifier);
        echo $this->Xml; 

    } 

    private function build_xml_tree($array, $numeric_identifier){ 

        if(is_array($array)){ 

            $keys = array_keys($array); 

            for($i = 0; $i < sizeof($keys); $i++){ 

                $tag = $keys[$i]; 

                if(is_numeric($tag)){ 

                    $tag = $numeric_identifier; 

                } 

                $this->Xml .= "\t"."<".$tag.">\n"; 

                    $this->build_xml_tree($array[$keys[$i]], $numeric_identifier); 

                $this->Xml .= "\t"."</".$tag.">\n"; 

            } 

        } else if(!empty($array)) {  

            if( $this->checkForHtml($array) ){
                $array = '<![CDATA['.$array.']]>';
            } 

            $this->Xml .= "\t" .$array. "\n"; 

        } else { 

            return false; 

        } 

    } 

    private function checkForHtml($string){ 

        if( strlen($string) != strlen(strip_tags($string)) ){
            return true;
        }
        return false; 

    } 

} ?>

Reflection ingeniería inversa

¿Qué es Reflection?
Reflection es un paradigma de programación que permite conocer como esta construida las clases del código que se esta ejecutanda(ingeniería inversa). PHP tiene una libreria conocida como Reflection(originales!).

Caso de Uso

Imaginate que tenemos una clase cargada tal que así:

class Prueba{
public function saluda(){
return "hola";
}

public function despedida(){
return "adios";
}
}

Una forma de hacerlo sería abrir el fichero donde contenemos la clase y parsearlo para obtener sus métodos pero esto es poco elegante y puede que nos de más de un dolor de cabeza sin contar con cambios en las clases.

Con Reflection podríamos realizar las siguiente lectura:

  $class = new ReflectionClass("Prueba");
$metodos=$class-&gt;getMethods(); // $metodo contendrá un array con los métodos de nuestra clase.

Ojo tendríamos que tener cargado la clase en nuestra clase para hacer uso de ella. Puedes utilizar el método require();

Librería para implentar client XMPP

Estaba desarrollado un chat para el helpdesk de la empresa y empecé a buscar script PHP de chats para la implementación dentro de la aplicación. Después analicé mi necesidades y comprendí lo improductivo de tener una aplicación web para el contacto con el usuario. Yo soy usuario de gtalk así que me decidí por implementar un helpdesk que interactuara con Gtalk y que los mensajes del usuario se remitieran a mi usuario. Buscando encontré esta interesante librería para gestionar comunicación mediante el protocolo XMPP.  Este protocolo es el más extendido por la mayoría de aplicaciones de mensajería instantánea así que si no te convence trabajar con gtalk puedes utilizarla para muchos otros(facebook, ICQ, MSN…) o  incluso  implantar en un server XMPP.

Comprobar mail en PHP

Está función la encontré por internet hace ya un tiempo y la suelo utlizar en los proyectos dentro de algún helper. Lo dejo por que me servirá, seguro, dentro de algún tiempo.

function _comprobar_email($email){
$mail_correcto = 0;
//compruebo unas cosas primeras
if ((strlen($email) >= 6) && (substr_count($email,”@”) == 1) && (substr($email,0,1) != “@”) && (substr($email,strlen($email)-1,1) != “@”)){
if ((!strstr($email,”‘”)) && (!strstr($email,”\”")) && (!strstr($email,”\\”)) && (!strstr($email,”\$”)) && (!strstr($email,” “))) {
//miro si tiene caracter .
if (substr_count($email,”.”)>= 1){
//obtengo la terminacion del dominio
$term_dom = substr(strrchr ($email, ‘.’),1);
//compruebo que la terminación del dominio sea correcta
if (strlen($term_dom)>1 && strlen($term_dom)<5 && (!strstr($term_dom,"@")) ){
//compruebo que lo de antes del dominio sea correcto
$antes_dom = substr($email,0,strlen($email) - strlen($term_dom) - 1);
$caracter_ult = substr($antes_dom,strlen($antes_dom)-1,1);
if ($caracter_ult != "@" && $caracter_ult != "."){
$mail_correcto = 1;
}
}
}
}
}
if ($mail_correcto)
return 1;
else
return 0;
}

links how do to make a API’s?

Autenticación oAuth
http://code.google.com/p/oauth-php/
http://php.net/manual/en/book.oauth.php
http://oauth.net/code/

Tutoriales para la API
http://particletree.com/features/how-to-add-an-api-to-your-web-service/
http://blog.realmofzod.com/blog/2009/05/06/implement-a-rest-api-with-the-zend-framework/
http://jasonirwin.ca/2009/05/24/simple-api/
http://www.recessframework.org/page/towards-restful-php-5-basic-tips
http://www.gen-x-design.com/archives/making-restful-requests-in-php/
http://www.gen-x-design.com/archives/create-a-rest-api-with-php/
adlemons

OpenLlavor y el conomiento universal

Durante mucho tiempo hemos estado debatiendo, hablando y pensando como empezar con el movimiento. En un principio creíamos que deberíamos empezar dando cursos de formación de forma voluntaria y gratuita, y quizas dentro de un tiempo poder montar una escuela de startup. Pero parece un poco difícil comenzar, dar a conocer la idea y sobretodo que la gente se implique participando. Por esta razón pensé que lo primero que debíamos de realizar es un evento sobre PHP, que la verdad aquí en Valencia no hay. Es una forma de conocer a gente con las mismas inquietudes, que al fin y al cabo son potenciales socios.

Total que parece que la idea a gustado entre algunos del PCUV (Parc Científic de la Universitat de València) y se va a crear. Es el primer acto que va a estar impulsado por la asociación y se llama Jornada PHP valencia.

Este evento se celebrará el próximo 28 de Enero en Valencia, con entrada gratuita y donde se reunirán grandes ponentes del sector del desarrollo mostrando casos de éxito y como ven ellos el futuro de la programación en PHP. Y sobretodo para vernos las caras y desvirtualizarnos, que también es importante. Es un foco de búsqueda de trabajo por que nos consta que existe empresas que están buscando programadores para sus proyectos y están invitadas.

Por cierto la asociación se llama OpenLlavor, llavor es semilla en Valenciano.

Nota Mental

Uno de los errores más absurdos de PHP es “Cannot modify header information – headers already sent by…” que  te vuelve loco buscando donde pelotas me deje ese espacio o ese salto de linea tan ca… Así que he decidido crear esta nota mental para no caer en la misma estupidez otra vez!!.

No olvidar y comprobar que, después de las etiquetas de apertura y cierre de PHP, no tenga ni espacios ni \n. ….

No olvidar y comprobar que, después de las etiquetas de apertura y cierre de PHP, no tenga ni espacios ni \n. ….

No olvidar y comprobar que, después de las etiquetas de apertura y cierre de PHP, no tenga ni espacios ni \n. ….

… Continuará

Evitar que un Spammer coja tu mail

Encontré navegando por internet esta precaución para evitar que un spammer coja tu mail y te llene de mails de viagra. La forma es muy sencilla, original y, por ahora en mi caso ya que me ha protegido la cuenta, efectiva . Escribes el texto alrevés: moc.olpmeje@olpmeje (ejemplo@ejemplo.com) y mediante CSS le damos la vuelta. La forma de realizarlo es así:

span .text{
direction:rtl;
unicode-bidi:bidi-override;
}
<span class=’text’>moc.olpmeje@olpmeje</span>
Espero que os sirva.

checkbox checked Jquery

Para introducir los valores de los checkbox seleccionados y que pertenezcan a la misma clase.

var n;
var categories = new Array();

$(“.categories:checked”).each(function(){

categories[n] = $(this).val();
n++;

});

De esta forma tendremos todos los valores chequeados. Una vez obtenidos sólo quedaría tratarlos a gusto del consumidor. Yo como normal general suelo comprobar los datos tanto en el cliente como en el server, pero vamos que lo podeis hacer desde el server y ahorraros la faena del javascript.

Me gusta más esta forma de programar más dinámica que darle a cada checkbox un id distinto ( Recordar que el Id no se puede repetir para todos lo elementos de una misma web, pero si la clase y el name).