Mostrando entradas con la etiqueta Programación. Mostrar todas las entradas
Mostrando entradas con la etiqueta Programación. Mostrar todas las entradas

09 diciembre 2016

Errores de programación: PhP

Este error es un ejemplo de cómo unas máquinas que, aparentemente, funcionan de manera del todo lógica, no se comportan de manera lógica.

En PhP, cuando se quiere que el intérprete dé información acerca de los errores, algo que es fundamental para un programador, es necesario saltarse la configuración por omisión del servidor. Para ello, es usual, con el propósito de asegurarse de que es posible cambiar la configuración, poner al principio del archivo PhP que se desea depurar, lo siguiente:

error_reporting(E_ALL);
ini_set("display_errors", 1);

El primero define los errores que van a mostrarse (todos) y el segundo, configura la directiva que hace que se muestren por pantalla.

Bien. Muchas veces, cuando se tiene un archivo llamado, por ejemplo, archivo_con_errores.php, sigue uno las especificaciones del manual (y recordad que eso de fiarse de la documentación no es buena práctica, a menudo), pone las dos líneas de código de antes al princpio de su archivo (sí, detrás de la etiqueta de apertura del modo PhP) y se encuentra que, aún poniendo errores a conciencia, el navegador te devuelve una pantalla vacía.

Entonces se va uno a los comentarios de php.net. Se encuentra uno de hace diez años o más que comenta que cuando le pasa lo que acabo de describir a él se le soluciona creando un archivo php nuevo, que voy a llamar depurador.php, donde escribe lo siguiente:

error_reporting(E_ALL);
ini_set("display_errors", 1);
include("archivo_con_errores.php");




Lo primero que pensé al verlo fue: tiene muchos años y lo que propone es absurdo. Está haciendo lo mismo que poner esas dos líneas delante del archivo, ya que el comando "include" agrega el contenido del archivo que se le pasa como argumento al fichero actual.

Pues sí, esto sí funciona. Incomprensible.

19 noviembre 2016

Errores de programación: no te fíes siempre de la documentación

Hoy vengo con algo que no es estrictamente un error de programación, sino, más bien de especificaciones.

Estoy trabajando en un código PhP que lea correos de una cuenta POP3 normal y corriente. Creo la cuenta siguiendo las instrucciones del proveedor, el cual indica que sus correos están protegidos por SSL y dice que hay que usar el puerto 993 para el protocolo IMAP y el 995 para el POP3.

Con toda inocencia, me quiero conectar al servidor de correo usando la función imap_open, utilizando como nombre del servidor:

{Servidor de correo del proveedor:993/imap/ssl}INBOX

Como ya soy programador viejo, me digo a mí mismo: "esto no va a funcionar". En efecto. Mi servidor se queda pensando y pensando y se queda la página en blanco. Después de varias ediciones del código, descubro que al poner la ruta en el navegador, en vez de, por ejemplo, email.php había puesto emaiil.php (dos "i") y el servidor en vez de tener el detalle de decirme "página no encontrada", intentaba ejecutarla y me daba una pantalla en blanco.

Cuando escribo correctamente el nombre del php, lo que me salta es "Error 500" porque el "script" estaba tardando mucho tiempo. Y yo sin saber qué pasaba, aunque sospeché que imap_open trataba de abrir el buzón y como algo lo bloqueaba, acababa excediendo el tiempo límite.

Después de muchas vueltas, decido intentar entrar por Telnet (que en los Windows nuevos ya no está instalado por omisión y hay que instalarlo). En Telnet, imap en el puerto 993 o pop3 en el 995 no entran; el servidor te echa. O es un problema con el ssl o con el certificado del servidor (o que este te rechaza si entras desde fuera, que de todo te encuentras en estas redes). Intento las opciones /notls y /novalidate-cert, lo que resulta inútil, y se me ocurre intentar la entrada por los puertos 143 y el 110, los estándar si no hay ssl.

Al final, funcionó el 110 con pop3...

Moraleja: diga lo que diga el dueño del servidor, si no puedes entrar a la primera, prueba las configuraciones por omisión, las de toda la vida y luego, si te interesa, rómpete la cabeza para que entren las que el proveedor de servicios te dice.

Moraleja 2: usar telnet te hace sentir poderoso... puedes leer un buzón de correo hablando directamente con el servidor (tú le das órdenes y el responde OK). Resulta gratificante, parece que eres un experto en ordenadores y todo.

10 septiembre 2016

La versión de código abierto de Age of Empires II: 0.A.D.

Ayer hablaba de la Batalla por Wesnoth. Hoy comentaré brevemente otro juego de código abierto que no conocía y que tampoco he probado. Se trata de una versión mejorada de Age of Empires II cuya web oficial es:

Web de 0 A.D.

La mayor diferencia es que la versión que uno puede descargarse es una "Versión Alpha", esto es una versión funcional, que se puede probar y depurar, pero que aún no está completa. De todos modos, según he leído, esta versión "alpha" es jugable y le queda muy poco para estar completa.

Está desarrollado, también, en C++. Para entornos Windows, es posible descargarse el código fuente para Visual Studio 2013, de manera que se puede usar el entorno de desarrollo de Microsoft para compilar el código.

¿Lo conocíais? ¿Lo habéis jugado?

09 septiembre 2016

Battle for Wesnoth o Batalla por Wesnoth

Leí hace unos días un artículo sobre los cinco mejores juegos "open source" que se pueden descargar gratuitamente. El artículo en concreto es el siguiente:

Los cinco mejores juegos de código abierto

De ellos me han gustado especialmente dos. Hoy hablaré de uno de ellos y otro día del otro. El primero es uno que ya conocía, pero al que perdí la pista hace varios años. Se trata de Battle of Wesnoth cuya web (en inglés) es:

Battle for Wesnoth

Lo más interesante de este tipo de juegos es que, aparte de binarios precompilados, es posible bajarse el código fuente del juego. Si te gusta la programación es algo que disfrutas. En el caso de Battle for Wesnoth, para compilar en entornos Windows puede hacerse son el Visual C a partir de la versión de Visual Studio 2008.

El juego, como podéis imaginaros, está programado en C++. ¿Conocéis el juego? ¿Habéis jugado?

04 septiembre 2016

Código Javascript para generar números aleatorios

Hoy publico un "script" en Javascript muy sencillo que permitirá mostrar en la pantalla del navegador un número aleatorio entre una cantidad máxima y otra mínima. En este caso concreto, el máximo será 100 y el mínimo 1, y marcaré en negrita donde están tales valores, de manera que el lector pueda cambiar el rango de valores.

El código javascript es el siguiente:

var num_aleatorio;

//Números de 1 a 100
num_aleatorio= 1+Math.round(Math.random()*(100-1));
document.write(num_aleatorio);


Como puede verse, este código suma a 1 un número aleatorio entre 0 y 99, dado que Math.random() va a devolver un número aleatorio decimal entre 0 y 1, y Math.round() redondeará el valor obtenido.

Una forma de utilizarlo es encerrarlo entre <script type="text/javascript"> y <script> y grabar el texto en un archivo .htm. De esa forma, se abre el archivo con el navegador y mostrará el primer número. Al recargar la página con el navegador, el "script" devolverá un nuevo número.

Si se desea una lista de números, separados con espacio, el código, para obtener 31 números, sería;

var num_aleatorio;
for (i=0;i<=30;i++)
{
//Números de 1 a 100
num_aleatorio= 1+Math.round(Math.random()*(100-1));
document.write(num_aleatorio+" ");
}


Y habría que tener en cuenta lo comentado anteriormente.





01 septiembre 2016

Mi presencia en las redes sociales

Desde bastante tiempo antes de dejar en suspenso esta bitácora, entré por curiosidad en otras redes sociales. Digo otras porque considero que la "blogesfera" ha sido, y sigue siendo, una red social, con la salvedad de que es abierta y está formada por varias aplicaciones de software web. A diferencia de Facebook o Twitter, donde todo el mundo se abre sus cuentas en un mismo sitio, para crear un blog hay muchas opciones: wordpress, blogger, livejournal e, incluso, wordpress es una aplicación de descarga gratuita que puedes montar en tu propio servidor.

En esta entrada, voy a poner cuatro cuentas que mantengo en Facebook y Twitter junto con el número de seguidores que tengo en cada una. Cuando termine septiembre, volveré a poner los números y nos reíremos, o lloraremos, según cómo se hayan modificado. De mayor a menor número de seguidores:

Página del Portal de Ciencia y Medio Ambiente. (página de Facebook dedicada a la ciencia y el medio ambiente). Seguidores: 817

Twitter de @sinciforma (ciberocupación del Twitter con el nombre de mi empresa. Hablo de ciencia, tecnología...). Seguidores 796.

Twitter de @jcuquejom (mi Twitter personal, dedicado a promover las cosas que escribo y que leo. Consideradlo un Twitter de autor). Seguidores: 341.

Página de Sinciforma (página de Facebook dedicada a mi empresa. Prácticamente sin contenido...). Seguidores: 28.

Si tenéis Twitter o Facebook, dejadlos en comentarios y los veo y sigo.

25 julio 2015

Errores de programación: PhP y las fechas

Este error de programación me ha gustado mucho, porque es tan absurdo y desconcertante que, cuando lo descubrí, me reí mucho. Voy a presentarlo despacio porque lo merece.

Supongamos, en primer lugar, que creo una cadena de fecha de la siguiente manera:

$dia_cad=date("d-m-Y");

Esto pretende reproducir la introducción de una fecha que venga por post rellena en un formulario, ya que estoy desarrollando un "script" de prueba de una función más compleja que maneja fechas. Bien, sigo con las pruebas y utilizo esta cadena para crear un DateTime de la siguiente manera:

$dia=date_create($dia_cad);

Necesito mostrar la fecha que representa ese día en un formato que una base de datos pueda entender. Según una llamada a print_r, descubro que invocando:

$dia->date

consigo una fecha en formato "AAAA-MM-DD HH:MM:SS" lo que es perfecto. Por tanto, al ejecutar este código:

$dia_cad=date("d-m-Y");

$dia=date_create($dia_cad);

print_r($dia);

echo $dia->date;

Se muestra, por ejemplo, como resultado de la última línea "2015-07-25 11:11:11". Genial. Yo, muy contento, elimino la línea de print_r($dia) y veo que nada funciona. La línea echo $dia->date; no devuelve nada. Tras una media hora de revisar, vuelvo a invocar print_r($dia) para ver si esa variable se vacía por algún motivo raro. Y vuelve a funcionar. Y al rato lo descubro:

¡¡Si no utilizo previamente print_r, $dia->date no devuelve nada!!

La solución es sencilla. En vez de la última línea, si quiero una cadena de fecha en el formato que quiera a partir de un DateTime, invoco simplemente:

$dias->format('Y-m-d H:i:s');

Pero ¿a que ha sido un error muy divertido?

22 enero 2014

Errores de programación (nueva edición)

Un artículo breve para hablar de errores de programación, concretamente, de un despiste que estoy empezando a cometer ya demasiadas veces. Se produce cuando programo en PhP.

Suponed que defino una variable, que se pasa por POST, al principio de un archivo PhP que graba o modifica un registro de una base de datos:

$variable=$_POST["variable"];

El valor de $variable puede ser, pongamos "nueva" o "modificar". Para determinar en qué caso estamos, escribo un "if" así:

if ($variable='nueva')
{
   // Se ejecuta la creación del nuevo registro.
}
else
{
   // Se modifica el registro.
}

En el código anterior está el fallo. El caso es que al ejecutarlo, resultaba que siempre ejecutaba la creación del nuevo registro, nunca la modificación. Casi media hora revisando las cabeceras HTML, viendo los valores de la variable $variable... Hasta que di con el error de casualidad.

¿Aún no habéis visto el error? Es fácil. La línea correcta del "if" es:

if ($variable=='nueva')

Esto es, en PhP $variable='nueva' es una asignación, esto es, la variable $variable pasa a valer 'nueva'. En cambio $variable=='nueva' es una evaluación lógica, esto es, PhP mira si $variable contiene el valor 'nueva'. Si lo contiene, devuelve "true", en caso contrario, "false". Yo estaba poniendo como condición lógica una asignación, que no devuelve en principio lo que tiene que devolver, y daba ese efecto extraño.

Un simple = me trajo por la calle de la amargura anoche...

21 octubre 2009

Errores de programación, capítulo 5

Llevo una temporada sin escribir. Ando muy atareado con diversos asuntos, como ya os habréis imaginado. Y, claro, ya tengo mis nuevas anécdotas como programador. Algunas se me han olvidado, pero esta no...

Supongamos una función de Visual Basic. Supongamos que tengo una variable global, booleana, llamada, por ejemplo, Supervariable. Ya de por sí, programar con variables globales, aunque sean variables visibles sólo en un formulario, valdría como error de programación, o al menos, como mala práctica de programación, pero cuando hay prisa...

Bien. Yo necesitaba ejecutar una función, que devolvería un valor u otro, con la sentencia Return, en función de determinadas circunstancias. Y cumpléndose ciertas condiciones, debería dar un valor True o False a la variable Supervariable. Pues bien... No había manera... Supervariable no cambiaba de valor ni de broma, siempre tenía el original (True, creo). Tras cerca de una hora, revisando el código, veo cambiarle de valor a tal variable, se hacía sólo en un par de líneas, y se hacía correctamente. Esas líneas eran tales que así (el código es inventado):

If Condicion1>5 then
' Calcular el valor de Aux...
Return Aux
' Y cambiar el valor de Supervariable
Supervariable=False

Else
' Calcular el valor de Aux cuando no se cumple que Condicion1 sea mayor que 5
Return Aux
' Y cambiar el valor de Supervariable
Supervariable=False

End If

¡Por supuesto! Dejad de leer si queréis adivinar cuál es el fallo... La solución unas líneas más abajo. Supongo que debería descansar un poco más, desconectar, relajarme algún día a la semana, y entonces, no tendría estos fallos tan absurdos.





SOLUCIÓN: A ver. La sentencia Return dentro de una función, devuelve, como resultado de la ejecución de la misma, el valor que ésta dará lugar al ser llamada. Así, si escribo:

Return 1

la función devolverá 1. Además, Return acaba la ejecución de la función en ese mismo punto.

Entonces... ¡¡todo el codigo que ponga inmediatamente a continuación de una sentencia Return no se ejecutará nunca!! Por eso nunca se modificaba Supervariable; la función terminaba su ejecución en la línea anterior.

16 junio 2009

Errores de programación, capítulo 4

Otro error muy gracioso de los que a mí me gusta cometer en PhP.

Si estáis trabajando con un formulario HTML, de esos en que uno o más elementos "input" son de tipo archivo (file), a la hora de poner la etiqueta form, su nombre, el valor de "method" y de "action", que no se os olvide indicar enctype="multipart/form-data", si no no funciona.

Si no lo ponéis, la variable superglobal $_FILE se queda vacía.

04 junio 2009

Errores de programación, capítulo 3

Este error es tan breve como estúpido. Estoy creando un formulario que deberá ejecutar un archivo PhP al pulsar un botón definido como input. Hasta aquí, trivial. Por algún motivo que aún no comprendo, en vez de poner input type="submit", como llevo haciendo toda la vida, me da por poner input type="button"... ¿Consecuencia? Dos o tres horas perdidas, desesperado, sin explicarme como un formulario que está bien escrito no hace nada al pulsar el botón...

Claro que no hace nada. un input de tipo "button" no tiene acción asociada, y deben definirse eventos para que se disparen al pulsarlo... Si pulsas un botón de tipo "button" no envía el formulario. Y que haya perdido casi dos horas con eso...

10 abril 2009

Errores de programación, segunda temporada, capítulo 2

Pues nada, un error de los que a mí me gustan, de esos que te hacen perder un tiempo delante del ordenador que estaría mejor aprovechado haciendo algo más agradable (nótese el tonillo irónico en "gustan" :-D). Esta vez, es con PhP.

Dice la teoría que tanto la función "header" de php, que redirige la ejecución del código a otra página, como la función "session_start()" sólo pueden utilizarse antes de que se envíe cualquier información a la pantalla dentro del archivo php en que se ubiquen. Así, no puedo llamar a "echo", o incluir código HTML antes de llamar a cualquiera de ambas funciones. Ello se debe a que en el protocolo HTTP, las cabeceras son lo primero que se envía, y ambas funciones envían información en las cabeceras del mencionado protocolo. Vale.

Incluyo ambas funciones en un archivo en PhP, miro cuidadosamente el código para asegurarme de que no envío nada delante, cosa que es correcta. Y... como el lector ya adivinará, falla. Ni idea de por qué. Me dedico a hacer pruebas y pruebas, y a perder un tiempo que podría haber empleado en salir de casa, en leer un libro o, por qué no, en jugar a algo (que mi nueva máquina y su supertarjeta gráfica se tragan ahora cualquier cosa). Por supuesto, todos los intentos infructuosos hasta que en una web perdida de Internet, gracias a buscar el error, al cuarto o quinto intento, leo algo tan misterioso como:

"A mí me funcionó quitando los espacios en blanco del archivo XXXXXX.php"

¿Espacios en blanco? Me da por revisar mi archivo PhP, y caigo en la cuenta de que la primera línea es "_< ?", donde _ es un espacio en blanco y < ? es cómo se le indica al servidor que, a partir de ahí, voy a ejecutar código php. ¿A que no sabéis lo que hice? Sí, exacto: borrar el espacio. Y funcionó perfectamente. Ni me había dado cuenta de que había un espacio ahí.

10 febrero 2009

Nueva temporada: Errores de programación.

He tenido abandonada la bitácora durante una buena temporada, básicamente, por exceso de trabajo. Y buena parte de la culpa de este exceso de trabajo la ha tenido un proyecto en C++ para móviles que ejecuten el sistema operativo Symbian, ideado por Nokia. Y, la verdad, ha sido una experiencia tan frustrante que me voy a desahogar en mi bitácora. Ahora me río, pero seguro que aquellos que programen de modo profesional, sabrán lo divertido que es pasarse horas y más horas intentando arreglar un error desconocido. Tengo tantas anécdotas que tengo cuerda para rato. Así que, sin más preámbulos, a por la primera.

Las aplicaciones en Symbian usan bastante los archivos de recursos, con extensión rss. Son interesantes, ya que encapsulan el aspecto estético de los controles de las interfases de usuario (Ui para los amigos). Pero luego están los compiladores... En mi caso, la extensión Carbide para Visual Studio .NET 2005.

Resulta que incorporo una serie de datos en un archivo de recursos. El compilador los lee y compila, y genera otro archivo de extensión rsg, en el que se listan los recursos que hayas definido y los códigos numéricos que los identifican. Todo recurso que no esté en el rsg que se incorpora en tiempo de compilación da lugar a errores de "Undefined identifier". Aunque claro, esto es la teoría.

En la práctica, el compilador, siguiendo unas pautas que él sabrá, no te genera un rsg, sino tres o cuatro, que te reparte en diversas carpetas de tu código fuente y de los SDK, y en función de determinadas configuraciones, te escoge uno de ellos. Pues bien. Incorporé ese recurso, como os había dicho, me sale el error ese de identificador desconocido. Veo el rsg que estaba en el sitio esperable y me encuentro con que la lista de recursos es correcta... o sea que eso estaba bien. Corto y pego el rsg que estaba en el sitio esperable, a ver si lo ha creado mal y nada. Limpio el proyecto... nada. No había explicación y creí que era que estaba mal construido el recurso...

Después de demasiado tiempo, se me ocurre plantearme si no será que la opción de limpiar no funciona. Hago una búsqueda del rsg y me salen cuatro. Revisando uno a uno me encuentro que uno de los cuatro no tiene el nuevo recurso, ¡¡¡¡y era el único de los cuatro que el compilador miraba!!!! Me limité a borrarlo y arreglado.

Y en la próxima entrada de la serie, más.

09 agosto 2008

Leído Ajax, guía práctica para usuarios, de Francisco Charte Ojeda (VIII)

Entre novela y novela he tenido tiempo de leerme esta guía fantástica sobre AJAX, el famoso sistema de programación web en el que se escribe buena parte de la llamada Web 2.0, y que está llamado a dotar de mucha más versatilidad a las páginas web.

En realidad, AJAX no es más que la combinación de diferentes tecnologías ya existentes: JavaScript, XML, DOM y lenguajes del lado del servidor como PhP o ASP, así que no estamos hablando de una tecnología, sino de una forma de trabajar con diferentes protocolos.

Así, utilizamos XHTML y CSS (hojas de estilo) para generar la interfaz de la aplicación en el navegador, JavaScript para encapsular la lógica, para asignar eventos a botones y elementos de la interfaz, el famoso objeto XMLHttpRequest, invocado desde JavaScript para la comunicación (síncrona o asíncrona, pero lo más interesante es esto último) con el servidor, y PhP, ASP u otro lenguaje de servidor para el acceso a base de datos almacenadas en el mismo.

Este libro es una guía de introducción, así que trata todas las tecnologías involucradas en AJAX a nivel muy elemental, pero lo que enseña basta para crear pequeñas aplicaciones web realmente sorprendentes. El libro tiene códigos de ejemplo que se pueden, incluso, descargar desde la página de la editorial. Asimismo, ofrece abundantes vínculos y dedica un capítulo a las API de AJAX más populares (Prototype, script.aculo.us y otras) y a los entornos de depuración y desarrollo más usuales.

Con este librito ya sé lo básico para empezar a construir aplicaciones en AJAX. Es muy recomendable.

02 enero 2008

Errores de programación (VI)

Viendo las estadísticas de las páginas web que administro, descubrí que en una de ellas se hacía referencia a un servidor brasileño, puesto como argumento de un parámetro pasado por GET. Hace meses, pasó lo propio con uno ruso y nunca le había prestado atención hasta ahora. Algún lector ya sabrá lo que está pasando, pero, para los demás, voy a seguir con el suspense.

Me pongo a indagar y descubro que están intentando redireccionar a un archivo que es un código en PhP bastante elaborado. Me cuesta muy poco tiempo descubrir que es cosa de "hackers" (Nota para hackers: los denomino "hackers" porque no han causado ningún daño en mis páginas... en otro caso, los llamaría "crackers"; que no se me enfade nadie). Bueno, el caso es que lo que he sufrido han sido ataques (o intentos, que ya digo que no he observado nada raro en mis páginas) de "deface". Esto del "deface" es, básicamente, entrar en un servidor de un tercero y manipular sus páginas. Por ejemplo, introducir una firma en la página principal, cambiar una imagen por otra... Es relativamente simple de hacer en cualquier página programada en PhP o ASP y, supongo, los daños que puedan hacer en el servidor dependerán de la configuración de seguridad del mismo.

Pues bien... Revisando el código de PhP de las páginas que administro, descubrí un error en una de ellas que las hacía vulnerables a uno de los tipos más simples de ataque de "deface". Tres líneas estúpidas que me dejé olvidadas después de copiar y pegar y que permitían incrustar código. Por eso lo considero error de programación.

Las páginas son obra de mi hermano, que es el que sabe PhP. Yo me limito a retocar el código, porque sé muy poco de ese lenguaje. Resulta que una regla básica de seguridad es no incorporar al código HTML que devuelve el PhP ninguna cadena que se haya introducido por POST o por GET. En caso contrario, basta con que el "hacker" copie y pegue el código que desea ejecutar en el formulario inseguro, o que cambie la URL interna para incrustar un fichero alojado en otra parte. Lo primero no es problema, lo segundo, mi hermano lo había mirado. De hecho, ahora es muy difícil que ese método vuelva a funcionar.

No quiero dar detalles para no dar pistas. El caso es que las diferentes secciones de la página se cargan de forma dinámica, usando una variable que pasamos por GET que se gestiona de manera que sólo pueda tomar una serie de valores. Si alguien cambia la URL en el navegador, o bien se produce un error, o bien se muestra una página prefijada, salvo en un sitio concreto, en que, por defecto, reenviaba a una página donde se incluía el valor de la variable. De todos modos, creo que lo que nos ha salvado es que la inclusión no era directa, de manera que las URLs formadas desde un servidor externo serían erróneas.

Ya está corregido, de manera que esa vulnerabilidad ha dejado de existir, aunque seguiremos estudiando el código por si acaso. Cuidado si, en vuestras estadísticas, descubrís algo como inurl:"index.php?var=*.php", porque es una de las formas en que se busca a las "víctimas".

08 noviembre 2007

Consecuencias en visitas de un cambio de servidor

Desde que empezó el mes, hemos estado bastante atareados con la página web de mi empresa. La historia es curiosa. Todo empezó cuando utilicé el excelente Ranking de Emezeta para evaluar la calidad de la página de mi empresa. Gracias al autor del ranking, supe que mi servidor devolvía la cabecera HTTP 200 cuando se intentaba acceder a una página inexistente bajo nuestro dominio, lo que no creo que le hiciera mucha gracia a Google.

Como eso podía afectar al posicionamiento, me puse en contacto con nuestro proveedor y tras un intento infructuoso de devolver las cabeceras correctas personalizando las páginas de error, nos proponen un cambio de servidor, de uno que ejecutaba php 4 a otro que funciona con PhP 5. Ojo que no ha sido un cambio de dominio sino de servidor.

Las consecuencias han sido variadas. En primer lugar, el código en PhP tenía incompatibilidades con PhP 5, referentes, en su mayoría, al uso de variables globales. El hecho de que la directiva register_globals ahora esté en "off", y sea recomendable que siga así, ha supuesto que variables que se pasaban por GET o por POST ya no estén accesibles directamente. Por ejemplo, pasar una URL así: programa.php?vble=valor, requiere ahora hacer, en las primeras líneas de programa.php, algo del estilo de $vble=$_GET["vble"]. Acceder directamente a $vble supone recuperar una variable vacía.

Me ha llevado una buena serie de ratos cambiar este tipo de cosas y hacer otras dos que hacían falta desde hace tiempo. La primera provenía de cómo estaba hecha la página antes. Anteriormente, sólo podíamos ejecutar archivos PhP dentro de una carpeta llamada cgi-bin, lo que obligaba a hacer una horrible redirección con Javascript desde index.html, que colocabamos en la raíz del servidor a cgi-bin. Esto está solucionado, ya que el nuevo servidor acepta como página por defecto index.php. Supuso un lío bastante grande al obligar a modificar rutas, pero ya está hecho. La segunda ha sido crear un Sitemap, que es sencillo pero tedioso (y no he terminado).

Lo bueno es que el servidor es ahora un poco más rápido y funciona mejor. Lo malo, que las visitas a la página se han reducido, exactamente, a cero. Se debe a que todas las URLs que están indexadas en Google contienen cgi-bin, cosa que ya no es así y que no he podido redirigir automáticamente. Lo más triste ha sido que la subpágina De todo un poco, que es la que usaba como pruebas para el posicionamiento y cuyas estadísticas mido con más cuidado, pasó de 8 visitas diarias antes de optimizar el código a unas 20 diarias... Y ahora está en cero... Hasta que Google no vuelva a pasarse...

28 octubre 2007

Desarrolladoras de videojuegos de España

Por pura casualidad, leyendo artículos acerca del venerable ZX Spectrum, he ido navegando de vínculo en vínculo y he terminado en páginas que no sabía ni que existieran y que me han parecido tan interesantes y relacionadas con la actividad de una empresa como la mía, que voy a hablar un poco de ellas.

La primera es la que más me ha gustado, y se trata de un artículo muy largo acerca del nacimiento, desarrollo y estado actual de la industria del videojuego en España. Se trata de Historia del software español de entretenimiento, de Fernando Rodríguez, cuya lectura os recomiendo, y a través de la cual he llegado a buena parte del resto de vínculos.

Según datos de AETIC, la Asociación de Empresas de Electrónica, Tecnologías de la Información y Telecomunicaciones de España, durante el año 2006 el sector de la comercialización de software facturó unos 1.600 millones de euros. Y según datos de ADESE (Asociación Española de Distribuidores y Editores de Software de Entretenimiento), durante el 2006, las ventas de videojuegos para PC supusieron 90 millones de euros. Es poco, pero si tenemos en cuenta que en videojuegos para consolas las ventas fueron de 486 millones de euros (que creo no están incluidos en los 1.600 millones de los datos de AETIC), vemos que los videojuegos son un sector dentro de los desarrollos de software que, al menos, en España, es muy relevante.

Hay muchos aspectos curiosos en estos datos. La comparación entre ventas de hardware y de software en los campos de la informática y las consolas da un resultado curioso. En informática resulta que el software factura 1.600 millones frente a 3.498 millones del hardware. En cambio, en videoconsolas, el software supone 486 millones y el hardware 391. Para empresas de desarrollo de software, los videojuegos parecen mejor mercado, ya que en la informática ordinaria predomina la venta de equipos. Hay una conclusión no muy optimista; en comparación con el PIB español, estos números no son demasiado grandes, teniendo en cuenta que, hoy en día, se usan ordenadores para casi todo.

El caso es que hay varias noticias de El Mundo (que no sé cómo se posiciona... cuando hago una búsqueda en Google, si me salen referencias a noticias de un periódico, casi siempre es El Mundo...). En esta noticia, se habla de que sólo 27 empresas españolas desarrollan videojuegos, lo que es muy poco. Sólo el 1% de las ventas van a parar a desarrolladoras españolas, con lo que el mercado está en manos de compañías extranjeras, a pesar de tanta gente preparada como tenemos aquí. Supongo que todo esto tiene las mismas causas que hacen que España sea el hazmerreir en investigación y desarrollo tecnológico. Mercado hay; somos el cuarto país de la Unión Europea en volumen de ventas de videojuegos, pero de los últimos a la hora de producirlos.

Después de una época "gloriosa", que llegó a su fin cuando los ordenadores pasaron de 8 bits a 16 bits, el sector se estancó. La mayoría de empresas con solera (Opera Soft, Dinamic Multimedia) fueron cayendo. Hoy nos quedan muy pocas, de las que voy a citar a tres de las más grandes:

  • Pyro Studios: desarrolladores de Comandos, uno de los mejores juegos que han salido de mentes españolas, y que fue un éxito de ventas mundial.
  • Virtual Toys: dedicada a la programación de videojuegos para consolas. Tiene tres centros de trabajo (Madrid, Barcelona y Valencia). Encuentro en esta web la explicación al escaso número de videojuegos que se producen aquí. En la sección de empleo se comenta que necesitan: "Programadores con experiencia en consolas de última generación, y/o conocimientos de física, matemáticas e inteligencia artificial". Como en física y matemáticas España da risa, ahí tenemos el por qué.
  • FX Interactive: empresa especializada en la edición de videojuegos de calidad. Tiene una buena implantación internacional, al estar representada en España e Italia.

En los años 80, era posible hacer un juego capaz de competir a nivel internacional reuniéndose un grupo de amigos que fueran forofos de los Spectrum o los Amstrad CPC. En esa época, España estuvo a la altura y surgieron excelentes profesionales. Cuando las cosas cambiaron, e hicieron falta equipos de decenas de profesionales, altas inversiones y empresas grandes para sacar al mercado un juego, nos vinimos abajo, porque nunca se nos ha dado bien cuidar el talento de los que viven por aquí - varios de los buenos desarrolladores de la "época dorada" han acabado en el extranjero -.

Me dejo muchas cosas en el tintero, juegos de código abierto, la página de Stratos, la importancia que la Administración le está dando a los videojuegos, en el seno de la generación de los contenidos digitales (el Foro Internacional de Contenidos Digitales, que dedica una ponencia a los mismos, el hecho de que dentro del Plan Avanza, dentro de la línea de contenidos digitales se haga referencia expresa a los Videojuegos "online"), pero eso, para la próxima.

13 octubre 2006

Errores de programación (V)

Este error quizá no sea tal, sino un problema de interpretación del funcionamiento del compilador, de todos modos, al ser un comportamiento curioso, voy a hablar de él.

Supongamos el siguiente fragmento de código:

' OpcListMin es una variable global, declarada en un módulo separado, que el formulario
' ListFrm necesita para, al cargarse, mostrar una cosa u otra.
OpcListMin = 2

' Cerramos para asegurarnos, por las bravas, de que ese listado no está abierto. La variable
' MiFormList es global al formulario MDI de la aplicación.
MiFormList.Close()

' Y lo volvemos a abrir, tan inocentemente
MiFormList = New ListFrm
MiFormList.MdiParent = Me
MiFormList.Show()


Pues bien, si hacemos esto, el valor de OpcListMin se pierde, esto es, la variable se queda a cero sin hacer caso a la asignación previa al cierre de MiFormList. No teníamos ni idea de a qué se debía este comportamiento hasta que se me ocurrió, por ver qué pasaba, invertir dos líneas, o sea:

' Cerramos para asegurarnos, por las bravas, de que ese listado no está abierto. La variable
' MiFormList es global al formulario MDI de la aplicación.
MiFormList.Close()

' OpcListMin es una variable global, declarada en un módulo separado, que el formulario
' ListFrm necesita para, al cargarse, mostrar una cosa u otra.
OpcListMin = 2

' Y lo volvemos a abrir, ya no tan inocentemente

MiFormList = New ListFrm
MiFormList.MdiParent = Me
MiFormList.Show()

Hecho de la segunda forma sí funciona.

Desde un punto de vista lógico, carece de sentido. ¿Por qué una variable global a una aplicación, definida en un módulo aparte, se vuelve cero por cerrar un formulario localmente y volverlo a abrir?

Curioso, ¿no?

02 septiembre 2006

Errores de programación (IV)

En el ámbito profesional, como habrá adivinado el lector que siga la serie de entradas sobre errores de programación, utilizo frecuentemente Visual Basic .NET. Es por ello que todos los errores se refieren a este lenguaje.

El último ha sido el más angustioso, así que pongo al lector en antecedentes. Mi hermano, y socio también de mi empresa, se infló de trabajar para desarrollar una aplicación a medida. A mí me quedó el control de la impresora y la edición de informes, que se me da bastante mejor. Estaba desarrollando eso cuando el entorno de programación se me bloquea y no me deja ni borrar una línea de código. Cierro el programa, lo vuelvo a abrir y lo mismo. Reinicio el ordenador, intento trabajar con la solución (en Visual Basic .NET los conjuntos de proyectos tienen ese nombre) y nada. Me llevo el código fuente a otro ordenador y nada... Total, que, a lo mejor, se habían perdido las actualizaciones realizadas desde la última copia de seguridad - que no eran muchas pero sí latosas -.

Por suerte, se me ocurrió mirar los archivos del proyecto. Entre ellos, hay algunos que el compilador genera, a saber, los distintos archivos Resx (uno por cada formulario y que guarda información sobre éste en formato XML; por ejemplo, se incluyen codificados en base64 los archivos gráficos que se muestre. No deja de ser curioso), y un archivo de extensión suo, oculto, e identificado como "Visual Studio Solution User Options". Considerando que algún archivo del proyecto se hubiera dañado, probé a eliminar el fichero .suo, por empezar con algo que no me hubiera costado hacer.

Y, mágicamente, la cosa se arregló. El entorno regeneró el fichero y ahora mismo estoy trabajando tan contento en el mismo proyecto.

Cosas de la informática.

26 agosto 2006

Errores de programación (III)

Volvemos a hablar de errores de programación por tercera vez. Lo raro es que trabajando en desarrollo de aplicaciones sólo sea la tercera vez.

El siguiente código, de Visual Basic .NET, donde Rs y Rs2 son dos recordset abiertos casi a la par:

ReDim Preserve EstrDatos(i)
With EstrDatos(i)
.NombreCli = Rs.Fields("Nombre").Value & " " & Rs.Fields("Apellidos").Value
.Codigo = Rs.Fields("Codigo").Value

.Total = PuntosSep(Rs2.Fields("Debe").Value)

.Bloque = CStrAv(Rs.Fields("Bloque").Value)
.Esc = CStrAv(Rs.Fields("Escalera").Value)
.Piso = CStrAv(Rs.Fields("Piso").Value)
.Letra = CStrAv(Rs.Fields("Letra").Value)
.CP = CStrAv(Rs.Fields("CP").Value)
.Poblacion = CStrAv(Rs.Fields("Poblacion").Value)
.Provincia = CStrAv(Rs.Fields("Provincia").Value)

.Saldo = PuntosSep(Rs2.Fields("Saldo").Value)
.Sello = PuntosSep(Rs2.Fields("Sello").Value)

(...)
End With

da el siguiente fallo:

Excepción no controlada del tipo System.Runtime.InteropServices.COMException en adodb.dll. Información adicional: El valor BOF o EOF es True, o el actual registro se eliminó; la operación solicitada requiere un registro actual.

Ahora bien, basta cambiar una sola línea de sitio, concretamente la quinta, y dejar el fragmento de código así:

ReDim Preserve EstrDatos(i)
With EstrDatos(i)
.NombreCli = Rs.Fields("Nombre").Value & " " & Rs.Fields("Apellidos").Value
.Codigo = Rs.Fields("Codigo").Value
.Bloque = CStrAv(Rs.Fields("Bloque").Value)
.Esc = CStrAv(Rs.Fields("Escalera").Value)
.Piso = CStrAv(Rs.Fields("Piso").Value)
.Letra = CStrAv(Rs.Fields("Letra").Value)
.CP = CStrAv(Rs.Fields("CP").Value)
.Poblacion = CStrAv(Rs.Fields("Poblacion").Value)
.Provincia = CStrAv(Rs.Fields("Provincia").Value)

.Total = PuntosSep(Rs2.Fields("Debe").Value)
.Saldo = PuntosSep(Rs2.Fields("Saldo").Value)
.Sello = PuntosSep(Rs2.Fields("Sello").Value)
(...)
End With


y se resuelve el problema.

Quizá sea alguna operación extraña del compilador que, para optimizar la velocidad, eliminaba Rs2 después de haber, teóricamente, terminado de trabajar con él, o un simple fallo de programación del propio compilador.