La aparentemente cosa más tonta del mundo me ha tenido todo el día liado. Y no es la primera vez. Anteriormente me había pasado al procesar RSS, hoy ha sido al consumir unos webservices (SOAP).
Nuestros sistemas trabajan con MsSql, Apache, PHP5 y Windows 2003 Server. De vez en cuando necesitamos crear tareas que lean desde determinadas fuentes de datos y los inserten en una base de datos. La última vez que me había ocurrido era leyendo un RSS. Si lo lanzaba a través de la línea de comandos con php.exe la codificación que se guardaba en la base de datos era errónea, todos los acentos, eñes y demás caracteres no ASCII se perdían. El caso es que al ejecutarlo a través de Apache todo funcionaba bien.
La otra vez, por falta de tiempo, lo dejé pasar y montamos la tarea a través de Apache con wget. Pero ahora no era la mejor solución, hay que procesar varios webservices y la tarea se puede prolongar durante mucho tiempo, con lo que tener un hilo de apache corriendo tanto tiempo no me parece lo más adecuado.
Después de mucho googlear he encontrado la solución. Resulta que al ejecutar la tarea desde la línea de comandos se produce una conversión automática de ANSI a OEM:
Any clients running Windows NT or Windows 95/98 are considered ANSI clients. Console-based applications, such as the isql utility, are considered OEM clients.
Por lo tanto nos cambia la codificación sin remedio. Para ello hay una solución, y es ejecutar nuestro script a través de un wrapper que lance el proceso sin ser bajo consola, digamos que engañando al sistema operativo. En tu instalación de php tendrás un php-win.exe que hace exactamente lo mismo que el cliente habitual pero sin lanzarlo en la línea de comandos, parecerá que no ha hecho nada pero si abres el administrador de tareas verás el proceso php-win.ese corriendo e insertando correctamente en la base de datos.