Mi primer script funcional en python.
Siguiendo las enseñanzas del libro Learn python – the hard way, me encontré con un ejercicio donde se invita al lector a hacer sus propias cosas, scripts chiquitos que puedan ayudarle en algo.
Me animé y con gusto noté que no ha sido tiempo perdido aquél que he invertido en leer y practicar sobre los ejercicios de este libro. El cuál, por cierto, es muy bueno.

Y aquí les dejo mis “pininos” en python.


#!/usr/bin/env python
# coding: utf8
# author: Pedro [byteStriker] Navarro

import sys
import os

"""
Script para conectarme a los servers de MySQL porque soy muy huevon para escribir los comandos a pata.
"""

# Aquí defini la lista donde accedo a las conexiones, se pueden meter tantas como se deseén.
mysql_servers = ['mysql -uroot -proot -h localhost', 'mysql -uroot -proot -h otropinche.hostname.mx', 'mysql -uroot -proot -h www.google.com']
def conectar ( conexion_indice ):
	"""Conecta a la base de datos."""
	os.system(mysql_servers[conexion_indice])
	sys.exit(0);

def salir ():
	"""Te saca del script."""
	print("\nSaliendo del programita\n");
	sys.exit(0);

def seleccionar_conexion ( param_conexion = 0):
	"""Recibe el parametro seleccionado y conecta al server requerido."""  

	if 'q' == param_conexion:
		salir()

	if len(param_conexion) == 1 :

		try:
			#prueba si el parámetro (string) que le pasaste puede convertirse a entero
			opcion_selccionada = int(param_conexion)
			opcion_selccionada = opcion_selccionada - 1 #Le resto 1 para acceder bien a los índices de la lista
                        #Como python no tiene SWITCH tuve que usar el viejo truco del if elif else

			if opcion_selccionada == 0:
				print("Conectando a la opcion 1, [MySQL Alias 1]")
				conectar(opcion_selccionada)

			elif opcion_selccionada == 1:
				print("Conectando a la opcion 2, [MySQL Alias 2]")
				conectar(opcion_selccionada)

			elif opcion_selccionada == 2:
				print("Conectando a la opcion 3, [MySQL Alias 3]")
				conectar(opcion_selccionada)
			#Si el usuario la cagó e intentó pasarse de corneta, pues le pintamos cremas:
			elif param_conexion not in (1,2,3):
				print("No existe una conexion definida para la opcion ", opcion_selccionada);
				iniciar()

			else:
				print(opcion_selccionada + "no es una opcion valida")
				iniciar()

		#Aquí es donde se cachan las excepciones que arroja la evaluacion del try de arriba
		except:
			print("Utilice solo numeros.")
			iniciar()

	else:
		print("El programa solo acepta una opcion, esta debe ser un digito que represente una de las opciones mostradas")
		iniciar()

def iniciar():
	"""Muestra un listado de eaeas que permite conectarte a una base de datos porque eres muy huevon y no quieres escribir el comando completo"""
	print("Presiona el numero correspondiente al server de MySQL que quieres conectarte")

	print("[1] MySQL Alias 1")
	print("[2] MySQL Alias 2")
	print("[3] MySQL Alias 3")
	print("[q] Para salir")
	opcion = raw_input("Opcion> ")

	if( len(opcion) == 0 ):
		print("\n=====Opcion no registrada, intentalo de nuevo=====\n")
		iniciar()
	else:
		seleccionar_conexion(opcion)

iniciar();

¡Voilà, ya tenemos un script en python que funciona y hace mi vida más sencilla!

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
 

Ahora vamos con el modelo, el modelo (por adaptación del concepto que tomé del manual de CodeIgniter) es una entidad que se encarga de interactuar con el controlador (que es de donde vienen las solicitudes del usuario y a donde éste envía las respuestas de las consultas para mostrar info al usuario final).


@name md_comentarios
@access publico
@description Esta clase se encarga de interactuar con la base de datos, básicamente es para la minería de datos
@parameters none
*/

class md_comentarios extends CI_Model {

	public function __construct()
	{
		parent::__construct();
	}

	/**
	@author Pedro Navarro 
	@name get_comentarios
	@access publico
	@description Busca dentro de la base de datos los registros que aún no estén publicados, esto es para "moderar" cada uno de ellos y decidir cuáles han de mostrarse y cuales no.
	@parameters none
	@return resultset object
	*/
	public function get_comentarios()
	{
		//inicializando la conexión de la base de datos
		$db_comentarios = $this->load->database('default', True);

		//creando la consulta para obtener los registros
		$sql_comentarios = " SELECT * FROM comentarios;";

		//ejecuto la consulta y con un operador ternario (condicion) ? parte verdadera : parte falsa; determino qué es lo que voy a enviar como resultado al controlador
		$resultado = ($db_comentarios->query($sql_comentarios)->num_rows() >= 1) ? $db_comentarios->query($sql_comentarios)->result() : Null;

		//escupo al log el valor asignado a la variable; desde aquí ya sé cómo se va a comportar el controlador
		log_message('info', "md_comentarios->get_comentarios->sql_comentarios: {$db_comentarios->last_query()}");

		//cierro la conexión con la base de datos
		$db_comentarios->close();

		return $resultado;
	}

	/**
	@author Pedro Navarro 
	@name get_comentario
	@access publico
	@description Busca dentro de la base de datos los registros que aún no estén publicados, esto es para "moderar" cada uno de ellos y decidir cuáles han de mostrarse y cuales no.
	@parameters none
	@return row object
	*/
	public function get_comentario ( $parametros = Null )
	{
		// la variable de retorno siempre es False al inicio
		$resultado = false;

		// verifica que los parámetros sean un arreglo y no sea Null
		if( ( ! is_null( $parametros ) ) && ( is_array( $parametros ) ))
		{
			//inicializando la conexión de la base de datos
			$db_comentarios = $this->load->database('default', True);

			//creando la consulta para obtener los registros
			$sql_comentarios_pendientes = " SELECT * FROM comentarios WHERE com_id = {$db_comentarios->escape($parametros['com_id'])} LIMIT 1; ";

			//ejecuto la consulta y con un operador ternario (condicion) ? parte verdadera : parte falsa; determino qué es lo que voy a enviar como resultado al controlador
			$resultado = ($db_comentarios->query($sql_comentarios_pendientes)->num_rows() == 1) ? $db_comentarios->query($sql_comentarios_pendientes)->row() : Null;

			// cierro la conexión a la base de datos
			$db_comentarios->close();
		}

		return $resultado;
	}

	/**
	@author Pedro Navarro 
	@name set_publicar_comentario
	@access publico
	@description Actualiza el campo com_publicar a 1 en la tabla comentarios
	@parameters array
	@return boolean
	*/
	public function set_publicar_comentario ( $parametros = Null )
	{
		// la variable de retorno siempre se inicia con False
		$resultado = False;

		// verifica que los parámetros sean un arreglo y no sea Null
		if( ( ! is_null( $parametros ) ) && ( is_array( $parametros ) ))
		{
			// inicializando la conexión a la base de datos
			$db_comentarios = $this->load->database('default', True);

			// creación de la consulta SQL con la actualización del registro
			$sql_publicar_comentario = "UPDATE comentarios SET com_publicar = 1 WHERE com_id = {$db_comentarios->escape($parametros['com_id'])};";

			// ejecuto el query
			$db_comentarios->query($sql_publicar_comentario);
			log_message('info', "md_comentarios->set_publicar_comentario->sql_publicar_comentario: {$db_comentarios->last_query()}");

			// checo si actualizó o no alguno de los comentarios y regreso True/False dependiendo de la respuesta
			$resultado = $db_comentarios->affected_rows() == 1 ? True : False;

			// cerrando conexión con la base de datos.
			$db_comentarios->close();
		}
		return $resultado;
	}

	/**
	@author Pedro Navarro 
	@name set_bannear_comentario
	@access publico
	@description Actualiza el campo com_publicar a 1 en la tabla comentarios
	@parameters array
	@return boolean
	*/
	public function set_bannear_comentario ( $parametros = Null )
	{
		//la variable de retorno siempre se inicia como False
		$resultado = False;

		// verifica que los parámetros sean un arreglo y no sea Null
		if( ( ! is_null( $parametros ) ) && ( is_array( $parametros ) ))
		{
			// inicializa la conexión con la base de datos
			$db_comentarios = $this->load->database('default', True);

			//creo la sentencia SQL para actualizar a 0 el campo com_publicar
			$sql_bannear_comentario = "UPDATE comentarios SET com_publicar = 0 WHERE com_id = {$db_comentarios->escape($parametros['com_id'])};";

			//ejecuto el query
			$db_comentarios->query($sql_bannear_comentario);
			log_message('info', "md_comentarios->set_publicar_comentario->sql_bannear_comentario: {$db_comentarios->last_query()}");

			// le pregunto con un operador ternario a la base de datos cuántos registros alteró y asigno True/False dependiendo de lo que haya hecho
			$resultado = $db_comentarios->affected_rows() == 1 ? True : False;

			// cerrando la conexión a la base de datos.
			$db_comentarios->close();
		}
		return $resultado;
	}

	//** De aquí para abajo van los métodos para la otra parte del ejemplo **//

	/**
	@author Pedro Navarro 
	@name get_comentarios_publicados
	@access publico
	@description Busca dentro de la base de datos los registros que aún no estén publicados, esto es para "moderar" cada uno de ellos y decidir cuáles han de mostrarse y cuales no.
	@parameters none
	@return resultset object
	*/
	public function get_comentarios_publicados()
	{
		//inicializando la conexión de la base de datos
		$db_comentarios = $this->load->database('default', True);

		//creando la consulta para obtener los registros
		$sql_comentarios = " SELECT * FROM comentarios WHERE com_publicar = 1;";

		//ejecuto la consulta y con un operador ternario (condicion) ? parte verdadera : parte falsa; determino qué es lo que voy a enviar como resultado al controlador
		$resultado = ($db_comentarios->query($sql_comentarios)->num_rows() >= 1) ? $db_comentarios->query($sql_comentarios)->result() : Null;

		//escupo al log el valor asignado a la variable; desde aquí ya sé cómo se va a comportar el controlador
		log_message('info', "md_comentarios->get_comentarios_publicados->sql_comentarios: {$db_comentarios->last_query()}");

		//cierro la conexión con la base de datos
		$db_comentarios->close();

		return $resultado;
	}

	/**
	@author Pedro Navarro 
	@name set_agregar_comentario
	@access publico
	@description Inserta un registro en la tabla comentarios
	@parameters array
	@return boolean
	*/
	public function set_agregar_comentario ( $parametros = Null )
	{
		/**
		En esta función voy a poner el ejemplo de la otra manera de escapar correctamente los queries usando el otro método de escape de CodeIgniter
		*/
		//la variable de retorno siempre va en False al inicio de la función
		$resultado = False;
		// verifica que los parámetros sean un arreglo y no sea Null
		if( ( ! is_null( $parametros ) ) && ( is_array( $parametros ) ))
		{
			// inicializa la conexión con la base de datos
			$db_comentarios = $this->load->database('default', True);

			//creo la sentencia SQL para insertar el registro
			$sql_insertar_comentario = "INSERT INTO comentarios (com_autor, com_comentario, com_fecha, com_publicar) VALUES (?, ?, ?, ?);";

			//ejecuto el query
			$db_comentarios->query($sql_insertar_comentario, $parametros);
			log_message('info', "md_comentarios->set_agregar_comentario->sql_insertar_comentario: {$db_comentarios->last_query()}");

			// le pregunto con un operador ternario a la base de datos cuántos registros alteró y asigno True/False dependiendo de lo que haya hecho
			$resultado = $db_comentarios->affected_rows() == 1 ? True : False;

			// cerrando la conexión a la base de datos.
			$db_comentarios->close();
		}
		return $resultado;
	}	

}

/* End of file md_comentarios.php */
/* Location: ./application/models/md_comentarios.php */

Ahora vamos a ver cómo hice el controlador, éste recibe solicitudes vía ajax de parte de la vista. El primero de los controladores que voy a poner está pensado para leer (en la vista pública, por llamarlo de alguna manera)

load->model('md_comentarios', 'md_comentarios');
	}

	/**
	@author Pedro Navarro 
	@name index
	@access publico
	@description Redirecciona al método admin.
	@parameters none
	@return void
	*/
	public function index()
	{
		//redirecciona a la URL del sitio a partir de la propiedad controller_name de la clase y lo manda al método admin
    redirect(base_url()."{$this->controller_name}/leer");
	} 

	/**
	@author Pedro Navarro 
	@name leer
	@access publico
	@description Muestra una vista general, con los comentarios aprobados por el moderador
	@parameters none
	@return void
	*/
	public function leer ()
	{

		//accedo al método get_comentarios de la clase (modelo) md_comentarios para obtener la lista de comentarios
		$parametros_vista['titulo_pagina'] = "{$this->controller_name}";

		// le empujo a esta variable el resultado que devuelva el modelo.
		$parametros_vista['rs_comentarios'] = $this->md_comentarios->get_comentarios_publicados();

		// cargo la vista y le aviento los parámetros que ya definí.
		$this->load->view('comentarios', $parametros_vista);

	}

	/**
	@author Pedro Navarro 
	@name agregar_comentario
	@access publico
	@description Muestra una vista con campos para ingresar comentarios.
	@parameters none
	@return void
	*/
	public function agregar_comentario ()
	{

		// cargo la vista y le aviento los parámetros que ya definí.
		$this->load->view('agregar_comentario');

	}

	/**
	@author Pedro Navarro 
	@name guardar_comentario
	@access publico
	@description Muestra una vista con campos para ingresar comentarios.
	@parameters none
	@return void
	*/
	public function guardar_comentario ()
	{
		$parametros['com_autor'] = $this->input->post('com_autor', true);
		$parametros['com_comentario'] = $this->input->post('com_comentario', true);
		$parametros['com_fecha'] = $this->input->post('com_fecha', true);
		$parametros['com_publicar'] = 0;

		$insertar_comentario = $this->md_comentarios->set_agregar_comentario($parametros);

		if ($insertar_comentario)
		{
			$this->lista_comentarios();
		}
	}

	public function lista_comentarios()
	{
		//accedo al método get_comentarios de la clase (modelo) md_comentarios para obtener la lista de comentarios
		$parametros_vista['titulo_pagina'] = "{$this->controller_name}";

		// le empujo a esta variable el resultado que devuelva el modelo.
		$parametros_vista['rs_comentarios'] = $this->md_comentarios->get_comentarios_publicados();

		// cargo la vista y le aviento los parámetros que ya definí.
		$this->load->view('lista_comentarios', $parametros_vista);
	}

}

/* End of file leer_comentarios.php */
/* Location: ./application/controllers/leer_comentarios.php */

Ahora viene el controlador que hace la “moderación” de los comentarios que los usuarios escriben.

load->model('md_comentarios', 'md_comentarios');

	}

	/**
	@author Pedro Navarro 
	@name index
	@access publico
	@description Redirecciona al método admin.
	@parameters none
	@return void
	*/
	public function index()
	{
		//redirecciona a la URL del sitio a partir de la propiedad controller_name de la clase y lo manda al método admin
    redirect(base_url()."{$this->controller_name}/admin");
	} 

	/**
	@author Pedro Navarro 
	@name admin
	@access publico
	@description Muestra la lista de todos los comentarios que hay dentro de la base de datos
	@parameters none
	@return void
	*/
	public function admin()
	{

		//accedo al método get_comentarios de la clase (modelo) md_comentarios para obtener la lista de comentarios
		$parametros_vista['titulo_pagina'] = "{$this->controller_name} admin";

		// le empujo a esta variable el resultado que devuelva el modelo.
		$parametros_vista['rs_comentarios'] = $this->md_comentarios->get_comentarios();

		// cargo la vista y le aviento los parámetros que ya definí.
		$this->load->view('moderador/lista_comentarios', $parametros_vista);

	}

	/**
	@author Pedro Navarro 
	@name publicar
	@access publico
	@description Recibe el parámetro del comentario a publicar y hace las operaciones propias en el modelo
	@parameters integer
	@return void
	*/
	public function publicar()
	{
		//recibo
		$parametros['com_id'] = $this->input->post('com_id', true);
		log_message('info', "\$parametros['com_id'] es: {$parametros['com_id']}");

		$comentario = $this->md_comentarios->get_comentario( $parametros );

		$respuesta_modelo = False;

		if($comentario)
		{
			log_message('info', "\$comentario->com_publicar es: {$comentario->com_publicar}");

			switch ($comentario->com_publicar)
			{
				case 1:
					$respuesta_modelo = $this->md_comentarios->set_bannear_comentario( $parametros ) ? 'Comentario deshabilitado.' : 'Error, no se pudo efectuar la operacion, revisa los logs.';

				break;

				case 0:
					$respuesta_modelo = $this->md_comentarios->set_publicar_comentario( $parametros ) ? 'Comentario publicado.' : 'Error, no se pudo efectuar la operacion, revisa los logs.';
				break; 

				default:
					$respuesta_modelo = False;
				break;
			}
		}

		log_message('info', "\$respuesta_modelo es: {$respuesta_modelo}");
		print($respuesta_modelo);

	}

}

/* End of file moderar_comentarios.php */
/* Location: ./application/controllers/moderar_comentarios.php */

Ahora, vamos a las vistas, la primera de ellas se llama comentarios.php, en esta lista se ponen los comentarios “moderados” que el administrador haya promovido.











com_comentario;?>
com_fecha?>
No hay registros para mostrar
#

Ahora, la vista que por medio de ajax se carga para agregar comentarios al programa y que le aparezcan al moderador



Fecha

Como ya les había comentado previamente,

AQUÍ

pueden descargar el demo que funciona y toda la cosa.

Happy coding!

 

Para entenderle sí van a tener que saber de PHP.

En varias ocasiones me he visto forzado a guardar en un campo de la base de datos un string así “1,2,3,4,5″, generalmente cada número representa un ID que concierne a una llave foránea. Precisamente porque soy holgazán, me di a la tarea de idear una función que me permitiera crear una cadena SQL válida con tantos OR como números (incluso palabras) separados por comas tenga el campo.

Esta función nace del siguiente caso práctico… tengo una tabla llamada campaña, la cual almacena cierta información, a cada campaña se le pueden asignar “N” cantidad de agentes, ergo hice un listado de agentes que (mediante ajax) se asignan a la campaña en dicho campo con el formato “1,2,3,4,5,6″, cada número significa el id del registro del agente. Para continuar, al consultar la campaña debía extraer el nombre de cada uno de los agentes para listarlos como “asignados” a “x” campaña…

La finalidad es escribir menos y hacer más.

 


	//Este convierte un '1,2,3' en un (campo = {1} OR campo = {2} OR campo = {3})
	function or_sql_cadena ( $parametros = null )
	{
		//el resultado siempre lo declaro al principio y como vacío para que si se cuelan... se lleven un '';
		$result = '';
		//Haciendo que el que llama esta funcíón sepa que debe mandar una rreglo como parámetro.
		if( is_array($parametros) )
		{
			//Variables para todo el flujo de la función.
			$campo_comparacion = '';
			$arr_temporal = array();
			$result_and = '';
			$result_or = '';

			if(array_key_exists('campo_comparacion', $parametros)) // que sí venga el parámetro
			{
				if(!empty($parametros['campo_comparacion'])) //Que el parámetro no sea vacío
				{
					$campo_comparacion = $parametros['campo_comparacion'];
				}
			}

			if(array_key_exists('cadena_texto', $parametros)) // que el parámetro sí venga
			{
				if( !empty($parametros['cadena_texto']) ) //que el paraámetro no sea vacío
				{
					$arr_temporal = explode(',', $parametros['cadena_texto']);
				}
			}
			//Si trae datos el arreglo, etonces continua
			if(count($arr_temporal)>=1)
			{
				//Armando la cadena SQL empezando con el AND
				$result_and .=  ' AND (';
				//por cada posición del arreglo temporal haz:
				foreach($arr_temporal as $idx => $campo_id)
				{
					//si ya trae algo la cadena, entonces métele un OR
					if ($result_or != '') { $result_or .= ' OR '; }
					//aquí hago que el query haga la comparación entre datos con el campo (casi siempre llave foránea) que se va a comparar
					$result_or .= " {$campo_comparacion} = {$campo_id}";
				}
				//concateno lo que armó el for
				$result_and .= $result_or;
				//cierro la condición
				$result_and .= ')';
			}
			//Si hubo incidencias en el for, entonces haz:
			if ($result_or != '')
			{
				//Si el query tiene AND
				if ($result_and != '')
				{
					//regresas la cadena al resultado
					$result = $result_and;
				}
			}

		}
		//regresa la cadena al resultado
		return $result;
	}

La manera en que se invoca dicha función es ésta:


//obtener todos los datos de la campaña
$sql_get_campana = "SELECT * FROM campana cmp WHERE cmp.cmp_id = {$db_indial->escape($campana_id)} AND cmp.cmp_estatus =  {$db_indial->escape(CAMPANA_ACTIVO)}  LIMIT 1; ';
$registro_campana = $db_indial->query($sql_get_campana)->num_rows() == 1 ? $db_indial->query($sql_get_campana)->row() : false;

//obtener todos los datos de los agentes
$agentes_asignados_cadena = (count($registro_campana)>=1) ? $registro_campana->cmp_agentes : ''; // asigno el valor del campo

//por si no trae ningún agente:
$registros_agentes = '';
$sql_get_agentes_or = '';
if(!empty($agentes_asignados_cadena)) // Cuando traigo un dato, entonces preparo la consulta SQL para que haga el OR
{
	$param_or_sql['cadena_texto'] = $agentes_asignados_cadena;
	$param_or_sql['campo_comparacion'] = 'agn.agn_id';
	$sql_get_agentes_or = $this->indial_utilerias->or_sql_cadena($param_or_sql);
	$sql_get_lista_agentes = "SELECT * FROM agente agn WHERE agn.agn_estatus = {AGENTE_ACTIVO}  {$sql_get_agentes_or}  AND agn.agn_enllamada = 0 ";
	$sql_get_lista_agentes .= " AND agn.agn_estatusoperativo IN (SELECT cat_id FROM catalogo WHERE sec_id = {$db_indial->escape(ESTATUS_PANEL_AGENTE)} AND cat_valor0 = UPPER('SI')) ";
	$sql_get_lista_agentes .= "ORDER BY agn_id ASC; ";
	$registros_agentes = $db_indial->query($sql_get_lista_agentes)->num_rows() >= 1 ? $db_indial->query($sql_get_lista_agentes)->result() : false;
} 

//Happy coding.
SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
 

Estuve peleando como pendejo contra el puto encoding de html en Internet Explorer, por que resulta que la mamada esa no sabe interpretar el meta tag

  <meta http-equiv="Content-Type" content="text/html; charset=utf8" />

y fué un verdadero pedo encontrar la sintáxis adecuada de htmlentities() para que funcionara bien, después de mucho interpretar el manual, dejo a su disposición un ejemplo que funciona bastante bien, en IE6-7, Opera, FF3 y Chrome. Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
 

Esta semana estuve liado con un script que hiciera el clásico ABC (altas, bajas y cambios) en una BD de PostgreSQL. Sí, como siempre PostgreSQL pero el por que de esa desición es harina de otro costal, vamos al grano, estaba con el script y honéstamente ya se deterioraron mis habilidades de hacer las cosas a pata; tenía rato que no hacía estas chivas, ya me había acostumbrado al metodo CodeIgniter el caso es que me dió mucha hueva hacer el INSERT INTO a la base de datos con la clásiquísima sentencia escrita a mano, con sus campos y valores, entonces pensé “la programación debe ser divertida y ahorrarte trabajo”, así que la hice, no es nada del otro mundo, solamente construye una instrucción SQL (INSERT INTO) con los parametros que se le mandan, funciona con las funciones integradas de php pg_send_prepare() y pg_send_execute() Greets: Continue reading »

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
 

Ya tenía rato sin postear y qué mejor que retomar el posting en el blog con la siguiente noticia, que para mi es importante:

En este preciso momento se está haciendo la demostración del software que he estado programando desde Octubre pasado, estoy muy nervioso, se que funcionará bien, pero no todo está terminado, como sea, son solamente detalles. En este desarrollo aprendí mucho más de lo que ya sabaía acerca de codeigniter, estandarización de código, normalización de base de datos, prototype js, scriptaculous, validation js, postgres y como olvidarme de las hermosas CSSs que tanto odiaba antes.

Me siento complacido por que un niño más está a punto de nacer, ya solo falta que lleguen los que fueron a hacer la demostración para felicitarme ó para darme mi ticket de “pase por su liquidación a la ventanilla 2″ (risas).

Espero que el esfuerzo no haya sido en vano y todo funcione correctamente, existen algunos bugsitos que quedaron pendientes, pero por la premura y todo ya no alcance a commitearlos para que los treparan al server en el que se va a hacer la prueba.

En ocasiones como estas me siento eufórico y preocupado, y en verdad sí es como cuando estas viendo como operan a tu esposa para sacarle a tu hijo. Es una experiencia que me gusta mucho, afortunadamente ahora solo podré parir soft-hijos (hijos de software).

Quiero agradecer a todas las personas que me hicieron aprender lo que ahora se. Lo dificil es el comienzo, pero una vez encarrerado el ratón, chíngue su madre el gato;  las ansias me comen por saber ¿qué está pasando en el salón donde se hace la demostración?. Me gustaría haber ido, pero seguramente me habría pedorreado nomás de los purititos nervios.

Bueno, espero que pronto venga la gente y me digan ¿cómo les fué?.

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
 

He estado pensando acerca de unas cuantas cosas que he hecho en PHP con CodeIgniter, me dí cuenta que sí en una función de PHP recibes 1 solo parametro entre controladores y modelos te ahorras unos cuantos teclazos….

Ejemplo de caso habitual de paso de parametros entre controlador y modelo:

****Controlador*****

<?php if (! defined('BASEPATH') ) { exit ('No direct script access allowed'); end();}
class Proove extends Controller{
  function __construct(){
	parent::Controller();
	$this->load->model('proove');
  }

  function index () {$this->proove();}

  function proove ($param1, $param2, $param3 = '', $param4 = -1){
	if (empty ($param3) ) {$param3 = 'GUEST';}
	//doing amazing stuff and stunts with this params
	$var = $this->proove->get_users($param1, $param2, $param3);
	if ($var) {
	  $data['records'] = $var;
	  $this->load->view('index.php',$data);
	}
  }
}

?>

****Controlador*****

<?php if (! defined('BASEPATH') ) { exit ('No direct script access allowed'); end();}

class Proove extends Model{

  function __construct (){
	parent::Model();
  }

  function get_users ($param1, $param2, $param3){
	$sql = 'SELECT * ';
	$sql .= ' FROM users ';
	$sql .= ' WHERE type = \''.$param1.'\'';
	$sql .= ' AND kind = \''.$param2.'\'';
	$sql .= ' AND domain = \''.$param3.'\'';
	$rsproove = $this->db->query($sql);

	if ($rsproove->num_rows()){
	  return $rsproove->result();
	} else {
	  return FALSE;
	}
  }
}

?>

Okay, continuemos… PHP te permite el uso de arreglos asociativos por lo cual podríamos usar esto para el paso de parametros a las funciones que sean necesarios. Lidiar con arreglos es muchas veces enfadoso, más sí no son asociativos, por que la iteración con bucles se vuelve pesada y más sí eres principiante como Yo y no sabes como accesar bien al índice que necesitas; en cambio con un arreglo asociativo (qué para mi gusto son como un hash de perl) puedes dirigirte perfectamente al índice que quieres del arreglo con el que estas trabajando…

La idea es principalmente usar los arreglos asociativos como parametro único, de esta manera podrías solo preocuparte por saber el nombre del índice que esperas y no por n parametros y validarlos todos.

Tengamos en mente el siguiente escenario de programación. Estás usando CodeIgniter (aplicación demo sin la aplicación de esta idea aquí)

Estas haciendo una clase que tiene varios metodos, uno de ellos necesita una serie de parametros muy específicos donde todos esos parametros son requeridos; haces tu validación con JS ó con algun framework, hasta aquí todo bien, te aseguras de que los parámetros llegan perfecto al método de la clase que quieres y haces de nuevo una validación para evitar “que te metan gol”. Una vez hecho eso, entonces comienzas a escribir chingomil (muchas) líneas de código con las que harás cosas impresionantes en tu aplicación. Bueno, imagina que tiempo después de que tu aplicación ha sido liberada alguien se encuentra TAMPER DATA en los agregados de FIREFOX y lo instala en su máquina *no estoy suponiendo que alguien va a hackearte, sino que un individuo curioso con el mínimo grado de conocimientos informáticos, decide probar lo que ha leído en un manualito de 20 minutos por que tiene tiempo libre*. Entonces comienza el juego, el píca un botón y le pregunta sí quiere modificar los parametros enviados, acepta la petición y pum a menear todo. Bueno, ahí tienes que tus validaciones con JavaScript han sido fácilmente burladas. Luego ¿qué sige?, fácil, tu controlador responderá de acuerdo a como ha sido creado, tomará los parametros y jugará con ellos, lo dificil del caso es cuando expones el borrado de usuarios de una tabla ó la alteración de los mismos, ya que puedes caer fácilmente en un SQL Injection Attack o algo por el estilo.

Veámos, aquí va el truco, como no puedes impedir que el usuario sea metiche y juegue con tu trabajo, entonces lo que sigue es ir un paso adelante; puesto que la mayoría de ataques exitosos de cualquier tipo a casi cualquier tipo de sitio son debido a un error humano, pués haremos esto más divertido, tanto para la persona que curiosea la respuesta del sitio como a nosotros mismos como programadores.

CodeIgniter tiene una librería para la base de datos llamada Active Record Class así como una cosa llamada SQL Binding, ambas dos sirven para cosas que tienen que ver con la base de datos. Active Record Class sabe defenderse de SQL Injection Attack, Cross Scripting Attack y otras chucherías del tipo nada más que para mi gusto, la librería es como un diamante en bruto, falta pulirla y en lo personal no me gusta. ¿Sí eres alguien que prefiere construir los queries a mano y sentir el poder del SQL en tus manos?, entonces el siguiente párrafo es para ti, veamos:

****Controlador*****

<?php if (! defined('BASEPATH') ) { exit ('No direct script access allowed'); end();}

class Proove extends Controller{

  function __construct(){
	parent::Controller();
	$this->load->model('proove');
  }

  function index () {$this->proove();}

  function proove (){

	//El último parámetro (TRUE) en $this->input->post('variable', TRUE) protege tu entrada de XSS
	$parametros[0] = $this->input->post('param1',TRUE) == '' ? $this->input->post('param1',TRUE) : '-1' ;
	$parametros[1] = $this->input->post('param2',TRUE) == '' ? $this->input->post('param2',TRUE) : '-1' ;
	$parametros[2] = $this->input->post('param3',TRUE) == '' ? $this->input->post('param3',TRUE) : '-1' ;
	$parametros[3] = $this->input->post('param4',TRUE) == '' ? $this->input->post('param4',TRUE) : '-1' ;
	$var = $this->proove->get_users($parametros);

	if ($var) {
	  $data['records'] = $var;
	  $this->load->view('index.php',$data);
	}
  }
}

?>

****Modelo*****

<?php if (! defined('BASEPATH') ) { exit ('No direct script access allowed'); end();}

class Proove extends Model{

  function __construct (){
	parent::Model();
  }

  function get_users ($parametros){
	if (is_array($parametros)){
	  $sql = ' SELECT * ';
	  $sql .= ' FROM users ';
	  $sql .= ' WHERE type = ? ';
	  $sql .= ' AND kind = ? ';
	  $sql .= ' AND domain = ? ';

	  $rsproove = $this->db->query($sql, $parametros);

	  if ($rsproove->num_rows()){
		return $rsproove->result();
	  } else {
		return FALSE;
	  }
	} else {
	  return FALSE;
	}
  }
}
?>

Notarás que las modificaciones han sido mínimas, pero esto te da a cambio de modificar tu código un poco más de tranquilidad ya que puedes explotar la ventaja de escape de bad characters que un framework como CodeIgniter te ofrece, hay muchísimo más que publicar de esta herramienta y de otras tantas que apenas estoy conociendo y no he tenido tiempo de picar.

Espero que el artículo haya sido de interés y opines al respecto.

PHP CodeIgniter JavaScript Framework SQL Sql Injection Attack XSS

SociBook del.icio.us Digg Facebook Google Yahoo Buzz StumbleUpon
© 2012 Geekeandome Suffusion theme by Sayontan Sinha