Feb
20
2009
4

Adios para siempre Internet Explorer

Me entero vía Maestros del Web, que en Noruega se ha iniciado una “guerra” en contra del navegador Internet Explorer 6, pues al parecer los desarrolladores y maquetadores de sitios web se cansaron los dolores de cabeza que da hacer algo solo para Internet Explorer.

Adios para siempre Internet Explorer

Adios para siempre Internet Explorer

Si quieres formar parte de una campaña para que los usuarios que aun usan este arcaico navegador, se pasen a otros, puedes usar un código como este en los sitios que administres:

Código CSS:

#usuarios-ie {
	font-family: Verdana, Arial, sans-serif;
	background: #FFFFDE;
	color:#000;
	text-align: center;
	border-bottom: 2px solid #7F0C00;
	margin-bottom: 10px;
	position: fixed;
}
#usuarios-ie p {
	font-size: 1em;
	margin: 0;
	padding: 5px 0;
	line-height: 1.5em;
}
#usuarios-ie a {
	text-decoration: underline;
	font-weight: bold;
	color: #D64411;
}

Código HTML:

Usaremos un comentario incondicional para que solo lo vean los usuarios que lleguen con Internet Explorer:

<!--[if IE 6]>
<div id="usuarios-ie">
<p>Oops...! Usuario de Internet Explorer? Te recomiendo usar <a href="http://www.mozilla.com" title="Firefox web browser" target="_blank">Firefox</a>, sin dudas el mejor navegador del mundo xD</p>
</div>
<![endif]-->

Este pedazo de código lo pones justo debajo de la etiqueta <body> y si quieres que la barrita sea vista por todos los usuarios de IE, entonces cambias la apertura del comentario incondicional por <!--[if IE]>

Desde que inicié este Blog puse un link en la esquina inferior derecha que es visible siempre. Invitando a los usuarios a conocer otros browsers, con un eslogan bien sugerente: “Muy Cool para Internet Explorer“.

Otros Navegadores:

Personalmente recomiendo Firefox, pues es un navegador que brinda muchas opciones y facilidades, sobre todo a la hora de desarrollar aplicaciones para la web. Ademas de miles de add-ons que puedes usar para mejorar tu navegación e integración con muchos servicios en Internet.

Oct
13
2008
4

Editando archivos de texto de forma remota, usando PHP.

Pienso que puede ser útil tener bajo la manga alguna manera de editar archivos que tengamos en nuestro servidor, de forma remota. Por eso me di a la tarea de preparar este script, y aunque no me salio de primer momento, lo pude resolver gracias a los asiduos al foro 18 en Foros del Web y aquí se los muestro a ustedes hoy.

Introducción:

En nuestro único archivo (editor.php), tendremos un formulario dividido en dos partes.

La primera constará de un campo de texto donde introduciremos la dirección del fichero que queremos editar y un botón que nos servirá para abrir el fichero como tal.

La segunda estará conformada por un área de texto donde mostraremos el contenido del archivo a modificar, un par de botones del tipo submit: Editar y Guardar y otro reset, para restablecer los cambios en caso de algún fallo humano.

Como podrán notar, nuestro formulario tiene hasta tres botones del tipo submit, es por eso que necesitamos guardar una variable en una sesión y así asegurarnos que esté presente en cada parte del script.

Codigo PHP:

<?php
if(!isset($_SESSION)){
session_start();
}
// comprobamos si el formulario
// ha sido enviado correctamente
if(isset($_POST['abrir']) && $_POST['abrir'] == 'Abrir archivo'){
if (!empty($_POST['archivo'])){
$archivo = $_POST['archivo'];
// creamos la variable de sesion
$_SESSION['archivo'] = $archivo;
// comprobamos que existe el archivo
if (!file_exists($archivo) && !is_file($archivo)){
$msg = "El archivo no existe";
} else {
if($archivo){
// mediante file_get_contents
// mostramos el contenido del archivo en forma de cadena
$codigo = htmlentities(file_get_contents($archivo));
}
$msg = "La ruta del archivo es <b>$archivo</b>";
}
} else {
$msg = "Debe introducir la diraccion del archivo a editar";
}
}
// vamos a editar el archivo
if(isset($_POST['editar']) && $_POST['editar'] == 'Editar archivo'){
$archivo = $_SESSION['archivo'];
$archivo_editado = $_POST['archivo_editado'];
// comprobamos si podemos escribir en el
if(is_writable($archivo)){
if(!$gestor = fopen($archivo, 'w')){
$msg = "No se puede abrir el archivo <b>$archivo</b>";
exit;
}
// escribimos en el archivo
// el contenido de $archivo_editado
if(fwrite($gestor, html_entity_decode($archivo_editado)) === false){
$msg = "No se puede escribir en el archivo $archivo";
}
// Exito...!
$msg = "El archivo <b>$archivo</b> se edito con exito";
if($archivo){
// otra vez mostramos el contenido del archivo
$codigo = htmlentities(file_get_contents($archivo));
}
fclose($gestor);
}else{
$msg = "No se peude escribir en el archivo <b>$archivo</b>";
}
}
// guardamos el archivo
// y destruimos todas las variables
if(isset($_POST['guardar']) && $_POST['guardar'] == 'Guardar'){
unset($archivo);
unset($_SESSION['archivo']);
}
?>
<!-- el formulario -->
<form action="<?php $_SERVER['PHP_SELF']; ?>" method="POST">
<p>URL: <input type="text" name="archivo" value="" size="50" />
<input type="submit" name="abrir" value="Abrir archivo" /></p>
<?php echo "<p>".$msg."</p>"; ?>
<textarea name="archivo_editado" rows="25" cols="100">
<?php
// mostramos el codigo
// o el texto del archivo a editar
echo $codigo;
?>
</textarea>
<p>
<input type="submit" name="editar" value="Editar archivo" />
<input type="submit" name="guardar" value="Guardar" />
<input type="reset" value="Restablecer" />
</p>
</form>

Algunas anotaciones y fuentes:

En primer lugar, este pedazo de programa lo cree con la idea de editar archivos de extensión .php o .html, por eso el uso de las funciones de cadenas htmlentities() y html_entity_decode(), para convertir todas las entidades html a sus caracteres correspondientes y viceversa, pero igual se puede escribir en ficheros de texto .txt.

También decirles que crear este tipo de algoritmo no es tan complicado, pues con solo ver los ejemplos que vienen en el Manual de PHP podemos crear los nuestros propios. En este ejemplo me guié fundamentalmente en los de las funciones de sistema de archivos: fopen(), file_get_contents() y fwrite(), además de file_exists(), is_file(), is_writable() y fclose().

Nota: Éste método que les acabo de mostrar solo funciona en un servidor local (que es donde lo pude probar). Para documentarse correctamente sobre este tema lea las Funciones del Sistema de Archivos en el Manual de PHP.

Nota Importante: Por cuestiones de seguridad, nunca deje este archivo al alcance de los usuarios.

Conclusiones:

Pienso que se puede hacer mucho más con este sencillo ejemplo que les acabo de mostrar aquí, como verificar las extensiones de los ficheros que vamos a editar, o crear la opción de ver el archivo una vez editado. ¿Algo mas que se te ocurra?

Como siempre espero esto sea útil a alguien, pues lo creé con tres objetivos, uno entretenerme (en estos días tengo poco trabajo xD), segundo tenerlo para mi, pues en algún momento me hará falta algo así y tercero y no menos importante, compartirlo con ustedes. Entonces, opiniones, sugerencias y alguna critiquilla serán siempre bien recibidos.

Saludos y Suerte.

Written by rogertm in: Tutoriales | Tags: , , ,
Sep
17
2008
19

Como hacer un Buscador sencillo, usando PHP y MySQL

Esta es una de las cosas que más deseaba hacer cuando comencé a programar y realmente creía que era bien difícil, pero no, es extremadamente fácil y lo puedes hacer en solo minutos.

Introducción:

En nuestro ejemplo, tendremos una tabla en la Base de Datos del tipo MyISAM, ya que este motor soporta Funciones de búsqueda de texto completo (Full-Text). La tabla en si seria en donde guardaríamos las noticias de nuestro sitio web y la búsqueda la vamos a hacer en los campos Titulo y Cuerpo de la Noticia, por lo tanto nos centraremos en ellos solamente.

Además, como es lógico, nos auxiliaremos de un formulario HTML donde introduciremos las consultas enviadas a la Base de Datos. Lo validaremos, para en caso de que no se genere ningún resultado, mostrar un mensaje al usuario y también advertir en caso de que se haya enviado vacío.

Otra de las cosas que debo destacar, es que los resultados de las búsquedas se ordenarán de forma tal, que los primeros serán los que mayor cantidad de coincidencias tengan con la cadena pasada a la consulta.

Bueno, creo que ya es hora de entrar en materia y ver el código, que como bien dice WordPress: Code is Poetry

La Base de Datos:

Como ya dijimos, nuestra tabla cuenta con un par de campos, título y cuerpo de la noticia, mas el ID claro. Lo que haremos en si es crear un campo FULL-TEXT con los campos en los cuales nos interesa realizar las búsquedas:

CREATE TABLE `noticias` (
`noticia_ID` int(11) NOT NULL auto_increment,
`noticiaTitulo` varchar(200) NOT NULL,
`noticiaNoticia` text NOT NULL,
PRIMARY KEY  (`noticia_ID`),
FULLTEXT KEY `buscador` (`noticiaTitulo`,`noticiaNoticia`)
) ENGINE=MyISAM;

El formulario HTML:

Todo lo vamos a hacer en una misma página: buscar.php

<h1><a href="<?php echo $_SERVER['PHP_SELF']; ?>">Buscador - By RogerTM</a></h1>
<form name="buscar" action="<?php $_SERVER['PHP_SELF'] ?>" method="get">
 Buscar: <input type="text" size="50" value="<?php echo $_GET['frase']; ?>" name="frase" />
 <input type="submit" name="buscar" value="Buscar" />
</form>

Esto no creo que necesite explicación, solo que el value de la caja de texto es la frase enviada por $_GET[], osea, que se mostrará la frase que buscamos una vez hecha la consulta.

El código PHP:

<?php
// conectar al servidor
$server_link = mysql_connect("localhost", "root", "*****");
if(!$server_link){
die("Falló la Conexión ". mysql_error());
}
// seleccionamos la base de datos
$db_selected = mysql_select_db("database", $server_link);
if(!$db_selected){
 die("No se pudo seleccionar la Base de Datos ". mysql_error());
}
// varificamos que el formulario halla sido enviado
if(isset($_GET['buscar']) && $_GET['buscar'] == 'Buscar'){
$frase = addslashes($_GET['frase']);
// hacemos la consulta de busqueda
// ver explicación mas abajo
$sqlBuscar = mysql_query("SELECT noticiaTitulo, noticiaNoticia,
MATCH (noticiaTitulo, noticiaNoticia)
AGAINST ('$frase' IN BOOLEAN MODE) AS coincidencias
FROM noticias
WHERE MATCH (noticiaTitulo, noticiaNoticia)
AGAINST ('$frase' IN BOOLEAN MODE)
ORDER BY coincidencias DESC", $server_link)
or die(mysql_error()); 
$totalRows = mysql_num_rows($sqlBuscar);
// Enviamos un mensaje
// indicando la cantidad de resultados ($totalRows)
// para la frase busada ($frase)
if(!empty($totalRows)){
echo stripslashes("<p>Su b&uacute;squeda arroj&oacute; <strong>$totalRows</strong> resultados para <strong>$frase</strong></p>"); 
// mostramos los resultados
while($row = mysql_fetch_array($sqlBuscar)){
echo "<strong><a href='#'>$row[noticiaTitulo]</a>:</strong> <em>Coincidencias: ". round($row['coincidencias']) ."</em><br />";
echo "<p>".substr(strip_tags($row['noticiaNoticia']), 0, 255)."...</p>";
}
}// si se ha enviado vacio el formulario
// mostramos un mensaje del tipo Oops...!
elseif(empty($_GET['frase'])){
echo "Debe introducir una palabra o frase.";
}
// si no hay resultados
// otro mensaje del tipo Oops...!
elseif($totalRows == 0){
echo stripslashes("Su busqueda no arrojo resultados para <strong>$frase</strong>");
}
}
?>

NOTA: Obsérvese el uso de la función strip_tags, en este caso nos sirve para eliminar etiquetas HTML no deseadas y evitar se muestren imágenes u objetos embebidos en el código.

La consulta de búsqueda:

La función MATCH() realiza una búsqueda de lenguaje natural para cadenas contra una colección de textos. Una colección es un conjunto de una o más columnas incluídas en un índice FULLTEXT. La cadena de búsqueda se da como argumento para AGAINST(). Para cada registro en la tabla MATCH() retorna un valor de relevancia, esto es, una medida de similaridad entre la cadena de búsqueda y el texto en el registro en las columnas mencionadas en la lista MATCH().
[...]
Para búsquedas FULL-TEXT en lenguaje natural, se requiere que las columnas nombradas en la función MATCH() sean las mismas columnas incluídas en algún índice FULLTEXT en su tabla. Para la consulta precedente, tenga en cuenta que las columnas nombradas en la función MATCH() (noticiaTitulo y noticiaNoticia) son las mismas que las nombradas en la definición del índice FULLTEXT de la tabla noticias.
[...]
La consulta retorna los valores de relevancia y también ordena los registros en orden decrecente de relevancia. Para conseguir este resultado, debe especificar MATCH() dos veces: una vez en la lista SELECT y otra en la cláusula WHERE. Esto hace que no haya sobrecarga adicional, ya que el optimizador de MySQL se da cuenta que hay dos llamadas MATCH() son idénticas e invoca la búsqueda FULL-TEXT sólo una vez.

Tomado del Manual de MySQL.

Concluyendo:

Como ves ha sido fácil y rápido, solo espero como siempre, que mis ejemplos sirvan a quienes se inician en la programación usando PHP.

Cualquier comentario, duda o sugerencia, no dudes en hacérmelos saber. Yo también aprendo mucho de las opiniones de los lectores que pasan por aquí.

E insisto, no dejes de leer en el Manual de MySQL el capitulo referente a las Funciones de búsqueda de texto completo (Full-Text). Aquí tienes una explicación detallada sobre las búsquedas booleanas, las búsquedas con expansión de consulta, sus limitaciones, como afinarlas y las cosas que quedan aun por hacer en este tipo de consultas.

Nota: Edito el post, pues me faltaba ponerle las funciones addslashes() y stripslashes() en las cadenas de entrada y salida respectivamente.

Written by rogertm in: Tutoriales | Tags: , , , ,
Jul
03
2008
9

Como hacer un examen o test con PHP

Hola nuevamente, aquí estoy con otra de las mías… Esta vez vamos a hacer un test, como esos que sueles intentar pasar mientras pierdes el tiempo en Internet, en lugar de ponerte a estudiar ¬¬.

Bueno, en realidad estaba aburrido y como no tenia nada que hacer, pensé en ponerme a ver de que manera podía crear uno de estos, con el objetivo principal de aprender yo y para brindárselo a ustedes aquí, entonces al grano y basta ya de muela.

Introducción

Nuestro script constara de un formulario con varias preguntas (3 para este ejemplo) y tres posibles respuestas (puedes agregar las que quieras), de ellas solo una será la correcta y la nota o evaluación será en base a 5 puntos.

Algo que debo explicar entes de presentar el código, es que para dar la nota al examinado, lo haremos por la bien conocida cuenta para calcular promedio, la suma del valor de las respuestas divididas por la cantidad de preguntas. Les comento esto, pues me paso, que yo le ponía a las respuestas incorrectas el valor 0 (value=”0″), pues de lo contrario me daría una evaluación falsa, pero esto me dio el palo a la hora de validar el formulario para obligar el examinado a responder todas las preguntas, pues evaluaba el valor cero como vacío, entonces me lo resolví dándole valor 1 (value=”1″) y sustituyéndolo por cero con str_replace.

El código

<?php
// como siempre
// comprobamos si ha sido enviado el formulario
if(isset($_POST['evaluar']) && $_POST['evaluar'] == 'Evaluar') {
// y que no llegue vacío
if(!empty($_POST['respuesta_1']) && !empty($_POST['respuesta_2']) && !empty($_POST['respuesta_3'])){
// asignamos los valores a la variables que usaremos
// y sustituimos los 1 por 0, en caso de respuestas incorrectas
$respuesta_1 = str_replace(1, 0, $_POST['respuesta_1']);
$respuesta_2 = str_replace(1, 0, $_POST['respuesta_2']);
$respuesta_3 = str_replace(1, 0, $_POST['respuesta_3']);
// calculamos el promedio
// y redondeamos el resultado (round()) para evitar números decimales
$promedio = round(($respuesta_1 + $respuesta_2 + $respuesta_3) / 3);
// usamos la sentencia switch
// para darle la evaluación al examinado
switch ($promedio){
case 5:
$nota = "Usted tiene $promedio puntos, Excelente...!";
break;
case 4:
$nota = "Usted tiene $promedio puntos, Bien...!";
break;
case 3:
$nota = "Usted tiene $promedio puntos, Por los pelos...!";
break;
case 2:
$nota = "Usted tiene $promedio puntos, Suspenso, lo esperamos el próximo curso...!";
break;
case 1:
case 0:
$nota = "Definitivamente, este curso no es para usted...!";
break;
}
echo $nota;
}else{
// mensaje de error en caso que no se respondan todas las preguntas
echo "Debe responder todas las preguntas";
}
}
?>
<!-- el formulario -->
<form name="examen" action="<?php $_SERVER['PHP_SELF']; ?>" method="post">
<p>Pregunta 1</p>
<input type="radio" value="1" name="respuesta_1" /> mal<br />
<input type="radio" value="5" name="respuesta_1" /> bien<br />
<input type="radio" value="1" name="respuesta_1" /> mal<br />
<p>Pregunta 2</p>
<input type="radio" value="1" name="respuesta_2" /> mal<br />
<input type="radio" value="5" name="respuesta_2" /> bien<br />
<input type="radio" value="1" name="respuesta_2" /> mal<br />
<p>Pregunta 3</p>
<input type="radio" value="1" name="respuesta_3" /> mal<br />
<input type="radio" value="5" name="respuesta_3" /> bien<br />
<input type="radio" value="1" name="respuesta_3" /> mal<br />
<p><input type="submit" name="evaluar" value="Evaluar" /></p>
</form>

NOTA: Como mejor se ve el funcionamiento de este script, es poniendo 5 o mas preguntas en el formulario o dando respuestas regulares que tengan valor 3 (value=”3″), pues como se muestra aquí, la función round() nunca devolverá el promedio con valor 4.

Conclusiones

Para terminar, pues lo de siempre, la esperanza de que algún aburrido pase por aquí y esto le sirva de algo y en lugar de ponerse a llenar un test, que haga el suyo propio y lo cuelgue en su web para hacer que los demás pierdan el tiempo xDDD.

Y decirles, que la dudilla de que el cero se enviara como un valor vacío, la resolví como siempre en Foros del Web, en este post: Que el cero no sea un valor vacío.

Saludos y suerte

Written by rogertm in: Tutoriales | Tags: , , , ,
Jun
18
2008
16

Como crear relaciones y lograr Integridad Referencial en tablas InnoDB usando phpMyAdmin

Esta siempre fue una de mis dudas en mis inicios, hasta que un día encontré este interesante tutorial en MySQL Hispano, pero les juro que no entendí mucho hasta que un amigo me explico como hacerlo usando phpMyAdmin, y les aseguro que es realmente sencillo, por eso quiero transmitirles mi experiencia y mostrarles como se hace, pero de manera gráfica, para que sea de fácil entendimiento para todos. De todas formas recomiendo fuertemente el tutorial de que les hablo antes.

Una pequeña introducción:

Para este ejemplo usaremos la clásica Base de Datos Padres a Hijos, para así lograr al final una relación de uno (Padre) a varios (Hijos) y no complicarnos con un sistema complejo.

La Base de Datos:

Asumo al lector familiarizado con phpMyAdmin, así que tratare de ir los más directamente al asunto.

Nuestra Base de Datos, como ya vimos, la llamaremos padres_hijos y tendrá la siguiente estructura:

-- Base de datos: `padres_hijos`
-- Estructura de tabla para la tabla `padres`
CREATE TABLE `padres` (
`padre_ID` int(11) NOT NULL auto_increment,
`padreNombre` varchar(25) NOT NULL,
PRIMARY KEY  (`padre_ID`)
) ENGINE=InnoDB ;
-- Estructura de tabla para la tabla `hijos`
CREATE TABLE `hijos` (
`hijo_ID` int(11) NOT NULL auto_increment,
`hijoNombre` varchar(25) NOT NULL,
`hijoPadre_ID` int(11) NOT NULL,
PRIMARY KEY  (`hijo_ID`)
) ENGINE=InnoDB ;

Como ven, lo que hemos hecho es simplemente crear un par de tablas. La tabla padres tiene un par de campos, padre_ID y padreNombre. Por su parte, la tabla hijos, tiene tres campos, hijo_ID, hijoNombre e hijoPadre_ID, este último será quien nos sirva para hacer nuestra relación

NOTA: Fíjense que el campo hijoPadre_ID es tipo INT, de lo contrario, nos enviará un error al intentar crear llaves foráneas utilizando este campo.

Creando un campo INDICE:

Una vez logrado lo anterior, ya podemos crear la relación entre ambas tablas. Para ello vamos a la estructura de la tabla hijos y creamos un INDICE de una columna:

indice-paso-1

En el siguiente paso, escogemos el tipo de índice, que será INDEX y el campo que utilizaremos: hijoPadre_ID:

indice-paso-2
Damos clic sobre el botón Grabar:

indice-paso-3

Y ya tenemos nuestra tabla lista para pasar a la siguiente fase (perdón esto de la fase, pero son los aires de la EURO 2008 :P)

Logrando la Integridad Referencial:

Para lograr la Integridad Referencial, que es nuestro objetivo principal, debemos ir primeramente a la vista de relaciones, por su puesto, en la tabla hijos:

vista-de-relaciones-paso-1

Una vez aquí, escogemos el campo que vamos a relacionar y que previamente convertimos en un INDICE y recuerden que tiene que ser de tipo INT:

vista-de-relaciones-paso-2

Elegimos las opciones ON DELETE: CASCADE y ON UPDATE: CASCADE, esto asegurará que si borramos o actualizamos algún registro de la tabla padre, todos los registros de la tabla hijos que estén relacionados con este, también se borren o actualicen, según la acción. Una vez mas, hacemos clic en Grabar y todo estará listo:

vista-de-relaciones-paso-3

Conclusiones:

La estructura final de la Base de Datos será la siguiente:

-- Base de datos: `padres_hijos`
--
-- Estructura de tabla para la tabla `padres`
CREATE TABLE `padres` (
`padre_ID` int(11) NOT NULL auto_increment,
`padreNombre` varchar(25) NOT NULL,
PRIMARY KEY  (`padre_ID`)
) ENGINE=InnoDB ;
-- Estructura de tabla para la tabla `hijos`
CREATE TABLE `hijos` (
`hijo_ID` int(11) NOT NULL auto_increment,
`hijoNombre` varchar(25) NOT NULL,
`hijoPadre_ID` int(11) NOT NULL,
PRIMARY KEY  (`hijo_ID`),
KEY `hijoPadre_ID` (`hijoPadre_ID`)
) ENGINE=InnoDB ;
-- Filtros para la tabla `hijos`
--
ALTER TABLE `hijos`
ADD CONSTRAINT `hijos_ibfk_1`
FOREIGN KEY (`hijoPadre_ID`)
REFERENCES `padres` (`padre_ID`)
ON DELETE CASCADE ON UPDATE CASCADE;

Como se puede ver, la tabla hijos a cambiado su estructura, ahora, además de la llave primaria (PRIMARY KEY) hijo_ID, tenemos una llave externa o foránea (KEY) hijoPadre_ID.

Ahora, lo más interesante de todo es la última consulta ALTER TABLE, que intentare explicar, desde mis modestos conocimientos:

ALTER TABLE `hijos`: Hacemos un cambio a la tabla hijos.
ADD CONSTRAINT `hijos_ibfk_1`: Añadimos una restricción, aquí con solo poner hijos es suficiente, pero al exportar la estructura con phpMyAdmin, automáticamente pone hijos_ibfk_1 :/
FOREIGN KEY (`hijoPadre_ID`): La llave externa será el campo hijoPadre_ID.
REFERENCES `padres` (`padre_ID`): Que hace referencia al campo padre_ID de la tabla padres.
ON DELETE CASCADE ON UPDATE CASCADE: Cuando se borre o actualice algún registro de la tabla padre, se afectaran los registros relacionados de la tabla hijos

Una vez más espero haber sido útil y recuerden que los comentarios siempre serán bien recibidos.

Para profundizar en el tema, les recomiendo las siguientes lecturas:

Saludos y Suerte.

Written by rogertm in: Tutoriales | Tags: , , ,
Página 1 de 3123»

Kilómetro Cero - RogerTM @ Bloggers Cuba
Powered by WordPress. Theme: TheBuckmaker. Insolvenz Konkurs, Autor werden
Modificado por: RogerTM para Kilómetro Cero

Kilómetro Cero es un Blog muy Cool para Internet Explorer