¿Cómo puedo verificar si PHP se compiló con la versión UNICODE de la API Win32?

10

Esto está relacionado con esta publicación de desbordamiento de pila:

glob () no puede encontrar nombres de archivo con caracteres multibyte en Windows?

Tengo problemas con PHP y archivos que tienen caracteres multibyte en Windows. Aquí está mi caso de prueba:

print_r(scandir('./uploads/')); 
print_r(glob('./uploads/*'));

Salida correcta en el servidor UNIX remoto:

Array
(
    [0] => .
    [1] => ..
    [2] => filename-äöü.jpg
    [3] => filename.jpg
    [4] => test이test.jpg
    [5] => имя файла.jpg
    [6] => פילענאַמע.jpg
    [7] => 文件名.jpg
)
Array
(
    [0] => ./uploads/filename-äöü.jpg
    [1] => ./uploads/filename.jpg
    [2] => ./uploads/test이test.jpg
    [3] => ./uploads/имя файла.jpg
    [4] => ./uploads/פילענאַמע.jpg
    [5] => ./uploads/文件名.jpg
)

Salida incorrecta localmente en Windows:

Array
(
    [0] => .
    [1] => ..
    [2] => ??? ?????.jpg
    [3] => ???.jpg
    [4] => ?????????.jpg
    [5] => filename-äöü.jpg
    [6] => filename.jpg
    [7] => test?test.jpg
)
Array
(
    [0] => ./uploads/filename-äöü.jpg
    [1] => ./uploads/filename.jpg
)

Aquí hay un extracto relevante de la respuesta que elegí aceptar (que en realidad es una cita de un artículo publicado en línea hace más de 2 años):

De los comentarios sobre este artículo: http://www.rooftopsolutions.nl/blog/filesystem-encoding-and-php

El resultado de su instalación de PHP en Windows es fácil de explicar: instaló una versión incorrecta de PHP y utilizó una versión no compilada para utilizar la versión Unicode de la API Win32. Por esta razón, las llamadas al sistema de archivos utilizadas por PHP utilizarán la API "ANSI" heredada, por lo que las bibliotecas C / C ++ vinculadas con esta versión de PHP primero intentarán convertir su cadena PHP codificada en UTF-8 en la "ANSI" local. página de códigos seleccionada en el entorno de ejecución (consulte el comando CHCP antes de iniciar PHP desde una ventana de línea de comandos)

Su versión de Windows NO ES PROBABLEMENTE responsable de esta cosa extraña. En realidad, esta es SU versión de PHP que no está compilada correctamente, y que usa la versión ANSI heredada de la API Win32 (por compatibilidad con las versiones heredadas de 16 bits de Windows 95/98 cuyo soporte de sistema de archivos en el núcleo en realidad no tenía soporte para Unicode, pero usó una capa de conversión interna para convertir Unicode a la página de códigos ANSI local antes de usar la versión ANSI real de la API).

Vuelva a compilar PHP usando la opción de compilación para usar la versión UNICODE de la API Win32 (que debería ser la predeterminada hoy, y de todos modos siempre la predeterminada para PHP instalado en un servidor que NUNCA será Windows 95 o Windows 98 ...)

No puedo confirmar si este es mi problema o no. Usé phpinfo()y no encontré nada interesante, pero no estaba seguro de qué buscar. He estado usando XAMPP para facilitar las instalaciones, por lo que realmente no estoy seguro de cómo se instaló.

Estoy usando Windows 7, 64 bits, así que perdona mi ignorancia, pero ni siquiera estoy seguro de si "Win32" es relevante aquí. ¿Cómo puedo verificar si mi versión actual de PHP se compiló con la configuración mencionada anteriormente?

  • Versión PHP : 5.3.8
  • Sistema : Windows NT WES-PC 6.1 build 7601 (Windows 7 Home Premium Edition Service Pack 1) i586
  • Fecha de construcción : 23 de agosto de 2011 11:47:20
  • Compilador : MSVC9 (Visual C ++ 2008)
  • Arquitectura : x86
  • Configurar comando : cscript /nologo configure.js "--enable-snapshot-build" "--disable-isapi" "--enable-debug-pack" "--disable-isapi" "--without-mssql" "--without-pdo-mssql" "--without-pi3web" "--with-pdo-oci=D:\php-sdk\oracle\instantclient10\sdk,shared" "--with-oci8=D:\php-sdk\oracle\instantclient10\sdk,shared" "--with-oci8-11g=D:\php-sdk\oracle\instantclient11\sdk,shared" "--enable-object-out-dir=../obj/" "--enable-com-dotnet" "--with-mcrypt=static" "--disable-static-analyze"

En caso de que sea relevante o revele información útil, aquí hay una captura de pantalla de mi phpinfo()(sección mbstring):

captura de pantalla de phpinfo

¿Cómo puedo saber si mi instalación de PHP fue "compilada con la versión UNICODE de la API Win32"? (¿Y eso tiene sentido?)

Wesley Murch
fuente
55
Votaron porque Wesley tiene que cuidarse unos a otros.
Wesley
¿Has hecho algo en tu script con respecto a la codificación? ¡Tuve lo contrario de este problema con mi instalación win7-64! Php leería las diéresis y todo eso, y el programa heredado de basura con el que me estaba comunicando cuando tenía esos descansos.
Chris K
Lamento no poder responder a esta pregunta, simplemente no obtuve la respuesta rápida y sucia que esperaba, y finalmente dejé de desarrollar este proyecto en Windows. Pronto instalaré PHP 5.4 localmente (en Windows), por lo que la pregunta ya no puede ser valiosa para mí, si alguien quiere sugerir una respuesta aceptada, soy todo oídos. Mientras tanto, votos a favor y gracias por todas partes.
Wesley Murch

Respuestas:

3

Creo que deberías descargar un binario oficial del repositorio PHP de Windows e instalarlo (toma nota de la ruta de instalación).

Después de eso, necesitará configurar Apache para usar el nuevo binario en lugar del que tenía por defecto. Es simple:

  • Busque su httpd.confarchivo en la carpeta WAMP (algo así como C: \ wamp \ bin \ apache \ ApacheXXX \ conf \ httpd.conf); también es posible pasar por el icono de bandeja.

  • Ok, ahora que lo encontraste busca una cadena que coincida LoadModule php5_module

  • Bien, simplemente reemplace esta línea con su nueva php5_moduleque es probaly en c: /php/php5apache2_2.dll (¡guardó la ruta de instalación!). Resultando en algo comoLoadModule php5_module "c:/php/php5apache2_2.dll"

Voila Reinicie el servidor wamp y pruebe su aplicación con la última versión de php build especialmente para Windows.

No estoy seguro de que esto resuelva su problema, pero seguramente es un verdadero camino a seguir. Si tiene problemas con la configuración de php, lea este artículo .

¡Buena suerte!

Thiago Macedo
fuente
2

Parece que esta pregunta ha estado ahí por un tiempo y si php se compiló o no con indicadores Unicode no afecta su soporte Unicode, pero si necesita determinar si una imagen PE dada probablemente se compiló contra la versión Unicode de API de Windows, puede usar dumpbinpara examinar las importaciones de kernel32.dll utilizadas. Esto no es exactamente algo que haría pragmáticamente, pero en un apuro, podría funcionar para el diagnóstico.

Por ejemplo, un ejecutable Unicode podría enumerar:

               4C CreateFileMappingW
               45 CreateDirectoryW
               33 CompareStringW
              12E GetCurrentDirectoryW
               AF ExpandEnvironmentStringsW
              2F0 SetFileAttributesW

observando el número de funciones que terminan en W, también conocido como Ancho para caracteres unicode.

Para un ejecutable ANSI o DLL, puede ver algo más cercano a:

              30A SetCurrentDirectoryA
              15E GetFileAttributesA
              171 GetLastError
               4B CreateDirectoryA
              319 SetFileAttributesA

con la mayoría de las funciones que terminan en A, podemos ver que el ejecutable probablemente se compiló con banderas ANSI.

Mitch
fuente
2

Aquí hay un código en el que trabajé para manejar un mbstringproblema con el que me encontraba. Terminé iterando a través de cada combinación de codificaciones y opciones hasta que una de ellas presentó la salida que necesitaba. Tengo la sensación de que este tipo de procedimiento podría ayudarlo a encontrar la respuesta que busca.

No confíe en la documentación , ya que en mi caso, los resultados no fueron lo que pensé que harían las opciones y las codificaciones. Recuerdo que en mi prueba, obtendría los rectángulos, y cosas como A ~. Mi prueba fue exactamente como la tuya, print_rla información. En mi caso, mi script está importando información de clientes y ventas en Quickbooks, que no puede manejar UTF-8. (O QB no puede o el controlador QODBC no puede) Tildes, tumbas y diéresis están fuera de discusión.

setlocale(LC_CTYPE, 'en_US.UTF-8');
$xmlstr=file_get_contents($file);           
// convert character encoding to get rid of accents, etc
// see http://www.php.net/manual/en/function.mb-detect-encoding.php#89915
// note that unlike ASCII//TRANSLIT and ASCII//TRANSLIT//IGNORE do not work
// in windows 7.
$xmlstr=iconv('UTF-8', 'ASCII//IGNORE', $xmlstr);   

Ese enlace de arriba es http://www.php.net/manual/en/function.mb-detect-encoding.php#89915 y si Google te encuentra aquí, definitivamente ve a leer eso.

Chris K
fuente
1

Creo que querrá verificar si PHP se compiló con mbstring (o si el módulo mbstring está instalado y habilitado si está utilizando módulos). Tener esa extensión habilitada debería resolver sus problemas. Esta página debe decirle todo lo que necesita saber para que funcione.

Aaron
fuente
Gracias por la sugerencia, pero creo que mbstring está instalado correctamente. Agregué un poco de información sobre esto al final de mi publicación. Estoy más interesado en conocer los comentarios que cité del artículo "SU versión de PHP que no está compilada correctamente y que utiliza la versión ANSI heredada de la API Win32" , cómo averiguar si este es el caso, y si esto es relevante o no.
Wesley Murch
No creo que el soporte unicode en PHP tenga mucho que ver con el soporte unicode en la API que PHP usa para hacer sus negocios. Sospecho que el último es el problema más que el primero. (Sin embargo, lamento no tener una respuesta al problema; estoy disgustado por lo horrible que es PHP después de probar lenguajes cuerdos, así que no tengo tanta experiencia con él).
gparent