jueves, 3 de enero de 2008

Agregar a favoritos

Hasta hace poco, el navegador por excelencia era el Internet Explorer y no habia muchos problemas al poner un enlace para añadir tu web como favoritos. Pero con la aparición de nuevos navegadores como el FireFox o Safary entre otros, ya no es posible usar un mismo link para todos los navegadores.

Con el siguiente JavasCript te damos la oportunidad de conseguirlo.

Añade el siguiente codigo entre <head> y </head>

<script type="text/javascript">
function agregar_favoritos(){
if ((navigator.appName=="Microsoft Internet Explorer") && (parseInt(navigator.appVersion)>=4)){
var url="Titulo de tu web";
var titulo="Titulo para el Favorito";
window.external.AddFavorite(url,titulo);
} else {
if(navigator.appName == "Netscape")
alert("Presione Crtl+D para agregar este sitio en sus Bookmarks");
}
}
</script>


Para poner el enlace utiliza el siguiente codigo:
<a onclick="agregar_favoritos()">Agreganos a favoritos</a>

Frame on top

Este es un pequeño código javascript que puesto en una página evitará que sea un frame. Si se muestra una página con el siguiente código dentro de un frame, la página del frame se recargará de forma automáticamente y se mostrará exclusivamente la pagina que tiene el código.
Es muy útil por ejemplo, para quitar la barra de publicidad de los subdominios .tk

<script type="text/javascript">
if (window.self != window.top){
window.top.location = window.self.location;
}
</script>

miércoles, 2 de enero de 2008

Clase para leer BBCodes en PHP

Si eres de los que, como yo, no terminas de entender las expresiones regulares y quieres permitir que los usuarios de tu web puedan usar los BBCodes típicos de los foros, también puedes conseguir el mismo efecto creando un intérprete simple que vaya leyendo caracter a caracter y remplazando las etiquetas.

La idea se basa en usar una "pila" para los códigos que vayamos encontrando y un buffer para el texto (realmente sería una cola, pues luego extraemos elementos en el mismo orden que los insertamos). Leeremos caracter a caracter el BBCode, y cuando encontremos una etiqueta apilaremos el texto que habíamos leido antes de encontrarla, para terminar luego de leer la etiqueta. Luego leeremos sus atributos (si tiene), lo guardaremos en un array y lo apilaremos. Más adelante recorreremos la "pila" desde la base hasta el final e iremos convirtiendo los códigos en html.

También comentar que la función realiza varias llamadas recursivas para procesar los códigos que pueden contener a su vez otras etiquetas en su interior (por ejemplo, [b][i]negrita y cursiva[/i][/b]), que permite especificar los colores más comunes por si nombre y no por su código RGB, y que permite habilitar y deshabilitar etiquetas (en el sitio que estoy programando necesito deshabilitar ciertas carácterísticas, por ejemplo insertar videos, en algunas partes donde sí se podrían usar otros códigos). También hay algunos códigos que todavía no están incluidos, pero viendo el código que ya hay programado no es dificil extender la clase.



class bbcode {

const BB_COLOR = 0;
const BB_IMAGES = 1;
const BB_QUOTES = 2;
const BB_VIDEO = 3;
const BB_LINKS = 4;
const BB_LUSERS = 5;
const BB_MUSICRELS = 6;

private $features;

public function __construct() {
$this->features = array(
self::BB_COLOR => false,
self::BB_IMAGES => false,
self::BB_QUOTES => true,
self::BB_VIDEO => false,
self::BB_LINKS => true,
self::BB_LUSERS => true,
self::BB_MUSICRELS => true
);
}

public function disable($feature) {
$this->features[$feature] = false;
}

public function enable($feature) {
$this->features[$feature] = true;
}

public function get_features() {
/* devuelve las características habilitadas */
return $this->features;
}

const BB_PARSER_INIT = 0;
const BB_LABEL_START = 1;
const BB_ATTRIB_NAME = 2;
const BB_ATTRIB_VALUE= 3;

const BB_TYPE_TEXT = 0;
const BB_TYPE_LABEL = 1;


private function real_parse($bbcode) {
/*esta función debe construir una pila con el BBCode a procesar
y pasársela a otra función que realizará los remplazos oportunos

esta función no sabe nada de la sintaxis del bbcode, ni que etiquetas tienen
otra de cierre, ni las que tienen parámetros internos, etc; solo crea una pila
*/
$buffer = $c = $attrib_name = '';
$label = $attrib_value = '';
$attrib_first_char = $attrib_quoted = false;
$attribs = $stack = array();
$state = self::BB_PARSER_INIT;
$textual_tag = '';

for($i=0,$l=strlen($bbcode) ; $i <= $l ; $i++) {

$c = $bbcode{$i};
switch($state) {

case self::BB_PARSER_INIT:
if($c != '[') $buffer .= $c;
else {
/* Cambiamos de estado, apilamos el texto "normal" que teníamos
e inicializamos variables que usaremos para leer la etiqueta */
if($buffer != '') {
$stack[] = array(self::BB_TYPE_TEXT, $buffer, array(), '');
}
$state = self::BB_LABEL_START;
$attribs = array();
$buffer = '';
$label = '';
$textual_tag = '[';

}
break;

case self::BB_LABEL_START:

$textual_tag .= $c;

if($c == ']') {
$state = self::BB_PARSER_INIT; //Apilamos la etiqueta con lista de atributos vacía
//y volvemos al inicio
$stack[] = array(self::BB_TYPE_LABEL, $label, $attribs, $textual_tag);
$textual_tag = '';
} elseif($c == ' ') {
//inicio lista atributos a una lista vacía
$state = self::BB_ATTRIB_NAME;
$attrib_name = '';
$attrib_value = '';
$attribs = array();

} elseif($c == '=') {
//"valor de etiqueta", x ejemplo [color=#FFFFFF]
//guarda un atributo de mismo nombre que la etiqueta
$state = self::BB_ATTRIB_VALUE;
$attrib_first_char = true;
$attrib_name = $label;
$attrib_value = '';
$attribs = array();

} else {
$label .= $c;
}
break;

case self::BB_ATTRIB_NAME:

$textual_tag .= $c;

if($c == ' ') {
//FIXUP: salta al siguiente atributo sin dar valor al
// actual, asi que ignoramos el anterior
$attrib_name = '';
} elseif($c == ']') {
//Cierra la etiqueta así que la guardamos y volvemos al inicio
$stack[] = array(self::BB_TYPE_LABEL, $label, $attribs, $textual_tag);
$state = self::BB_PARSER_INIT;
$textual_tag = '';
} elseif($c != '=') {
$attrib_name .= $c;
} else {
$state = self::BB_ATTRIB_VALUE;
$attrib_first_char = true;
$attrib_value = '';
}

break;

case self::BB_ATTRIB_VALUE:

$textual_tag .= $c;

if($attrib_first_char && ($c == '"')) {
//Si el primer caracter del atributo son unas comillas,
// significa que el valor estará entre comillas, así
// que leeremos hasta las siguientes comillas
$attrib_quoted = true;
$attrib_first_char = false;
$attrib_value = '';

} elseif($attrib_first_char && ($c == ']')) {
//En el primer caracter está el caracter de cierre
//luego el atributo no tendrá valor
$stack[] = array(self::BB_TYPE_LABEL, $label, $attribs, $textual_tag);
$state = self::BB_PARSER_INIT;

} elseif($attrib_first_char && ($c != '"')) {
//Si el primer caracter no son comillas, leeremos hasta
// que encontremos un espacio o un ]
$attrib_quoted = false;
$attrib_first_char = false;
$attrib_value = $c;

} elseif(!$attrib_first_char) {

if($attrib_quoted) {
//atributo entre comillas -> leemos hasta encontrar las de cierre
if($c != '"') {
$attrib_value .= $c;
} else {
$attribs[$attrib_name] = $attrib_value;
$attrib_name = $attrib_value = '';
$state = self::BB_ATTRIB_NAME;
}

} else {
//atributo sin comillas -> leemos hasta encontrar un espacio o un ]
if( ($c != ' ') && ($c != ']') ) {
$attrib_value .= $c;
} else {

$attribs[$attrib_name] = $attrib_value;
$attrib_name = $attrib_value = '';

if($c == ' ') {
$state = self::BB_ATTRIB_NAME;
} else {
//Fin de etiqueta, la guardamos
$stack[] = array(self::BB_TYPE_LABEL, $label, $attribs, $textual_tag);
$state = self::BB_PARSER_INIT;
}
}

}
}
break;
}

}

//$stack contiene una pila con los códigos a procesar, que pueden estar mal cerrados, no existir, etc
//var_export($stack);

//Comprobamos que lo que estaba entre [] eran realmente etiquetas BBCode,
// lo que no lo fuera vuelve a convertirse en texto
$this->check_tags(&$stack);

$last = 0;
echo $this->tags_to_html(&$stack, 0, false, $last);

}

private function tags_to_html(&$stack, $first_element=0, $closing_tag=false, &$last_processed) {

//Esto va leyendo todos los elementos y creando un buffer con todo el texto formateado a html
//En caso de encontrar un tag que no sepa formatear, lo escribe directamente al buffer

//Se trata de una función recursiva, y va leyendo la pila desde $first_element
//Cuando encuentra un tag de apertura, se llama a si misma para obtener todo el texto formateado
// hasta la etiqueta de cierre; eventualmente, si encuentra otras etiquetas de apertura antes de la etiqueta
// de cierre buscada, hará lo propio para formatear los bCodes intermedios

//Debemos intentar por todos los medios crear HTML válido aunque el BBCode sea incorrecto, por tanto, si
//encontramos una etiqueta de cierre distinta de la que buscamos deberemos actuar como si la hubiéramos encontrado,
//devolviendo el formateo correcto hasta la etiqueta (incorrecta) de cierre actual, y forzando que se vuelva a procesar
//la etiqueta incorrecta de cierre encontrada por si era de un elemento anterior. ÉSTO CAUSA QUE, en caso de encontrar una
//etiqueta de cierre existente, pero que no cierra nada que estuviera abierto, SE CIERREN TODAS LAS ETIQUETAS ABIERTAS

//... AL final esto último no es así; si una etiqueta se abre dentro de otra pero se cierra fuera ([b][i] lalala [/b][/i]),
// al convertirlo en html resultará que se cierra la cursiva al encontrar el /i, pero no el b (ya que se encontró cuando buscábamos
// el /i)

$buffer = '';
$last = count($stack);

for($i=$first_element ; $i <= $last ; $i++) {

if($stack[$i][0] == self::BB_TYPE_TEXT) {
$buffer .= $stack[$i][1];

} else { //TYPE_LABEL

if(($closing_tag !== false) && ($closing_tag == $stack[$i][1])) {
//Encontrado tag de cierre, devolvemos el buffer procesado hasta ahora
$last_processed = $i;
return $buffer;
}

switch($stack[$i][1]) {

case 'img':
//Lo de dentro tiene que ser una URL, asi que recreamos todo como texto hasta el tag [/img]
//Si no encontramos un tag [/img], no procesamos el tag

$url = ''; $align = false; $found = false; $title=false;

if(isset($stack[$i][2]['align'])) {
if($stack[$i][2]['align'] == 'left') $align = 'left';
if($stack[$i][2]['align'] == 'right') $align = 'right';
if($stack[$i][2]['align'] == 'center') $align = 'center';
}

if(isset($stack[$i][2]['title'])) {
$title = $stack[$i][2]['title'];
}

for($j=$i+1 ; $j <= $last ; $j++) {

if($stack[$j][0] == self::BB_TYPE_LABEL) {
//hemos encontrado una etiqueta dentro del tag [img]
if ($stack[$j][1] == '/img') {
//si es la de cierre

$url = htmlentities($url,ENT_QUOTES);
if(is_valid_url($url)) {

$found = true;
if(!$title) {
if($align == 'center') {

$buffer .= '< div style="width:100%;clear:both;text-align:center;">';
$buffer .= "< img alt="\" src="\" />";
$buffer .= '< /div>';

} elseif($align != false) {
$buffer .= "< img alt="\" src="\" style="\" />";
} else {
$buffer .= "< img alt="\" src="\" />";
}
} else {
if($align == 'center') {

$buffer .= '< div style="width:100%;clear:both;text-align:center;">';
$buffer .= "< img alt="\" src="\" title="\" />";
$buffer .= '< /div>';

} elseif($align != false) {
$buffer .= "< img alt="\" src="\" title="\" style="\" />";
} else {
$buffer .= "< img alt="\" src="\" title="\" />";
}
}
}
//Avanzamos el bucle original hasta el final de la etiqueta
$i = $j;
break;
} else {
//hemos encontrado una etiqueta dentro de otra, la tratamos
//como parte de la URL...
$url .= $stack[$j][3];
}
} else {
$url .= $stack[$j][1];
}

} // - for
if(!$found) {
//Se hemos llegado aquí significa que no hemos encontrado un tag [/img],
//ponemos el tag [img] en el buffer y seguimos después de él
$buffer .= '['.$stack[$i][1].']';
}
break;
case 'b':

//Enviamos $i como referencia para que nuestra iteración continue donde
//acabe la de la llamada recursiva
$buffer .= '< b>'.$this->tags_to_html(&$stack, $i+1, '/b', &$i).'< /b>';
break;

case 'i':

$buffer .= '< i>'.$this->tags_to_html(&$stack, $i+1, '/i', &$i).'< /i>';
break;
case 'u':

$buffer .= '< span style="text-decoration:underline;">'.
$this->tags_to_html(&$stack, $i+1, '/u', &$i).'< /span>';
break;
case 's':

$buffer .= '< strike>'.$this->tags_to_html(&$stack, $i+1, '/s', &$i).'< /strike>';
break;

case 'color':

if(isset($stack[$i][2]['color'])) {

$color = $this->color_to_hex($stack[$i][2]['color']);

if($color !== false) {
//hemos determinado que el color es válido
$buffer .= '< span style="color:'.$color.';">'.
$this->tags_to_html(&$stack, $i+1, '/color', &$i).'< /span>';
} else {
//color no válido, no hacemos cambios en la salida
$buffer .= $this->tags_to_html(&$stack, $i+1, '/color', &$i);
}

} else {
//no ha especificado qué color quiere usar... así que procesamos el tag sin incluir
//cambios en la salida
$buffer .= $this->tags_to_html(&$stack, $i+1, '/color', &$i);
}


break;

case 'url':

if(isset($stack[$i][2]['url'])) {
//tag tipo [url=URL]texto enlace[/url]
if(is_valid_url($stack[$i][2]['url'])) {

$buffer .= '< a href="'.$stack[$i][2]['url'].'">'.
$this->tags_to_html(&$stack, $i+1, '/url', &$i).'< /a>';

} else {
//URL inválida, la mostramos como texto
$buffer .= $this->tags_to_html(&$stack, $i+1, '/url', &$i).
' ['.$stack[$i][2]['url'].']';
}

} else {
//tag tipo [url]URL[/url]
$url='';
for($j=$i+1 ; $j <= $last ; $j++) {

if($stack[$j][0] == self::BB_TYPE_TEXT) {
$url .= $stack[$j][1];
} elseif($stack[$j][1] != '/url') { //($stack[$i][0] == self::BB_TYPE_LABEL)
//Lo habíamos "confundido" con un tag, leemos la representación textual
$url .= $stack[$j][3];
} else { //$stack[$i][1] == '/url' && $stack[$i][0] == self::BB_TYPE_LABEL
$i = $j;
break;
}

}

if(is_valid_url($url)) {
$buffer .= '< a href="'.$url.'">'.$url.'< /a>';

} else {
//URL inválida, la mostramos como texto
$buffer .= $url. ' ['.$url.']';
}


}
break;
default:
//Recrear etiqueta, ya que no existe
//esto no deberia pasar, pues ya habíamos comprobado que existia
$buffer .= '['.$stack[$i][3].']';
}

}

}

$last_processed = $i;
return $buffer;

}

private static function color_to_hex($name) {

//La lista de nombres está sacada de http://www.w3schools.com/css/css_colornames.asp
static $color_table = array(
'aliceblue' => '#F0F8FF', 'antiquewhite' => '#FAEBD7',
'aqua' => '#00FFFF', 'aquamarine' => '#7FFFD4',
'azure' => '#F0FFFF', 'beige' => '#F5F5DC',
'bisque' => '#FFE4C4', 'black' => '#000000',
'blanchedalmond'=> '#FFEBCD', 'blue' => '#0000FF',
'blueviolet' => '#8A2BE2', 'brown' => '#A52A2A',
'burlywood' => '#DEB887', 'cadetblue' => '#5F9EA0',
'chartreuse' => '#7FFF00', 'chocolate' => '#D2691E',
'coral' => '#FF7F50', 'cornflowerblue'=> '#6495ED',
'cornsilk' => '#FFF8DC', 'crimson' => '#DC143C',
'cyan' => '#00FFFF', 'darkblue' => '#00008B',
'darkcyan' => '#008B8B', 'darkgoldenrod' => '#B8860B',
'darkgray' => '#A9A9A9', 'darkgrey' => '#A9A9A9',
'darkgreen' => '#006400', 'darkkhaki' => '#BDB76B',
'darkmagenta' => '#8B008B', 'darkolivegreen'=> '#556B2F',
'darkorange' => '#FF8C00', 'darkorchid' => '#9932CC',
'darkred' => '#8B0000', 'darksalmon' => '#E9967A',
'darkseagreen' => '#8FBC8F', 'darkslateblue' => '#483D8B',
'darkslategray' => '#2F4F4F', 'darkslategrey' => '#2F4F4F',
'darkturquoise' => '#00CED1', 'darkviolet' => '#9400D3',
'deeppink' => '#FF1493', 'deepskyblue' => '#00BFFF',
'dimgray' => '#696969', 'dimgrey' => '#696969',
'dodgerblue' => '#1E90FF', 'firebrick' => '#B22222',
'floralwhite' => '#FFFAF0', 'forestgreen' => '#228B22',
'fuchsia' => '#FF00FF', 'gainsboro' => '#DCDCDC',
'ghostwhite' => '#F8F8FF', 'gold' => '#FFD700',
'goldenrod' => '#DAA520', 'gray' => '#808080',
'grey' => '#808080', 'green' => '#008000',
'greenyellow' => '#ADFF2F', 'honeydew' => '#F0FFF0',
'hotpink' => '#FF69B4', 'indianred' => '#CD5C5C',
'indigo' => '#4B0082', 'ivory' => '#FFFFF0',
'lhaki' => '#F0E68C', 'lavender' => '#E6E6FA',
'lavenderblush' => '#FFF0F5', 'lawnGreen' => '#7CFC00',
'lemonchiffon' => '#FFFACD', 'lightblue' => '#ADD8E6',
'lightcoral' => '#F08080', 'lightcyan' => '#E0FFFF',
'lightgoldenrodyellow' => '#FAFAD2', 'lightgray' => '#D3D3D3',
'lightgrey' => '#D3D3D3', 'lightgreen' => '#90EE90',
'lightpink' => '#FFB6C1', 'lightsalmon' => '#FFA07A',
'lightseagreen' => '#20B2AA', 'lightskyblue' => '#87CEFA',
'lightslategray'=> '#778899', 'lightslategrey'=> '#778899',
'lightsteelblue'=> '#B0C4DE', 'lightyellow' => '#FFFFE0',
'lime' => '#00FF00', 'limegreen' => '#32CD32',
'linen' => '#FAF0E6', 'magenta' => '#FF00FF',
'maroon' => '#800000', 'mediumaquamarine'=> '#66CDAA',
'mediumblue' => '#0000CD', 'mediumorchid' => '#BA55D3',
'mediumpurple' => '#9370D8', 'mediumseagreen'=> '#3CB371',
'mediumslateblue'=> '#7B68EE', 'mediumspringgreen'=> '#00FA9A',
'mediumturquoise'=> '#48D1CC', 'mediumvioletred'=> '#C71585',
'midnightblue' => '#191970', 'mintcream' => '#F5FFFA',
'mistyrose' => '#FFE4E1', 'moccasin' => '#FFE4B5',
'navajowhite' => '#FFDEAD', 'navy' => '#000080',
'oldlace' => '#FDF5E6', 'olive' => '#808000',
'olivedrab' => '#6B8E23', 'orange' => '#FFA500',
'orangered' => '#FF4500', 'orchid' => '#DA70D6',
'palegoldenrod' => '#EEE8AA', 'palegreen' => '#98FB98',
'paleturquoise' => '#AFEEEE', 'palevioletred' => '#D87093',
'papayawhip' => '#FFEFD5', 'peachpuff' => '#FFDAB9',
'peru' => '#CD853F', 'pink' => '#FFC0CB',
'plum' => '#DDA0DD', 'powderblue' => '#B0E0E6',
'purple' => '#800080', 'red' => '#FF0000',
'rosybrown' => '#BC8F8F', 'royalblue' => '#4169E1',
'saddlebrown' => '#8B4513', 'salmon' => '#FA8072',
'sandybrown' => '#F4A460', 'seagreen' => '#2E8B57',
'seashell' => '#FFF5EE', 'sienna' => '#A0522D',
'silver' => '#C0C0C0', 'skyblue' => '#87CEEB',
'slateblue' => '#6A5ACD', 'slategray' => '#708090',
'slategrey' => '#708090', 'snow' => '#FFFAFA',
'springgreen' => '#00FF7F', 'steelblue' => '#4682B4',
'tan' => '#D2B48C', 'teal' => '#008080',
'thistle' => '#D8BFD8', 'tomato' => '#FF6347',
'turquoise' => '#40E0D0', 'violet' => '#EE82EE',
'wheat' => '#F5DEB3', 'white' => '#FFFFFF',
'whitesmoke' => '#F5F5F5', 'yellow' => '#FFFF00',
'yellowgreen' => '#9ACD32'
);

//$name puede ser un nombre de color o un código rgb
//admitiremos nombres de color, RGB sin # y RGB con #
//En caso de que no sea ninguna de estas cosas retornaremos false

$name = strtolower(trim($name));

//Si es un nombre de color, lo devolvemos usando la tabla
if(isset($color_table[$name])) return $color_table[$name];

//Ajuste previo: ya que no es un nombre de color, solo puede
//ser un código RGB. Si empieza por # lo eliminamos para simplificar
if($name{0} == '#') {
$name = substr($name,1); //omitimos el #
}

//Solo puede ser un codigo RGB sin el # al principio o algo incorrecto

//comprobar si es un RGB correcto sin el #
if(!eregi("^[0-9abcdef]+$", $name)) {
return false; //no esta formado sólo por caracteres hex
} else {
//está formado solo por caracteres hex, comprobar si la longitud es correcta
//los codigos hex pueden tener longitud 2, 3 o 6
$l = strlen($name);
if(($l==6) || ($l==3) || ($l==2))
return '#'.$name;
else
return false;
}


}

private function check_tags(&$stack) {

/*
self::BB_QUOTES => true,
self::BB_VIDEO => false,
self::BB_LUSERS => true,
self::BB_MUSICRELS => true*/

//siempre habilitados....
$labels = array('b','/b','i','/i','u','/u','s','/s');

if($this->features[self::BB_COLOR]) {
$labels[] = 'color';
$labels[] = '/color';
}
if($this->features[self::BB_LINKS]) {
$labels[] = 'url';
$labels[] = '/url';
}
if($this->features[self::BB_IMAGES]) {
$labels[] = 'img';
$labels[] = '/img';
}


//Leemos toda la pila, lo que esté en nuestra lista de etiquetas válidas es
//dejado tal cual, lo que no es reconstruido
$new_stack = array();
foreach($stack as &$s) {

switch($s[0]) {

case self::BB_TYPE_LABEL:
if(array_search($s[1], $labels) === false) {
//La etiqueta no existe, guardamos su representacion textual
// (almacenada en el 3er elem. del label)
$new_stack[] = array(self::BB_TYPE_TEXT, $s[3], '');
} else {
//La etiqueta existe, la guardamos tal cual
$new_stack[] = $s;
}
break;

default: //es decir, BB_TYPE_TEXT, solo texto
$new_stack[] = $s;
break;
}

}

$stack = $new_stack;

}

public function parse($bbcode) {

//Operamos directamente sobre la variable $bbcode

//$bbcode = $this->escape_amp($bbcode);
$bbcode = str_replace('&', '&', $bbcode);
$bbcode = mb_convert_encoding($bbcode, 'HTML-ENTITIES', 'UTF-8');
$bbcode = nl2br($bbcode);
$pattern = array();
$replacement = array();

return $this->real_parse($bbcode);

}



}

$bb = new bbcode();
$bb->enable(bbcode::BB_COLOR);
$bb->enable(bbcode::BB_IMAGES);
//$bb->disable(bbcode::BB_LINKS);
echo $bb->parse('[color=#FF0000][b][i][u]red![/u][/i][/b][/color] & & ¿
[img]http://userserve-ak.last.fm/serve/160/328697.jpg[/img]
[img align="left"]http://userserve-ak.last.fm/serve/160/265995.jpg[/img]
[img align=left]http://userserve-ak.last.fm/serve/160/265995.jpg[/img]
[img align=right]http://userserve-ak.last.fm/serve/160/386255.jpg[/img]
[img align=center]http://userserve-ak.last.fm/serve/160/6371.jpg[/img]
[url]http://www.google.es/a[/url] - [url]http://www.google.es[/url] - [url]ftp://www.google.es/a[/url]
[url]ftp://pepe:1234@www.google.es/a[/url]
[url=http://www.google.es/dsgggggd/hds]Google[/url]
[url=http://www.google.es/search?q=hangar+18&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:official&client=firefox-a]Búsqueda hangar 18[/url]
[url]http://www.google.es/search?q=hangar+18&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:official&client=firefox-a[/url]
---------------
[b][url=http://www.google.es/dsgggggd/hds][color=]Google[/color][/url][/b]
[s]tachado[/s]

[img][b]black!
[color=purple][b]Deep Purple[/b][/color]
');


?>

Formulario de logeo en phpBB3

Si antes os enseñabamos como integrar phpBB3 en vuestra web ahora os damos el codigo para que inserteis un formulario para identificarse en phpBB3

<form method="post" action="/foros/ucp.php?mode=login">
Nick:<input name="username" type="text" value="" size="20" />
Password:<input name="password" type="password" size="20" value=""
/>
Recordarme <input type="checkbox" name="autologin" />
<input type="hidden" name="redirect" value="/index.php" />

<input type="submit" value="Entrar" name="login" />

</form>

AVISO: Acordaros de modificar la ruta del foro .

El campo oculto redirect sirve para que una vez identificados, se cargue una pagina. En este caso, se cargaría la pagina /index.html

Quedaría de la siguiente manera:

Nick:
Password:
Recordarme


Integra phpBB3 en tu web

Hoy te damos el codigo para que puedas integrar completamente el nuevo foro phpBB3 en tu web sin complicaciones :)
Debemos poner el siguiente codigo al principio de cada pagina en la que vayamos a necesitar algo de phpbb3, antes de enviar nada al navegador.

define('IN_PHPBB', true);
$phpbb_root_path = '/foros/';
$phpEx = substr(strrchr(__FILE__, '.'), 1);
include($phpbb_root_path . 'common.' . $phpEx);
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);

// Start session management
$user->session_begin();
$auth->acl($user->data);


Tener encuenta que $phpbb_root_path = '/foros/'; almacena la ruta donde está almacenado el foro. En nuestro caso esta en una carpeta llamada foros alojada en el directorio raiz.

Una vez añadido este código ya tenemos acceso a las variables de usuario del foro. Algunas de ellas son:
$user->data['user_id']; /* Devuelve el identificador del usuario conectado */
$user->data['is_registered'] /* TRUE si el usuario esta identificado FALSE en caso contrario */

martes, 1 de enero de 2008

Filtrar archivos de un directorio por extensión

Si has tenido que mostrar alguna vez las entradas de un directorio y has tenido que filtrarlas de alguna forma (para ver, por ejemplo, todos los archivos de texto, los archivos XML, las imágenes …) posiblemente lo hayas resuelto abriendo el directorio, leyendo una a una cada entrada, comparándola con lo que buscabas y, después de hacer lo que necesitas, cerrando el directorio.

Pues has hecho mal. Existe una forma mucho más rápida de hacerlo. En PHP desde la versión 4.3 se hace uso de una función también disponible en la biblioteca estándar de C llamada glob().

En PHP su uso es, como suele suceder con todas las demás, mucho más fácil que en C. Pero qué mejor que un ejemplo:

foreach (glob("*.txt") as $nombre_archivo)
{
echo $nombre_archivo ' con tamaño ',
filesize($nombre_archivo), " bytes\n";
}