lunes, 5 de abril de 2010

Conversiones entre "encodings" sin pérdidas

Hace un tiempo comentaba los problemas que surgían cuando se trabaja con diferentes "encoding".
Lo más seguro hoy en día es trabajar con el mismo "encoding" en todas las capas y sistemas: bases de datos, ficheros php, plantillas html, ficheros js, configuración del servidor web, ...
Lo malo es que no siempre esto es posible. Muchas veces tenemos que integrar contenidos o hacer que dos sistemas diferentes interaccionen y cada uno puede estar configurado de diferente manera.
Para estas tareas de conversión, existen muchas herramientas y funciones. Por ejemplo, en PHP tenemos la función iconv(). Es muy sencilla de utilizar:
string iconv ( string $in_charset , string $out_charset , string $str )

El problema que surge a menudo es cuando estamos pasando de un encoding más "rico" (p. ej., UTF-8) a otro más restringido en caracteres (p. ej., ISO-8859-1). Si se aplica la función sin más, se nos puede cortar la cadena que estamos convirtiendo cuando se encuentra con un carácter extraño al "encoding" de destino (las famosas "comillas tipográficas" de los procesadores de texto, por ejemplo, dan muchos problemas).
Afortunadamente, la función iconv() está preparada para estos casos. Si se utiliza el parámetro $out_charset con la cadena //TRANSLIT, los caracteres problemáticos pueden ser convertidos a un carácter similar en el "encoding" final:
$txtFinal = iconv("UTF-8", "ISO-8859-1//TRANSLIT", $txtOriginal);

jueves, 18 de febrero de 2010

martes, 22 de diciembre de 2009

Enlaces y "popups" accesibles

A veces nos surge la necesidad de forzar que un enlace se abra en una ventana nueva o "popup". El problema es que debemos mantener el HTML válido para que estos enlaces sean seguidos por motores de búsqueda o puedan ser utilizados por navegadores sin Javascript.

En todos los sitios se ve el típico tutorial que dice "... utiliza el window.open() de Javascript ...". Efectivamente, hay que usarlo, pero sin obstruir ni hacer HTML chapucillas.

Vamos a presentar 3 formas de abrir un "popup", una "mala" y dos mejores.
  1. Con HTML "guarrete":
        onclick="window.open('http://davidasorey.net',
            'popup1', 
            'height=800,width=600,resizable=1,scrolling=1')">Enlace 1

    Fatal. El destino de este enlace está "falseado". A veces también nos podemos encontrar algo como:
    <a href="void(0)">
    Esta forma de hacer los "popups" puede ser aceptable sólo si explícitamente queremos que este enlace no se siga.

  2. Un poco mejor, dejando un href correcto:

    <a href="http://davidasorey.net/" target="popup2"
        onclick="window.open('', 
            'popup2', 
            'height=800,width=600,resizable=1,scrolling=1')">Enlace 2</a>
    
    
    Aquí jugamos con el atributo "target". El evento "click" abre una ventana "vacía" pero con un identificador "popup2". Cuando el navegador va a abrir el enlace, ya encuentra una ventana con este identificador y abre el enlace en esta nueva ventana.
    Es una mejora, desde luego: el enlace ya es un enlace "real" e indexable.

  3. Una solución sin Javascript "inline":

    <a class="popup3" href="http://davidasorey.net/">Enlace 3</a>

    Obviamente, esta es la solución más limpia, pero requiere un poco más de trabajo adicional.
    Con jQuery (se puede hacer con cualquier otra librería o "framework") hay que "capturar" todos los enlaces con la clase "popup3" y alterar su comportamiento:
    $(document).ready(function (d) {
     $('a.popup3').click(function (e) {
      e.preventDefault();
      var href = $(this).attr('href');
      window.open(href, 
                 'popup3', 
                 'height=800,width=600,resizable=1,scrolling=1');
     });
    });

    En pocas líneas alteramos el comportamiento de todos los enlaces con la clase 'popup3'. Nos ahorramos andar escribiendo el código Javascript en el evento onclick y todo el código y control de este comportamiento está en un sólo punto.

miércoles, 2 de diciembre de 2009

Manifiesto: "En defensa de los derechos fundamentales en internet"

Algunos argumentos o puntos de este "manifiesto" me chirrían un poco. Que conste que no estoy defendiendo este anteproyecto, en absoluto, pero si queremos que no salga adelante, las argumentaciones deben ser más sólidas.
Punto 4 del manifiesto: "La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural. [...]"

Según el proyecto, "los órganos competentes podrán imponer a los prestadores de servicios que vulneren la propiedad intelectual en Internet el cese en tal práctica o la retirada del material". ¿Cómo puede esto afectar negativamente a un nuevo creador que, por ejemplo, publica su obra en la red con alguna licencia libre? ¿Entorpece en algo esto a un compositor o a un guionista? No veo la relación.
Punto 5 del manifiesto: "Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades asociadas a sus creaciones. [...] Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo."

¿Quiénes somos nosotros para dictar a un trabajador cómo debe plantear su negocio? ¿Me puede sugerir alguien alguna alternativa viable para una multitud de autores y artistas que no viven del directo?
Estoy realmente cansado de leer y escuchar la típica frase "... los músicos quieren vivir de las rentas ..." o "... que dejen descargar la música gratis y ya les veremos en directo ...". Quien argumenta así, no se ha parado a pensar en las "características" de la profesión "artista". Simplifican y aplican los mismos parámetros que podrían ser aplicables a  unos pocos artistas superventas privilegiados al resto.

La vida de muchísimos músicos es muy dura (ojo, estoy hablando de músicos, no de triunfitos ni nada similar). Años y años de estudio, inestabilidad laboral, en muchos casos, conciertos y giras en una furgoneta noche tras noche (no todos viajan en "jets" o superautocares lujosísimos). Hay que amar mucho a una profesión para dedicarse a esto y no dejarlo por una plaza fija en un conservatorio o en una academia. Me parece que eso no es tratar de "vivir de las rentas".

Se critica que los autores traten de vivir "de las rentas" y de que sus ingresos en un modelo basado en el control de las copias. Pongamos de nuevo el ejemplo de un compositor, para más "transversalidad", de bandas sonoras de cine.

Si su banda sonora gusta mucho a la gente, se reproducirá muchas veces, en radio, en los cines que pasan la película, en locales de ocio, venderá discos con la grabación de su obra, etc. ¿Cómo podemos remunerarle si no es con el control de las copias vendidas, emisiones de su obra, etc? ¿Alguna alternativa? Este señor (o señora) no se gana la vida dando conciertos. Componer es muy difícil. No se escribe una orquestación en diez minutos en la servilleta de un bar.
Si nos ponemos en términos mercantilistas (lo cual odio), este señor (o señora) ha sido muy productivo: su trabajo ha tenido mucha repercusión. Es lógico y deseable que se le remunere en proporción a ello, y la forma más directa que se me ocurre es midiendo la difusión de su obra (copias vendidas, emisiones radiofónicas, etc).

¿Qué pasa con los músicos de estudio? ¿Y con los guionistas? ¿Y con los ingenieros de grabación? ¿Cómo evaluamos lo que debemos pagarles? ¿Un fijo mensual? ¿Alguien se compromete?

Los artistas y creadores suelen ser trabajadores autónomos (no en el sentido legalista del término) y viven de "vender" su trabajo. Si deciden comerciar su trabajo con un determinado modelo, nuestra decisión como "consumidores" (odio  escribir en estos términos hablando de creación artística) es "adquirir" o no el producto.

Lo que hay que criticar es la voracidad de algunas discográficas y productoras (no todas son el demonio, no seamos simples, por favor), la falta de control y transparencia de algunas entidades de gestión y la imposición de un canon chapucero e inadecuado.

Vuelvo a citar el texto del manifiesto: "[...] y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo [...]".

Mas argumentación chapucera. Primero: en Internet sí es posible tener un control de las "copias" vendidas o, para ser más correcto, de las emisiones de una obra. Es técnicamente factible y sencillo.
Segundo: "deberían buscar otro modelo". No puedo estar más en desacuerdo. Si un artista publica con una licencia o modelo que me desagrada, no lo leo, o escucho, o veo. Así de sencillo. Si nos empeñamos en acceder a la obra de esta persona contrariando sus deseos o forma de comercializarla, somos nosotros los que estamos vulnerando su derecho a elegir cómo llevar su negocio.

Soy desarrollador de software, me gustan las licencias libres y los pocos programas que he escrito fuera de mi trabajo los he licenciado abiertos y me gusta que la gente se los descargue. Pero no puedo pretender que todos los desarrolladores de software piensen como yo. Si un programa me gusta y no es gratuito tengo dos opciones: lo compro o no lo uso. Si me lo descargo o pirateo estoy vulnerando el derecho del autor (particular o empresa) a comercializar su obra como le apetezca.

La anterior sí que es una analogía válida y no las muchas simplonerías que se pueden leer por la red. Es válida porque habla de un producto inmaterial (un software), al igual que un bien cultural; que puede distribuirse en un soporte físico o por la red, como muchas creaciones de autores; y además está sujeto a la misma problemática: las descargas indeseadas de la obra (lo cual algunos llaman piratería).

Y aquí llegamos al meollo de la cuestión: la "piratería". No voy a entrar en el terreno legal, en el cual parece que está clara una cosa: la copia privada no es un delito ni nada que se le parezca. Se paga un (injusto) canon por cada soporte físico que se compra para compensar a los autores e industria por las copias originales que han dejado de vender.

¿Puede entenderse la distribución a través de la red de obras como copia privada o es una vulneración de alguna ley o reglamento?
Éste es el punto clave. No soy abogado y lo que he podido leer (y entender) es que no es un delito, aunque puede ser considerado un ilícito civil (no sé ni lo que significa).

Independientemente de su legalidad o alegalidad, personalmente, no puedo prescindir de analizar los factores éticos. Que algo sea legal para mí no es condición suficiente para que deba hacerse. En mi escala de valores personal, también debe ser legítimo, o ético, o como quieran llamarlo. Lo que me da realmente pena no es que la discográfica o el triunfito de turno vendan menos copias por las descargas, sino el montón de gente desconocida que vive de esta industria y que ve reducidos sus ingresos.

Eso sí, intentar frenar este fenómeno es como ponerle puertas al campo. Por cada medida de protección o cortapisa que se inventen, saldrá un parche o "hack" que lo evite o anule. Y lo que no puede hacerse es que para evitar este fenómeno se invada la esfera de la intimidad y se viole un derecho fundamental.

Para acabar, mis conclusiones:

El canon por los soportes es injusto porque se aplica indiscriminadamente, independientemente del uso que se le da al soporte. Debería cambiarse.

La recuadación que hacen algunas entidades de gestión es también injusta por su falta de transparencia y equitatividad para con sus socios. Su actuación debería ser pública y supervisada.

Muchas discográficas, productoras y artistas están en la inopia. El modelo de mercado está cambiando. El soporte físico desaparece, la cadena de distribución tendrá menos intermediarios. Deberían adaptarse a estos cambios, pero no podemos obligarles. Están en su derecho si quieren seguir en el Paleolítico. Desaparecerán.

Este anteproyecto de ley es injusto porque pretende violar un derecho fundamental, que es la inviolabilidad de las comunicaciones si no media un mandato judicial. No debe salir adelante.

Pero por favor, arguméntenlo bien, no digan sandeces y no mezclen churras con merinas. No nos hace ningún favor a nadie.

Este es el texto completo que está circulando por la red. Aunque no estoy plenamente de acuerdo con todos los puntos, como ya he expuesto, me parece interesante difundirlo:
Ante la inclusión en el Anteproyecto de Ley de Economía sostenible de modificaciones legislativas que afectan al libre ejercicio de las libertades de expresión, información y el derecho de acceso a la cultura a través de Internet, los periodistas, bloggers, usuarios, profesionales y creadores de internet manifestamos nuestra firme oposición al proyecto, y declaramos que...

  1. Los derechos de autor no pueden situarse por encima de los derechos fundamentales de los ciudadanos, como el derecho a la privacidad, a la seguridad, a la presunción de inocencia, a la tutela judicial efectiva y a la libertad de expresión.

  2. La suspensión de derechos fundamentales es y debe seguir siendo competencia exclusiva del poder judicial. Ni un cierre sin sentencia. Este anteproyecto, en contra de lo establecido en el artículo 20.5 de la Constitución, pone en manos de un órgano no judicial -un organismo dependiente del ministerio de Cultura-, la potestad de impedir a los ciudadanos españoles el acceso a cualquier página web.

  3. La nueva legislación creará inseguridad jurídica en todo el sector tecnológico español, perjudicando uno de los pocos campos de desarrollo y futuro de nuestra economía, entorpeciendo la creación de empresas, introduciendo trabas a la libre competencia y ralentizando su proyección internacional.

  4. La nueva legislación propuesta amenaza a los nuevos creadores y entorpece la creación cultural. Con Internet y los sucesivos avances tecnológicos se ha democratizado extraordinariamente la creación y emisión de contenidos de todo tipo, que ya no provienen prevalentemente de las industrias culturales tradicionales, sino de multitud de fuentes diferentes.

  5. Los autores, como todos los trabajadores, tienen derecho a vivir de su trabajo con nuevas ideas creativas, modelos de negocio y actividades asociadas a sus creaciones. Intentar sostener con cambios legislativos a una industria obsoleta que no sabe adaptarse a este nuevo entorno no es ni justo ni realista. Si su modelo de negocio se basaba en el control de las copias de las obras y en Internet no es posible sin vulnerar derechos fundamentales, deberían buscar otro modelo.

  6. Consideramos que las industrias culturales necesitan para sobrevivir alternativas modernas, eficaces, creíbles y asequibles y que se adecuen a los nuevos usos sociales, en lugar de limitaciones tan desproporcionadas como ineficaces para el fin que dicen perseguir.

  7. Internet debe funcionar de forma libre y sin interferencias políticas auspiciadas por sectores que pretenden perpetuar obsoletos modelos de negocio e imposibilitar que el saber humano siga siendo libre.

  8. Exigimos que el Gobierno garantice por ley la neutralidad de la Red en España, ante cualquier presión que pueda producirse, como marco para el desarrollo de una economía sostenible y realista de cara al futuro.

  9. Proponemos una verdadera reforma del derecho de propiedad intelectual orientada a su fin: devolver a la sociedad el conocimiento, promover el dominio público y limitar los abusos de las entidades gestoras.

  10. En democracia las leyes y sus modificaciones deben aprobarse tras el oportuno debate público y habiendo consultado previamente a todas las partes implicadas. No es de recibo que se realicen cambios legislativos que afectan a derechos fundamentales en una ley no orgánica y que versa sobre otra materia.


miércoles, 23 de septiembre de 2009

Algunos fallos tontos en el desarrollo web con PHP

¿A qué desarrollador web no le ha pasado alguna vez tener algo que no funciona, probar mil cosas y luego darse cuenta que era un error o fallo trivial? Para tirarse de los pelos, ¿verdad? Voy a relatar algunos.

  • ¿Por qué no entra por el if?
    Este es típico: un if que controla una sóla condición. Ejemplo en PHP, pero aplicable a cualquier lenguaje -excepto Python :-)
    loQueSea();
    if ($varControl)
    hazAlgo();
    otraCosa();

    Al cabo de un rato piensas que  si entra por el if, además debes cambiar otra variable y escribes:
    loQueSea();
    if ($varControl)
    hazAlgo();
    $otraVarControl = true;
    otraCosa();

    Y nunca consigues que otraVarControl se quede a true. ¿Qué pasa aquí? Fácil: no hemos puesto llaves al if.
    Conclusión: aunque el if sólo controle una sentencia, mejor con llaves siempre. Al final siempre va a haber más de una sentencia bajo ese if:
    loQueSea();
    if ($varControl) {
    hazAlgo();
    $otraVarControl = true;
    }
    otraCosa();


  • ¡No pilla los cambios!
    Es la típica llamada de un cliente (o un jefe): ¡me has dicho que cambiaste el XXX y no lo veo, sigue como antes!
    Nuestro XXX puede ser un fichero .js, un .css, una imagen o cualquier otro tipo de recurso que estamos seguros que hemos actualizado y que aún así, nos dicen que no lo ven.
    A los desarrolladores web no nos gustan mucho las cachés, ni proxies, etc, y además nos conocemos todos los típicos trucos para hacer un refresco completo de la página, pero nuestros jefes, clientes y usuarios sí que utilizan cachés (en el navegador, en su proxy). Además no se saben esos "mágicos" atajos de teclado que utilizamos sistemáticamente (Ctrl-Shift-R, Ctrl-F5 en IE) para ver cómo va nuestro trabajo en el navegador.
    Solución: forzar el refresco. Supongamos el siguiente HTML que incluye un .js sobre el cual hemos hecho cambios importantes:



    ...

    Subimos el fichero actualizado al hosting o servidor de producción, hacemos la llamada o enviamos el correo de rigor ("oye, ya está hecho") y al rato tenemos el típico "yo lo veo como antes".
    Nuestro fallo: presuponer que el entorno del usuario es el mismo que el nuestro. Puede que esté navegando a través de un proxy (suelen guardar en caché los elementos que le solicitan), su navegador puede estar configurado para que también "cacheé" algunos recursos, etc.
    La solución más fácil es añadir un "query string" a la llamada al recurso. Esto nos garantiza que será tratado como un fichero diferente y cargado de nuevo:



    ...

    Nos da igual cuál es esta "query string", simplemente lo que queremos es que todos los proxies, navegadores y demás clientes entiendan que es un recurso diferente. Este truco es válido para CSS, imágenes, swf. Por ejemplo, en la regla CSS:

    div.cabecera {background-image: http://mi.servidor.com/img/fondo.png?r=1}

    Si se tiene todo el trabajo integrado en un sistema de control de versiones, es muy útil configurar nuestro "deploy" para que este "parámetro" tome siempre el número de versión. Si estamos desarrollando la aplicación todavía, el truco infalible para que el navegador siempre lea los recursos como "nuevos" es hacer las llamadas así en nuestro fichero .php:



    <script src="fichero.js?version=" type="text/javascript">
    <link href="fichero.css?version="  rel="stylesheet" type="text/css" />

  • Página en blanco, no se ve nada. ¿Qué falla?
    Este típico error suele pasar cuando PHP está configurado para no mostrar ningún error (lo más recomendable en producción). Las soluciones son dos:

    • Editar el php.ini y cambiar el ajuste "display_errors" (nada recomendable).

    • Escribir la siguiente instrucción para saltarnos este ajuste para un "script" en concreto:
      <?php
      ini_set('display_errors', 1);
      // Sigue nuestro script

      La función ini_set() permite ajustar parámetros de configuración para un script determinado. Es muy útil cuando algo falla y no vemos dónde.



  • Los usuarios de mi aplicación no pueden hacer "login", o unos acceden al perfil del otro.
    Este es un error bastante insidioso y puede tener diferentes orígenes. Hay que conocer cómo maneja PHP las sesiones: PHP asigna al usuario una 'cookie' única con el identificador de sesión. En el servidor se guardan ficheros de sesiones en un directorio, un fichero para cada sesión 'asignada' a un usuario. Problemas potenciales:

    • El usuario no está aceptando cookies: en este caso es imposible que PHP asocie una sesión y sus datos con un usuario. Se puede configurar para que PHP mande el identificador de sesión en la URL, pero no es nada recomendable. Se puede comprobar si el usuario acepta cookies intentando enviarle una y leyéndola a continuación. Si no la tenemos, sacamos una advertencia al usuario.

    • El directorio del servidor donde se guardan las cookies no está accesible (problemas de permisos, falta de espacio, etc).

    • Si tenemos una configuración con balanceo de carga (varios servidores atendiendo a la misma URL) tenemos que asegurarnos que una vez que un usuario 'entra' por un servidor, sigue siempre en el mismo servidor. Otra solución es guardar las sesiones en una base de datos en vez de almacenarlas como ficheros.




Hay muchísimos más fallos tontos que nos podemos encontrar, pero éstas son algunas de las que más tiempo me han hecho perder ;-)