Recuperar el Password MySQL en Linux

El mismo día que comentaba como recuperar el password Root de MySQL en windows, Dragon de DragonJar nos contaba como hacerlo desde linux.

Hoy entonces paso a explicar este proceso.


Primero detenemos el servicio

$ /etc/init.d/mysql stop

una ves que el servicio está apagado reiniciamos el servidor en modo seguro:

$ mysqld_safe --skip-grant-tables --skip-networking

acto seguido abrimos otra consola y entramos como root al servidor:

$ mysql -u root -p mysql

Ahora ya deberiamos tener el acceso a mysql, el siguiente paso es cambiar la contraseña:

$ mysql> UPDATE user SET Password=PASSWORD('unapassowrdnueva') WHERE User='root';
mysql> flush privileges;

El último paso es terminar el proceso mysql-safe y reiniciar el servidor SQL:

$ pkill mysql -safe
$ /etc/init.d/mysql start


Fuente original DragonJar: Como recuperar clave mysql

10 Recomendaciones para programar en PHP

Hoy tocaba dedicarse un rato a arreglar aquellos posts de foro.el-hacker.com que sufrieron una descodificación al pasar la base de datos de SMF a vB...

Bueno este es una versión de un artículo de hace siglos olvidado entre el polvo.

Recomendaciones para programar en PHP

1- Saber programar, que es diferente a conocer el lenguaje...
Aprende metodologías de programación, algoritmos, etc.

2- Dominar el HTML, usar DreamWeaver no cuenta, PHP es un lenguaje orientado a generar HTML así que es lógica la necesidad de conocer el lenguaje

3- Crea tu código pero no olvides el de los demás.
No siempre es necesario idear un código completamente de 0, aprende a compenetrar tus necesidades con la documentación de la red y así ahorrarte horas de trabajo innecesarias.

4- Aprende SQL, un sitio PHP suele ser dinámico por lógica y la solución más usada para guardar datos a día de hoy son bases de datos SQL, aprende como funcionan y cómo administrarlas.

5- Separa el código del diseño, para ello usa CSS o programas como Smarty.

6- Usa un buen editor de código como Zend (de pago) o Eclipse (Open Source).

7- Reutiliza tu código, allí donde puedas meter una función y reaprovechar ese código hazlo.

8- Ten algún conocido que te ofrezca ayuda en momentos puntuales.

9- Siempre ten en consideración a quien va destinado el sitio web, dales facilidad (la facilidad del programador no es la misma que del usuario final), crea un código rápido y optimízalo.

10- La cloud computing no se compone solo de PHP, tenemos AJAX, Java, ASP, Python, entre otros. Si PHP no es el lenguaje que necesitas usa el más idóneo.

Cuando el administrador se duerme

A lo largo de mi "carrera", que no es larga precisamente he tenido la oportunidad de comprobar la verdad absoluta de un administrador web, "si te duermes te joden".

Cuando un admin dice "no tengo ganas de actualizar el soft", "una contraseña robusta es dificil de recordar" y todas esas frases que a los amantes de la seguridad nos da pánico escuchar es cuando se producen los mayores errores en la securisación del servidor.


Hoy vamos a hablar de un caso en especial, resulta que anoche estaba aburrido y me dirijí a la comunidad DragonJAR donde leí un paper de Shell Root sobre controlar un servidor via XAMPP, entusiasmado con la idea y con ganas de probar lo aprendido ideé una dork en google que, impresionantemente, el tercer resultado de esta tenia los valores por defecto de XAMPP es decir:

user: root
no password

Cuando lo vi me dió verguenza ajena....

Lo mas "divertido" de la página es lo que reza en su index:

The main objective of the MOMENT project is to design and implement a mediator architecture to offer a unified interface to all data bases and measurement facilities for IP traffic monitoring and service supervision. Thus its users will be able to submit advanced queries based on semantic access, with possible combinations of different data sources, with privacy protection mechanisms.

Y bien... para finalizar dejo un par de capturas del desastre

xammp owned

Se aprecia claramente que el usuario es root


Y el desastre de desastres... una shell subida...

Espero que a partir de ahora configuren con un mínimo de seguridad sus servidores!!

La mejor forma de administrar las fechas entre PHP y MYSQL

Luego de mucho tiempo trabajando con la función date(), creando campos INT en MySQL y luego usando una función para calcular a partir de ese INT la fecha que almacena (al mas puro estilo SMF) creo haber dado con la fórmula perfecta, al menos para mi, de trabajar con este dato.

El proceso va orientado a una web con sistema de noticias, comentarios, peticiones y demás por lo que es importante tener un registro de fechas y horas.

Empezamos montando la tabla de ejemplo

mysql> DESCRIBE horas;
+-------+-----------+------+-----+-------------------+--------------------------+
| FIELD | Type      | NULL | KEY | DEFAULT           | Extra
   |
+-------+-----------+------+-----+-------------------+--------------------------+
| hora  | timestamp | NO   |     | CURRENT_TIMESTAMP | ON UPDATE CURRENT_TIMESTA
MP |
+-------+-----------+------+-----+-------------------+--------------------------+
 
mysql> SELECT * FROM horas;
+---------------------+
| hora                |
+---------------------+
| 2010-01-28 15:38:26 |
| 2010-01-28 15:38:49 |
| 2010-01-28 15:38:54 |
+---------------------+
3 rows IN SET (0.00 sec)
 
Se puede apreciar claramente que estamos utilizando el tipo timestamp y como valor por defecto CURRENT_TIMESTAMP.
Podemos apreciar que estas funciones guardan los datos en formato EEUU (2010-01-28 15:38:54), cosa que no nos interesa y por la cual normalmente buscariamos otro método, pero aquí viene lo interesante.

La función DATE_FORMAT

Con esta función nos podemos permitir el lujo de formatear las fechas a nuestro anotjo a la hora de hacer las consultas.

Un ejemplo:

mysql> SELECT DATE_FORMAT(hora, '%H:%i:%s %e/%m/%y') AS hora FROM horas;
+-------------------+
| hora              |
+-------------------+
| 15:38:26 28/01/10 |
| 15:38:49 28/01/10 |
| 15:38:54 28/01/10 |
+-------------------+

Como se aprecia en el ejemplo tenemos una hora y fechas perfectamente formatadas.

Tratando las fechas en PHP

Ahora ya solo importa como vayamos a utilizar esta información, para el ejemplo yo voy a comprobar que se haya escrito hace menos de una hora, hoy o ayer, en caso de no ser ninguno de estos casos muestro la fecha mas no la hora.

He agregado un valor y modificado dos para que se produzca cada caso, así que ahora tenemos:


mysql> SELECT DATE_FORMAT(hora, '%H:%i:%s %e/%m/%y') AS hora FROM horas;
+-------------------+
| hora              |
+-------------------+
| 15:38:26 28/01/10 |
| 13:38:49 28/01/10 |
| 22:38:54 27/01/10 |
| 22:38:54 25/01/10 |
+-------------------+
4 rows IN SET (0.01 sec)
 
El código encargado de tratar con las fechas es:

<?php

$con 
mysql_connect('localhost','root','') or die(mysql_error());
mysql_select_db('z_test',$con) or die(mysql_error());

$query mysql_query("SELECT DATE_FORMAT(hora, '%H:%i:%s %e/%m/%y') 

                     AS hora FROM horas;",$con);

while ($list mysql_fetch_array($query)) {
   
$all explode(' '$list['hora']);
   
$data explode('/'$all[1]);
   
$time explode(':'$all[0]);

   echo 
'<br />Publicado: ';
   
   if (
date('H') - $time[0] <= && date('d') == $data[0])
      echo 
'Hace una hora';
   else if (
date('d') == $data[0])
      echo 
'Hoy';
   else if (
date('d') - $data[0] == 1)
      echo 
'Ayer';
   else
      echo 
$all[1];
}

?> 



Y para finalizar la salida de la página:

Publicado: Hace una hora
Publicado: Hoy
Publicado: Ayer
Publicado: 25/01/10

Espero que os sirva para un futuro.

Como convertir un Array en un Objeto de PHP?

La pregunta es clara, quizá en algún momento nos interese o nos sea mas comprensible trabajar con un Array como un Objeto y no como Array.

El código es:

<?php

$hoy 
= array('comida' => 'arros''postre' => 'pastel');

$hoyObjeto = (object)$hoy;

echo 
$hoyObjeto->comida// Salida: arros
echo $hoyObjeto->postre// Salida: pastel


?>


Como se puede apreciar no tiene dificultad ninguna.

Pero como queremos ir siempre mas allá probamos un array numérico:

<?php

$hoy 
= array('comida' => 'arros''postre' => 'pastel'=> 'nada');

$hoyObjeto = (object)$hoy;

echo 
$hoyObjeto->comida// Salida: arros
echo $hoyObjeto->postre// Salida: pastel

/*
echo $hoyObjeto->0;

Esta linea produce el siguiente error:

Parse error: syntax error, unexpected T_LNUMBER, 
expecting T_STRING or T_VARIABLE or '{' or '$' ....
*/

var_dump($hoyObjeto); 
/*
Salida: object(stdClass)#1 (3) { 
   ["comida"]=>  string(5) "arros" 
   ["postre"]=>  string(6) "pastel" 
   [0]=>  string(4) "nada" } 

*/

?>


Como se aprecia en el código hacer un echo del objeto con un índice numérico es imposible, eso lo sabemos gracias al error:

Parse error: syntax error, unexpected T_LNUMBER, expecting T_STRING or T_VARIABLE or '{' or '$' ....

Basandome en ese error he intentado encapsularlo entre {}, meter el numero en una variable, y algunas cosillas mas. El resultado es que no produce un error, pero la variable tampoco se muestra.

Gracias al var_dump() vemos en todo momento que dentro del objeto existe el dato, pero no hay forma de moestrarlo, por lo que podemos decir que las Arrays no pueden tener índices numéricos al pasarlas a objetos, al menos no si queremos mantener los datos.

Otra forma de calcular el resto en PHP

Simplemente a modo de curiosidad dejo esta entrada.

Siento que no sea algo mas elaborado pero he estado y estaré el resto del día ocupado.

La función lo que hace es calcular el resto, para ello contamos con un operador en PHP pero me pareció cuanto menos divertido descubrir, por casualidad, que este era el algoritmo que usa dicho operador (%) para calcular restos

La función en cuestión es:

<?php

function resto($numero1$numero2) {
   
      
$res $numero1   $numero2;
      
$res explode('.',$res);
      
      
$res $numero1 - ($res[0] * $numero2);
      return 
$res;
   }

echo 
resto(11,2);

?>


Recibe dos parámetros (dividendo y divisor) y devuelve el resto.

Entonces así queda la curiosidad.

Aprendamos sobre Expresiones regulares

Hoy toca un poco de expresiones regulares.

Primero deberíamos saber que funciones utilizan dichas expresiones.

Todas las que empiezan por 'preg' como son:

preg_filter
preg_grep
preg_last_error
preg_match_all
preg_match
preg_quote
preg_replace_callback
preg_replace
preg_split

Estas son todas las funciones y podéis encontrar su explicación
En el paper de PCRE de php.net http://es2.php.net/manual/en/book.pcre.php

Cómo funcionan las expresiones regulares?

Bien, básicamente lo que hacemos es dar un Pattern (o patrón) y a partir
de este buscamos coincidencias.

Cabe destacar que cuando damos el patrón 'am' lo que buscamos es cualquier palabra
que contenga 'am' y no la palabra 'am' en sí.
Siendo validos: am, amanecer, mama, entre otros...


Caracteres de las expresiones regulares:

Tenemos varios caracteres con funciones especiales

\ - Carácter de escape. Escapa un carácter especial.
^ - Inicio de cadena. Indica que el patrón especificado a continuación va al inicio
siguiendo el ejemplo anterior '^am' siendo válidos solo: am y amanecer
$ - Fin de cadena. Exactamente lo mismo que el anterior pero al final
. - Representa cualquier carácter, pero solo uno. Con el patrón c.d
podemos pensar como válidos: cad, cod,cud,clda, code pero no caac o ccld por ejemplo
[ - Inicio de definición de clase de caracteres
] - Fin de la definición anterior
| - Operador lógico OR. si tenemos: v|a podemos dar como válidos v o a por ejemplo
* - Cuantificador de cero o más. Con el ejemplo: "a*" podemos pensar en 'a' o 'aa' o 'abb'
+ - Cuantificador de uno o más. Igual que el anterior pero no será válido 'a'
{ - Inicio de valores mínimo máximo
} - Fin de valores mínimo máximo
? - Puede servir de cuantificador, modificador de codicia y para definir clases especiales.


Ahora vamos a tratar de hablar de ellos un poco más a fondo.

Carácter de escape

Si tenemos uno de los caracteres mencionados anterior, por ejemplo ^, pero no queremos
que este ejerza su función sino que sea un carácter más usaremos el carácter de escape.

Ejemplo:

Patrón: "\^Hola!"
Válido: ^Hola!!, C^Hola!, etc
No válido: "Hola!", "^Hol!"

Según e leído (y aún no he comprobado) si PHP encuentra un carácter de escape y su siguiente
no es un carácter de la lista toma el carácter de escape como carácter normal

Por lo que: "\(" y "\\(" Representan lo mismo: "\("

Hay algunos caracteres que no están en la lista anterior y son caracteres de escape:

\n - Salto de línia
\r - Retorno de carro
\t - tabulación
\xhh - Hexadecimal, hh son números en hexadecimal
\ddd - Octal.

También disponemos de otros caracteres de escape dentro de las expresiones regulares:

\d - Cualquier digito decimal, 0-9 y los superíndices
\D - Digitos no decimales (todos los que no son los anteriores)
\s - Caracteres espaciadores: ' ', '\n', '\t', '\r'
\S - Caracteres no espaciadores
\w - Carácter alfanumérico o '_'
\W - Caracteres no alfanuméricos ni '_'
\a - Carácter de inicio de cadena. Equivale a ^
\A - Inicio de línea. Todo carácter que inicia una línea
\z - Carácter de fin de cadena. Equivale a $
\Z - Todo carácter que finaliza una línea

Las clases de caracteres

Para refrescar un poco las clases de caracteres son las que están entre [ y ]

Dentro de estas clases no funcionan todo lo expuesto anteriormente. Estos si funcionan:

\ - Carácter de escape
- - Definir rango de caracteres. Ejemplo: [a-z] define de la a la z
^ - Es un carácter de expulsión, con esto quitamos aquellos que no queremos en la clase
Ejemplo: [a-z^dbg], son todos los caracteres de la a a la z menos dbg.

Nota: Recordamos que esto se rige por los códigos ASCII por lo que no es lo mismo a que A

Para estos tres es necesario escaparlos para usarlos, pero no los de la lista del principio
Por lo que $ o + son perfectamente funcionales sin escaparlos.

La segunda lista proporcionada en "caracteres de escape" es reutilizable en esta
sección, por lo que podemos hacer cosas como: "[\w^_]+"

Subpatrones

Los subpatrones se delimitan con paréntesis y pueden estar concatenados.

Encontramos dos utilidades principales:

- Agrupaciones para usar el OR:

Ejemplo:
Pattern: "per(sona|ro)"
Coincide: tanto con persona como con perro

- Capturar fragmentos que luego utilizaremos

Esta me he planteado no presentarla por lo complicado que puede ser entenderla al
principio, así que si os la queréis saltar no hay problema.

Supongamos que queremos encontrar todo lo que esté encerrado entre ":

Patrón: "\"+\"" (PHP necesita que escapemos las comillas.

Ahora supongamos que también queremos que detecte las comillas simples:

Patrón: "(\"|\')+(\"|\')"
Pero esta expresión no es del todo correcta, puede darse el caso de capturar: " "hola' "

Lo cual no tiene sentido. Entonces podríamos pensar:

Patrón "\"+\"|\'+\'"
Pero imaginemos que también capturamos caracteres entre #, /*, etc...

Entonces lo mejor es:
Patrón "(\"|\'|\#|...)+\1"

Los ... referencian a los demás subpatrones que podríamos agregar.
Destaco el \1 es una "referencia anterior" y hace referencia al primer subpatrón,
el \2 haría referencia al segundo, etc..

De forma vulgar sería como hacer: "(\"|\'|\#|...)+(\"|\'|\#|...)"

solo que no se producen casos como " "Hola' ". Es decir, una maravilla.

Cuantificación

Funciona de la siguiente manera:

"X{min,max}" X representa un carácter, una clase de caracteres o subpatron y min y max
representan el número de veces mínimo y máximo que aparece X.

Ejemplo:
Patrón: "\w{2,4}"
Este patrón nos indicaría palabras de dos a cuatro letras.

Si se omite 'max', se entiende que X se repite 'min' o más veces

Ejemplo:
Patrón: "\w{2,}"
Dos letras o más, NO ONITIR LA COMA!

Si omitimos la coma significa que se repite ese número exacto.

Ejemplo:
Patrón: "\w{10}"
Palabras de 10 letras exactas.

Tenemos a nuestra disposición otros cuantificadores, pero se pueden crear con el método
normal, de todas formas los menciono:

X* equivale a X{0,}
X+ equivale a X{1,}
X? equivale a X{0,1}

Codicia

Usando el ejemplo de los subpatrones "(\"|\')+\1" podremos explicar que significa exactamente
la codicia.

Las expresiones regulares son codiciosas, es decir intentarán coincidir el mayor número posible.

Ejemplo:
Patrón: "(\"|\')+\1"
Cadena: "a href='index.php' target='_self'>"
Coincidirá: "'index.php' target='_self'"

Como podéis notar toma desde la primera comilla simple hasta la última, para evitar
este suceso se puede evitar enredando un poco más la expresión:

Ejemplo:
Patrón "(\"|\')[^\1]+\1"

Con este ejemplo lo que le decimos es que el carácter capturado en el subpatron no puede
estar dentro de la cadena resultado

Por lo que la coincidencia será: 'index.php'


Con esto acabamos una clase básica de expresiones regulares.

Hay algunas cosillas más pero esto es lo más frecuente
No es nada difícil, sino que hay que echarle ganas y repasar dos o tres veces los ejemplos
y crear unos propios.

Basado en la información de:
php-hispano.net
php.net

Curso PHP 5 VI || Aprendamos sobre Formularios

Actividades V

Crea un programa en PHP a forma de calculadora utilizando el mínimo de funciones posible.


<?php 

function calcula($num$oper$num2) { 
    switch (
$oper) { 
     
        case 
'+'
            
$res $num $num2
        break;; 
        case 
'-'
            
$res $num $num2
        break;; 
        case 
'*'
            
$res $num $num2
        break;; 
        case 
'/'
            
$res $num $num2
        break;; 
        case 
'%'
            
$res $num $num2
    } 
    return 
$res


echo 
calcula(2,'+',2); # Resultado: 4 
?> 



Crea un programa en PHP en el que tengas que exponer todo lo aprendido en este apartado
Este ejercicio era bastante libre, y podíais aplicar todo lo aprendido o solo lo de la última clase. Aquí las soluciones son infinitas.


<?php 

$message 
"Este es mi mensaje! saludos, nax"

$fake givetome($message"nax""thief"); 
echo 
$fake

function 
givetome($original$autor$ladron) { 
    
$original explode(' '$original); 
    if (
in_array($autor,$original)) 
        
$original[array_search($autor,$original)] = $ladron;     
    return 
implode(' ',$original); 

?> 


Este ejemplo toma un mensaje original y cambia el autor por el que le indicamos, un ejemplo como cualquier otro que me hayas enviado.

VIII. Introducción a los formularios


Ya hemos dado todos los puntos que me había propuesto para este tutorial/curso, por lo tanto voy a dar una clase práctica de integración con formularios y ya doy por cerrado este curso.

Por supuesto seguiré trayendo cosas tanto en Bl4ck-P0rt4l y CUH como en mi blog. Así que si seguís interesados en el mundo de PHP y sus áreas derivadas no os alejéis mucho.

Empecemos por el principio:

Un formulario web es, a día de hoy, un elemento imprescindible para una página web dinámica, gracias a ellos podemos loguear y registrar usuarios, enviar mensajes, publicar encuestas, comentarios, etc.
Por lo tanto conocer su funcionamiento y proporcionar facilidades a los usuarios es una tarea importante en el desarrollo web.
Hay mucha gente, quizá por comodidad o facilidad, que crea un .html para los formularios y un .php para el código, yo tengo por costumbre hacerlo todo en vista de código y por lo tanto siempre lo hago todo en un .php así que vamos a aprender a hacerlo de esa forma.

Un simple formulario:

Vamos a ver un ejemplo simple.


<?php 

if (isset($_POST['nombre'])) { 
    echo 
"Bienvenido "$_POST['nombre']; 
} else { 
    echo 
'<form action="'.$_SERVER['PHP_SELF'].'" method="post"> 
          Bienvenido desconocido por favor dinos tu nombre: 
          <input name="nombre" type="text" /> 
            <input type="submit" name="Submit" id="button" value="Enviar" /> 
          </form>'


?> 


Este es un ejemplo muy claro, una página que se envía un form a sí mismo.
El if() comprueba que se haya enviado la variable, en caso de ser así es porque se nos ha enviado un nombre para mostrar, sino, mostramos el formulario pidiéndole que nos dé su nombre.

En este ejemplo ya podemos destacar dos cosas, la variable $_SERVER y la variable $_POST, como ya comenté anteriormente la variable $_SERVER es una variable propia del sistema PHP lo mismo pasa con $_POST ambas tienen su función y existen más variables de servidor que explicaremos a continuación.

Variables de Servidor útiles:

La variable $_SERVER contiene un montón de elementos más, pero nos vamos a centrar en aquellos que nos puedan ser de mayor utilidad.

Elemento Ejemplo Descripción
PHP_SELF /pagina.php Nos devuelve la ruta de la página en que se ejecuta
QUERY_STRING id=3&post=4 Es la parte que vemos en la url (store.php?id=3)
PATH_INFO pagina.php?/browse Es parecido a lo anterior pero con directorios
SERVER_NAME http://www.bl4ck-p0rtal.org Nombre del servidor que ejecuta el intérprete
DOCUMENT_ROOT /usr/local/htdocs Ruta local de la carpeta html
REMOTE_ADDR 175.56.23.2 IP del usuario/cliente
REMOTE_HOST pool.cvx.dialup.. Nombre del host del usuario/cliente
HTTP_REFERER foro.el-hacker.com Si se hizo clic para llegar al link esta variable lo contiene
HTTP_USER_AGENT Mozilla/4.0… Información del navegador y sistema operativo.

Os invito a probar el resto estas son, quizá, las más utilizadas.

Procesando y accediendo a los parámetros de los documentos:

Los formularios funcionan con dos métodos POST y GET.
La principal diferencia entre ambos (y las que nos interesa ahora) es que POST se envía en segundo plano y GET se puede ver fácilmente en la barra de direcciones (esto no implica que los POST no se puedan ver, solo que es más ‘dificil’).

Entonces te preguntarás ¿y porqué existe GET si POST es claramente mejor? Bueno, mi profesor de PHP me enseñó en su momento que en PHP si hay 2 formas de hacer las cosas siempre prevalece la mejor y la otra se elimina de el intérprete, pero en el caso de que ambas formas sean útiles en determinados momentos se mantienen ambas. Es decir, un POST es útil con un formulario que, por ejemplo envía una contraseña para que no se vea en la URL, pero sin embargo no podemos enviar datos a otra página (o a la misma) sin usar un formulario y en ese momento es GET el que entra en acción.

Un claro ejemplo de variables GET son los foros SMF todo lo que va detrás de .php? se está enviando vía GET.

Entonces, como conclusión usaremos POST para los formularios y GET para las url. En php accedemos a los métodos con $_POST y $_GET. En los formularios el parámetro name es el que marca el nombre que tendrá en el $_POST o $_GET.

Los elementos de múltiples valores serán enviados como un array:

<?php 

if (isset($_POST['nombre'])) { 
    echo 
"Bienvenido "$_POST['nombre'] . 
    
'<br />Hoy quieres comer: ' $_POST['food'][0] .  

    ' y ' $_POST['food'][1]; 
} else { 
    echo 
'<form action="'.$_SERVER['PHP_SELF'].'" method="post"> 
          Bienvenido desconocido por favor dinos tu nombre: 
          <input name="nombre" type="text" /> <br /> 
            
         <select name="food[]" multiple> 
             <option value="Fideos"> Fideos </option> 
            <option value="carne"> Carne </option> 
            <option value="pescado"> Pescado </option> 
         </select> 
          
         <br /><input type="submit" name="Submit" id="button" 

         value="Enviar" /> 
         </form>'


?> 



Como veis en el form agregamos una lista en la cual al nombre ya le indicamos que será un array con los signos [] y le damos el parámetro múltiple.

En el ejemplo estamos dando por supuesto que se recibirán 2 parámetros, para asegurarnos de ello deberíamos crear una función en JS para asesorarnos que es así.

Comprobar direcciones de correo:

Como este último capitulo pretende ser un repaso muy por encima de los formularios no voy a hablar de validación de datos, pero si os voy a dejar la forma de validar, en parte, un correo electrónico.

Luego, cuando estéis más acostumbrados a PHP se puede verificar que estos correos existan de verdad haciendo consultas whois y cosas por el estilo. Pero con este ejemplo nos aseguraremos de que al menos la sintaxis del correo sea correcta

<?php 

if (! preg_match('/^[^@s]+@([-a-z0-9]+.)+[a-z]{2,}$/i'$_POST['email'])) { 
    
$errores[] = 'Introduce un email valido'
?> 


Valores por defecto:

Al principio hablábamos de dar comodidad al usuario. Una de las formas de hacerlo es recordando los datos que se ingresaron y en caso de haber algún error rellenar los datos que el usuario tiene bien y otra forma es crear valores por defecto a modo de ejemplo.

<?php 

if ($_POST['_check']) { 
    
$defaults $_POST
} else { 
    
$defaults = array( 'nombre' => 'nax'
                        
'edad'  => '20'
                        
'ciudad' => 'Villanax' ); 

?> 


Con este ejemplo tenemos una variable llamada _check que en caso de no existir significa que no se envió un formulario y por lo tanto nombramos nuestros valores por defecto, sino lo que estaríamos haciendo es guardar los valores enviados.

Para establecer valores por defecto es imperativo hacer los form en PHP. Un ejemplo de cómo se cargarán dichos valores es:

<?php 

if ($_POST['_check']) { 
    
$defaults $_POST
} else { 
    
$defaults = array( 'nombre' => 'nax'
                        
'edad'  => '20'
                        
'ciudad' => 'Villanax' ); 

echo 
'<form action="'.$_SERVER['PHP_SELF'].'" method="post">  
          Bienvenido desconocido por favor dinos tu nombre:  
          <input name="nombre" type="text" value="'
. 

          $defaults['nombre'].'" /> <br />  
             
          Edad: <input name="nedad" type="text" value="'
. 

          $defaults['edad'].'" /> <br /> 
           
          Ciudad: <input name="ciudad" type="text" value="'
.

          $defaults['ciudad'].'" /> <br /> 
          <br /><input type="submit" name="Submit" 

          id="button" value="Enviar" /> 
          </form>'

?> 


Con esta buena práctica ahorramos muchos dolores de cabeza a las personas con tendencia a equivocarse en los formularios de registro por ejemplo, y si... lo digo por experiencia propia.


Y bien, con este último capítulo doy por concluido el tutorial de PHP 5. Gracias a todos los que lo han ido siguiendo día a día, a los que enviaron los ejercicios y a los comentarios de crítica (tanto buenos como malos).
Si creen que falta algo o creen que sería bueno ampliar alguna parte del tutorial solo háganmelo saber.

Para:
~ Syntax Error ~
Bl4ck~P0rtal -
http://foro.el-hacker.com

Saludos Nax.


Version .doc:Formularios.doc
Version .pdf: Formularios.pdf

Bug en Mysql en tipos BINARY, VARCHAR, CHAR

Como un artículo anterior este viene de la mano de ^Tifa^ y como su descubridora todos los méritos a su persona.

El escenario




mysql> CREATE TABLE ejemplo(
    -> nombres BINARY(20));
Query OK, 0 rows affected (0.39 sec)
 
mysql> INSERT INTO ejemplo VALUES('Juan'),('Pepe'),('Jose');
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
 
mysql> SELECT * FROM ejemplo;
+----------------------+
| nombres              |
+----------------------+
| Juan                 |
| Pepe                 |
| Jose                 |
+----------------------+
3 rows IN SET (0.00 sec)
 
 
Ese es el escenario.
Ahora una actualización de datos:
mysql> UPDATE ejemplo SET nombres = 'Carlos' WHERE nombres = hex('Juan');
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
 
mysql> UPDATE ejemplo SET nombres = 'Carlos' WHERE nombres = 'Juan';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
 
mysql> DELETE FROM ejemplo WHERE nombres = 'Pepe';
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT * FROM ejemplo;
+----------------------+
| nombres              |
+----------------------+
| Juan                 |
| Pepe                 |
| Jose                 |
+----------------------+
3 rows IN SET (0.00 sec) 

Como se aprecia ni se actualiza ni se borra...

Intentamos solucionar el tema con un alter:

 
mysql> DESCRIBE ejemplo;
+---------+------------+------+-----+---------+-------+
| FIELD   | Type       | NULL | KEY | DEFAULT | Extra |
+---------+------------+------+-----+---------+-------+
| nombres | BINARY(20) | YES  |     | NULL    |       |
+---------+------------+------+-----+---------+-------+
1 row IN SET (0.00 sec)
 
mysql> ALTER TABLE ejemplo MODIFY nombres varchar(25);
Query OK, 3 rows affected (0.45 sec)
Records: 3  Duplicates: 0  Warnings: 0
 
mysql> UPDATE ejemplo SET nombres = 'Carlos' WHERE nombres = 'Juan';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
 
mysql> DELETE FROM ejemplo WHERE nombres = 'Pepe';
Query OK, 0 rows affected (0.00 sec)
 
mysql> SELECT * FROM ejemplo;
+----------------------+
| nombres              |
+----------------------+
| Juan                 |
| Pepe                 |
| Jose                 |
+----------------------+
3 rows IN SET (0.00 sec)
 
 
ni por ahí...
Esto también se aplica también a tablas con datos tipo char, varchar,etc 
si se altera a binary.
 
mysql> CREATE TABLE ejemplo2(
    -> nombres varchar(20));
Query OK, 0 rows affected (0.38 sec)
 
mysql> INSERT INTO ejemplo2 VALUES('pepe'),('Juan'),('pedro'),('luis');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
mysql> SELECT * FROM ejemplo2;
+---------+
| nombres |
+---------+
| pepe    |
| Juan    |
| pedro   |
| luis    |
+---------+
4 rows IN SET (0.00 sec)

Un ejemplo con varchar funcionando perfectamente

mysql> UPDATE ejemplo2 SET nombres = 'Cucu' WHERE nombres = 'pepe';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> SELECT * FROM ejemplo2;
+---------+
| nombres |
+---------+
| Cucu    |
| Juan    |
| pedro   |
| luis    |
+---------+
4 rows IN SET (0.00 sec)
 
 
Ahora alteramos a Binary
mysql> ALTER TABLE ejemplo2 MODIFY nombres BINARY(20);
Query OK, 4 rows affected (0.27 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
mysql> SELECT * FROM ejemplo2;
+----------------------+
| nombres              |
+----------------------+
| Cucu                 |
| Juan                 |
| pedro                |
| luis                 |
+----------------------+
4 rows IN SET (0.00 sec)
 
mysql> UPDATE ejemplo2 SET nombres = 'Marta' WHERE nombres = 'Cucu';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
 
 
se jodió la tabla...
volvemos a varchar
 
mysql> ALTER TABLE ejemplo2 MODIFY nombres varchar(20);
Query OK, 4 rows affected (0.10 sec)
Records: 4  Duplicates: 0  Warnings: 0
 
mysql> DESCRIBE ejemplo2;
+---------+-------------+------+-----+---------+-------+
| FIELD   | Type        | NULL | KEY | DEFAULT | Extra |
+---------+-------------+------+-----+---------+-------+
| nombres | varchar(20) | YES  |     | NULL    |       |
+---------+-------------+------+-----+---------+-------+
1 row IN SET (0.00 sec)
 
mysql> UPDATE ejemplo2 SET nombres = 'Marta' WHERE nombres = 'Cucu';
Query OK, 0 rows affected (0.00 sec)
Rows matched: 0  Changed: 0  Warnings: 0
 
Como se aprecia gracias al Changed: 0
no se actualizaron los datos pese a su tipo varchar.
 
 
Fuente original: Mini-Bug en Mysql 

Recuperar el password de MySQL en Windows

La información me llega desde elhacker.net de la mano de ^Tifa^.

Una de las posibles maneras de recuperar una contraseña en MySQL.

Lo vamos a explicar bajo una plataforma Windows.

Necesario:

- Ser administrador o privilegios de administrador.


Proceso:

- Inicio > ejecutar > cmd o win+R cmd

- Detenemos el Proceso de MySQL, esta parte depende de cada uno... si es un Cpanel o nuestro windows.

En windows puede hacerse así por ejemplo:
C:\> net stop mysql

- nos dirijimos a la carpeta de mysql/bin o si tenemos el path para usar mysql desde cualquier dirección (Tutorial aquí), escribimos:

c:\>cd path/to/bin

- ejecutamos la siguiente sentencia:
c:\> mysqld.exe -u root --skip-grant-tables

donde root es el usuario, pero va especialmente orientado a root.

- Ahora abrimos otra cmd y escribimos

c:\> mysql

- ya deberiamos haber logueado sin ningún tipo de problema.

- ahora ejecutamos una query para ver si el usuario existe realmente.
mysql> select user from mysql.user;

- y updateamos el campo password
mysql> update mysql.user set password = password('TU_NUEVA_CONTRASENA') where user = 'root';

- por último
mysql> flush privileges;

- ahora ya cerramos la anterior cmd e iniciamos el proceso mysql

c:\>net start mysql

Usar mySQL desde consola de comandos msdos

Bueno lo haremos con un XAMPP pero la idea es básicamente encontrar donde está el mysql.exe y hacer los mismos pasos.


Paso 1 Buscar myql.exe

Yo uso XAMPP instalado por default así que está aquí:

C:\xampp\mysql\bin
Paso 2: Agregar a variables de entorno

una ves con esta ruta vamos a:

inicio - mipc - propiedades - opciones avanzadas - variables de entorno

seleccionamos PATH y damos a modificar.

agregamos un ; y la ruta anteriormente citada a mi me quedaria así:


C:\Archivos de programa\Nmap;C:\xampp\mysql\bin
Aceptamos todo, y abrimos una cmd.


Paso 3: comandos básicos

Para entrar en MYSQL escribimos:


mysql -u usuario -p
(si no hay password no ponemos -p)

ya estamos en mysql modo consola

voy a listar una serie de comandos básicos de mysql, mas adelante pondré mas.

show databases;
muestra todas las BD


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cdcol              |
| main               |
| mydb               |
| mysql              |
| pbxt               |
| phpmyadmin         |
| scam               |
| smf_test           |
| users              |
| website            |
| z_test             |
+--------------------+
12 rows in set (0.00 sec)
use nom_db;
seleccionamos una DB.


mysql> use z_test;
Database changed
show tables;
mostramos todas las tablas.


mysql> show tables;
+------------------+
| Tables_in_z_test |
+------------------+
| monsters         |
| mvp              |
| players          |
+------------------+
3 rows in set (0.00 sec)
describe tabla;
hace una descripción de la tabla


mysql> describe monsters;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | int(11)      | NO   | PRI | NULL    | auto_increment |
| monster   | varchar(100) | YES  |     | NULL    |                |
| dead      | int(11)      | YES  |     | NULL    |                |
| id_player | int(11)      | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
select * from tabla;
vemos todo los datos de la tabla.


mysql> select * from monsters;
+----+-----------+------+-----------+
| id | monster   | dead | id_player |
+----+-----------+------+-----------+
|  1 | monster 1 |    0 |         1 |
|  2 | monster 2 |    5 |         1 |
|  3 | monster 2 |    4 |         2 |
|  4 | monster 1 |    0 |         2 |
+----+-----------+------+-----------+
4 rows in set (0.02 sec)
exit;
salir

mysql> exit
Bye
A partir de aquí simplemente hacemos consultas SQL. Hay algunos comandos interesantes pero lo dejaremos para otra ocasión.

No os olvideis de poner el punto y coma al final de las sentencias.

Curiosidad con tablas, echo y funciones en PHP

Después de varios días depurando las tablas SQL (os explicaré otro día dicho proceso) por fin empieza la etapa desarollo de un proyecto web.

El principal "problema" del proyecto es que tiene que ser compatible a SMF por lo que la metodología que usa es similar (que no igual).

El index.php trabaja de la siguiente forma:
- Carga unos textos
- Carga unas funciones básicas
- Carga las funciones gráficas y de procesos de la sección que se quiere acceder.
Para mostrarlo se llama a 3 procesos:
head(); middle(); foot();

La primera es variable según los metadatos y la última, en principio, es fija.
La que mas varía es la del medio.

head(): marca el principio de la tabla y la deja a medias para rellenarla con middle(), una vez que middle() acabó se llama a la función foot() que cierra todo.

Ahora, donde está la curiosidad? Esta está en middle(), al llamar a la función esta hace un echo con HTML y llama algunas funciones. Aquí viene el problema.

index.php
<?php
include_once('text.php');
include_once(
'functions/basic.php');
 
if (
$_GET['ac'] == 'news')
   include_once(
'news.php');
 
head(); //las 3 mas abajo
middle();
foot();
//no es exactamente así pero para que se entienda xD
?>


functions/basic.php

<?php

function head() {
      echo 
'los heads y el inicio de una tabla';
}
function 
foot() {
     echo 
'el final de la tabla y el pie de pagina';
?>


news.php
<?php
 
function middle() {
 
echo 
'la continuacion de la tabla'.funcion().'cierro celdas'//lo raro esta aqui
}
function 
funcion {
 echo 
'por ejemplo el contenido de la celda';
 
}
?>
 


como veis en news.php se concatena un string con una funcion que trae un string.
Bueno, ponga un echo o un return resulta que las tablas se descuadran totalmente y el código HTML se situa donde no debe ir.

Un par de imágenes para entenderlo:

asi está mal:


así esta bien:





como apreciais, al concatenar, el recuadro del menú se descuadra a una posición inferior y las tablas parecen no estar bien creadas.

Solución a esta curiosidad?

<?php echo 'la continuacion de la tabla'funcion() ; echo 'cierro celdas'?>

en vez de concatenar echo lo que hacemos es separar sentencias con un ; y a otra cosa mariposa...