domingo, 4 de junio de 2017

Problema al crear una carpeta src en un proyecto con PyDev

Hace poco tiempo tuve un problema bastante tonto, y me costo un poco resolverlo, así que decidí realizar esta entrada a modo de nota mental, para que si en un futuro cercano (o lejano), me ocurre nuevamente, recordar como fue la solución. 

Siempre, por usos y costumbres suelo generar una carpeta /src dentro de mis proyectos. De forma tal que el árbol del proyecto quedaría mas o menos así.. 


El tema, surgió, porque al momento de crear el proyecto con PyDev, no seleccione el checkbox que dice "Create src folder and add to PYTHONPATH".


Es por ese motivo, que las carpetas base de datos, dialogs, forms, etc.. no las gráfica como si fueran paquetes, y es también por ese motivo, que si yo dentro de un archivo .py quiero hacer un import del tipo:

from base_de_datos.conexion import conexion 

No me lo va a permitir, ya que el interprete no relaciona la carpeta  base_de_datos con un paquete importable, por mas que dentro hayamos puesto el archivo __init__.py. 

La forma de solucionar este problema, si no tuvimos la precaución de hacer de entrada el check en el checkbox arriba expuesto, es haciendo click derecho sobre el proyecto, luego abrir Properties
 
 

Vamos al menú. PyDev -> PYTHONPATH y apretamos el boton "Add Source Folder"


Seleccionamos la carpeta src, que se encuentra dentro del proyecto, y luego apretamos OK.


A continuación removemos la carpeta que aparecía por defecto como /$/PROJECT_DIR_NAME, seleccionándola y apretando sobre Remove.


Luego apretamos OK, y hacemos un Refresh sobre el proyecto. 


y a continuación veremos el proyecto de la siguiente manera: 

y ya estaremos en condiciones de realizar los imports que deseemos. 

Espero a alguien le sirva esta simple información. No se si sera un problema recurrente o no, pero como nota mental, al menos a mi me va a servir seguro.. :) 


viernes, 10 de mayo de 2013

Malas noticias

Aparentemente googlevoice no funciona en Argentina.. asi que la solucion que habia pensado que iba a funcionar para poder usar WhatsApi para enviar mensajes desde la PC no se va a poder utilizar...

Espero mañana poder tener novedades!.

jueves, 9 de mayo de 2013

Enviar mensajes con Whatsapp desde la PC

No se descubre nada si se dice que Whatsapp esta siendo cada vez más popular, y creo que la siguiente es una pregunta que nos hemos hecho varios ¿Se pueden enviar mensajes utilizando una PC por medio de Whatsapp?. En primera instancia y sabiendo que los mensajes de Whatsapp son enviados vía Web (Es decir no utiliza las lineas telefónicas) podríamos decir que si es posible, ahora la pregunta del millón es ¿Como?.

Bueno, la forma mas "sencilla" y directa es instalar un emulador de Android en nuestra computadora, y luego instalarle Whatsapp, configurarlo y LISTO!.

No gastaremos tiempo en explicar como hacer la descarga de BlueStack ya que esta lleno de tutoriales dando vueltas por la web, ni tampoco explicaremos como hacer la configuración de WhatsApp, ya que también se encuentra en muchos sitios. Para los mas perezosos aquí les dejo el link en donde se muestra como instalar BlueStack y como configurar WhatsApp.

Tutorial instalacion BlueStack configura WhatsApp

Para la gran mayoría de las personas, la instalación de este emulador y la configuración de WhatsApp, seria suficiente para satisfacer sus necesidades, de todas formas a muuuuuuuchos les gustaría tener mas control sobre lo que se puede hacer, como enviar mensajes de forma automática, o realizar alguna acción algo mas compleja al recibir un mensaje.

Seguramente que si llegamos a este punto, contamos con algún conocimiento al menos básico de programación ya que tenemos que empezar a ver cosas algo mas complejas.
Solo como anécdota, les puedo contar que la gente de WhatsApp se encuentra muy pero muy reacia a la posibilidad de que los usuarios tengan algún tipo de control sobre el envió de mensajes desde fuera de los teléfonos moviles, quizás sea un tema de estructura o de capacidad, no se bien a que se debe, pero se que están permanentemente realizando actualizaciones que hacen laburar cada vez mas a los cráneos que han logrado desenmarañar por medio de ingeniería inversa las directrices de la comunicación por medio de WhatsApp.

Como la mayoría sabe, el nombre de usuario en WhatsApp no es ni mas ni menos que el numero telefonico competo del usuario, con esta idea innovadora los creadores de WhatsApp lograban desligar al usuario final de los tediosos pasos para la registracion de sus cuentas, sin embargo como todos sabemos Whatsapp no solicita un password a la hora de loguearnos al sistema, sino que genera uno en base a de algunos datos de nuestro telefono movil. En primera instancia era un md5 del IMEI invertido, luego fue un dato en base64 del mismo imei o de la MAC de acuerdo al sistema operativo que se utilizaba. El tema es que habian graves problemas de seguridad, ya que teniendo el numero de telefono y el imei o la MAC de un telefono ajeno, se podia suplantar la identidad de alguna persona, y hasta incluso segun cuenta la leyenda se podian leer conversaciones y cambiar foto de perfil y estado de WhatsApp... :)...

La ultima medida que tomaron los señores "Whatsapperos" fue brindar una clave mas compleja a sus usuarios, y por lo tanto mas dificil de comprender su armado. De todas formas hecha la ley, hecha la trampa.. :)..

Existe una API (Application Programming Interface), ingeniosamente llamada WhatsApi, que se ha desarrollado y se ha liberado al mundo, la misma permite tener control sobre gran parte de la mensajería de WhatsApp, lamentablemente esta API "deschavo" algunos de los graves problemas de seguridad con los que contaba WhatsApp, por lo cual la empresa comenzó acciones legales contra los creadores para que bajen dicha API de la Web, de todas formas ya se había extendido demasiado, por lo cual a estas alturas es casi imposible evitar que cualquiera pueda tenerla en sus manos. Por este motivo a la gente de WhatsApp Inc. no les quedo otra que poner manos a la obra y tratar de tapar esos baches. Ahí es que comenzó el tire y afloje entre los dueños de WhatsApp y los creadores de WhatsApi, el sistema de mensajería realizaba cambios en su validación de usuarios y la comunidad actualizaba la API para soportar ese cambio. Ahora se llego a un punto en el que no se ha podido descifrar el método de creación de la clave, peroooooooooooooo, aún así se puede seguir usando esta API.

Por ahora solo dejare un link en donde dice cuales serian los pasos a seguir para poder comenzar o continuar trabajando con WhatsApi. Aún no he podido probar a fondo esta solución, pero en breves lo haré y lo comentare para que haya algo en Español.

Continuar usando Whatsapi

Eso seria todo por ahora. Nos estamos viendo en la próxima publicación.

jueves, 7 de marzo de 2013

Recomendada programacion orientada a objetos PHP

Ya hace un tiempo que programo con PHP, cerca de 2 años, el tema es que hasta hace 1 mas o menos no comprendía los beneficios de programar orientado a objetos (Ojo no soy un purista de esto, si me queda mas sencillo resolver algo proceduralmente lo haría sin ponerme colorado). 

La estructura basica que estoy usando es una forma de "modelado" en la cual por cada clase tengo dos clases, una que se ocupa de toda la comunicacion con la Base de datos y otra que es el objeto propiamente dicho al cual simplemente le envio mensajes tales como:
  • $usr = Usuario::obtenerPorId($id) y me devuelve un objeto Usuario al cual luego le puedo hacer cosas tales como  $usr->getNick() y me devolvería el nombre de usuario.. :)
Entonces si vamos al ejemplo de la clase usuario tendría las siguiente clases:
  • Usuario.php
  • dUsuario.php
Con estas clases podria resolver toda la lógica. 

La clase Usuario tendría toda la lógica incluyendo los geters y los seters y se ocuparía de hacer el mapeo a objetos de las tablas relacionales. 
Yo para hacer esto suelo tener un método estático que se ocupa de hacer dicho mapeo.
Simplemente le paso un registro de la base de datos obtenido con mysql_fetch_array o con mysqli.. :)

public static function  mapearTablaConObjeto($reg){
    $usuario = New Usuario();
    $usuario->setNick($reg["nombre"]);
    $usuario->setMail($reg["mail"]);
    $usuario->setPass($reg["clave"]);
    $usuario->setSid($reg["sid"]);
    $usuario->setIp($reg["ip"]);
    $usuario->setIdUsuario($reg["idUsuario"]);
    $usuario->setUltimaAccion($reg["ultima_accion"]);
    $usuario->setOnline($reg["online"]);
    $usuario->setPerfil($reg["perfil"]);
    return $usuario;
}

Basicamente la clase Usuario suele devolver un usuario en particular o un arreglo de varios usuarios.
Para mostrar un ejemplo voy a poner obtenerUsuarioPorId($id)

    /*
     * OBTIENE UN USUARIO A PARTIR DE UN ID
     */
    public static function obtenerUsuarioPorId($idUsuario){
        $reg_usuario = dObtenerUsuarioPorId($idUsuario);
if(!is_null($reg_usuario)){
    return Usuario::mapearTablaConObjeto($reg_usuario);
}
return NULL;
    }

Aquí lo que se hace es llamar a la función que se encuentra en dUsuario.php y se ocupa de obtener un usuario de la Base de Datos. 

Nota: Es importante que los datos lleguen validados. Es decir que si tiene que entrar un entero, sea un entero y que si tiene que ser una cadena sea una cadena valida. 

La función dObtenerUsuarioPorId($idUsuario) se veria como sigue:

function  dObtenerUsuarioPorId ($id){

    global $conexion;

    $registros = mysql_query("select * from usuarios 
                              where idUsuario=$id",$conexion) or
    die("Problemas en el select USUARIO:".mysql_error());
    if(mysql_num_rows($registros))
return mysql_fetch_array($registros);
    return NULL;
}

Puede verse que la dObtenerUsuarioPorId obtiene un usuario por un id, y en caso de que no recupere ninguno devuelve NULL, la funcion obtenerUsuarioPorId si recibe NULL devuelve NULL y si recibe un registro hace el mapeo y devuelve el objeto usuario!! para ser utilizado como plazca. 

Luego se podrían hacer cosas tales como:

include_once "Usuario.php";

$usr = Usuario::obtenerUsuarioPorId(1);
if(!is_null($usr)){
    echo $usr->getNick();   // Muestra el nick del usuario 1
    // Cambio el nick del objeto pero no lo persisto en la BD
    $usr->setNick("Otro nick");  
    echo $usr->getNick();  // Muestra "Otro nick"
    $usr = Usuario::obtenerUsuarioPorId(1); // Vuelvo a obtener el usuario 1
    // Como no lo habia guardado en la BD vuelvo a mostrar el nick del usuario 1
    echo $usr->getNick(); 
    // Cambio el nick del objeto pero aún no lo persisto en la BD
    $usr->setNick("Otro nick"); 
    // Guardo los cambios en la BD. Si el usr->isNew() inserto sino actualizo
    $usr->save();  
    echo $usr->getNick();  // Muestra "Otro nick"
    $usr = Usuario::obtenerUsuarioPorId(1); // Obtengo el usuario 1.
    echo $usr->getNick();   // Muestro "Otro nick" porque ya habia guardado los cambio. :) 
}

Espero que se haya entendido más o menos cual es mi idea, porque fue una explicación medio rapida.. :).. cualquier consulta hagan!. jeje 

Saludos! 

El proyecto de un juego de navegador

Bueno el proyecto del juego de navegador quedara relegado por el momento... :). es necesario a mi entender tener ciertos privilegios sobre la Base de Datos que en el servicio de hosting con el que cuento no los tienen (Y tampoco tengo el dinero para invertir, no es mucho pero tengo otras prioridades por el momento).

Para hacer que un juego on-line funcione, le cuento a los mas despistados tienen que resolver casi todo del lado del servidor sin estar obligado a que el usuario intervenga ni este conectado.
El usuario simplemente ejecuta una acción

Por ejemplo:

  • Transportar recursos o realizar un ataque.

Pero no tiene que ejecutar ninguna acción para que el transporte llegue a destino, simplemente envía y espera a que pase el tiempo necesario para que la acción concluya, el usuario puede estar conectado o fuera de linea al momento de la llegada, pero lo que es seguro es que la acción debe finalizar igual.. :)

La forma que encontré de desarrollar esta "Asincronidad" o "Desatendimiento" de las acciones fue utilizar Eventos de la Base de datos.. :)

En un primero momento lo hacia con javascript que cuando viera que se terminaba un tiempo revisara que se había finalizado... perooooo eso obliga al usuario a estar conectado o al menos con el navegador abierto.. jejeje detalles de diseño..

Si a alguno se le ocurre otra idea bienvenida, pense en usar Cron pero no hubo caso.

jueves, 27 de diciembre de 2012

Nada en particular.

Hace ya poco más de un mes que comencé un proyecto Web personal, de esos en los que se suele invertir mucho y que seguramente nos dejara poca ganancia monetaria pero mucha, mucha intelectual, cuyo valor no es para nada despreciable.. :)

Comencé a hacer un juego de navegador. Siempre me llamaron la atención algunos juegos simples pero no por ello poco "enviciantes". Me preguntaba que es lo que habría detrás de esos juegos, que tanta estructura de personal y que tanto hardware sería necesario para hacer y mantener un juego on-line.
Por ahora el proyecto es unipersonal y lo vengo llevando bastante bien.. Creo que todo esta en el análisis y en saber hacia el lugar al que debe ir el proyecto.. Lo cual no se limita únicamente a los juegos, sino que es extensible a cualquier proyecto software.

Con este proyecto me estoy dando cuenta de algunas cosas bastante agradables. Por ejemplo:

  • Que no hace falta usar grandes framework para hacer un buen trabajo web con PHP. 
  • Que las formas de evitar los ataques de XSS, no son tan complejas como muchos nos quieren vender.
  • Y que se puede ser prolijo programando con PHP.. jeje

Si quieren que les di una mini receta para evitar los ataques de XSS, sería:


  1. Validar todos los datos de entrada, que puedan llegar a la Base de datos. Si son datos de tipo Entero, validar que nos hayan ingresado solo valores enteros. :).. con PHP asi como con la mayoria de lenguajes de programación de alto nivel, esto es muy sencillo y se resuelve en una sola linea.. 
  2. Si los campos que les pueden ingresar, son de tipo texto la validación es un poco mas complicada, porque siempre esta la posibilidad que nos quieran inyectar código si no dejamos controlados caracteres tales como las comillas simples (').
Si hacemos que a partir del ingreso de un formulario si ejecute algo similar a esto:

select * from tabla1 where nombreCampo = 'Valor ingresado desde el formulario';

estariamos dandole la posibilidad a algun usuario malicioso de ingresar en el formulario por ejemplo el valor.

' basura

Con lo cual fallaría la sentencia SQL si esto no esta controlado y quizas el error obtenido le daria pistas al usuario mal intencionado de obtener información acerca de la estructura de nuestra Base de datos que no queremos que sea pública.

Para hacer la validacion de campos de texto, lo que puedo recomendar es 

hacer la conexión con mysqli de la siguiente manera:

$conexion = new mysqli("<hostname>", nombreUsuario, password, nombreBaseDeDatos);

Esta forma de conexión nos brinca la posibilidad de utilizar las sentencias prepare y bind_param

Prepare sirve para "preparar" la consulta que luego querremos ejecutar en la base de datos, y nos permite dejar sin enlazar los parametros, son el uso de los signos de pregunta (?). 

$consulta=$conexion->prepare("insert into tabla
   (valorEntero1,  valorEntero2 , valorCadena,  valorEntero3) 
values 
(?, ?, ?, ?)");

Luego con la sentencia bind_param, bindeamos los signos de preguntas con los valores que le queremos pasar a la secuencia SQL. El primer parámetro de bind_param es una cadena con el formato de los parámetros que se insertaran a continuación. "iisi" significa que el primer parámetro es (i) (INTEGER), que el segundo parametro es (i) INTEGER que el tercer parámetros es (s) STRING y que el cuarto y último parámetro es (i) INTEGER. 
$res = $consulta->bind_param("iisi",$val1,$val2,$str1,$val3);
if($res){
$res = $consulta->execute();
        }

Con esto tendríamos validados los campos de tipo texto... Previo a hacer el binding, deberíamos comprobar que los valores integer, sean realmente enteros. Ya que en mi versión no se porque razón no falla cuando le envió cadena en los datos de tipo entero. :)



Bueno solo quería contar esa pequeña experiencia..
Supongo que seguiré comentando algunas cosas más de mi desarrollo en los dias subsiguiente..

sábado, 10 de noviembre de 2012

Framework Python

Bueno lo prometido es deuda.. :)..

Así que pasare a mostrar mi framework.

Básicamente es un framework que sirve para hacer aplicaciones de escritorio utilizando Python, hace uso de un ORM que es SqlAlchemy y para la parte de interfaz gráfica utiliza PyQT... Cabe aclararar que esta es una primera aproximacion a lo que realmente estoy buscando... por lo cual tiene varias cosas que pulir, y el que quiera colaborar puede hacerlo.. :)..

Por ahora tiene soporte solo para las Bases de Datos:

  • SQLite
  • MySQL
Pero es fecalmente extensible a PostgreSQL.

Es importante como dije en el vídeo seguir ciertas convensiones, la principal es que el nombre del archivo con el cual se guarda el Form, sea igual al nombre del objeto form.. :). el resto practica mente queda a gusto del usuario..

En cuanto a la definición del modelo, hay unas pocas palabras reservadas por el momento:

  • tabla:  # Especifica que se debe crear una nueva tabla, con el nombre que sigue a continuación de los dos puntos
  • campo: # Especifica el nombre del campo y su tipo.
  • ucamp: # Especifica que es el ultimo campo de la tabla.
Tener en cuentas que tabla, campo y ucamp SI O SI deben estar seguidas de dos puntos ":"

En cuanto a los tipos de datos tenemos:

  • entero: Tipo de dato entero. :)
  • cadena: Tipo de dato String. Debe seguir a continuación la longitud de la cadena, en caso que no se especifique la longitud, se toma por defecto 50 caracteres.
  • real. Tipo de dato Real.
Para comprender un poco mas el uso del Framework, recomiendo ver estos dos videitos, que espero se entiendan.. :).. Si no lo logran ver bien, ponganlo en pantalla completa y mejorenle la calidad a 480p y lo verán perfectamente.

Video 1

Video 2

Para descargar el Ejecutable para Windows, pueden hacerlo desde el siguiente Link:

Descargar PyFrame

Espero que les guste, y que les sirva.. Cualquier comentario o sugerencia sera bienvenido..

Saludos y hasta la próxima..