links for 2008-10-09

links for 2008-10-08

¿Qué es linux y por qué lo uso?

Linux vs Windows

Acabo de leer una entrada que intenta explicar qué es Linux en 10 frases a personas que no lo conocen; aunque es certero en lo que señala, creo que es una mala pésima forma de presentar Linux a un novato. Si en la primera frase habla del Kernel, en la segunda, el principiante salió corriendo. Eso es seguro.

Sin duda, creo que las distros modernas de Linux,  como Ubuntu o CentOS, son sistemas robustos, seguros y amigables con el usuario que no quiere ni debe ser un experto. De hecho, no hay nada más fácil y confiable que instalar programas con Synaptic o Yum. Pero la verdad es que intentar explicar qué es Linux en 10 frases me parece estéril, sobre todo si esperamos con ello convencer sobre las bondades del pingüino.

Lo digo porque llevo 11 años usando Linux y aunque he visto infinidad de veces la cara de envidia que ponen los usuarios Windows el ver mi escritorio con Compiz y Cairo-Dock, ninguno se ha atrevido a instalar Linux por su cuenta (a uno le gusta Quanta para trabajar, pero igual tiene su notebook con Windows y añora tener un Mac).  Yo mismo comencé alternando entre Windows 95 y Redhat 5.0 en 1997, y luego entre Win XP y SuSe; vicio que dejé sólo hace 3 años cuando me hice fan de Ubuntu.

Es cierto que desde los ’90 hasta ahora Linux ha evolucionado muchísimo como Sistema Operativo orientado al uso de Escirtorio Personal, primero emulando a Mac con Compiz-Fusion (Beryl) y ahora entrando con fuerza en el mercado de los NetBooks con versiones ligeras y adaptadas al uso de la Red como Ubuntu Netbook Remix o la versión Xandros para el EeePC de Asus.

A pesar de esto, creo que los usuarios se resiste a cambiar sus hábitos frente al computador. Sin ir más lejos, esta semana  Microsoft nuevamente ha aunciado que extenderá “la vida” de Windows XP y tanto MSI como Canonical han tenido que salir a dar explicaciones frente a la noticia sobre alto número de Netbook’s con linux que devueltos por usuarios que no quieren complicarse la vida aprendiendo un nuevo Sistema Operativo.

Por eso creo que ni 100 razones son suficientes para cambiarse de Sistema Operativo (Linux no es más que eso) si antes no se está dispuesto a cambiar de vicios hábitos y eso requiere tiempo. Aunque hay dos hábitos que se olvidan rápido: correr el antivirus como paranoico y reiniciar el equipo como necio.

PD. Sabía usted que Windows también tiene un Kernel. plop!

Problemas comunes I: Max File Uploads en PHP

Como programador y administrador de servidores muchas veces me encuentro con problemas simples que, por diversas razones, se repiten cada cierto tiempo. Algunas veces son tareas que fueron realizadas en  proyectos antiguos que nadie recuerda o conoce; otras, en cambio, se pierden en la trivialidad de lo cotidiano y, por lo tanto, no están debidamente documentadas para que el resto de las personas con las que trabajo puedan resolverlas por su cuenta.

La idea entonces es crear y compartir algo así como un repositorio de soluciones rápidas a estos problemas comunes. Por tanto, si se animan, espero que en los comentarios pregunten lo que sea pertinente al tema expuesto o propongan nuevos problemas.

Problema: aumentar tamaño máximo para subir archivos con PHP

Estamos trabajando con un gestor de contenidos como Wordpres o Drupal y necesitamos subir mediante un formulario archivos PDF, PNG o DOC que pesan sobre 2 MB, pero resulta que no se puede y nos sale un mensaje de error.

El problema no es del gestor de contenidos. La configuración por defecto de PHP en un servidor Linux permite copiar o subir archivos desde la máquina local al servidor que tengan un tamaño máximo de 2MB. Aunque no es recomendable aumentar esta cuota en entornos poco protegidos o públicos es posible hacerlo de la siguiente forma:

serumax@bunbury:~$  sudo nano /etc/php5/apache2/php.ini
[sudo] password for serumax:

Ingresamos la clave sudo de nuestra máquina y con CTRL+W procedemos a buscar “upload_max_filesize“:

;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;

; Whether to allow HTTP file uploads.
file_uploads = On

; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =

; Maximum allowed size for uploaded files.
upload_max_filesize = 2M

Nos fijamos que el parámetro file_uploads esté en On y donde dice upload_max_filesize = 2M reemplazamos por el tamaño que necesitamos, pero ojo con el tiempo de ejecución de los script en PHP, que por defecto es de 30 segundos (se archiva un nuevo draft) y si subimos un archivo muy grande esto puede verse afectado.

Por ejemplo, podemos aumentarlo a 5 Megas:

; Maximum allowed size for uploaded files.
upload_max_filesize = 5M

Guardamos con CTRL+O y salimos con CTRL+X.  Con esto ya hemos hecho lo más díficil. Ahora sólo nos resta volver a iniciar Apache, sí Apache, para  que los cambios tengan efecto. Esto porque PHP generalmente corre como módulo de Apache

serumax@bunbury:~$sudo /etc/init.d/apache2 restart
[sudo] password for serumax:

o mejor solo recargamos la nueva configuración

serumax@bunbury:~$sudo /etc/init.d/apache2 reload
[sudo] password for serumax:

Como comentario final, este ejemplo lo hice pensando en un servidor Linux  Ubuntu 8.04, con Apache2 y PHP5. Espero que sea de utilidad 🙂

El drama de getElementsByClassName

Hace rato que uso la librería jQuery por lo que me resulta súper fácil manipular elementos HTML por su su clase, independiente de su tagName (a, div, span, etc). Por ejemplo en una breve y simple líena puedo darle display:none a todos los elementos con clase hide:

//lo simple es bello
$(‘.hide’).hide();

En Prototype (que no ocupo desde que comencé a usar jQuery), aunque era un poco más complejo y limitado, tampoco daba muchos dolores de cabeza:

//Sólo hay que dominar bien los selectores tipo CSS de Prototype
$$(‘div.hide’).invoke(‘hide’);

Incluso era posible de esta forma:

//iteramos sobre cada elemento
documetnt.getElementsByClassName(‘hide’).(Element.hide);

Pero resulta que la función getElementsByClassName() aún no es un estándar (lo que significa
que obviamente no funciona de froma nativa ni en IE6 ni en IE7, pero sí en Firefox3, Safari y Chrome), por
lo tanto, para que funcione en IE debe estar soportada por la librería que ocupemos.

En el caso que estemos trabajando sin ninguna librería o que no esté soportada (por ejemplo en las versiones nuevas de Prototype está obsoleta), la podemos implementar fácilmente con el siguiente código:

document.getElementsByClassName = function(cl) {
var retnode = [];
var myclass = new RegExp(‘\\b’+cl+’\\b’);
var elem = this.getElementsByTagName(‘*’);
for (var i = 0; i < elem.length; i++) {
var classes = elem[i].className;
if (myclass.test(classes)) retnode.push(elem[i]);
}
return retnode;
};

Referencias:

Tips para .htaccess

Quienes trabajan con WordPress y URL’s amigables en los permalinks seguramente habrán tenido que retocar pelear más de alguna vez el archivo .htaccess (hypertext access).

En el caso de las rewrite rules de WordPress lo que se hace es redirigir todas las peticiones al servidor web al archivo index.php, salvo  que el archivo o la carpeta que se está solicitando en la URL exista realmente en el servidor, pues, de ser así, prevalecerá dicha condición:

Reglas de redirección de WordPress
En este caso se necesita tener activado el módulo rewrite.load de Apache

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Por otra parte, se establece que se trabajará en la raíz (document root) del servidor web, lo que se puede cambiar fácilmente modificando los parámetros RewriteBase y RewriteRule de una forma que sea coherente.

# el espacio entre el “.” y el “/” no es casual
RewriteBase /folder
RewriteRule . /folder/index.php [L]

Pero lo cierto es que a través del archivo  .htaccess se puede hacer bastante más que redirigir URL’s

Habilitar la navegación del directorio

Options +Indexes
## bloquea algunos tipos de archivos para mostrar
IndexIgnore *.wmv *.mp4 *.avi

Deshabilitar la navegación del directorio

Options All -Indexes

Personalizar mensajes de error

ErrorDocument 403 /forbidden.html
ErrorDocument 404 /notfound.html
ErrorDocument 500 /servererror.html

Hacer que los SSI trabajen con HTML/SHTML

AddType text/html .html
AddType text/html .shtml
AddHandler server-parsed .html
AddHandler server-parsed .shtml
# AddHandler server-parsed .htm

Cambiar la página por defecto (en el siguiente orden)

DirectoryIndex mihome.htm index.htm index.php

Bloquear el acceso al sitio a ciertas IP

order deny,allow
deny from 202.54.122.33
deny from 8.70.44.53
deny from .spammers.com
allow from all

Permitir el acceso sólo a usuarios de la red local (LAN)

order deny,allow
deny from all
allow from 192.168.0.0/24

Redireccionar visitantes a Nueva Página/Carpeta

Redirect viejapagina.html http://www.midominio.com/nuevapagina.html
Redirect /viejacarpeta http://www.midominio.com/nuevacarpeta/

Bloquear el acceso al sitio a ciertas referencias

RewriteEngine on
RewriteCond %{HTTP_REFERER} site-to-block\.com [NC]
RewriteCond %{HTTP_REFERER} site-to-block-2\.com [NC]
RewriteRule .* – [F]

Bloquear el acceso a nuestros ficheros desde otros servidores (Hot Linking)

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://(www\.)?midominio.com/.*$ [NC]
RewriteRule \.(gif|jpg)$ – [F]

Mostrar un mensaje cuando se acceda desde otros sevidores a nuestros ficheros
Agrega la siguiente línea al código para bloquear el acceso a nuestros ficheros desde otros servidores

RewriteRule \.(gif|jpg)$ http://www.midominio.com/no_robes.gif [R,L]

Hacer invisible el archivo .htaccess (o cualquier otro)

order allow,deny
deny from all

Evitar el error 500

# Avoid 500 error by passing charset
AddDefaultCharset utf-8

Conceder el acceso CGI a una carpeta

Options +ExecCGI
AddHandler cgi-script cgi pl
# To enable all scripts in a directory use the following
# SetHandler cgi-script

Cambiar la extensión del script

AddType application/x-httpd-php .gne
gne será ahora tratado cómo un archivo PHP, se puede hacer lo mismo con x-httpd-cgi para archivos CGI, etc.

Ahorrar ancho de banda
Unicamente si utilizas PHP

php_value zlib.output_compression 16386

Apagar las magic_quotes_gpc
Solamente si utilizas PHP

php_flag magic_quotes_gpc off

Referencias

  1. http://enespanol.com.ar/2006/04/03/tutorial-de-htaccess/
  2. http://www.desarrolloweb.com/manuales/htaccess-para-urls-amigables.html
  3. http://www.desarrolloweb.com/articulos/pasar-url-a-buscadores-con-rewriterule.html
  4. http://www.desarrolloweb.com/articulos/introduccion-htaccess.html

Producir plantillas HTML con wget

Seguramente muchas veces un cliente les ha pedido un sitio completo y enorme sólo en HTML. O sea, nada de utilizar PHP, Ruby o Python, ni menos hablar de un CMS como Drupal o WordPress. Si es así, entonces sabrán lo tedioso que se vuelve modificar una pequeña parte del sitio en una centena de plantillas cuando éste ya está prácticamente listo.

Por suerte en linux existe una pequeña pero poderosa herramienta llamada wget, que sirve para descargar sitios completos.

Con wget y un poco de ingenio podremos producir las plantillas HTML que necesitamos, pero usando nuestro gestor de contenidos favoritos. Para conseguirlo, por ejemplo, podemos usar reglas de reescritura en el .htaccess para que los archivos .html sean tratados tal como uno .php; también sería posible usar un pequeño y muy básico modelo MVC para que según la variable $_SERVER[“REQUEST_URI”] (quitando los slashes y  la extension .html con ereg_replace o split) se pueda obtener el nombre de la plantilla HTML/PHP que deseamos utilizar.

En index.php:
if (file_exists(“/ruta_template/”.$mvc->uri.’.php’)){
include(“/ruta_template/”.$mvc->uri.’.php’);
}

Y en .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Y finalmente descargamos con wget usando sus opciones:

  • recursive: descarga el sitio web completo.
  • domains misitio.org: no descarga enlaces fuera de website.org.
  • no-parent: no sigue los enlaces fuera del directorio micarpeta/html/.
  • page-requisites: obtiene todos los elementos que componen la página (imágenes, css, javascript)
  • html-extension: guarda los archivos con extensión .html (ojo con esto que no lo he probado y seguro nos ahorra harto trabajo)
  • convert-links: convierte los enlaces para que puedan trabajarse fuera de línea.
  • restrict-file-names=windows: modifica el nombre de archivos para que también funcionen en Windows.
  • –no-clobber: no sobrescribe ningún archivo existente (en caso de reanudar una  descarga interrumpida)

Debug PHP en Firebug

Desde que entendí cómo funcionaba firebug se ha vuelto una de mis extensiones favoritas de firefox para desarrollar aplicaciones Jacascript y, también, para solucionar problemas de CSS y HTML, incluso por sobre web developer.

Pero como la mayor parte del tiempo estoy trabajando con formularios y validaciones que corren sobre PHP necesitaba tener una funcionalidad similar para este lenguaje. Sin embargo, pese a haber probado algunas herramientas que me prometían el cielo de la depuración no encontré nada que funcionase fácilmente y bien. En otras palabra, ni Pear ni FirePHP fueron opción. PHP_debug, por otra parte, se me hizo muy atractivo de usar en algún momento, pero como también corre sobre Pear, me terminó desencantando.

Determinado a conseguir un depurador que pudiese usar con Firebug, me propuse crear uno, pero en eso encontré un pequeño script que hizo la magia.

Lo nuevo de jquery 1.2

La librería jquery se ha transformado en mi preferida, tanto así que dejado de usar prototype, incluso en AyerViernes, por una cuestón de kb, ya es la librería oficial de los proyectos en curso.

El 14 de enero salió la versión 1.2.2 bug fix release que trae algunas cosas nuevas, entre las que destaca una mejora en la función .ready(), pues ahora puede usarse tanto de la forma tradicional como a través de .bind()


$(document).bind("ready", function(){
// put all your jQuery goodness in here.
});

o bien


$(document).ready(function() {
// put all your jQuery goodness in here.
});

Puedes ver lo nuevo de jquery 1.2.2 en su anuncio oficial