Paginación de Twitter Bootstrap en WordPress

El twitter Bootstrap entre sus componente que tiene trae incorporado un sistema de paginación con links activos, normales y deshabilitados.

Paginación de twitterBootstrap en WordPress

Resultado Paginación de twitterBootstrap en WordPress

http://twitter.github.com/bootstrap/components.html#pagination

Por otra parte el sistema WordPress suele agregar la paginación de los posts en el archivo loop.php de la plantilla en cuestión, desgraciadamente la función paginate_links nos genera un código html algo diferente a lo que requerimos para adaptarlo al bootstrap.

Salida en HTML necesaria

Salida en HTML necesaria

http://codex.wordpress.org/Function_Reference/paginate_links

Navegando por Internet encontré algunas implementaciones, p.e:

http://panosgalatis.com/2012/08/14/wordrpess-and-twitter-bootstrap-pagination/#.UHvXCqyqyio

Sin embargo incluyen modificaciones al CSS, cuando este renderizado se puede hacer solo con PHP como se muestra continuación:

loop.php

loop.php

Hice un gists en github con el código fuente para que se pueda descargar:

Agregando Tooltips de Twitter Bootstrap al calendario de WordPress

Ejemplo Calendario con tooltip de twitterBoostrap

Ejemplo Calendario con tooltip de twitterBoostrap

El Twitter Boostrap trae integrado en su sección de javascript un plugin de JQuery (el ToolTip) el cual resulta muy útil e interesante a la hora de mostrar información extra sobre algún elemento o enlace de nuestro sitio.

Por otra parte WordPress nos proporciona un calendario que nos muestra los posts por fecha, el código html del calendario que nos interesa es básicamente este:

 
<table id="wp-calendar">
..
<td>
<a href="url" title="descripcion detallada">num día</a>
</td>
...
</table>

Conociendo el código HTML al que queremos acceder podemos acceder a estos elementos y agregarle el tooltip, como se muestra a continuación:

/** Le agregamos el toolTip a los elementos que nos interesan **/
$('#wp-calendar').find('td a').tooltip();

Queda a reflexión del lector por que use $('#wp-calendar').find('td a') en lugar de $('#wp-calendar td a').

Tema para phpmyadmin.

Hace un tiempo hice una plantilla para el phpmyadmin ya que no me gusta el que viene por defecto, hoy la comparto:

phpmyadmin theme dark orange

phpmyadmin theme dark orange

¿Como instalar?

Descargue el proyecto descomprima la carpeta y adentro ejecute como superusuario:

 ./install.sh 

Para mayores informes visitar el micrositio oficial del proyecto:

http://fitorec.github.com/phpmyadmin_theme_dark_orange/

Como Joomla genera sus passwords

Hace un par de días realice un posts en donde unifico el sistema de autenticación de Joomla con otro sistema en PHP (ver posts), mientras realizaba y estudiaba el código del Joomla, note algunas cosas que aqui dejo para que no se me olviden y por a alguien más le sirve.

Joomla Divide el campo password en 2 partes.

Algo que caracteriza a joomla es que el campo password en 2 partes de forma encrypt’:’salt la segunda parte(salt) es una cadena generada de forma (seudo) aleatoria y es empleada en conjunto con una función dominante de la derivación (KDF) y la contraseña del usuario para generar  la primera parte encrypt como se muestra en la siguiente imagen.

Como joomla trata los passwords

Figura 1 . -Como joomla trata los passwords

Como se puede ver el password finalmente es la concatenación de la cadena salt y encrypt con el carácter ‘:‘ . El empleo de esta cadena salt es típica en los sistemas de cifrado y en seguridad informática la obtención de esta cadena salt un gran paso para la obtención de la contraseña(con un Dic. y FB).

Joomla emplea MD5 como mecanismo de cifrado.

Joomla al igual que la mayoría de los sistmas Web  cifra sus contraseñas con algún algoritmo de cifrado irreversible, Joomla emplea MD5 (al menos que se configure de forma contrario) , en la figura se ve como la cadena salt es obtenida mediante la función getSalt() dicha función se encuentra definida en las librerías del Joomla en la versión 1.5-1.6 se encuentra en:  JOOMLA1.6/libraries/joomla/user/helper.php (Descargar Joomla y cerciorarse )cuando es llamada con los parámetros por defecto lo que nos genera es:

$salt    = md5(mt_rand());

Como podemos observar emplea la función mt_rand, la cual nos devuelve un número pseudo aleatorio haciendo uso de la implementación de algoritmo Mersenne twister, esto es bueno ya que genera los números es un poco mas eficiente tanto en tiempo de ejecución como en el echo en que te garantiza que es el número generado es mas seudo aleatorio que el que se genera con el rand() que es como lo implementa típicamente lenguajes como C.

Por otra parte para obtener la cadena encrypt hace uso de la cadena salt generada previamente con los parametros por defecto toma el comportamiento como:

$crypt = md5($password.$salt);

Finalmente si quisiéramos hacer un sistema en donde se puedan registrar usuarios desde otra aplicación tendríamos que generar este comportamiento en nuestra aplicación, dejo aquí la función password que recibe una contraseña sin cifrar(tal como la recibe un formulario) y devuelve la contraseña como típicamente la generaría el joomla antes de guardar en su BD.

#genera un password en el formato como lo hace el joomla
#la El password lo genera en 2 partes P1:P2
#P1 Es el resultado del md5 de concatenación del password con P2
#P2 Es la cadena security salt generada con md5
#
#para mayor info respecto la cadena salt revisar la función getSalt
#definida en: JOOMLA1.6/libraries/joomla/user/helper.php
function password($password){
	$salt	= md5(mt_rand());
	$encrypt = md5($password.$salt);
	return $encrypt.':'.$salt;
}

#prueba con la contraseña admin
echo password('admin')."\n";

Código fuente disponible en:  http://gist.github.com/596732

No se recomienda tener más de un sistema de registro en un sistema ya que la duplicidad de funciones genera ambigüedades y por lo consiguiente inconsistencias (DIE), es por esto que si sólo la recomiendo en caso que bloquees los registros desde tu joomla.

Poniendo a prueba el sistema de generación de passwords.

Como se menciono previamente es una de las características del Joomla que genere una cadena salt por cada password, la pregunta seria ¿que tantan seguridad le brinda al sistema esta metodología de generación de passwords? y si ¿en lugar de md5 cambio la configuración por defecto para ocupar  otro mecanismo como sha1?.

Si cambiamos la función hash de md5 a sha1 para este mecanismo en lo personal considero que no mejora mucho ya que la cadena salt quedaría definida como sha1(mt_rand()) .A pesar que sha1 genera una cadena de 160bits a diferencia de md5 que genera una de 128bits ambas generarían la cadena hash del resultado obtenido por mt_rand(), algo análogo pasa con la cadena encrypt la cual seria  la cadena hash de la contraseña(en texto plano) concatenada con la cadena salt, algo similar a sh1(‘Contraseña’.$salt).

Por otra parte si observamos lo que cambia es que con md5 generamos 2 cadenas de 32 caracteres y el password final queda con 65caracteres  y con sha1 generamos 2 cadenas de 40 caracteres generando un password de 81caracteres, lo cual es un poco peligroso ya que si alguien llega a obtener el campo password de un usuario joomla automáticamente obtiene la cadena salt y encrypt y  al revisar la longitud de dichos campos sabe cual fue la funcion hash empleada para obtener la cadena crypt.

Por lo tanto la vulnerabilidad Seguridad de un campo password en joomla se encuentra delimitada por la prediccion de algoritmo Mersenne twister o de su implementacion en PHP mt_rand() , de los diccionarios disponibles para funciones hash (por ahí vi un Blog, vi un elegante  bot  que empleaba un diccionario cifrar MD5) y como siempre de la contraseña en texto plano de los usuarios….

Generando la autenticación de Joomla 1.5 , 1.6 desde otra aplicación en PHP.

El Joomla es un sistema manejador de contenidos(CMS por sus siglas en ingles) que últimamente  ha adoptado cierta tendencia a ser una especie de frameWork de desarrollo de aplicaciones Rich por Internet, sin embargo si deseas unir este CMS con algún otro desarrollo empotrado ahí es en donde se complican un poco las cosas(sólo un poco).

Uno de los problemas derivados es el sistema de autenticación cuando tenemos una BD compartida entre ambos sistemas.

Hace un par de días me enfrente con este problema(el de autenticación) y después de varias horas revisando el código del Joomla, logre plantear la solución que a continuación expongo.

Consideraciones:

Técnica y reglas a emplear:

Hay ciertas cosas que un desarrollador debe(y no debe) de hacer para no meterse en problemas o si a caso se llega a meter le puedan ayudar, en este caso son 3:

  • No modificar ninguna librería interna del Joomla (en todo caso hacer un componente).
  • En el caso de usar otro FrameWork(tal es el caso) de igual forma no modificar lo que no debes y seguir la documentación adecuada.
  • La técnica empleada fue estudiar el login del Joomla para implementarlo (en este caso al cakephp), en otras palabras el sistema de autenticación cakephp sera quien se adapte al Joomla(todas las modificaciones se hicieron sobre el cakephp).

Nota: El siguiente post  habla sobre el sistema de autenticación: de como los sistemas pueden compartir una misma BD de sus usuarios con sus mismos campos(user,password). El manejo de sesiones (posterior a la autenticación) sera tema que espero tocar proximamente.

Sistema de autenticación de Joomla 1.5 y 1.6

El sistema de login de Joomla en la actualidad es bastante complejo ( antes no lo era tanto, por ahí recuerdo algunos xploits con js ) y ya que ofrece distintos mecanismos de cifrados y demas opciones.
“De todos estos mecanismos sólo  vamos extraer el que estemos ocupando en nuestra aplicación Joomla”.
para esto estudiemos dichos mecanismos.

Lo que hace el Joomla cuando se autentifica un usuario en un sitio.

  • El usuario abre la pagina de Internet y por medio de modulo de login(JOOMLA/modules/mod_login) o por medio de la ruta de administracion (http://mi-joomla/administrator/) inserta su username y password.
  • Estos datos enviados en el arreglo $credencials y son procesados por la función onUserAuthenticate del archivo JOOMLA/plugins/authentication/joomla.php la cual nos sede la autenticación en caso de ser valida.

Eso es todo!, al parecer el generar la autenticación se resume al estudiar y replicar el comportamiento de la función onUserAuthenticate que aquí se muestra:

#función de Joomla definida en: JOOMLA/plugins/authentication/joomla.php

function onUserAuthenticate($credentials, $options, &$response)
	{
		jimport('joomla.user.helper');
		$response->type = 'Joomla';}
 #Validación/Sanidad de los datos
		if (empty($credentials['password'])) {
			$response->status = JAUTHENTICATE_STATUS_FAILURE;
			$response->error_message = JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
			return false;
		}

		$conditions = '';

		#buscamos un usuario en la BASE de datos a partir de su 'username'
		$db		= JFactory::getDbo();
		$query	= $db->getQuery(true);

		$query->select('id, password');
		$query->from('#__users');
		$query->where('username=' . $db->Quote($credentials['username']));

		$db->setQuery($query);
		$result = $db->loadObject();
		if ($result) {
            		#Jooomla guarda el password en 2 parte la cadena encriptada y el secury.Salt ver Nota1
			$parts	= explode(':', $result->password);
			$crypt	= $parts[0];
			$salt	= @$parts[1];
            		#getCryptedPassword(cadena,salt) genera la cadena encriptada Revisar Nota2
			$testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt);
			if ($crypt == $testcrypt) {
            		#login correcto
				$user = JUser::getInstance($result->id);
				$response->email = $user->email;
				$response->fullname = $user->name;
				$response->status = JAUTHENTICATE_STATUS_SUCCESS;
				$response->error_message = '';
			} else {
            		#contraseña erronea
				$response->status = JAUTHENTICATE_STATUS_FAILURE;
				$response->error_message = JText::_('JGLOBAL_AUTH_INVALID_PASS');
			}
		} else {
            		#El usuario no existe
			$response->status = JAUTHENTICATE_STATUS_FAILURE;
			$response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
		}
	}

Existen ciertas cosas que vale la pena comentar de la autenticación de Joomla, primero que

Nota1: Joomla guarda en el campo password 2 cadenas separadas por el simbolo ‘:’ de la forma primera_parte:segunda_parte la primera_parte es la contraseña cifrada(por algún mecanismo de cifrado irreversible) y la segunda parte es una cadena “security salt” la cual ocupa(en conjunto con el password sin cifrar) para generar la cadena cifrada.

Nota2: Ese proceso de generar la contraseña cifrada lo hace la función getCryptedPassword como sigue.

#función de joomla definida en: JOOMLA/libraries/joomla/user/helper.php 
public static function getCryptedPassword($plaintext, $salt = '', $encryption = 'md5-hex', $show_encrypt = false)
	{
		#notar que los parametros por defecto #$encryption = 'md5-hex' #$show_encrypt = false

		$salt = JUserHelper::getSalt($encryption, $salt, $plaintext);

		switch ($encryption)
		{
			case 'plain' :
				return $plaintext;
 #mas cassos.....
 #mas cassos.....
			case 'md5-hex' :
			default :
				#Esto es lo unico que se ejecuta.
				$encrypted = ($salt) ? md5($plaintext.$salt) : md5($plaintext); return ($show_encrypt) ? '{MD5}'.$encrypted : $encrypted;
                    }
}

Como se puede ver al llamar a la función getCryptedPassword sin los argumentos encryption, show_encrypt la única parte del código que se ejecuta del joomla es la que esta de color morado, que para este caso se puede apreciar que la configuración por defecto del Joomla ocupa MD5 como mecanismo de cifrado irreversible.

Generando nuestro sistema de login para joomla.

Una vez que estudiamos las entrañas del Joomla y comprendemos como funciona podemos generar este comportamiento de autenticación, para hacerlo mas genérico y se pueda implementar dejo un código en PHP(versión 4 ) puro:

La versión de autenticación con php puro(M4ch0-c0d3r) la puedes descargar desde: http://gist.github.com/575849

#Requere que se configure la ruta del joomla para extraer la configuracion de la BD $joomla_path = './joomla1.6';

require_once($joomla_path.'/'.'configuration.php');

function joomla_login($username, $pass){
	$jconf = new JConfig;

	$conexion = @mysql_connect($jconf->host,$jconf->user,$jconf->password,false,0);
	@mysql_select_db($jconf->db);
	$sql = sprintf("SELECT * FROM %susers  WHERE  %susers.username='%s' LIMIT 1;",
				$jconf->dbprefix,$jconf->dbprefix, $username);
	$request = @mysql_query($sql);

	if (mysql_num_rows($request) == 1) {
		$user = array('User' => mysql_fetch_assoc($request));
		print_r($user);
		$parts	= explode( ':', $user['User']['password'] );
		$crypt	= $parts[0];
		$salt	= @$parts[1];
		$testcrypt = md5($pass.$salt);
		if ($crypt == $testcrypt) {
			echo "login correct!\n";
		}
	}
	if($request)
		mysql_free_result($request);

}

#probamos la función con un usuario que conozcamos 
joomla_login('admin','libertad')

implementación en cakephp

Una vez que se entiende el funcionamiento del login del Joomla quizás implementarlo en algún framework sea lo mas fácil, dejo aqui la implementa.

Definiendo la BD.

Se edito el archivo de la Base de datos del cakePHP para que reconociera de forma trasparentes las tablas se le tuvo que agregar el atrubuto prefix.

#CAKEPHP/APP/config/database.php
class DATABASE_CONFIG {

	var $default = array(
		'driver' => 'mysql',
		'persistent' => false,
		'host' => 'localhost',
		'login' => 'root',
		'password' => '',
		'database' => 'sidep',
		'prefix' => 'jos_', #Se le agrego el prefijo _jos
	);
}

Agregando el elemento de autenticación para la aplicación.

Se le agrego el componente de Auth al controlador de la aplicación.

#CAKEPHP/APP/app_controller.php
class AppController extends Controller {
	var $components = array('Auth');
}

Creando el modelo Users.

Se creo el modelo de usuario como se muestra a continuación.

#CAKEPHP/APP/models/user.php
class User extends AppModel {
	var $name = 'User';
	var $displayField = 'name';
	var $validate = array();
	#aqui van las relaciones(belonsTo,hasMany,etc..) con otras tablas, agregar las necesarias para su aplicacion.
}

Vista login:

Se le agrego la vista del login la cual es solo el formulario de acceso.

#CAKEPHP/APP/views/users/login.ctp
	if ($session->check('Message.flash')) {
		$session->flash();
	}
	if ($session->check('Message.auth')) {
		$session->flash('auth');
	}
    echo $session->flash('auth');
    echo $form->create('User', array('action' => 'login'));
    echo $form->input('username');
    echo $form->input('pass', array('type'=>'password'));
    echo $form->end('Login');

Controlador Users definiendo la función login.

Aquí es donde va la lógica que tanto estuvimos estudiando previamente, la cual se basa del código en PHP definido  previamente.

#CAKEPHP/APP/controllers/users.php
function login(){
	$user = null;
	#buscamos un usuario en la BASE de datos a partir de su 'username'
	if(!empty($this->data) && strlen($this->data['User']['pass'])>6)
		$user = $this->User->findAllByUsername($this->data['User']['username']);
		#verificamos que el usuario exista
		if(count($user) == 1) {
			$user = $user[0];
			#hacemos el login del joomla #dividiendo el password en la BD en 2 partes a partir del simbolo ':'
			$parts	= explode( ':', $user['User']['password'] );
			#la 1ra parte es el password ya encriptado
			$crypt	= $parts[0];
			#la 2da la cadena salt q se concatena con el password para ecriptar
			$salt	= @$parts[1];
			#Joomla ocupa MD5 como mecanismo de encriptacion y cakephp SHA1
			$passcrypt = md5($this->data['User']['pass'].$salt);
			#comparamos el password encriptado con el generado.
			if ($crypt == $passcrypt) {
				#CONGRATULATION! ';¬D,
				$this->data['User']['password'] = $passcrypt.':'.$salt;
				$this->Auth->login($this->data);
				$this->redirect('index');
			}
	}
}

espero les sea útil

cakePHP videos tutoriales descargalos aqui.

Solo por entrar en contexto el cakePHP: Es un framework de desarrollo de aplicaciones web escrito en PHP, creado sobre los conceptos de Ruby on Rails. (wikipedia).

El día de hoy me encontré con la grata sorpresa que cakePHP puso a disposición a través su portal una serie de vídeos tutoriales.

Desde hace un par de meses me he esforzado por aprender todo sobre este FrameWork así que no pude dejar pasar la oportunidad de descargar estos vídeos. Elabore un pequeño —pero útil– script en bash, el cual también lo dejo disponible en mi gitHub desde la dirección (http://gist.github.com/549457).

#!/bin/bash

#descarga los vídeos tutoriales del cakePHP
#los cuales los puedes ver desde:
#        http://cakephp.org/screencasts/
#código disponible en:
#        http://gist.github.com/549457

for i in {1..7}
do
   wget -O - http://cakephp.org/screencasts/view/$i | grep -E -o 'http.*.mov' | xargs wget
done

Si no usas Linux( mal ), dejo las URLs para que las agregues a tu gestor de descargas favoritos (p.e. jdownloader, tucan, etc..).

http://www.archive.org/download/SettingUpTheCakephpConsoleOnnix/nix_console_setup.mov
http://www.archive.org/download/CakePHP_BuildingtheBakery_Part1/BakeryStep1.mov
http://www.archive.org/download/SyncDevAppAndProductionApp/phpnut_does_svn.mov
http://ia300240.us.archive.org/2/items/CakePHP_BlogTutorialJohn/BlogTutorial.mov
http://ia301239.us.archive.org/1/items/UsingDebugMessages/using_messages.mov
http://www.archive.org/download/AdminRouting/admin_routing.mov
http://www.archive.org/download/SettingUpTheCakephpConsoleOnWindows/windows_console_setup.mov

Espero te sea útil.