Archive for April, 2005

Páginación de resultados

Tuesday, April 19th, 2005

La paginación de resultados es la única solución adecuada para poder mostrar al usuario los 4281 resultados que ha devuelto su búsqueda… ¿pero como hacerlo?

Bien, ya sabes lo que quieres. Quieres paginar resultados. ¿Pero como hacerlo? ¿Cuantos resultados por página? ¿Cuantas páginas? ¿Y si resultan que me salen 1000 páginas… muestro un enlace a cada una de ellas? ¿Solo muestro enlaces a las primeras 10 páginas? Y al cambiar de página… ¿que hago? ¿debo volver a hacer la busqueda? Este artículo pretende dar respuesta a todas estas preguntas.

En realidad, paginar resultados es tan fácil como seguir los siguientes 3 pasos:

Paso 1

Hacer una llamada a la base de datos para obtener el número total de resultados de la busqueda y asignar el resultado a una variable que llamaremos $total. Con MySQL la llamada debería ser algo así:

< ?php
$get = mysql_query('select count(*) from mitabla where ...');
$total = mysql_result($get,0);
?>

Paso 2

Hacer otra llamada que devuelva los resultados de la busqueda, limitando los resultados devueltos mediante las variables $pp y $st. $pp define el número de resultados por páginas. $st define el número, del total de resultados, desde donde empezar a mostrar los resultados en la página actual.

Usando MySQL la llamada será algo así:

< ?php
// obtener el valor de $st
if(isset($_GET['st'])) {
$st = $_GET['st'];
} else {
$st = 0;
}

// la llamada a base de datos
$get = mysql_query('select * from mitabla where ... limit '.$st.','.$pp);
while($row=@mysql_fetch_row($get)) {
// imprimir resultados
echo $row[0].'<br />';
}
?>

$st es una variable que se obtiene de la dirección de la página actual, por lo que su valor se debe obtener de la variable $_GET[’st’]. En la primera página de resultados $_GET[’st’] no esta definida, por lo que como puedes observar en el código superior tendremos que comprobarlo, y si resulta que no esta definida, tendremos que asignarle el valor 0.

Paso 3

Aplicar la función paginacion() que se muestra a continuación. Esta función se encarga de imprimir una serie de enlaces a las páginas resultantes de la busqueda.

< ?php
// resultados por pagina
$pp = 10;

// la función
function paginacion($total,$pp,$st,$url) {

if($total>$pp) {
$resto=$total%$pp;
if($resto==0) {
$pages=$total/$pp;
} else {
$pages=(($total-$resto)/$pp)+1;
}

if($pages>10) {
$current_page=($st/$pp)+1;
if($st==0) {
$first_page=0;
$last_page=10;
} else if($current_page>=5 && $current_page< =($pages-5)) {
$first_page=$current_page-5;
$last_page=$current_page+5;
} else if($current_page&lt;5) {
$first_page=0;
$last_page=$current_page+5+(5-$current_page);
} else {
$first_page=$current_page-5-(($current_page+5)-$pages);
$last_page=$pages;
}
} else {
$first_page=0;
$last_page=$pages;
}

for($i=$first_page;$i< $last_page;$i++) {
$pge=$i+1;
$nextst=$i*$pp;
if($st==$nextst) {
$page_nav .= '['.$pge.']';
} else {
$page_nav .= ''.$pge.'';
}
}

if($st==0) { $current_page = 1; } else { $current_page = ($st/$pp)+1; }

if($current_page< $pages) {
$page_last = '[>>>]';
$page_next = '[>]';
}

if($st>0) {
$page_first = '[< <<]';
$page_previous = '[< ]';
}
}

return "$page_first $page_previous $page_nav $page_next $page_last";
}

// mostrar resultado de la funcion
echo paginacion($total, $pp, $st, 'http://tudominio.com/mostrar.php?st=');

?>

A continuación una explicación de cada una de las variables que recibe la función paginacion():

  • $total. Número total de resultados que ha devuelto la busqueda. La forma de obtener este valor se ha explicado en el paso 1).
  • $pp. Número de resultados que queremos mostrar por en cada página.
  • $st. Número del primer resultado de la página actual. $st vale 0 en la primera página, en la siguientes valdrá 10, 20, 30, …
  • $url. La dirección completa de las páginas de resultados pero sin el valor de $st. Es decir, si la dirección de una página de resultados es http://tudominio.com/mostrar.php?st=30, el valor de $url debe ser http://tudominio.com/mostrar.php?st=

Como hacer “thumbnails” de tus fotografias

Tuesday, April 19th, 2005

PHP, junto con la librería GD, permiten la creación y manipulación de imágenes en tiempo real con gran facilidad y lograr unos resultados de una calidad más que aceptable.

Dependiendo de la versión de PHP y la librería GD, es posible crear y manipular imágenes de tipo JPEG, GIF, PNG y WBM, aunque en las últimas versiones no hay soporte para gráficos de tipo GIF. Para saber que formatos soporta tu instalación de PHP solo tienes que ejecutar el siguiente script:

< ?php
if (imagetypes() & IMG_PNG) echo 'Formato PNG soportado.&lt;br&gt;';
if (imagetypes() & IMG_JPG) echo 'Formato JPG soportado.&lt;br&gt;';
if (imagetypes() & IMG_GIF) echo 'Formato GIF soportado.&lt;br&gt;';
if (imagetypes() & IMG_WBMP) echo 'Formato WBMP soportado.&lt;br&gt;';
?>

Al ser el más complejo (o al menos completo) de realizar, haremos una función para redimensionar y ajustar la calidad de imágenes JPEG. Crear una función similar para imágenes PNG o WBMP debería resultaros sencillo.

La función recibe 5 parámetros:

  • Localización completa de la imagen original.
  • ocalización completa de la nueva imagen, es decir, el "thumbnail" que vamos a crear.
  • Calidad o compresión de la nueva imagen. Los valores posibles van de 0 (peor calidad, mayor compresión) a 95 (mejor calidad, menor compresión).
  • Anchura de la nueva imagen en pixels.
  • Altura de la nueva imagen en pixels.

A propósito de la calidad de las imágenes, debemos tener en cuenta que si la calidad de la imagen original era de por ejemplo el 75% y si especificamos que la calidad de la imagen redimensionada sea del 85%, la calidad de esta no mejorara, se mantendrá igual y solo conseguiremos incrementar el tamaño en bytes de la imagen. Por lo tanto, antes de aplicar esta función a una imagen debemos conocer su calidad actual.

Siguiendo con el mismo tema, los valores de calidad o compresión que se le puede aplicar a una imagen JPEG van del 0% al 95%. Lo lógico sería que fueran del 0% al 100%, pero por algún extraño motivo, la imagen resultante de una compresión del 97% es idéntica a la imagen comprimida al 95%.

A continuación puedes ver la función redimensionar_jpeg() y su aplicación:

&lt;?php
function redimensionar_jpeg($img_original, $img_nueva, $img_nueva_anchura, $img_nueva_altura, $img_nueva_calidad) {

// crear imagen desde original
$img = ImageCreateFromJPEG($img_original);

// crear imagen nueva
$thumb = ImageCreate($img_nueva_anchura,$img_nueva_altura);

// redimensionar imagen original copiandola en la imagen
ImageCopyResized($thumb,$img,0,0,0,0,$img_nueva_anchura,$img_nueva_altura,ImageSX($img),ImageSY($img));

// guardar la imagen redimensionada donde indicia $img_nueva
ImageJPEG($thumb,$img_nueva,$img_nueva_calidad);
}

redimensionar_jpeg('/home/yo/foto.jpg','/home/yo/mini_foto.jpg',100,100,75);
?&gt;

Ahora no tienes más que aplicar la función a cada una de las imágenes que desees redimensionar. También existe la posibilidad de ampliar la funcionalidad del script y hacer que este redimensione todas las imágenes de un directorio concreto. Por ejemplo, ejecutar el siguiente script en un directorio redimensionaría todas las imágenes de tipo JPEG del mismo:

&lt;?php
function redimensionar_jpeg($img_original,$img_nueva,$img_nueva_anchura,$img_nueva_altura,$img_nueva_calidad) {

// crear imagen desde original
$img = ImageCreateFromJPEG($img_original);

// crear imagen nueva
$thumb = ImageCreate($img_nueva_anchura,$img_nueva_altura);

// redimensionar imagen original copiandola en la imagen
ImageCopyResized($thumb,$img,0,0,0,0,$img_nueva_anchura,$img_nueva_altura,ImageSX($img),ImageSY($img));

// guardar la imagen redimensionada donde indicia $img_nueva
ImageJPEG($thumb,$img_nueva,$img_nueva_calidad);
}

$dir = opendir('.');

while(false !== ($file = readdir($dir))) {
if (!is_dir($file) && $file != '.' && $file != '..' && exif_imagetype($file)==2) {

// aplicar funcion
redimensionar_jpeg($file,'mini_'.$file,100,100,75).'&lt;br&gt;';
}
}
closedir($dir);
?&gt;

El trozo de código añadido al script simplemente recorre todos los archivos del directorio en busca de imágenes de tipo JPEG y cada vez que encuentra uno, le aplica la función redimensionar_jpeg().

¿Sirven de algo los intercambios de banners?

Tuesday, April 19th, 2005

Los hay a montones así que a estas alturas ya te habrás encontrado alguna que otra vez en la web de uno de esos programas de intercambio de banners. ¿A que resultan tentadores?

Ciertamente resultan tentadores. Al fin y al cabo, ¿quien no quiere recibir miles de visitas al día en su web? Desgraciadamente, me parece que todo esto suena demasiado bien para ser verdad. Lo demasiado bueno normalmente nunca lo es y si lo ha sido, lo habrá sido durante un periodo de tiempo muy corto, demasiado corto para que los mortales, es decir, tu y yo, nos hallamos podido enterar a tiempo como para sacar algún provecho.

Teniendo presente la regla de oro que acabo de mencionar podemos analizar el asunto de los intercambios de banners desde un punto de vista algo más realista.

¿Es posible recibir miles de visitas?

Si. Por supuesto que es posible, de hecho habrá miles de sitios web que reciben cientos de miles de visitas simplemente por haberse enrolado a uno de estos programas.

¿Si participo en un intercambio de banners recibiré miles de visitas?

Mejor respondes a esta pregunta por ti mismo, simplemente ten en cuenta los siguientes tres puntos:

  1. ¿Cual es el ratio de impresión del programa? Si es de 1:1, cada vez que tu muestres un banner, tu banner será mostrado en alguna otra web. Si es del 1:2, por cada 2 banners que muestres el tuyo será mostrado 1 vez.
  2. ¿Cuantos impresiones de página, es decir, cuantos banners puedes mostrar en tu web a lo largo de un mes? Si tu muestras 2000 banners y el ratio del programa es de 1:2 tu banner será mostrado 1000 veces.
  3. ¿Cuantas veces es clickeado un banner diseñado por un profesional por cada mil impresiones del mismo? Entre 0,15 y 5 veces por cada mil impresiones. Es decir, que recibirás entre 0,15 y 5 visitas al mes.

Estoy recibiendo montones de visitantes mediante un intercambio de banners ¿me ayudará esto a vender más?

Obviamente, esto depende de lo que vendas y de si el programa al cual te has enrolado es específico a un tipo de sitios web o si por el contrario, es generalista. Analicemos dos posibles escenarios que te ayudaran a comprender fácilmente:

  1. Supongamos que recibes mil visitas y dispones de un producto a bajo precio y que este resulta útil para un gran número de personas. Recibes 1000 visitantes, tu producto es un software que acelera la conexión a internet 1000 veces. Yo te compraría el producto.
  2. Has logrado 10.000 visitantes y vendes pienso para caballos de alta calidad a un precio excelente. Sinceramente, de esos 10.000 visitantes ¿cuantos crees que tienen caballos? Es decir, ¿crees que venderás algo?
  3. Vendes el mismo pienso para caballos y recibes 50 visitantes gracias a un programa de intercambios de banners especifico para dueños de caballos. Ahora, al menos ya sabes que todos tus visitantes tienen caballos.

Es curioso, tengo la sensación de no haber respondido a nada.

Por qué no es siempre bueno tener muchos visitantes

Tuesday, April 19th, 2005

A más de uno le parecerá una contradicción, al fin y al cabo ¿como va a ser malo recibir decenas de miles de visitas en tu web? Cuantas más visitas, más ventas, o ¿no?

Parece claro que cuantas más gente visite tu sitio web, venderás más y que por lo tanto, tendrás mayores beneficios. Pero las cosas no siempre son tan sencillas.

Por ejemplo, el tener muchos visitantes no debe suponer que vayas a vender más, puedes recibir miles de visitas y no vender nada. Todo depende de si tu producto es del interés de tus visitantes o no. El tener muchos visitantes, lo único que te asegura es que vas a pagar más por el alojamiento de tu sitio web.

Lo mismo ocurre con los sitios web que ofrecen información y cuyos ingresos se limitan a los de la publicidad. Estos sitios web deben convencer a las empresas del sector de los beneficios que supone anunciarse en su web. Para ello es imprescindible disponer de tráfico de calidad, es decir, visitantes interesados en los productos de los anunciantes. No sirve con tener montones de visitantes.

Por lo tanto, el objetivo de un sitio web no es simplemente atraer visitantes, sino más bien, atraer visitantes que estén interesados en la temática de la web, y más bien, en los productos que se vendan o anuncien en las misma.

¿Pero como lograr visitantes que estén interesados en tu producto? Lo más evidente: atrayendo visitantes desde otros sitios web relacionados con la temática de tu web. Publicitar tu producto únicamente en portales verticales, es decir, portales cuya temática indique que sus visitantes pueden estar interesados en tu producto.

Conclusión: Es mejor tener un solo visitante que compre tus productos, que 100 visitantes de los cuales solo uno compre tus productos.

Multiples instalaciones de MySQL en tu PC

Tuesday, April 19th, 2005

En algunos casos resulta muy práctico disponer de varias instalaciones de MySQL en tu ordenador. Disponer de varias versiones nos permite comprobar y asegurar la compatibilidad de nuestros programas.

Disponer de varias instalaciones de MySQL en un mismo ordenador puede resultar de gran utilidad. Por ejemplo, si estas desarrollando cierta aplicación que hace uso de MySQL y quieres estar seguro de que funciona correctamente con todas las versiones de MySQL, lo único que puedes hacer para asegurarte de ello es probar tu aplicación con todas y cada una de las versiones de MySQL.

Es obvio que podrías instalar y posteriormente desinstalar tantas versiones de MySQL como quieras comprobar. Pero esto no resulta elegante ni práctico, ya que tendrías que repetir el proceso de instalaciones y desinstalaciones cada vez que quisieras comprobar la compatibilidad de una aplicación. Por lo tanto, la única solución viable es que varias versiones de MySQL coexistan en el mismo ordenador.

Antes de exponer posibles soluciones al problema, debemos tener en cuenta los distintos métodos de configurar el servidor MySQL. La primera de ellas consiste en indicar las variables en la línea de comandos al iniciar el servidor MySQL, los demás métodos se basan en los distintos ficheros de configuración que el servidor MySQL busca cada vez que se inicia.

Para poder ejecutar varios demonios de MySQL simultáneamente cada instalación debe tener ciertos parámetros de configuración especificas. Estos parámetros los especificaremos en lo ficheros de configuración my.cnf situados en el directorio de datos (donde MySQL guarda las bases de datos) de cada instalación de MySQL. Este fichero es uno de los que MySQL busca cada vez que se inicia.

En sistemas Unix, dos demonios no pueden compartir el mismo "PID file" por lo que hay que especificar la variable "pid-file" con un valor distinto en cada instalación.

Supongamos que el directorio base de datos de la instalación A de MySQL es /var/lib/mysql_A (esto se debe definir a la hora de compilar o instalar MySQL), por lo tant0, el fichero /var/lib/mysql_A/my.cnf debería incluir lo siguiente:

[mysqld]
pid-file=/var/run/mysql_408.pid

En caso de la instalación B, el fichero my.cnf, situado en /var/lib/mysql_B/my.cnf, incluiría lo siguiente:

[mysqld]
pid-file=/var/run/mysqld_32354.pid

En sistemas Unix, si usamos sockets como método de conexión local con el servidor MySQL, también tendremos que especificar un socket distinto para cada demonio.

La configuración de la instalación A debería ser similar a lo siguiente:

[mysqld]
pid-file=/var/run/mysqld-A.pid
socket=/var/lib/mysql-A/mysql.sock

Mientras que en la instalación B tendríamos

[mysqld]
pid-file=/var/run/mysqld-B.pid
socket=/var/lib/mysql-B/mysql.sock

En el caso de que usemos TCP (y así permitir la conexión desde hosts remotos) los demonios que se ejecuten simultáneamente tampoco pueden usar el mismo puerto, por lo que debemos especificar un puerto diferente para cada instalación. Para la primera instalación podríamos utilizar el puerto estándar usado por MySQL, el 3306, y para el segundo el puerto 3307.

Añadimos la variable "port" en el fichero de configuración de la instalación A e indicamos el uso del puerto 3306:

[mysqld]
pid-file=/var/run/mysql-A.pid
port=3306

Mientras que en la instalación B usamos el puerto 3307:

[mysqld]
pid-file=/var/run/mysql-B.pid
port=3307

Resulta obvio que dos instalaciones diferentes tampoco pueden usar los mismos ficheros de log, por lo que en caso de que queramos usarlos, tendremos que especificar distintos valores para las siguientes variables:

  • log=path
  • log-bin=path
  • log-update=path
  • log-isam=path
  • bdb-logdir=path

En definitiva, el fichero de configuración de las instalación A podría ser algo así:

[mysqld]
pid-file=/var/run/mysqld-A.pid
socket=/var/lib/mysql-A/mysql.sock
log=/var/lib/mysql-A/log
log-bin=/var/lib/mysql-A/log-bin
log-update=/var/lib/mysql-A/log-update
log-isam=/var/lib/mysql-A/log-isam
bdb-logdir=/var/lib/mysql-A/bdb

Mientras que el de la instalación B sería:

[mysqld]
pid-file=/var/run/mysqld-B.pid
socket=/var/lib/mysql-B/mysql.sock
log=/var/lib/mysql-B/log
log-bin=/var/lib/mysql-B/log-bin
log-update=/var/lib/mysql-B/log-update
log-isam=/var/lib/mysql-B/log-isam
bdb-logdir=/var/lib/mysql-B/bdb

Recordar, que a parte de los ficheros de configuración específicos de cada instalación, ambos servidores buscaran el fichero de configuración principal cada vez que se inician. El fichero de configuración general suele estar situado en /etc/my.cnf es sistemas Unix y en c:/WINDOWS/php.ini sistemas Windows. En este fichero debes incluir los parámetros de configuración que desees que afecten a todas las instalación MySQL del ordenador.

Bueno, por el momento esto es todo y suerte!

Como conectarse a MySQL usando Free Pascal

Tuesday, April 19th, 2005

Free Pascal es un excelente compilador Pascal compatible con Turbo Pascal y el más reciente Borland Delphi que se distribuye gratuitamente bajo licencia GPL.

Pascal es un excelente lenguaje que gracias a multitud de colaboradores que desarrollan "unidades", resulta valido para realizar infinidad de tareas, incluyendo la administración de bases de datos MySQL.

La versión actual de Free Pascal es distribuido con una gran variedad de Unidades, entre ellas "mysql", la cual nos permitirá conectarnos y administrar MySQL desde nuestros propios programas.

Antes de empezar a programar necesitas tener instalados Free Pascal y MySQL en tu sistema. Si trabajas en un entorno Windows, la instalación automática de Free Pascal configurará todo correctamente, simplemente tendrás que recordar que debes colocar la librería dinámica libmysql.dll en el mismo directorio que tus programas compilados. libmysql.dll viene con la versión Windows de MySQL y debería estar en el directorio "c:/mysql/lib" o equivalente. Si trabajas con Linux o Unix, tendrás que especificar la localización de las librerías de MySQL en el archivo mysql.pp previamente a compilar Free Pascal.

Suponiendo que lo tengas todo listo para empezar a programar es recomendable que leas la sección que explica el funcionamiento de la API C en el manual de MySQL. Al fin y al cabo, la unidad "mysql" de Pascal ha sido portada de la librería de C, por lo que su funcionamiento y las funciones disponibles son prácticamente idénticas.

A continuación un ejemplo de un programa que se conecta a la base de datos, imprime información de la conexión, selecciona una base de datos que hemos llamado "db_prueba" y muestra el número de registros existentes en la tabla "tb_prueba":

PROGRAM test;
USES mysql;
CONST
DataBase : Pchar = 'db_prueba';
Query : Pchar = 'select count(*) from tb_prueba';

VAR
sock : PMYSQL;
qmysql : TMYSQL;
recbuf : PMYSQL_RES;
rowbuf : TMYSQL_ROW;

BEGIN
{ ####- CONECTAR CON MYSQL ####- }
Write('Conectando con MySQL...');
sock := mysql_connect(PMysql(@qmysql),nil,nil,nil);
if sock=Nil then
begin
Writeln(stderr,'No es posible conectar con MySQL.');
Writeln(stderr,mysql_error(@qmysql));
halt(1);
end;
writeln('HECHO');

{ ####- MOSTRAR DATOS DE LA CONEXIÓN ####- }
writeln('Datos de la conexión:');
{$ifdef linux}
writeln ('Mysql_port : ',mysql_port);
writeln ('Mysql_unix_port : ',mysql_unix_port);
{$endif}
writeln ('Host info : ',mysql_get_host_info(sock));
writeln ('Server info : ',mysql_stat(sock));
writeln ('Client info : ',mysql_get_client_info);

{ ####- SELECCIONAR BASE DE DATOS ####- }
writeln('Seleccionando base de datos ',DataBase,'...');

if mysql_select_db(sock,DataBase) &lt; 0 then
begin
writeln (stderr,'No es posible selecciona base de datos',Database);
writeln (stderr,mysql_error(sock));
halt (1);
end;

{ ####- EJECUTAR UN QUERY EN UNA TABLA ####- }
writeln('Ejecutando query: ',Query,'...');
if (mysql_query(sock,Query) &lt; 0) then
begin
writeln(stderr,'Ejecución del query erronea.');
writeln(stderr,mysql_error(sock));
halt(1);
end;

{ ####- MOSTRAR NÚMERO DE REGISTROS ####- }
recbuf := mysql_store_result(sock);
if RecBuf=Nil then
begin
Writeln ('El query no ha devuelto nada.');
mysql_close(sock);
halt (1);
end;
rowbuf := mysql_fetch_row(recbuf);
writeln('La tabla contiene ',rowbuf[0],' registros.');
END.

Ahora que ya sabes todo lo que necesitas para poder crear un programa cliente que sirva para administrar una base de datos MySQL, podrías crear el "trastero" o "back office" de tu web con Pascal. Esto te permitiría administrar tu web cómodamente desde el escritorio de tu web… Aunque en realidad no parece que este sistema resulte más cómodo que una interfaz web… ;)

Validación de formularios con JavaScript

Tuesday, April 19th, 2005

La validación de datos de un formulario mediante JavaScript o cualquier otro lenguaje del lado del cliente es la forma mí¡s cómoda de verificar los datos introducidos.

Aunque la comodidad no lo es todo, existen multitud de casos en el que el uso exclusivo de JavaScript para la validación de datos es insuficiente y la utilización de algun lenguaje como PHP, Perl o Java resulta imprescindible.

Por ejemplo, no puedes validar los datos de acceso a una zona segura de tu web mediante JavaScript ya que el login y el password deberán de estar escritos en alguna parte y el usuario no tardará en averiguarlo. Otro caso en el que el uso de lenguajes de servidor es imprescindible es cuando se debe verificar la validez de una dirección de correo o un URL.

Ademí¡s, no podemos olvidad, que como cualquier lenguaje del lado del cliente, el navegador del usuario debe soportar Javascript, si no lo hace la validación no se realizarí¡. Por lo tanto, si los datos a validar son importantes… olví­date de JavaScrit, usa un lenguaje del lado del servidor.

Una vez expuestos los inconvenientes de JavaScript… veamos el siguiente ejemplo:

<html>
<head>
<title>Mi Pagina</title>

<script language="javascript">
<!--
function validar() {
var msg = "";

if((document.form.nombre.value.length > 100) || (document.form.nombre.value.length&lt;5)) {
msg = "Nombre Incorrecto";
}

if((document.form.edad.value>99) || (document.form.edad.value&lt;3)) {
msg = "Edad Incorrecta";
}

if(msg != "") {
window.alert(msg);
return false;
} else {
return true;
}
}
-->
</script>

</head>
<body>
<form method="post" name="form" onsubmit="validar()">
<input type="text" name="nombre"/>
<br />
<input type="text" name="edad"/>
<br />
<input type="submit" value=" enviar "/>
</form>
</body>
</html>

Como puedes observar el código superior se trata de una simple pí¡gina HTML con un formulario y un script que sirve para validar los datos introducidos en el formulario.

En el tag que abre el formulario puede ver como este se llama "form" y al enviarlo llama a la funcion validar(), esta función se encuentra en la cabecera del documento (entre <head> y </head>) y es lo que se encarga de validar los datos introducidos por el usuario.

Modificar la forma y datos a validar, así­ como los errores que se mostrarí¡n es una tarea bastante sencilla. Por lo tanto no tengas miedo y a trastear!

Mostrar ventanitas pop-up con JavaScript

Tuesday, April 19th, 2005

Todos los hemos visto alguna vez, posiblemente incluso estés harto de ellos, pero aún así, seguro que habrás clickado en más de uno. Así son las ventanitas pop-ups, irritantes e interesantes al mismo tiempo.

Lo admito, odio todas esas ventanitas con las que nos bombardean en nuestra navegación diaria por la red. A veces incluso te encuentras en sitios web que en todas y cada una de sus páginas te abren dos o tres ventanitas. Resultan irritantes pero si todo el mundo las usa será por algo…

Efectivamente, las ventanitas pop-up se usan normalmente para publicitar algún producto o promocionar algún servicio de la web que de otra forma podría pasar inadvertido. Y se usan porque son efectivas, mucho más que los banners, botones o skycrappers a los que nos hemos acostumbrado y que a estas alturas, ni siquiera vemos. Los pop-ups al menos los vemos, otra cosa es que no les prestemos atención, pero los vemos.

Supongo que a estas alturas ya te habrás convencido de que lo que tu web necesita es una ventanita pop-up de esas… Pues no lo se, pero por lo menos te cuento como se hacen.

Lo primero que debes decidir es cuando abrir estas ventanitas, lo normal es abrirlo cuando el usuario acceda a una página concreta. Esto se logra mediante la directiva "onload" que se debe poner dentro del tag "<body>". Más o menos quedaría así:

<body onload="window.open('ventanita.html','Mi Ventanita','width=400,height=300,scrollbars=no,toolbars=no')"></body>

La función window.open() es la que se encarga de abrir la ventanita. Esta función recibe varios parámetros:

  1. La página a mostrar en la ventanita. Esta página la tendrás que hacer y no es más que una simple página HTML. En nuestro ejemplo, se llama "ventanita.html".
  2. El titulo de la ventanita, en nuestro ejemplo lo hemos llamado "Mi ventanita".
  3. Las propiedades de la ventanita, incluyendo su anchura (width=400), altura (height=300), si debe o no mostrar scrollbars (scrollbars=no), si debe o no mostrar los toolbars (toolbars=no), si es redimensionable (resizable=yes), etc.

Si usas el código superior tendrás una página que abre una ventanita cada vez que se visita. Esto puede resultar útil pero también excesivamente molesto, por lo que mi recomendación es que uses el siguiente código más complejo que hace que la ventanita solo se abra una vez por sesión, es decir, cada visitante vera la ventanita una sola vez.

&lt;html&gt;
&lt;head&gt;

&lt;script language="javascript"&gt;
//Pop-under window- By JavaScript Kit
//Credit notice must stay intact for use
//Visit http://javascriptkit.com for this script

// Especifica la página que quieres abrir
var popunder="ventanita.html"

// Especifica las características de la ventanita
// 1 -&gt; activado, 0 -&gt; desactivado
var win="width=800,height=510,scrollbars=1,resizable=1,toolbar=1,location=1,menubar=1,status=1"

// No editar nada más
function get_cookie(Name) {
var search = Name + "="
var returnvalue = "";
if (document.cookie.length &gt; 0) {
offset = document.cookie.indexOf(search)
if (offset != -1) {
offset += search.length
// set index of beginning of value
end = document.cookie.indexOf(";", offset);
// set index of end of cookie value
if (end == -1) {
end = document.cookie.length;
}
returnvalue=unescape(document.cookie.substring(offset, end))
}
}
return returnvalue;
}

function ventanita(){
if (get_cookie('pop')==''){
window.open(popunder,"Mi ventanita",win)
document.cookie="pop=si"
}
}
&lt;/script&gt;

&lt;/head&gt;
&lt;body onload="ventanita()"&gt;
Esta es una simple página.
&lt;/body&gt;
&lt;/html&gt;

También existe la posibilidad de limitar las veces que un mismo usuario verá la ventanita en cuestión. Esto se hace mediante cookies, de forma similar al último ejemplo, y podrías hacer que cada visitante viera la ventanita solo una vez al día, una vez por semana, etc.

Introducción a la programación CGI en Pascal

Tuesday, April 19th, 2005

Seguro que no son muchos los que usan Pascal para crear aplicaciones CGI, pero este lenguaje es tan válido como cualquier otro. Bueno, aunque la realidad es que no resulta demasiado cómodo.

Free Pascal ofrece una gran variedad de "Unidades" que permiten la realización de multitud de tareas, desde conectarse a bases de datos hasta programación CGI.

Es verdad que Pascal no es el lenguaje más apropiado para crear aplicaciones CGI, existen otros lenguajes como PHP o ASP mucho más adecuados para programación web. En realidad, usar Pascal para programación web tiene un gran número de inconvenientes pero en ciertas situaciones la utilización de un lenguaje compilado como Pascal puede resultar muy beneficiosa.

Free Pascal dispone de una Unidad llamada "uncgi" que facilita la programación CGI de forma considerable. Esta unidad, entre otras cosas, permite acceder a las variables enviadas mediante los métodos GET y POST. De todas formas, nuestro primer programa no usará "uncgi", simplemente te mostrará como mostrar texto o html.

PROGRAM test;
BEGIN
{ IMPRIMER LA CABECERA QUE INDICA EL TIPO DE DOCUMENTO }
writeln('Content-type: text/html');
writeln;

{ ## TEXTO O CÓDIGO HTML DE NUESTRA PRIMERA PÁGINA ## }
writeln('&lt;HTML&gt;');
writeln('&lt;HEAD&gt;');
writeln('&lt;TITLE&gt;Mi primer programa...&lt;/TITLE&gt;');
writeln('&lt;/HEAD&gt;');
writeln('&lt;BODY&gt;');
writeln('Mi primer programa');
writeln('&lt;/BODY&gt;');
writeln('&lt;/HTML&gt;');
END.

Lo más importante del código mostrado y donde debemos prestar mayor atención es la cabecera. Esta consiste en una línea que indica al servidor el tipo de documento que queremos mostrar y un salto de línea, o simplemente una línea vacía. La inclusión de la cabecera es imprescindible, ya que de lo contrario el servidor HTTP (Apache) no sabría como actuar. El programa de nuestro ejemplo muestra una página de texto o HTML normal, por ello hemos indicado que el tipo de contenido es "text/html".

writeln('Content-type: text/html');
writeln;

Si nuestro programa mostrara como resultado una imagen JPEG, deberíamos indicar que el documento es de tipo "image/jpeg". Por lo tanto, la cabecera debería ser similar a el siguiente código:

writeln('Content-type: image/jpeg');
writeln;

La segunda parte del documento no es más que el contenido del mismo, código HTML en este caso.

Ahora que ya sabemos como mostrar una página HTML usando un programa en Pascal, pasemos a ver el siguiente ejemplo que mediante el uso de la unidad "uncgi" muestra información acerca del navegador cliente y algunas variables que le pasamos mediante el método GET:

PROGRAM miprograma;
USES uncgi;
BEGIN
{ ##- IMPRIME CABECERA STANDAR PARA TEXT/HTML ##- }
cgi_init;

{ ##- CONTENIDO DEL DOCUMENTO ##- }
Writeln ('Agente = ', http_useragent);
Writeln ('Página = ', http_referer);
Writeln ('Nombre = ', get_value('nombre'));
Writeln ('Apellido = ', get_value('apellido'));
END.

Una vez compilado el código, es imprescindible que le apliques los permisos apropiados para poder así ejecutarlo. Es preciso que Apache pueda ejecutar el fichero, por lo que en la mayoría de los servidores, será suficiente con aplicarle el permiso 755 mediante el comando chmod, es decir:
chmod 755 &lt;fichero&gt;

Esto lo puedes hacer usando prácticamente cualquier cliente FTP, aunque también lo puedes hacer mediante telnet o SSH.

Ahora debes llamar al fichero desde tu navegador, para ello no tienes más que teclear la dirección donde se ubica y pasarle los parámetros "nombre" y "apellido" de la siguiente forma:
http://tudominio.com/miprograma?nombre=TUNOMBRE&amp;apellido=TUAPELLIDO

El programa mostrará la información sobre el "Agente" (el navegador…) que lo esta llamando, la página desde donde ha sido referido el agente, el valor de la variable "nombre" que le hemos pasado y el valor de la variable "apellido" que también se lo hemos pasado mediante el método GET.

Protegiendo directorios. Autentificación básica de Apache

Tuesday, April 19th, 2005

Este artículo describe como funciona la autentificación básica de Apache y como proteger recursos fácilmente usando esta caracterísitica del servidor. Este artículo es la versión revisada y corregida de aquel articulo que escribí hace ya más de uno año y que lo podéis leer aquí.

Antes de empezar indicar que este artículo es la versión revisada y corregida de aquel articulo que escribir hace ya más de uno año y que lo podéis leer aquí.

El servidor Apache permite el uso de los llamados “distributed configuration files”, osea “ficheros de configuración distribuidos”. Estos permiten personalizar el funcionamiento del servidor en un directorio concreto sin necesidad de modificar el fichero de configuración principal de Apache, el “httpd.conf”.

Por defecto, estos “ficheros de configuración distribuidos” deben llamarse “.htaccess”, pero si no te gusta ese nombre lo puedes cambiar facilmente según se explica en este mini artículo.

Cada vez que un cliente le hace una petición al servidor Apache, es decir, cada vez que tú con tu navegador accedes a una página web, Apache busca uno de esos ficheros .htaccess en el mismo directorio de la página que has pedido a Apache. Si encuentra uno de esos .htaccess lo lee y lo interpreta antes de mostrarte la página que le has pedido. De esta forma, si en el .htaccess se indica la necesidad de autentificar a los clientes, Apache lo hará. Y precisamente de esto trata el artículo, de la autentificación de usuarios mediante el módulo mod_auth_basic, el método de autentificación más básico y sencillo de implementar de Apache.

La implementación más básica

A continuación la implementación más básica del método de Autenficación Básica de Apache, donde se limita todo tipo de acceso (GET, POST y HEAD) a un determinado directorio:

AuthType Basic
AuthName "Directorio Protegido"
AuthUserFile /var/www/dir/.htpasswd
require valid-user

La sentencia “AuthType Basic” indica el método de autentificación que deseamos usar. En nuestro caso el método de autentificación básico.

AuthUserFile debe indicar la ubicación completa del fichero que contiene los datos de los usuarios (nombre de usuario y contraseña). No es válido indicar una ubicación relativa.

El fichero que contiene los datos de autentificación de los usuarios, aunque habitualmente se le llame “.htpasswd”, puedes usar cualquier nombre.

En Windows, las contraseñas del fichero “.htpasswd” pueden o no estar encriptadas, en todos los demás sistemas es necesario que estén encriptadas.

En sistemas Unix (Linux, BSD, etc.) este fichero lo debes crear (y actualizar) mediante la herramienta htpasswd de Apache. En sistemas Windows lo puedes hacer manualmente (sin encriptar las contraseñas) o usando htpasswd.

AuthName indica el nombre que deseas darle al recurso. Este nombre aparecerá en la ventanita de autentificación donde el usuario tiene que introducir su nombre de usuario y contraseña, por lo que es recomendable darle un nombre descriptivo.

Suponiendo que aún no dispones del fichero .htpasswd, que deseas crearlo en /var/www/dir y que quieres permitir el acceso al usuario “pepito”, debes ejecutar el siguiente comando en la línea de comandos:

$ htpasswd -c /var/www/dir/.htpasswd pepito

Para añadir un nuevo usuario a un fichero “.htpasswd” ya existente, ejecuta el siguiente comando:

$ htpasswd /var/www/dir/.htpasswd nuevo_usuario

Cada vez que ejecutes cualquiera de los comandos mencionados se te pedirá que introduzcas la contraseña del nuevo usuario.

La sentencia “Require valid-user” indica que se limitará todo acceso ya sea de tipo GET, POST o HEAD y que solo se permitirá el acceso a los usuarios que aparezcan en el fichero “.htpasswd”.

Limitando el acceso dependiendo del método HTTP utilizado

Si solo deseas limitar el acceso POST, de forma que cualquiera pueda ver los contenidos del directorio
/var/www/dir, pero solo los usuarios que aparezcan en “.htpasswd” puedan enviar peticiones de tipo POST usa la siguiente configuración:

AuthType Basic
AuthName “Directorio Protegido"
AuthUserFile /var/www/dir/.htpasswd
&lt;Limit POST&gt;
require valid-user
&lt;/Limit&gt;

Esto podría ser útil, si por ejemplo, el el directorio en cuestión tienes algún formulario para subir ficheros al servidor. Usando la configuración sugerida, solos los usuarios autentificados podrían hacerlo.

Autentificación de grupos

Supongamos que disponemos de algunos documentos ultra secretos que solo el grupo de administradores puede ver. Siempre podrías crear un nuevo directorio donde ubicar estos documentos y duplicar el procedimiento descrito anteriormente. Esto supondría la necesidad de mantener varios ficheros “.htpasswd”, lo cual resultaría bastante incomodo. Por esto existe una forma alternativa y mucho más sencilla.

Suponiendo que nuestro nuevo directorio ultra secreto es /var/www/dir/secreto, creamos un .htaccess con el siguiente contenido y lo ubicamos en el nuevo directorio:

AuthType Basic
AuthName “Directorio secreto"
AuthUserFile /var/www/dir/.htpasswd
AuthGroupFile /var/www/dir/secreto/.htgroup
require group administradores

Como puedes ver, en AuthUserFile se indica el mismo fichero .htpasswd, no es necesario crear uno adicional.

AuthGroupFile indica la ubicación completa del fichero que relaciona los grupos y los usuarios pertenecientes a cada grupo.

El fichero AuthGroupFile se edita manualmente, usando tu editor de texto preferido, y su formato es el siguiente:

nombre_del_grupo: usuario1 usuario2 usuario3

Es decir, que suponiendo un grupo “administradores” y que solos los usuarios “pepito” y “jaimito” pertenecen al mismo, nuestro fichero .htgroup tendría el siguiente aspecto:

administradores: pepito jaimito lola juanmi pedrito

La sentencia “require group administradores” permitiría el acceso únicamente a los usuarios que pertenezcan al grupo “administradores” y que se autentifiquen correctamente según los datos del fichero “.htpasswd”.

¿Un único administrador?

Continuando con lo anterior… y ¿si únicamente el usuario pepito fuera administrador? En vez de crear el fichero .htgroup indicando que pepito pertenece al grupo “administradores” e incluir la directiva AuthGroupFile en nuestro fichero “.htaccess”, crearíamos un .htacces con el siguiente contenido:

AuthType Basic
AuthName “Directorio Protegido"
AuthUserFile /var/www/dir/.htpasswd
require user pepito

De esta forma, solo “pepito” podría acceder a nuestro directorio ultra secreto.

Si en algún momento decidiésemos dar acceso al usuario “lola” a nuestro directorio ultra secreto, solo tendríamos que modificar el fichero .htaccess anterior de la siguiente forma:

AuthType Basic
AuthName “Directorio Protegido"
AuthUserFile /var/www/dir/.htpasswd
require user pepito lola

Y esto es todo por ahora…