Jak mogę sprawdzić, czy PHP zostało skompilowane z UNICODE wersją Win32 API?

10

Jest to związane z tym postem przepełnienia stosu:

glob () nie może znaleźć nazw plików ze znakami wielobajtowymi w systemie Windows?

Mam problemy z PHP i plikami, które mają znaki wielobajtowe w systemie Windows. Oto mój przypadek testowy:

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

Prawidłowe wyjście na zdalnym serwerze UNIX:

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
)

Niepoprawne dane wyjściowe lokalnie w systemie 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
)

Oto odpowiedni fragment odpowiedzi, którą zdecydowałem się zaakceptować (która w rzeczywistości jest cytatem z artykułu opublikowanego online ponad 2 lata temu):

Z komentarzy do tego artykułu: http://www.rooftopsolutions.nl/blog/filesystem-encoding-and-php

Dane wyjściowe z instalacji PHP w systemie Windows można łatwo wyjaśnić: zainstalowałeś niewłaściwą wersję PHP i użyłeś wersji nieskompilowanej do korzystania z wersji Win32 API interfejsu Unicode. Z tego powodu wywołania systemu plików używane przez PHP będą używać starszego API „ANSI”, więc biblioteki C / C ++ połączone z tą wersją PHP najpierw spróbują przekonwertować ciąg PHP zakodowany w UTF-8 na lokalny „ANSI” strona kodowa wybrana w uruchomionym środowisku (zobacz komendę CHCP przed uruchomieniem PHP z okna wiersza poleceń)

Twoja wersja systemu Windows NIE JEST PRAWDOPODOBNIE odpowiedzialna za tę dziwną rzecz. W rzeczywistości jest to TWOJA wersja PHP, która nie jest poprawnie skompilowana i która korzysta ze starszej wersji interfejsu API Win32 systemu Win32 (w celu zachowania zgodności ze starszymi 16-bitowymi wersjami systemu Windows 95/98, których obsługa systemu plików w jądrze nie miała bezpośredniego obsługa Unicode, ale użyła wewnętrznej warstwy konwersji do konwersji Unicode na lokalną stronę kodową ANSI przed użyciem rzeczywistej wersji interfejsu API ANSI).

Ponownie skompiluj PHP przy użyciu opcji kompilatora, aby użyć UNICODE wersji Win32 API (która powinna być dzisiaj domyślna, a zresztą zawsze domyślna dla PHP zainstalowanego na serwerze, który NIGDY nie będzie Windows 95 lub Windows 98 ...)

Nie mogę potwierdzić, czy to mój problem, czy nie. Użyłem phpinfo()i nie znalazłem niczego interesującego, ale nie byłem pewien, czego szukać. Używam XAMPP do łatwej instalacji, więc naprawdę nie jestem pewien, jak dokładnie został zainstalowany.

Korzystam z systemu Windows 7, wersja 64-bitowa - więc wybacz moją ignorancję, ale nie jestem nawet pewien, czy „Win32” jest tutaj istotny. Jak mogę sprawdzić, czy moja bieżąca wersja PHP została skompilowana z wyżej wymienioną konfiguracją?

  • Wersja PHP : 5.3.8
  • System : Windows NT WES-PC 6.1 build 7601 (Windows 7 Home Premium Edition Service Pack 1) i586
  • Data kompilacji : 23 sierpnia 2011 11:47:20
  • Kompilator : MSVC9 (Visual C ++ 2008)
  • Architektura : x86
  • Skonfiguruj polecenie : 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"

W przypadku, gdy jest to istotne lub ujawnia przydatne informacje, oto zrzut ekranu mojego phpinfo()(sekcja mbstring):

zrzut ekranu phpinfo

Jak mogę się dowiedzieć, czy moja instalacja PHP została „skompilowana z UNICODE wersją Win32 API”? (i czy to ma jakiś sens?)

Wesley Murch
źródło
5
Głosowano, ponieważ Wesleyowie muszą uważać na siebie nawzajem.
Wesley
Czy zrobiłeś coś w swoim skrypcie w odniesieniu do kodowania? Miałem odwrotność tego problemu z moją instalacją Win7-64! Php czytałby Umlats i wszystko inne i ten gówniany program, który komunikowałem z przerwami, kiedy je otrzymałem.
Chris K,
Przepraszam za kaucję za to pytanie, po prostu nie dostałem szybkiej i brudnej roboczej odpowiedzi, na którą liczyłem, i ostatecznie przestałem opracowywać ten projekt w systemie Windows. Wkrótce zainstaluję PHP 5.4 lokalnie (w systemie Windows), więc pytanie może już nie być dla mnie cenne, jeśli ktoś chce zasugerować zaakceptowaną odpowiedź, jestem cały. W międzyczasie opinie i podziękowania dookoła.
Wesley Murch,

Odpowiedzi:

3

Myślę, że powinieneś pobrać oficjalny plik binarny z repozytorium PHP Windows i zainstalować go (zwróć uwagę na ścieżkę instalacji).

Następnie musisz skonfigurować apache, aby używał nowego pliku binarnego zamiast domyślnego. To jest proste:

  • Znajdź swój httpd.confplik w folderze WAMP (coś w rodzaju C: \ wamp \ bin \ apache \ ApacheXXX \ conf \ httpd.conf) - może być również możliwe przejście przez trayicon.

  • Ok, teraz, kiedy znalazłeś, zlokalizuj pasujący ciąg LoadModule php5_module

  • Dobrze, po prostu zamień ten wiersz na nowy, php5_modulektóry jest prawdopodobnie w c: /php/php5apache2_2.dll (zapisałeś ścieżkę instalacji!). W wyniku czego coś takiegoLoadModule php5_module "c:/php/php5apache2_2.dll"

Voila Zresetuj serwer Wamp i przetestuj aplikację za pomocą najnowszej wersji kompilacji php specjalnie dla systemu Windows.

Nie jestem pewien, czy to rozwiąże problem, ale z pewnością jest to prawdziwa droga. Jeśli masz problemy z konfiguracją php, przeczytaj ten artykuł .

Powodzenia!

Thiago Macedo
źródło
2

Wygląda na to, że pytanie to istnieje już od jakiegoś czasu i to, czy php został skompilowany z flagami Unicode, nie wpływa na jego obsługę Unicode, ale jeśli musisz ustalić, czy dany obraz PE został prawdopodobnie skompilowany z wersją Unicode Windows API, możesz użyć dumpbindo zbadania zastosowanego importu kernel32.dll. Nie jest to dokładnie coś, co chciałbym zrobić pragmatycznie, ale w skrócie, może pracować dla diagnostyki.

Na przykład plik wykonywalny Unicode może wyświetlać:

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

zwracając uwagę na liczbę funkcji kończących się na W, czyli Szeroki dla znaków Unicode.

W przypadku pliku wykonywalnego ANSI lub biblioteki DLL możesz zobaczyć coś bliższego:

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

z większością funkcji kończących się na A, widzimy, że plik wykonywalny najprawdopodobniej został skompilowany z flagami ANSI.

Mitch
źródło
2

Oto kod, nad którym pracowałem, aby rozwiązać mbstringproblem, na który wpadłem. Skończyło się to na powtarzaniu każdej kombinacji kodowania i opcji, dopóki jedna z nich nie przedstawiła potrzebnych danych wyjściowych. Mam wrażenie, że taka procedura może pomóc ci znaleźć odpowiedź, której szukasz.

Nie polegaj na dokumentacji , ponieważ w moim przypadku wyniki nie były zgodne z oczekiwaniami opcji i kodowania. Pamiętam, że w moich testach dostawałem prostokąty i takie rzeczy jak A ~. Informacje o moich testach były dokładnie takie jak twoje print_r. W moim przypadku mój skrypt importuje informacje o klientach i sprzedaży do Quickbooks, które nie obsługują UTF-8. (Albo sama QB nie może, albo sterownik QODBC nie.) Tyld, groby i umlaty nie wchodzą w rachubę.

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);   

Powyższy link to http://www.php.net/manual/en/function.mb-detect-encoding.php#89915, a jeśli Google cię tu znajdzie, koniecznie przeczytaj to.

Chris K.
źródło
1

Wierzę, że będziesz chciał sprawdzić, czy PHP zostało skompilowane z mbstring (lub czy moduł mbstring jest zainstalowany i włączony, jeśli używasz modułów). Włączenie tego rozszerzenia powinno rozwiązać problemy. Ta strona powinna powiedzieć ci wszystko, co musisz wiedzieć, aby móc działać.

Aaron
źródło
Dzięki za sugestię, ale uważam, że mbstring jest poprawnie zainstalowany. Na końcu mojego wpisu dodałem trochę informacji na ten temat. Bardziej interesuje mnie nauka o komentarzach, które zacytowałem w artykule „TWOJA wersja PHP, która nie jest poprawnie skompilowana i która korzysta ze starszej wersji interfejsu API Win32 dla Win32” , jak dowiedzieć się, czy tak jest, i czy jest to istotne, czy nie.
Wesley Murch
Nie sądzę, aby obsługa Unicode w PHP miała wiele wspólnego ze wsparciem dla Unicode w API, którego PHP używa do prowadzenia swojej działalności. Podejrzewam, że to drugie jest raczej problemem niż pierwszym. (Przepraszam, że nie mam odpowiedzi na problem; jestem zniesmaczony tym, jak całkowicie okropny jest PHP po wypróbowaniu rozsądnych języków, więc nie mam z tym większego doświadczenia).
gparent