28 abril, 2009

Código PHP para mostrar la ubicación de una IP o un visitante

Hace uso de las herramientas de iplocationtools.com, de myip.eu para la IP propia y de la API de Mapas estáticos de Google..

function locateIp($ip){
    $d = file_get_contents("http://iplocationtools.com/ip_query.php?ip=$ip&output=raw");
    if (!$d)
        return false; // error al abrir conexion
    $d= explode(",",$d);
    if ($d[1] != 'OK')
        return false; // codigo de estatus no valido
    $country_code = $d[2];
    $country_name = $d[3];
    $region_name = $d[5];
    $city = $d[6];
    //$zippostalcode = $answer->ZipPostalCode;
    $latitude = $d[8];
    $longitude = $d[9];
    // Devuelve datos como array
    return array('latitude' => $latitude, 'longitude' => $longitude, 'city' => $city, 'region_name' => $region_name, 'country_name' => $country_name, 'country_code' => $country_code, 'ip' => $ip);
}

// Para obtener la IP del visitante
function getIP(){
    if( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] )) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    else if( isset( $_SERVER ['HTTP_VIA'] ))  $ip = $_SERVER['HTTP_VIA'];
    else if( isset( $_SERVER ['REMOTE_ADDR'] ))  $ip = $_SERVER['REMOTE_ADDR'];
    else $ip = null ;
    return $ip;
}

// Para obtener la IP del propio servidor
function ownIP(){
 $ip= file_get_contents('http://myip.eu/');
 $ip= substr($ip,strpos($ip,'<font size=5>')+14);
 $ip= substr($ip,0,strpos($ip,'<br'));
 return $ip;
}

// Obtiene la información y la muestra
$rec= locateIp(getIP());

// es posible que la API de Google necesite una key. Solicitar en
// http://code.google.com/intl/ca/apis/maps/signup.html
// y ubicar la clave tras "&key=CLAVE"
echo '<img style="border:1px solid black;" src="http://maps.google.com/staticmap?center='.$rec[latitude].','.$rec[longitude].'&markers='.$rec[latitude].','.$rec[longitude].',tinyblue&zoom=11&size=200x200&key=" /><br/>',$rec['city'], ',', $rec['country_code'];

27 abril, 2009

Youtube: Una excursión por una granja de servidores de Google



45.000 servidores en 45 contenedores y un montón de tuberías.

En Youtube via simonwillison.net Notas: El botón HQ permite ver el vídeo en alta definición y es posible traducir los subtítulos:

23 abril, 2009

W3C Widgets

En QuirksMode Peter-Paul Koch hace una extensa descripción de este estándar que está pasando el lento proceso de aprobación por parte de la W3C.

Esencialmente, un widget es una aplicación web local estática con HTML/CSS/JavaScript que un usuario de móvil descarga una vez. Ángel Nieto ha realizado una traducción/resumen del artículo de Koch con ejemplo paso a paso incluido. Esperemos que el estándar se extienda y podamos disfrutar de una plataforma ubicua.

Mejorando Internet Explorer desde "fuera"

Es sólo un experimento de Andrea Giammarchi. Aprovechando que recientemente fue lanzado el último proyecto de Google (O3D, un plugin para traer toda la capacidad del hardware gráfico 3D al navegador y que incluye V8, el motor Javascript de Google Chrome ), ha hecho uso de ese motor para intentar mejorar el motor Javascript del propio navegador.

Los resultados son un incremento mínimo de la velocidad del 500% (algo que seguramente jamás alcance la tecnología de Microsoft, ya que no le interesa competir con su propio sistema operativo). Aunque las limitaciones son importantes, Andrea hace una reflexión al respecto de contar con esfuerzos de proyectos ajenos a Microsoft para mejorar ese navegador (yo mismo tuve registrado durante un año el dominio ie7.org con esa idea).

Pero si se piensa bien, Google ya hubiese podido hacer eso hace mucho tiempo. No sólo sabe como integrar su motor V8, además tiene la tecnología para hacerlo de forma transparente en cualquier navegador, y se llama Gears. Supongo que si no lo hace es para no iniciar ninguna guerra, aunque las ventajas de poder disponer de la máxima cantidad de elementos idénticos en todos los navegadores son tantas que miles de desarrolladores darían lo que fuese por disponer de esa posibilidad... ¿Hay alguien en Google escuchando?

21 abril, 2009

Interactive CouchDB

Un nuevo proyecto para mostrar interactivamente el funcionamiento de CouchDB ha sido publicado. Escrito 100% con JavaScript y jQuery, implementa los esquemas de colación, los algoritmos map/reduce, los documentos JSON sin esquema o la reducción incremental. Permite hacerse una idea de cómo funciona todo junto. También puede hacer las funciones de tutorial rápido de CouchDB.

Respecto al anterior artículo sobre usar CouchDB como interfície para el almacenamiento de datos en el navegador, quizás resultaría un buen impulso si se implementase como sistema alternativo de consulta sobre la pequeña base de datos SQLite que está convirtiéndose en estándar para usos ligeros. He buscado algún proyecto similar, pero no he encontrado nada.

Otra review sobre nuevas bases de datos

Sólo publicar el enlace ( http://randomfoo.net/2009/04/20/some-notes-on-distributed-key-stores ) y las conclusiones del autor: Tokyo Cabinet fue su elección entre MySQL, Voldemort, LightCloud, Cassandra, Dynomite, Hypertable, Scalaris, Memcachedb, Redis, CouchDB, MongoDB y Flare. Las razones son:

  • Rápido, maduro, muy bien documentado y con múltiples enlaces a varios lenguajes
  • Almacenamiento comprimido de elementos (ZLIB deflation)
  • Threading (multi-hilo)
  • Más de 1600 inserciones por segundo con 5 hilos en las pruebas del autor
  • Coste medio de búsqueda de un elemento en el orden de O(1)

20 abril, 2009

CouchDB en el navegador

Primero fue Google Gears. Ahora HTML5 incluye propuestas de estándar como Web Workers o almacenamiento local DOM, éste último con la forma de una base de datos ligera (generalmente implementada sobre SQLite). Y como toda base de datos, viene con un lenguaje SQL y con todas las variaciones del lenguaje que dependen de ella.

Las críticas no se han hecho esperar. Por ejemplo, Vladimir Vukicevic denunciaba lo inadecuado del lenguaje SQL para implementar consultas en el lado del cliente. Y lo cierto es que existiendo alternativas como CouchDB, es una auténtica lástima que no se imponga una solución aprovechando los elementos con los que ya contamos en el navegador: El DOM, XHTML, CSS y, en concreto, JavaScript. CouchDB es una base de datos orientada a documentos (definidos mediante JSON) y que utiliza funciones Javascript como mecanismo de filtrado (aplicado mediante la tecnología de MapReduce) en lugar del omnipresente SQL.

Y ha sido Atul Varma del equipo de Mozilla quien ha tomado el proyecto CouchDB de Damien Katz para implementarlo en el navegador. Aún se trata de una beta muy primitiva, pero ya permite visualizar su funcionamiento.

Sin duda, el sistema de consultas de CouchDB respeta mucho más la filosofía de programación en el navegador que SQL, hasta ahora utilizado principalmente en servidores. Aunque también es cierto que los desarrolladores tendemos ha tocar ambos mundos y resulta más coherente usar un mismo lenguaje en ambos sitios... ¿será hora de plantearse migrar a CouchDB en el servidor?

Esquemas JSON para la extensiones de Chrome

Para el sistema de extensiones del navegador Google Chrome, se ha optado por aprovechar la idea de GreaseMonkey ya que muchas de las extensiones de Firefox son manipulaciones sobre páginas web. Como un medio de simplificar la documentación y también para simplificar la verificación de los parámetros recibidos por las funciones, se ha propuesto el uso de esquemas JSON, que son una especificación de un formato basado en JSON para definir estructuras de datos JSON. Un esquema facilita un contrato sobre los requisitos de datos de una aplicación, como pueden ser modificados y el control de la interacción de esos datos.

La idea, propuesta en un primer momento por Aaron Boodman, y que ha sido detallado en estos artículos, es poder hacer lo siguiente:

// llamada a la función
chromium.tabs.createTab = function(tab, callback) {
  validate(arguments, arguments.callee.params); // validación de argumentos
  sendRequest(CreateTab, tab, callback);
};

// especificación del esquema (parámetros para la función)
chromium.tabs.createTab.params = [
  {
    type: "object",
    properties: {
      windowId: chromium.types.optPInt,
      url: chromium.types.optStr,
      selected: chromium.types.optBool
    },
    additionalProperties: false
  },
  chromium.types.optFun
];

Via Ajaxian.

17 abril, 2009

Jabbify, mensajería instantánea fácil en el navegador con Comet

Via Ajaxian. Traduzco:

Brian Moschel y Justin Meyer de JavaScriptMVC han abierto su cliente de chat Jabbify a un servicio Comet de propósito general llamado Jabbify. Algunas características son:

  • Escalado automático: Jabbify escala a miles de usuarios por dominio sin mantenimiento adicional por parte del programador.
  • Instalación instantánea: Descarga este script y en 30 segundos o menos ya estás desarrollando sobre Comet.
  • Simple: Es fácil. Realmente fácil. Todo lo que necesitas es la API Javascript o peticiones GET, tecnologías con las que la mayoría de desarolladores están muy familiarizados. Simplemente conecta y envía tu mensaje.

Aquí hay un gráfico que muestra como funciona el servicio:



A continuación se puede ver un ejemplo de cómo enviar un mensaje a todos los usuarios conectados a un dominio:
      <script type='text/javascript' src='jabbify.js'></script>
      <script type='text/javascript'>
        // suscripción a mensajes Comet entrantes
        OpenAjax.hub.subscribe("jabbify.message.create", function(name, results){ alert(name) });
        // conexión al servidor
        Jabbify.connect({name: "Brian"}, function(){
          // envía un "hola" a todos los usuarios conectados
          Jabbify.send("message", "create", { message: "hola" });
        })
      </script>
El servicio está en beta y su uso es gratuito. Es más será siempre gratis para websites con un pequeño número de usuarios concurrentes. Han intentado hacer que empezar a usarlo sea lo más fácil posible, generando mucha documentación y demos:

Nota: Hay otro servicio similar en frozenmountain.com

15 abril, 2009

Essential Selector - Motor de selección CSS ligero

Traduzco este artículo de Andrea Giammarchi sobre un nuevo motor ultraligero de selección de elementos DOM a partir de cuatro selectores CSS básicos:

Gracias a los nuevos métodos DOM introducidos recientemente en los navegadores más comunes (p.e. querySelectorAll) esperamos no tener que necesitar librerías completas para implementar los selectores CSS comunes. Hoy día, esta podría ser la base para crear cualquier tipo de motor de selección pero aún nos faltan los navegadores anticuados como Internet Explorer versiones 6 o 7, ambos muy lejos de los estándares W3 y con el motor Javascript más lento de la industria.

Al mismo tiempo, cualquier que sea el gran motor o API de selección que tengamos bajo control, los selectores más usados son realmente pocos:

  • #id
  • .class
  • tag
  • tag.class
Las razones detrás de este hecho son diferentes, pero en mi opinión la más válida es que los Desarrolladores Web usamos selectores CSS de la misma forma que creamos archivos CSS, y puesto que CSS se ha convertido en un estándar recientemente gracias al pleno soporte de Internet Explorer a CSS 2.1 (aunque otros navegadores funcionan con CSS3 desde hace mucho) nuestros archivos CSS y nuestros selectores serán así de simples durante un largo tiempo.

De acuerdo con eso, y ya que tenemos algunos buenos prototipos intermediarios como getElementsByClassName, todo lo que necesitamos es un motor de selección básico que sea capaz de recuperar los nodos de la forma más rápida posible.

Desde luego, si querySelectorAll está presente, este método será necesario, pero ¿qué hacer cuando no esté disponible?

La librería Sizzle es uno de los motores de selección más famosos, pero necesitamos "mover" 4KB de código minificado y comprimido (no es tanto pero a menudo es más de lo necesario) para obtener algo simple, especialemnte si los selectores indicados arriba son los que usamos en nuestro proyecto.

La librería Essential Selector


Quizás suene obvio, pero para cubrir los primeros 3 selectores de la lista necesitamos el rápido getElementById, el estándar getElementsByTagName y el aún no estándar getElementsByClassName, fácil de implementar en navegadores antiguos. ¿Y querySelectorAll? Superfluo en este caso, pero aún así bienvenido, obviamente. Los 4 selectores de arriba son los únicos considerados en mi pequeña librería: cerca de 1Kb minificada y comprimida, adaptada para librerías y/o desarrollo de GUI.

Se puede echar un vistazo directamente en el repositorio para comprobar que se comportará realmente rápido en cada navegador y que devolverá resultados en un tiempo razonable.

Filosofía de Essential Selector


Los selectores #id, .class, tag y tag.class serán rápidos para cada navegador mientras que los selectores más complejos dependerán del navegador. El foco principal está en los selectores más usados pero si decides usar uno más específico:

// Ejemplo de selector CSS
$e("div ul.myclass p");

los navegadores más modernos tardarán cerca de 1 milisegundo mientras que los más antiguos tendrán que llevar a cabo una modificación específica del CSS. Esto significa que los navegadores tendrán aproximadamente el mismo retardo para un selector como "div p" y "div p #content ul li.testcase" pero al menos, si el selector es compatible con el motor CSS del navegador, el resultado será el mismo para cada navegador.

Es más, debido a la ligereza de la librería, aquellos navegadores con errores no estarán perfectamente soportados. Por ejemplo, hay una versión de Opera que no comprende className en mayúsculas... bueno, ese no es nuestro problema, es un error específico del navegador de forma que debería resolverlo su creador. Lo mismo vale para casos extraños... vamos, no podemos considerar cada versión alfa/beta/inestable/intermediaria/vieja, así que si el CSS funciona, el navegador responderá como se espera.

Esta es la filosofía detrás de este simple motor de selección, en el que una búsqueda como

$e("div p")

tendrá sentido, mientras que otra como

$e("div[class^=whatever]")

no lo tendrá, a causa de ese selector aún no estándar.

Resumen


¿Quieres un selector ligero que funcione bien con entornos diarios? Prueba la librería Essential, y si no ya te dí una alternativa válida y plenamente compatible ;-)

14 abril, 2009

También en PHP

Aunque tampoco es soporte nativo (al igual que Javascript) como sería deseable, gracias al proyecto Quercus es posible ejecutar código PHP sobre la nueva máquina virtual Java de Google App Engine. Lo explican en PhpClasses.org

Para soporte nativo del resto de lenguajes, en especial PHP, Javascript, Perl o Ruby, tocará seguir esperando...

EcmaScript 5

Tras la polémica con la ya difunta propuesta de actualización 4.0 de Javascript/EcmaScript, se propone esta nueva versión con una serie de cambios menores:

  • nuevas propiedades internas de objetos y nuevas formas de acceder a ellos (via Object.defineProperty, Object.defineProperties, Object.getOwnPropertyNames)
  • poder establecer propiedades para los getters/setters (p.e. llamar a funciones cuando se establece o se obtiene un valor)
  • propiedades para poder establecer cómo los objetos pueden ser modificados y funciones para acceder a ellos y chequearlos (frozen, seal y preventExtensions)
  • poder establecer si un objeto es enumerable (p.e. si aparece en un bucle for…in)
  • adición al prototipo de array de las funciones map, reduce, reduceRight, filter, some, y forEach
  • una función Object.create de verdad en lugar de tener que hacerla a mano (¡por fin!)
  • JSON nativo (más por fin ;-)
Aún tardará en ser contemplada por los navegadores, pero esta vez, según afirman en Ajaxian, hay una diferencia: en esta propuesta ha participado Microsoft por lo que es de esperar (siendo ligeramente optimista) que esta vez llegará a todos los navegadores pronto. Ojalá.

13 abril, 2009

Helma NG sobre Google App Engine

Apenas han pasado unas horas desde que comenté que Rhino corría sobre la nueva versión Java de Google App Engine y la gente de Helma acaba de lanzar Helma NG, una versión de su framework JavaScript que funciona directamente sobre el motor de Google. via Simon Willison. Traduzco su artículo:

Con el anuncio de Google de soportar Java en App Engine aparecen de repente muchas nuevas opciones muy atractivas para alojar aplicaciones web basadas en Java. Desde luego, mi primer impulso fue comprobar si ejecutaría Rhino y Helma NG (tenía pocas esperanzas con Helma 1 ya que ejecuta un montón de hilos de fondo y confía mucho en soporte de base de datos relacionales o basada en archivos, ninguna de las cuales está disponible en App Engine).

Para mi sorpresa, Rhino funciona perfectamente sin modificaciones, y sólo tuve que hacer unos pocos cambios a Helma NG para conseguir que la aplicación demo funcionase en App Engine. Esto es algo en contradicción con lo que otros han experimentado, pero descubrí más tarde que tuve suerte de no encontrar ninguna SecurityException, pero por otra parte es virtud de Rhino por no hacer ninguna chapuza truculenta en su interior, y Helma NG de hacer todas sus lecturas de arhivos a través de una estructura de recursos unificada.

Este artículo cubre dos opciones, una usando la framework de aplicaciones web Helma NG y otra usando la interfície Jack para aplicaciones web Javascript. Ambas están actualmente por terminar y sujetas a cambios, pero son suficientes para mojarse los pies.

Prerrequisitos: Instalar el SDK de App Engine y Helma NG


Primero, instala el SDK de App Engine para Java conforme se describe en las páginas de Google. Ya estés usando el plugin de Eclipse o la línea de comandos del SDK, no debe haber diferencias. Yo uso Eclipse, pero las cosas deben ser similares con la línea de comandos.

Siguiente, necesitas Helma NG, que es efectivamente Rhino con una fina capa sobre él de funcionalidad relacionada con el servidor. Helma NG viene con su propia copia de Rhino ya que estamos usando algunas características experimentales de JS 1.8, pero esto podría cambiar pronto en cuanto esas características formen parte de una release de Rhino.

No ha habido una release de Helma NG recientemente por lo que hay que obtenerla de Subversion o Git. Para Subversion, el comando es:

svn co https://dev.helma.org/svn/helma-ng/trunk/ helma-ng

Para Git:

git clone git://github.com/hns/helma-ng.git

Necesitas Apache Ant para construir Helma NG. Cambia al directorio de helma-ng que has bajado (check out) y ejecuta ant en él con el objetivo/target "jar":

ant jar

Si todo ha ido bien, debes tener un archivo llamado lib/helma.jar.

Creando un nuevo proyecto de aplicación web


Una vez que está todo en su sitio, crea una nueva aplicación en App Engine. Con el plugin Eclipse haces esto usando el nuevo asistente de proyectos y seleccionando "Web Application Project" en la categoría Google. Pedirá un nombre de proyecto y un nombre para el paquete. El nombre del paquete no importa a menos que planees escribir código Java, pero es necesario indicar uno.

El nuevo proyecto deberá tener dos subdirectorios, "src" y "war". De nuevo, el directorio src es sólo relevante para el código Java, ya que pondremos directamente nuestro código Javascript en war/WEB-INF y nuestros archivos jar en war/WEB-INF/lib.

Ahora copia algunos archivo jar desde el directorio lib de Helma NG al directorio war/WEB-INF/lib del proyecto. Necesitarás probablemente los siguientes:

  • lib/js.jar
  • lib/helma.jar
  • lib/log4j-1.2.15.jar

App Engine tiene su propio servidor web por lo que no serán necesarios los archivos jar de jetty o de servlet.

A partir de aquí hay dos opciones: Ejecutar la aplicación usando el framework de Helma NG o usando la interfície Jack. La primera opción está sujeta a un rediseño profundo, mientras que la segunda no está terminada, por lo que usa tus herramientas sabiamente :-)

Ejecutando aplicaciones de Helma NG


Para ejecutar la aplicación demo de Helma NG sigue los siguientes pasos:
  1. Copia los directorios de módulos desde el directorio de Helma NG a war/WEB-INF de forma que el directorio resultante sea war/WEB-INF/modules.
  2. Copia la aplicación demo desde apps/demo a war/WEB-INF de forma que el directorio resultante sea war/WEB-INF/demo.
  3. Copia o mueve el directorio static dentro de la aplicación demo dos niveles arriba al directorio war/static.
  4. Edita el archivo web.xml en el directorio war/WEB-INF para que parezca esto, o simplemente copia el archivo.

Ya está. Guarda todos los cambios y pulsa el botón verde de ejecución en Eclipse para iniciar el servidor de desarrollo. Si todo funciona conforme a lo previsto, deberías tener acceso a la aplicación demo en http://localhost:8080/.

Nota: El framework de aplicaciones web Helma está actualmente en estado de rediseño general. Si estás buscando una plataforma de desarrollo estable, recomiendo esperar hasta la inminente versión 0.3.

Ejecutando aplicaciones Jack


Helma NG provee un servlet para ejecutar aplicaciones Jack sin usar la propia infraestructura modular de Helma. En este modo, obtienes un entorno de ejecución (runtime) Javascript relativamente desnudo que cumple totalmente con la propuesta de ServerJS Securable Modules.

Copia el directorio modules desde el directorio de Helma NG a war/WEB-INF de forma que el directorio resultante se llame war/WEB-INF/modules, pero para un entorno mínimo, copia sólo los dos siguientes archivos:
  • modules/global.js para una funcionalidad básica como la carga de módulos y recursos.
  • modules/helma/jack.js para funciones de ayuda usadas por el servlet Jack

Ahora crea un directorio llamado war/WEB-INF/myapp, y crea un archivo en su interior llamado main.js con el siguiente contenido:

  function handler(env) {
    return [200, {"Content-Type": "text/plain"}, "Hello World!"];
  }

Finalmente, edita el archivo war/WEB-INF/web.xml para que se parezca a esto o descárgalo y sobreescríbelo.

Guarda todos los cambios y pulsa el botón verde de ejecución en Eclipse para iniciar el servidor de desarrollo. Si todo funciona conforme a lo previsto, deberías tener acceso a la aplicación demo en http://localhost:8080/.

Si no quieres o necesitas Helma NG, otra opción para ejecutar Jack sobre App Engine es usar la librería Jack original de Tom Robinson.

Nota: El soporte de Jack sobre Helma NG es uy novedoso y, por tanto, bastante incompleto. Siéntete libre de rellenar los agujeros que encuentres.

10 abril, 2009

Los navegadores desde 1996

Asa Dotzler de Mozilla publica esta elocuente gráfica sobre el uso de los navegadores a lo largo de estos 13 años de Internet:



Destacan la curva de adopción que apenas ha variado desde el 97, la enorme adopción del eterno rechazado Microsoft Internet Explorer, la relativa poca importancia de Netscape pese a que en su día fue el navegador y las brechas crecientes de Firefox, Chrome, Safari y Opera.

via Ajaxian

09 abril, 2009

Javascript en Google AppEngine con Rhino

Desde hace unas horas, Java es el nuevo lenguaje disponible para Google App Engine (via Google Dirson), y con él la posibilidad, como explican en este blog de usar Rhino para ejecutar también Javascript.

Se trata de un simple experimento, y posiblemente para aplicaciones grandes convendrá esperar a que Google ofrezca la posibilidad de usar directamente JavaScript. En cualquier caso, un miembro de Google, Steve Yegge, estaba portando el framework Ruby On Rails a Javascript (sobre Rhino, precisamente) como proyecto personal, por lo que no es descartable que antes o después se publique otra ampliación de Google App Engine.

Addendum: Parece que también Scala puede ser ejecutado, aunque la restricción de no usar hilos probablemente impedirá que los actores de Scala funcionen.

02 abril, 2009

Google desvela detalles de sus servidores

Google es conocida por utilizar hardware clónico para sus propios servidores. En este artículo de CNET se desvelan, por fin, detalles de su forma de actuar.

Algunos detalles: en lugar de usar SAIs a nivel de centro de datos y fuentes de alimentación redundantes, cada servidor tiene su propia batería de 12V. Los servidores se agrupan en contenedores estándar que albergan 1160 unidades cada uno.



Google uncloaks once-secret server via Simon Willison.

Addendum: En Google Dirson publican dos vídeos:



Dojo 1.3

Nueva versión de esta completa librería del siempre interesante Alex Russell. Sólo destacar la coincidencia con TaskSpeed, un conjunto de pruebas de rendimiento que ofrecen este espectacular resultado (las barras más cortas son mejores):



Aunque como recuerda Andrés Nieto, no es necesario que sea la mejor librería técnicamente para que la comunidad la prefiera sobre las demás:



Dojo 1.3. Via Ajaxian

Últimos links en indiza.com