30.5.07

Foro "sencillo"

Comencemos suavemente, con lo que ya está al 100%. La unidad (o módulo, o include) que se encarga de crear una variable $admin que servirá para restringir el contenido de ciertos contenidos a los administradores del foro. (Sí, al final terminé por usar sesiones y cookies).

Quizás para entender del todo el código haga falta el resto, pero ya lo iré poniendo.

login.php

<?php
include ("conectar.php");
$admin = FALSE;
$result = mysql_query ("SELECT * FROM admin where nombre='".$_COOKIE["admin"]."' AND clave='".$_COOKIE["pass"]."'");
if ( $row = mysql_fetch_array($result) ) {
   $admin = TRUE;
}
?>


UPDATE(09 - 06 - 07 /16:46)
Versión 1.0b del código. Por supuesto para el trabajo que estoy realizando va todo metido dentro de tablas y muy bonito. Una vez esté terminado lo postearé también.



foro.php

<?php
// By Aladaris 2007 -- GNU 
// http://www.es.gnu.org/modules/content/index.php?id=8 
// http://www.gnu.org/philosophy/selling.es.html
   include("includes/login.php");
// ############################## GENERALIDADES ###############################
   if ( $act == "" ) {   // Redireccionamos al indice de TOPICOS si no se especifica acción
 ?><!-- Pequeño Script en Java que se encarga de redirigir al admin al índice de tópicos -->
      <SCRIPT LANGUAGE="javascript">
         location.href = "<? $_self ?>?act=topicos";
      </SCRIPT><?php
   }
// ############################## ADMINISTRACION ##############################
// ----------------------------------------------------------------------------
   if ( $act == "logadminF" ) {   // Formulario para el login del ADMIN si NO esta LOGUEADO
       if ( !($admin) ) {
       ?><form method="post" action="<? $_self ?>?act=logadminC">
            Nombre: <INPUT TYPE="text" NAME="nombre" SIZE=28 MAXLENGTH=50><br />
            Clave: <INPUT TYPE="password" NAME="clave" SIZE=28 MAXLENGTH=50><br />
            <input name="submit" type="submit" class="boton" value="Log-In">
         </form><?
       }else{
         setcookie("admin", $nombre, time()-3600);   // Eliminacion de las COOKIES
         setcookie("pass", $clave, time()-3600);
         echo ('Se ha cerrado con éxito la sesión de <b>ADMINISTRADOR</b>');
       }
    }
// ----------------------------------------------------------------------------
   if ( $act == "logadminC" ) {   // Inicio de sesión mediante la creación de COOKIES
      $result = mysql_query ("SELECT * FROM admin where nombre='$nombre'");
      if ( $row = mysql_fetch_array($result) ) {   // Si exíste ese nombre de ADMINISTRADOR seguimos
         if ( $row["clave"] == $clave ) {   // Comprobamos el PASSWORD
            setcookie("admin", $nombre, time()+3600);   // Las COOKIES duraran 1 Hora
            setcookie("pass", $clave, time()+3600);
            echo ('Sesión iniciada con éxito.');
         }else{
            echo ('Error: La contraseña proporcionada no es válida.');
         }
      }else{
         echo ('Error: No exíste un administrador con ese nombre.');
      }
   }
// ----------------------------------------------------------------------------
   if ( $act == "adminF" ) {   // Formulario de cambio de clave del ADMIN
      if ( $admin ) {   // Si es un ADMINISTRADOR proseguimos
    ?><!-- Formulario para cambiar la clave del administrador -->
      <form name="nueva clave" method="post" action="<? $_self ?>?act=adminC">
 Clave actual: <INPUT TYPE="password" NAME="pass" SIZE=28 MAXLENGTH=50><br />
 Nueva clave: <INPUT TYPE="password" NAME="newpass" SIZE=28 MAXLENGTH=50><br />
 Repetir clave: <INPUT TYPE="password" NAME="newpass2" SIZE=28 MAXLENGTH=50><br />
         <input name="submit" type="submit" class="boton" value="Cambiar">
      </form>
  <? }else{ 
         echo ('ERROR: No tiene permiso para realizar esta operación. Sólo un <b>ADMINISTRADOR</b> tiene acceso.'); 
      }
   }
// ----------------------------------------------------------------------------
   if ( $act == "adminC" ) {   // Cambio de clave del ADMIN
      if ( $admin ) {   // Si es un ADMINISTRADOR proseguimos
         if ( $newpass == $newpass2 ) {   // Evitamos errores al cambiar de clave
            $result = mysql_query ("SELECT * FROM admin WHERE nombre='".$_COOKIE["admin"]."'");
            if ( $row = mysql_fetch_array($result) ) {   // Si nos devuelve columna es que es correcto y proseguimos  
               $sql = ("UPDATE admin SET clave='$newpass' WHERE clave='$pass'");
               mysql_query($sql);
               echo ('Contraseña cambiada con éxito.');?>
            <!-- Pequeño Script en Java que se encarga de redirigir al admin al índice de tópicos -->
               <SCRIPT LANGUAGE="javascript">
          location.href = "<? $_self ?>?act=topicos";
       </SCRIPT>
      <?    }else{
               echo ('La clave de administrador que ha proporcionado no es correcta, no se realizará ningún cambio.');
            }
         }else{
            echo ('Has escrito mal la nueva contraseña, asegurese de que al repetirla lo hace exactamente igual.');
         }
      }else{ 
         echo ('ERROR: No tiene permiso para realizar esta operación. Sólo un <b>ADMINISTRADOR</b> tiene acceso.');
      }
   }
// ----------------------------------------------------------------------------
   if ( $act == "eliminarT" ) {   // Eliminar TOPICO y todos los MENSAJES relacionados
      if ( $admin ) {   // Si es un ADMINISTRADOR proseguimos
         echo ('Autentificación correcta, borrando Tópico y sus Mensajes.');
         $sql = ("DELETE FROM topicos WHERE id='$Tid'");
         $sql2 = ("DELETE FROM mensajes WHERE ref_topic='$Tid'");
         mysql_query($sql);
         mysql_query($sql2);?>
      <!-- Pequeño Script en Java que se encarga de redirigir al admin al índice de tópicos -->
         <SCRIPT LANGUAGE="javascript">
    location.href = "<? $_self ?>?act=topicos";
 </SCRIPT>
   <? }else{ 
         echo ('ERROR: No tiene permiso para realizar esta operación. Sólo un <b>ADMINISTRADOR</b> tiene acceso.'); 
      }
   } 
// ----------------------------------------------------------------------------
   if ( $act == "eliminarM" ) {   // Eliminar MENSAJE
      if ( $admin ) {   // Si es un ADMINISTRADOR proseguimos
         echo ('Autentificación correcta, borrando Mensaje.');
         $sql = ("DELETE FROM mensajes WHERE id='$Mid'");
         mysql_query($sql);?>
         <!-- Pequeño Script en Java que se encarga de redirigir al admin al topico donde se encontraba -->
         <SCRIPT LANGUAGE="javascript">
    location.href = "<? $_self ?>?act=mensajes&Tid=<? echo ($Tid); ?>";
 </SCRIPT>
   <? }else{ 
         echo ('ERROR: No tiene permiso para realizar esta operación. Sólo un <b>ADMINISTRADOR</b> tiene acceso.'); 
      }
   } 
// ################################# TOPICOS ##################################
// ----------------------------------------------------------------------------
   if ( $act == "aniadirT" ) {   // Escribir nuevo TOPICO en la BD
      if ( trim($Fnombre) != "" && trim($Ftitulo) != "" ) {   // Comprobamos que no estén en blanco nombre y título
         $sql = ("INSERT INTO topicos (nombre,apellidos,email,titulo,fecha,descripcion) VALUES 
    ('$Fnombre','$Fapellidos','$Femail','$Ftitulo',curdate(),'".nl2br($Fdescripcion)."')");
         mysql_query($sql);
         echo ('Tópico añadido');?>
         <!-- Pequeño Script en Java que se encarga de redirigir al usuario al índice de tópicos -->
         <SCRIPT LANGUAGE="javascript">
    location.href = "<? $_self ?>?act=topicos";
 </SCRIPT>
   <? }else{
         echo ('Introduzca su <b>Nombre</b> y un <b>Título</b>, como mínimo.');
      }
   }
// ----------------------------------------------------------------------------
   if ( $act == "topicos" ) {   // Ver TOPICOS
      $contador = 1;   // $contador nos sirve para acotar el máximo de tópicos mostrado por página
      $result = mysql_query("SELECT * FROM topicos order by id DESC");
      while ( $row = mysql_fetch_array($result) ) {
         echo ('<div><a href="'.$_self.'?act=mensajes&Tid='.$row["id"].'">'.$row["titulo"].'</a>'); 
         if ( $admin ) {   // Sólo mostramos la opción de borrado al ADMIN
            echo ('  (<a href="'.$_self.'?act=eliminarT&Tid='.$row["id"].'">Borrar</a>)</div>');
         }else{
            echo ('</div>');   // Cerramos la etiqueta DIV
         }
         $contador ++;
      }
      ?>
         <!-- Formulario para añadir un nuevo TOPICO -->
         <form name="nuevo_topico" method="post" action="<? $_self ?>?act=aniadirT">
            <p>Nombre: <input name="Fnombre" type="text" id="Fnombre" size="32"></p>
            <p>Apellidos: <input name="Fapellidos" type="text" id="Fapellidos" size="64"></p>
            <p>E-mail: <input name="Femail" type="text" id="Femail" size="64"></p>
            <p>Título: <input name="Ftitulo" type="text" id="Ftitulo" size="55"></p>
            <p>Descripción:</p>
            <p><textarea name="Fdescripcion" cols="55" rows="6" id="Fdescripcion"></textarea></p>
            <p><input type="submit" name="Submit" value="Publicar"></p>
         </form>
      <?
   }
// ################################# MENSAJES #################################
// ----------------------------------------------------------------------------
   if ( $act == "aniadirM" ) {   // Escribir nuevo MENSAJE en la BD
      if ( trim($Fnombre) != "" && trim($Fmensaje) != "" ) {   // Comprobamos que no estén en blanco nombre y mensaje
         $result = mysql_query("SELECT * FROM topicos order by id");   // Evitar mensajes en tópicos inexistentes
         while ( $row = mysql_fetch_array($result) ) {
            if ( $Tid == $row["id"] ) {
               $sql = ("INSERT INTO mensajes (nombre,apellidos,email,mensaje,fecha,ref_topic) VALUES 
    ('$Fnombre','$Fapellidos','$Feamil','".nl2br($Fmensaje)."',curdate(),'$Tid')");
               mysql_query($sql); 
               echo ('Mensaje añadido');?>
               <!-- Pequeño Script en Java que se encarga de redirigir al usuario al topico donde se añade el mensaje -->
               <SCRIPT LANGUAGE="javascript">
          location.href = "<? $_self ?>?act=mensajes&Tid=<? echo $Tid ?>";
       </SCRIPT> 
      <?    }   // Cerrando IF
         }   // Cerrando WHILE
      }else{
         echo ('Introduzca su <b>Nombre</b> y un <b>Mensaje</b>');
      }
   }
// ----------------------------------------------------------------------------
   if ( $act == "mensajes" ) {   // Ver MENSAJES de un TOPICO dado y su DESCRIPCION
      $result = mysql_query ("SELECT * FROM topicos WHERE id='$Tid'");      
      if ( $row = mysql_fetch_array($result) ) {   // Si nos devuelve columna es que es correcto y proseguimos
         $result = mysql_query("SELECT * FROM mensajes WHERE ref_topic=$Tid order by id");
         while ( $row = mysql_fetch_array($result) ) {
            echo ('<div>'.$row["mensaje"]);
            if ( $admin ) {   // Sólo mostramos la opción de borrado al ADMIN
               echo ('  (<a href="'.$_self.'?act=eliminarM&Mid='.$row["id"].'&Tid='.$Tid.'">Borrar</a>)</div>');
            }else{
               echo ('</div>');   // Cerramos la etiqueta DIV
            }
         }
         ?>
         <!-- Formulario para añadir un nuevo MENSAJE en el TOPICO especificado -->
         <form name="nuevo_topico" method="post" action="<? $_self ?>?act=aniadirM&Tid=<? echo $Tid ?>">
            <p>Nombre: <input name="Fnombre" type="text" id="Fnombre" size="32"></p>
            <p>Apellidos: <input name="Fapellidos" type="text" id="Fapellidos" size="64"></p>
            <p>E-mail: <input name="Femail" type="text" id="Femail" size="64"></p>
            <p>Mensaje:</p>
            <p><textarea name="Fmensaje" cols="120" rows="10" id="Fmensaje"></textarea></p>
            <p><input type="submit" name="Submit" value="Enviar"></p>
        </form>
        <?
      }else{
         echo ('El tópico al que intenta acceder no existe');
      }
   }?>

22.5.07

Foro, sencillo, funcional y simple (o más)

Pues lo dicho, hoy me han ofrecido un pequeño (pero no por ello menos importante) proyecto para la creación de un 'foro' utilizando PhP y MySql. No se tratará en sí de un foro sino más bien de un tablón de anuncios con tópicos (como los foro, con sus comentarios dentro), sin usuarios y lo mas simple y sencillo posible.
Hacía tiempo que no me ponía 'serio' con el PhP; lo que me falta es que me pasen la plantilla donde introducir (y por lo que veo, también maquetar y hacer interfaces) para ponerme serio.

Supongo que al cliente (porque sí, se trata de un trabajillo [gracias Edu ;)]) no le importe que cuelgue aquí el código (no revelaré donde estará corriendo, ya que no va a ser un trabajo muy meticuloso en cuanto a seguridad y sql injection).
Lo único que puedo decir por ahora es que sólo trabajaré con un archivo php que se usará como plantilla para hacer que todo funcione.

Sin más, saludos y sí, aún no he dejado esto.

UPDATE(26 - 05 - 07 /01:55): Al final la especie de foro éste si que tendrá un administrador con privilegios para borrar tópicos (y todos los mensajes que le correspondan) y mensajes en sí mismo.
Sigo esperando la plantilla para empezar a meter en tablas los formularios y los resultados...

UPDATE(28 - 05 - 07 /18:35): Ya está todo hecho, he pasado del uso de sesiones (iba a hacerlo para el administrador) ya que el admin solo quiere borrar tópicos y mensajes y además por el dinero que me dan (no es que me queje) paso de complicarme más la vida.
Sólo queda por implementar el típico máximo de tópicos / mensajes mostrados por página y meterlo todo en la plantilla, que por cierto aun no tengo ...

14.5.07

PhP - Indentador V 1.0

Al fin he conseguido crear una versión funcional del "Indentador de Código para Entornos Htm" ICEH ('hieloh'[x'DDD]).

Ten encuenta que para poder visualizar correctamente el codigo he añadido el caracter "·" en la sección de "str_replace" justo después del Ampersand, "&". Para que funcione tienes que eliminar esos puntos.

Ya sin más, el código:

<!--  ------------------ -->
<!-- | By Aladaris 2007 |-->
<!--  ------------------ -->
<!-- Se hace uso del script descargar.php obtenido en http://www.php.net -->
<html>
<head>
  <title>Indentador</title>
</head>
<body>
<?
   if(trim($HTTP_POST_VARS["inicial"]) != "")
   {
      $code = $HTTP_POST_VARS["inicial"];
      $code = str_replace("<","&·lt;",$code);
      $code = str_replace(">","&·gt;",$code);
      $code = str_replace(" ","&·nbsp;",$code);
      $code = str_replace("\'","&·#39;",$code);
      $code = str_replace('\"',"&·quot;",$code);
      $code = str_replace("\\\\","&·#92",$code);                     
      $code = nl2br($code);   // Sustituimos los saltos de línea por <br>
      $salida = fopen("identado.txt","w");
      fputs($salida, $code);
      fclose($salida);
      echo ('<div><a href="descargar.php?f=identado.txt">Descargar codigo identado</a></div>');
   }
   else
   { ?>
      <FORM ACTION="identador.php" METHOD="post">
         <textarea name="inicial" cols="120" rows="40" id="inicial"></textarea></br>
         <input type="submit" value="Identar">
      </form>
<? } ?>
</body>
</html>

Si ya has mirado el código, habrás comprobado que se hace uso de un script externo llamado descargar.php, y tal y como se cita en la cabecera del código, lo extraje de la web php.net. Paso a copiar el código del script de descarga (repito, no es mio, aunque se sigue ajustando a la filosofia del blog):

<?php
//Script conseguido en http://www.php.net/
    $archivos = array("identado.txt", "identador.php", "descargar.php");
    $f = $_GET["f"];
    if(strpos($f,"/")!==false){
        die("No puedes navegar por otros directorios");
    }
    if(!in_array($f,$archivos)){
        die("<b>ERROR!</b> no tienes permiso descargar $f");
    }
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$f\"\n");
    $fp=fopen("$f", "r");
    fpassthru($fp);
?>

----- Pendiente por publicar -----
*Comentarios extendidos del code

11.5.07

Indentación...

Sigo buscando un modo para indentar el código. Creo que voy a optar por hacerme algun tipo de aplicación que me sirva para reemplazar los espacios, " ",(y en general cualquier simbolo que pueda interferir con el código del blog) por su correspondiente caracter html.

UPDATE(14 - 05 - 07 /11:00): Ya he implementado el identador, al final he optado por hacerlo en php que me resulta mucho más cómodo y puedo compartir la herramienta sin necesidad de su descarga. Me queda solucionar un problemilla que crea un doble salto de línea y publico el código.
Ya lo he usado en la entrada "Linux - Montar imágenes" arreglando el doble salto de línea a mano :P.

CSS - Personalizando el blog

He estado mirando como funciona el blogger este y me he dado cuenta de que las plantillas son grandes archivos html, xml o lo que sea, con unas cabeceras inmensas donde se define el estilo. Por eso, y visto que voy a ir poniendo código en este blog, he creado una nueva clase, "codigo" que lo que hace básicamente es dar formato al código que publique. Configura la fuente, situa el texto más centradamente, colorea el fondo y lo rodea por un elegante (xD) "dashed" borde rojo.
Sin más os copio el fragmento simple de código css que he generado.

.codigo{
   font-family : times new roman;
   font-size : 85%;
   text-align : justify;
   margin-left : 19%;
   padding : 15px;
   background-color : #FFF8DC;
   border : dashed 2px red;
}
Según un par de sitios de referencia que vi para modificar bloggers, lo ideal es copiar ese fragmento de código justo debajo de las declaraciones de los "headings" (< .h1> < .h2> ...).
Para utilizarlo simplemente hay que poner el codigo deseado entre las siguientes etiquetas:

< .table class="codigo" border="0" cellpadding="0" cellspacing="0">< .tbody>< .tr>< .td>
...Aquí el Código...
< /td>< /tr>< /tbody>< /table>

He decidido hacerlo con tablas porque al hacerlos con "div" o "span" no conseguía ajustar el ancho del recuadro (que varíe según la longitud del texto). Es un poco más engorroso, pero investigaré el método para hacerlo mas sencillo.
(Pongo puntos y espacios para que no se vuelva loco el editor de entradas)

10.5.07

Linux - Montar imágenes

Dando mis primeros pasos en el Bash Scripting he hecho este pequeño script, con interface y todo, para facilitarme el montaje de imágenes de disco *.iso, *.img, *.nrg, *.mdf.

#!/bin/bash
#By Aladaris 2007 GNU License
#Este script facilita la tarea de montar imagenes ya sean de extension *.iso *.img *mdf ó *.nrg
#
clear
echo Este script depende de los paquetes cc2iso y mdf2iso
echo
echo Introduce el nombre, ruta incluida, SIN LA EXTENSIÓN:
read NAME
clear
function ppal {
   echo La imagen que se va a montar es: "$NAME"
   echo
   OPTIONS="ISO IMG MDF NRG CAMBIAR DESMONTAR SALIR"
   select opt in $OPTIONS; do
      if [ "$opt" = "ISO" ]; then
         sudo mount -t iso9660 -o loop "$NAME".iso /media/imagen
         ppal
      elif [ "$opt" = "IMG" ]; then
         sudo ccd2iso "$NAME".img "$NAME".iso
         sudo mount -t iso9660 -o loop "$NAME".iso /media/imagen
         ppal
      elif [ "$opt" = "MDF" ]; then
         sudo mdf2iso "$NAME".mdf "$NAME".iso
         sudo mount -t iso9660 -o loop "$NAME".iso /media/imagen
         ppal
      elif [ "$opt" = "NRG" ]; then
         sudo mount -t iso9660 -o loop,offset=307200 "$NAME".nrg /media/imagen
         ppal
      elif [ "$opt" = "CAMBIAR" ]; then
         echo Introduce el nombre, ruta incluida, SIN LA EXTENSIÓN:
         read NAME
         clear 
         ppal
      elif [ "$opt" = "DESMONTAR" ]; then
         sudo umount /media/imagen
         ppal
      elif [ "$opt" = "SALIR" ]; then
         echo Recuerda que el punto de montaje es /media/imagen
         exit
      else
         clear
         echo Opción incorrecta
         ppal
      fi
done
}
ppal

Iniciando el Blog

Hace 5 minutos (o menos [lo que se tarde en crear un blog en blogger]) se me ocurrió crear este blog en el que ir publicando todo el código que vaya generando en mi vida y que considere interesante compartir. Me parece una buena idea, que no se si dejaré de lado en un futuro (como casi todo lo que empiezo), para dentro de X tiempo poder observar mi evolución en cuanto a programación.