Agile Programming

General

Written on July 19th, 2008

Menu web multinivel con HTML y CSS

Un recurso muy utilizado en web son los menús horizontales y verticales, y realmente los que más problemas nos presentan son estos últimos debido a la incompatibilidad de algunos navegadores que no siguen los estándares. Existen diversas formas de llevar a cabo los menús horizontales con elementos anidados: desde mostrar los submenús con javascript, hasta hacerlo directamente con CSS. En esta ocasión trataré de explicar como se crea un menú con esta última opción, por su portabilidad además que nos va a ser indiferente que el cliente tenga o no Javascript en su navegador. imagen 21 Menu web multinivel con HTML y CSSEl resultado final debería ser algo como lo que se ve en la imagen. El nivel de anidamiento es indiferente y tengo comprobado que funciona en todos los navegadores (salvo lógicamente links). El código HTML es bastante simple, para anidar sub-menús simplemente se inserta una estructura <ul><li></li></ul> dentro de los <li> así la hoja de estilos (que también adjunto) recoja la estructura correcta y muestre nuestro precioso menú. Read the rest of this entry »

Written on July 4th, 2008

Migración de datos de sqlite3 a MySQL

sqlite1 Migración de datos de sqlite3 a MySQL

Es algo común que estés desarrollando contra un gestor de bases de datos de “juguete” como puede ser sqlite3 y en un momento dado querer pasar a uno “de verdad” para probar cuanto rendimiento tiene tu app.

En este caso y como reza el título explico como hacer la migración de sqlite3 a MySQL, que resulta bastante trivial.

SQLite a MySql

  1. Se hace un dump de la bbdd que queremos
  2. sqlite3 BasedeDatosaExportar .dump .quit >fichero-dump.sql
  3. Ahora toca adaptarla a la sintaxis expecial de MySQL
    - Reemplazar ” (comillas dobles) por ` (acento grave)
    - Elimina “BEGIN TRANSACTION;” “COMMIT;“, y las líneas “sqlite_sequence
    - Substituye “autoincrement” con “auto_increment
  4. Y el fichero ya está listo para importar en MySQL.

Facil y bonito oye.

Written on July 4th, 2008

dotfiles para Unix/Linux

imagen 1 dotfiles para Unix/Linux

A veces encuentras perlas por internet gracias a las cuales aprendes más que leyendo libros.

En esta ocasión he encontrado una web que recompila ficheros de configuración de muchísima gente con buscador incorporado. http://dotfiles.org/

Ya conocía en GitHub un proyecto conjunto donde todos los usuarios creaban un repositorio en git donde colgaban sus ficheros .files, y la verdad es que ayuda mucho sobre todo encontrar ficheros de configuración de autenticos gurús en distintos campos. Si os interesa aquí teneis una lista en github.

Written on May 22nd, 2008

SQL Injection, PHP y Bases de Datos

SQL Injection, la temida dirían algunos y la verdad es que si no tienes cuidado al programar suelen ser verdaderos quebraderos de cabeza, que ciertamente despues de retomar código es un tanto dificil de depurar si no sabes lo que ha sucedido.
Aquí voy a relatar modos de tratar ataques SQL Injection, que harán nuestras apps más seguras y a nosotros estár más tranquilos.
Las SQL Injections son consultas sql que son generadas por scripts/programas que concatenan entradas del usuario con consultas a bases de datos, y ahí es donde está el problema ya que no toda la entrada que proporciona el usuario es segura.
Por ejemplo consideremos la siguiente instrucción:

SELECT * FROM users WHERE user = 'Pepito'

Si quieres en este momento recoger una fila de la base de datos con información del usuario insertada debes reemplazar “Pepito” con la cadena proporcionada por el usuario.
En PHP se vé tal que así:

SELECT * FROM users WHERE user = '$_GET[nombreUsuario]'

El problema es simple: si el usuario inserta una cadena formateada especialmente como el nombre de usuario el puede modificar tu consulta para ejecutar lo que el desee.

Por ejemplo si inserta esto:

';DROP TABLE users;--

Ahora la consulta se verá así:

SELECT * FROM users WHERE user = '';DROP TABLE users;--'

Hay varias formas con las que alguien puede atacar nuestra base de datos mediante sql injection. Las más rudimentarias son escapar los caracteres ‘, pero no siempre funcionan correctamente ya que hay otras formas de alterar la consulta. Echemos un vistazo a esto.

Hay una solucion muy simple a este problema. No concatenes texto proporcionado por el usuario en una consulta, vinculalo. La mayoría de las bases de datos soportan bindings, mysql es una de ellas, postgresql, oracle y la lista crece. La idea es simple: proporcionas un marcador en tu consulta que será reemplazado con la variable actual, por lo que no es posible ninguna modificación posible.

Nuestra anterior consulta se puede escribir tal que así:
Mysql (en php con la extensión mysqli)

SELECT * FROM users WHERE user = ?

Oracle

SELECT * FROM users WHERE user = :user

Ejemplo de la extensión mysqli PHP (para más información lee la función de mysqli_stmt bind_param

/* recoger los datos del usuario */
$nombreUsuario = $_GET['nombreUsuario'];
/* preparar la consulta */
$stmt = $mysqli->prepare('SELECT * FROM users WHERE user = ?');
/* vincular el valor */
$stmt->bind_param('s', $nombreUsuario);
/* ejecutar la declaración preparada */
$stmt->execute();

$stmt->bind_result($name, $surname);
/* recoger los datos de usuario*/
while ($stmt->fetch())
{
  //imprimir los datos del usuario
  echo $nombre, ' =>  ', $apellido , "\n";
}
/* cerrar la operación */
$stmt->close();

Ejemplo con la extensión PHP PDO (para más información lee la función prepare de PDO

/* recoger los datos del usuario */
$nombreUsuario = $_GET['nombreUsuario'];
/* preparar la consulta */
$sth = $dbh->prepare('SELECT * FROM users WHERE user = ?');
/* vincultar y ejecutar la consulta */
$sth->execute($userName);
$row = $sth->fetchAll();

Por lo tanto es muy facil para nosotros evitar la reescritura evitando que concatenar los datos proporcionados por el usuario con nuestra consulta, pero hay escenarios donde debes generar una consulta con los datos del usuario, no solo enviando una consulta. Por ejemplo, quieres mostrar diferentes tipos de libros basados en lo que inserta el usuario. El usuario puede elegir ver libros de ciencia ficción, literatura o libros de cocina.

Podrías estar tentado a escribir algo como esto:

SELECT * FROM $_GET[categoriaLibro]

¿Pero, que pasa si el usuario quiere modificar tu script e inserta ‘users’ como una categoría? En ese caso podrá ver el contenido de la tabla de usuarios. La solución para este problema es comprobar la categoría proporcionada por el usuario en vez de la cadena directamente.

En php deberías hacer algo como esto:

switch ($_GET['bookCategory'])
{
        case 'sf_books':
                $table = 'sf_books';
                break;
        case 'literature_books':
                $table = 'literature_books';
                break;
        default:
                $table = 'cooking_books';
}
$query = "SELECT * FROM $table";

Si escribes tu script de esta forma, cuando el usuario inserte ‘users’ como una categoría, el verá los libros de cocina, o puedes elegir mostrar un error, esa es tu elección.
Para resumir este post, quiero decir que deberías utilizar el binding de variables cuando quieras enviar datos a la base de datos que proporciona el usuario. Y si formas tus consultas según la entrada de usuario, simpre compara lo que inserta con algun valor predefinido y usa el valor por defecto.
Nunca concatenes entrada de usuario en tus consultas, sin excepciones