Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Sprawdzanie poprawności składniowej kodu PHP
Forum PHP.pl > Forum > PHP
hawk
Chciałbym sobie - z poziomu skryptu php - wczytać z dysku jakiś inny skrypt i sprawdzić, czy jest on poprawny składniowo. Potem można by wysłać do usera info: "tak, plik jest OK" lub "nie, jest błąd w linii tej a tej".

Problemy są dwa:

1) Chcę tylko sparsować plik, a nie wykonywać. Temu akurat można zaradzić wstawiając przed kodem do sprawdzenia return, coś w stylu:
[php:1:dcb9e2b8c6]<?php eval(' return; ' . file_get_contents('foo.php')); ?>[/php:1:dcb9e2b8c6]
Wtedy jedyne błędy to będą błędy parsowania lub błędy kompilatora, czyli te o które chodzi.

2) Tutaj jest pies pogrzebany: można sobie zrobić set_error_handler i przechwytywać błędy, ale błedy parsowania zawsze są brutalnie wywalane na wyjście i kończą skrypt. Kompletnie olewają mój piękny error handler sad.gif .

Tak więc, czy ktoś zna sposób na sprawdzenie poprawności pliku (lub stringa, na jedno wychodzi) bez jego wykonywania i bez wywalania całego skryptu w przypadku błędu? Przecież php robi to bez przerwy, php.exe chyba ma taki switch, analizator lexykalny jest dostępny (tokenizer), a tu nie można sparsować głupiego kawałka kodu angrysmiley.gif .
Seth
Cytat
2) Tutaj jest pies pogrzebany: można sobie zrobić set_error_handler i przechwytywać błędy, ale błedy parsowania zawsze są brutalnie wywalane na wyjście i kończą skrypt. Kompletnie olewają mój piękny error handler sad.gif .

Moze by uzyc buforowania outputu (ob_*) ?
hawk
Cytat
Moze by uzyc buforowania outputu (ob_*) ?

Nope sad.gif . Parser php przy pierwszym błędzie składniowym kończy cały skrypt. Nawet nie dojdzie do linijki w której pobiera wartość bufora.
DeyV
ALe chyabw ajakis sposób można przechwycić nawet takie komunikaty.
Co prawda nie do końca wiem jak, ale pamiętam kiedyś nasze zdziwienie, gdy eZ obsłużył nam wszystkie możliwe błędy, łącznie z przerwaniem skryptu przez die()

Pamiętam, że zarówno ja jak i seth byliśmy tym mocno zaskoczeni. Niestety - przynajmniej mi nie udało się rozszyfrować zasady działanie tego mechanizmu.
Bakus
A może skrypt wykonać w powłoce? W tedy przetwarzanie skryptu było by wykonywane jako osobny wątek, więc nie było by problemu z przerywaniem parsowania macierzystego skryptu.

Niestety nie jestem w stanie wyobrazić sobie w jaki sposób zabezpieczyć system, by sprawdzane skrypty nie korzystały np. z funcji [manual:605bee3d62]system[/manual:605bee3d62] lub podobnych...
Jabol
jestem pewien, że w którymś changelogu php5 widziałem funkcje, która to robi.

php5beta3, a funkcja zwie się php_check_syntax()
hawk
@Bakus:
Myślałem o tym smile.gif ale:
- nie potrafię ustalić w skrypcie gdzie znajduje się php.exe
- coś u siebie namieszałem w php bo php.exe nie znajduje bibliotek i w ogóle nie rusza
Ale ogólnie to powinno działać. Co do zabezpieczenia systemu: podobno php.exe ma switcha który powoduje że skrypt jest tylko parsowany, nie wykonywany.

@jabol:
Piękna funkcja. Niestety, to moje musi chodzić na PHP4, ale to kolejny powód, by lubić PHP5 biggrin.gif .

A generalnie to poradziłem sobie tak:
Jest skrypt, który przyjmuje dowolny kod php w POST, i zapisuje do tymczasowego pliku taki string:
Kod
"<?php echo 'No syntax errors found'; die(); ?>" . $_POST['code']

a potem wykonuje ten plik. Skutek prosty:
- nie ma błędów: wypluwamy info i kończymy bez wykonywania nieznanego kodu
- są błędy: parser php sam wypluwa info i kończy skrypt

A w głównym skrypcie po prostu otwieram socketa, wysyłam żądanie HTTP POST i odczytuję odpowiedź serwera... Styknie.
FiDO
Cytat
- nie potrafię ustalić w skrypcie gdzie znajduje się php.exe

pod Unixem wywolac which php, pod windowsem gorzej... mozna sprobowac odczytac przez ini_get wartosc extension_dir, mysle ze 99% ma ta sciezke nie zmieniona, czyli w katalogu php
Cytat
- coś u siebie namieszałem w php bo php.exe nie znajduje bibliotek i w ogóle nie rusza

Wersja CLI/CGI php szuka php.ini tam gdzie sie odpala, a pewnie masz php.ini w windowsie albo katalogu apache'a... jak nie chcesz drugiej kopii php.ini no to mozesz jeszcze do php.exe przekazac parametr
-c sciezka/do/php.ini
Cytat
Ale ogólnie to powinno działać. Co do zabezpieczenia systemu: podobno php.exe ma switcha który powoduje że skrypt jest tylko parsowany, nie wykonywany.

Podobno ma smile.gif
Kod
-l             Syntax check only (lint)
Bakus
http://www.php.net/features.commandline

Cytat
Usage: php [options] [-f] <file> [args...]
      php [options] -r <code> [args...]
      php [options] [-- args...]
 -s               Display colour syntax highlighted source.
 -w               Display source with stripped comments and whitespace.
 -f <file>        Parse <file>.
 -v               Version number
 -c <path>|<file> Look for php.ini file in this directory
 -a               Run interactively
 -d foo[=bar]     Define INI entry foo with value 'bar'
 -e               Generate extended information for debugger/profiler
 -z <file>        Load Zend extension <file>.
 -l               Syntax check only (lint)
 -m               Show compiled in modules
 -i               php information
 -r <code>        Run php <code> without using script tags <?..?>
 -h               This help

 args...          Arguments passed to script. Use -- args when first argument  
                  starts with - or script is read from stdin
hawk
Cytat
Jeśli wszystko inne zawiedzie, przeczytaj instrukcję...

biggrin.gif
Ale jak zauważył FiDO, ciężko z poziomu skryptu wywołać php.exe, bo nie wiadomo gdzie to jest. A w moim przypadku na pewno nie będzie działać, bo ja php sam porozrzucałem po katalogach jak mi się widziało.

Tak czy siak, IMHO to poważne niedopatrzenie twórców php: jest w języku funkcjonalność, całkiem przydatna, do której nie ma dostępu. Przynajmniej w PHP5 się poprawi...
Bakus
A nie możesz do katalogu skryptu wrzućić pliku php.exe i wywołać go przez exec, lub podobną funkcję ?
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.