Blokira li PHP proc_open web zahtjev? Otvaranje datoteka i vanjskih podataka. Potencijalna ranjivost PHP skripti Provjera dnevnika zahtjeva
U ovom poglavlju ćemo vas naučiti kako otvoriti, pročitati i zatvoriti datoteku na poslužitelju.
PHP Otvaranje datoteke - fopen()
Bolji način otvaranja datoteka je funkcija fopen(). Ova vam funkcija daje više opcija od funkcije readfile().
Tijekom lekcija koristit ćemo tekstualnu datoteku, "webdictionary.txt":
AJAX = Asinkroni JavaScript i XML
CSS = Cascading Style Sheets
HTML = Hyper Text Markup Language
PHP = PHP pretprocesor hiperteksta
SQL = Structured Query Language
SVG = skalabilna vektorska grafika
XML = Extensible Markup Language
Prvi parametar funkcije fopen() sadrži naziv datoteke koju treba otvoriti, a drugi parametar određuje u kojem načinu se datoteka treba otvoriti. Sljedeći primjer također generira poruku ako funkcija fopen() ne može otvoriti navedenu datoteku:
Primjer
echo fread($myfile,filesize("webdictionary.txt"));
fclose($myfile);
?>
Savjet: Funkcije fread() i fclose() bit će objašnjene u nastavku.
Datoteka se može otvoriti u jednom od sljedećih načina:
Načini rada | Opis |
---|---|
r | Otvorite datoteku samo za čitanje |
w | Otvorite datoteku samo za pisanje |
a | Otvorite datoteku samo za pisanje |
x | Stvara novu datoteku samo za pisanje |
r+ | Otvorite datoteku za čitanje/pisanje. Pokazivač datoteke počinje na početku datoteke |
w+ | Otvorite datoteku za čitanje/pisanje. Briše sadržaj datoteke ili stvara novu datoteku ako ne postoji, pokazivač datoteke počinje na početku datoteke |
a+ | Otvorite datoteku za čitanje/pisanje. Postojeći podaci u datoteci su sačuvani. Pokazivač datoteke počinje na kraju datoteke. Stvara novu datoteku ako datoteka ne postoji |
x+ | Stvara novu datoteku za čitanje/pisanje. Vraća FALSE i pogrešku ako datoteka već postoji |
PHP čita datoteku - fread()
Funkcija fread() čita iz otvorene datoteke.
Prvi parametar fread() sadrži naziv datoteke iz koje se čita, a drugi parametar navodi maksimalan broj bajtova za čitanje.
Sljedeći PHP kod čita datoteku "webdictionary.txt" do kraja:
Fread($myfile,filesize("webdictionary.txt"));
PHP Zatvori datoteku - fclose()
Funkcija fclose() koristi se za zatvaranje otvorene datoteke.
Dobra je programska praksa zatvoriti sve datoteke nakon što ste završili s njima. Ne želite da otvorena datoteka radi okolo na vašem poslužitelju i zauzima resurse!
Funkcija fclose() zahtijeva naziv datoteke (ili varijablu koja sadrži naziv datoteke) koju želimo zatvoriti:
$myfile = fopen("webdictionary.txt", "r");
// neki kod koji treba izvršiti....
fclose($myfile);
?>
PHP čita jedan redak - fgets()
Funkcija fgets() koristi se za čitanje jednog retka iz datoteke.
Primjer u nastavku daje prvi redak datoteke "webdictionary.txt":
Bilješka: Nakon poziva funkcije fgets(), pokazivač datoteke se pomaknuo u sljedeći redak.
PHP provjera kraja datoteke - feof()
Funkcija feof() provjerava je li dostignut "kraj datoteke" (EOF).
Funkcija feof() korisna je za kretanje kroz podatke nepoznate duljine.
Primjer u nastavku čita datoteku "webdictionary.txt" redak po redak, dok se ne dosegne kraj datoteke:
Primjer
$myfile = fopen("webdictionary.txt", "r") or die("Nije moguće otvoriti datoteku!");
// Izlaz jedan redak do kraja datoteke
dok(!feof($myfile)) (
echo fgets($myfile) . "
";
}
fclose($myfile);
?>
PHP čitanje jednog znaka - fgetc()
Funkcija fgetc() koristi se za čitanje jednog znaka iz datoteke.
Primjer u nastavku čita datoteku "webdictionary.txt" znak po znak, sve dok se ne dosegne kraj datoteke:
Primjer
$myfile = fopen("webdictionary.txt", "r") or die("Nije moguće otvoriti datoteku!");
// Ispis jednog znaka do kraja datoteke
dok(!feof($myfile)) (
echo fgetc($myfile);
}
fclose($myfile);
?>
Bilješka: Nakon poziva funkcije fgetc(), pokazivač datoteke pomiče se na sljedeći znak.
Kompletna referenca PHP datotečnog sustava
Za potpunu referencu funkcija datotečnog sustava idite na naš kompletan
(PHP 4, PHP 5, PHP 7)
fopen - Otvara datoteku ili URL
Opis
Resurs fopen (niz $ime datoteke , string $mode [, bool $use_include_path = false [, resurs $kontekst ]])
fopen() dodjeljuje imenovani resurs naveden u argumentu naziva datoteke toku.
Popis parametara
Ako je naziv datoteke proslijeđen u obliku "scheme://...", smatra se URL-om i PHP će tražiti rukovatelja protokolom (također poznat kao "omot") za tu shemu ako omot nije dodijeljen protokola, PHP će izdati upozorenje kako bi vam pomogao pronaći potencijalni problem u vašoj skripti i zatim nastaviti s izvođenjem kao da naziv datoteke upućuje na običnu datoteku.
Ako je PHP instaliran, taj naziv datoteke upućuje na lokalna datoteka, zatim se pokušava otvoriti tok ove datoteke. Datoteci mora biti dostupan PHP, pa biste trebali provjeriti dopuštaju li to dozvole za datoteku. Ako ste omogućili sigurni način rada ili open_basedir, tada se primjenjuju dodatna ograničenja.
Ako PHP utvrdi da naziv datoteke upućuje na registrirani protokol, a taj je protokol registriran kao mrežni URL, PHP provjerava stanje direktive allow_url_fopen. Ako je onemogućen, PHP će izdati upozorenje i fopen poziv neće uspjeti.
Komentar:
Popis podržanih protokola dostupan je u odjeljku Podržani protokoli i omoti. Neki protokoli ( omoti) podrška kontekst i/ili opcije php.ini. Pogledajte stranicu odgovarajućeg protokola za popis opcija koje se mogu postaviti. (na primjer php.ini vrijednost korisnički agent koristi omotač http).
Na Windows platformi morate izbjeći sve obrnute kose crte u putu datoteke ili koristiti kose crte.
$handle = fopen("c:\\folder\\resource.txt" , "r" );
?>
Parametar načina specificira vrstu pristupa koju tražite od niti. To može biti jedna od sljedećih opcija:
način rada | Opis |
---|---|
"r" | Otvara datoteku samo za čitanje; postavlja pokazivač na početak datoteke. |
"r+" | Otvara datoteku za čitanje i pisanje; postavlja pokazivač na početak datoteke. |
"w" | Otvara datoteku samo za pisanje; postavlja pokazivač na početak datoteke i skraćuje datoteku na nultu duljinu. Ako datoteka ne postoji, pokušava je stvoriti. |
"w+" | Otvara datoteku za čitanje i pisanje; postavlja pokazivač na početak datoteke i skraćuje datoteku na nultu duljinu. Ako datoteka ne postoji, pokušava je stvoriti. |
"a" | Otvara datoteku samo za pisanje; postavlja pokazivač na kraj datoteke. Ako datoteka ne postoji, pokušava je stvoriti. |
"a+" | Otvara datoteku za čitanje i pisanje; postavlja pokazivač na kraj datoteke. Ako datoteka ne postoji, pokušava je stvoriti. |
"x" | Stvara i otvara samo za pisanje; postavlja pokazivač na početak datoteke. Ako datoteka već postoji, nazovite fopen() završi neuspjehom, vratit će se NETOČNO i dat će pogrešku razine E_UPOZORENJE. Ako datoteka ne postoji, pokušat će je stvoriti. Ovo je ekvivalentno određivanju zastavica O_EXCL|O_CREAT za unutarnje sistemski poziv otvoriti (2). |
"x+" | Stvara i otvara za čitanje i pisanje; inače ima isto ponašanje kao "x". |
"c" | Otvara datoteku samo za pisanje. Ako datoteka ne postoji, kreira se. Ako datoteka postoji, tada nije skraćena (za razliku od "w"), a pozivanje ove funkcije ne uzrokuje pogrešku (kao što je slučaj s "x"). Pokazivač datoteke bit će postavljen na početak datoteke. Ovo može biti korisno ako želite zaključati datoteku (pogledajte stado()) prije promjene, od upotrebe "w" može skratiti datoteku prije nego što se zaključa (ako želite skratiti datoteku, možete koristiti funkciju ftruncate() nakon zahtjeva za blokiranje). |
"c+" | Otvara datoteku za čitanje i pisanje; inače ima isto ponašanje kao "c". |
Komentar:
Različite obitelji operativnih sustava imaju različite konvencije u vezi s završecima redaka. Kada pišete tekst i želite umetnuti prijelom retka, morate koristiti ispravne znakove (ili simbole) za svoj operativni sustav. Korištenje obiteljskih sustava Unix \n sustavi obitelji Windows koriste kao znak za kraj retka \r\n kao završni znakovi retka i Macintosh sustavi koriste \r kao znak za kraj retka.
Ako prilikom uređivanja datoteka koristite pogrešan znak za završetak retka, te datoteke mogu izgledati "čudno" kada ih otvorite.
Windows nudi oznaku načina emitiranja teksta ( "t"), koji će se automatski prevesti \n V \r\n tijekom rada s datotekom. I obrnuto - također možete koristiti "b" za forsiranje binarnog načina rada, koji neće pretvoriti vaše podatke. Za korištenje ovih načina, navedite "b" ili "t" posljednje slovo parametra moda.
Budući da zadana postavka oznake prijevoda ovisi o SAPI i PHP verziji koja se koristi, preporučujemo da izričito postavite navedenu oznaku zbog prenosivosti. Morate koristiti način "t" ako radite sa tekstualna datoteka i koristiti \n za označavanje kraja retka u vašoj skripti bez brige o čitljivosti vaših datoteka u drugim aplikacijama poput Notepada. U svim ostalim slučajevima koristite zastavu "b".
Ako eksplicitno ne navedete oznaku "b" kada radite s binarnim datotekama, mogli biste doživjeti čudno oštećenje podataka, uključujući oštećene slikovne datoteke i probleme s čudnim simbolima \r\n.
Komentar:
Zbog prenosivosti, snažno se preporučuje da uvijek koristite oznaku "b" kada otvarate datoteke s fopen() .
use_include_pathKomentar:
Osim toga, zbog prenosivosti, također se snažno preporučuje ponovno pisanje naslijeđenog koda koji se oslanja na "t" tako da umjesto toga koristi ispravne završetke redaka i način "b".
Neobavezni treći parametar use_include_path može se postaviti na "1" ili PRAVI ako također želite tražiti datoteku u include_path.
Kontekst
Komentar: Podrška za kontekst dodana je u PHP 5.0.0. Za opis kontekstima pogledajte odjeljak Streams.
Povratne vrijednosti
Vraća pokazivač na datoteku ako je uspješno, ili NETOČNO u slučaju greške.
Greške
Ako se datoteka ne može otvoriti, generirat će se pogreška razine E_UPOZORENJE. Možete koristiti operator za uklanjanje ove pogreške.
Popis promjena
Primjeri
Primjer #1 Primjeri upotrebe fopen()
$handle = fopen("/home/rasmus/file.txt" , "r" );
$handle = fopen ("/home/rasmus/file.gif" , "wb" );
$handle = fopen("http://www.example.com/", "r");
$handle = fopen ( "ftp://korisnik: [e-mail zaštićen]/neka datoteka.txt", "w" );
?>
Bilješke
Pažnja
Kada koristi SSL, Microsoft IIS prekida protokol zatvaranjem veze bez slanja indikatora zatvori_obavijestiti. PHP će to prijaviti kao "SSL: Fatal Protocol Error" u trenutku kada dođete do kraja podataka. Da biste to izbjegli, trebali biste postaviti error_reporting na razinu koja isključuje E_WARNING. PHP verzije 4.3.7 i starije mogu otkriti da postoji problematičan IIS na strani poslužitelja prilikom otvaranja streama pomoću omotača https:// i ne prikazuje upozorenje. Ako koristite fsockopen() za stvaranje ssl:// utičnicu, vaša je odgovornost otkriti i potisnuti ovo upozorenje.
Komentar: Kada je omogućena opcija sigurnog načina rada, PHP provjerava ima li direktorij s kojim ćete raditi isti UID (vlasnik) kao skripta koja se izvršava.
Komentar:
Ako naiđete na probleme tijekom čitanja ili pisanja datoteka, a koristite PHP kao poslužiteljski modul, provjerite ima li poslužiteljski proces pristup datotekama i direktorijima koje koristite.
Komentar:
Ova funkcija također može uspjeti ako je naziv datoteke direktorij. Ako niste sigurni je li naziv datoteke datoteka ili direktorij, trebate upotrijebiti funkciju je_dir(), prije poziva fopen() .
Imao sam malo vremena preko vikenda pa sam malo istražio o proc_open() na *nix sustavima.
Iako proc_open() ne blokira izvršavanje PHP skripte čak i ako se skripta ljuske ne izvodi u pozadina. PHP automatski poziva proc_close() nakon PHP skripta potpuno se izvršava ako ga ne pozovete. Dakle, možemo zamisliti da uvijek imamo liniju s proc_close() na kraju skripte.
Problem leži u neočitom, ali logičnom prototipu proc_close(). Recimo da imamo skriptu poput:
$proc = proc_open("top -b -n 10000", array(array("pipe", "r"), array("pipe", "w")), $pipes); //Obradi neke podatke koje ispisuje naša skripta, ali ne sve podatke echo fread($pipes,100); //Nemojte čekati da se završi izvršavanje scipta - izlaz //zatvaranje cijevi array_map("fclose",$pipes); //zatvaranje procesa proc_close($proc);
Čudno, proc_close() čeka dok se skripta ljuske ne završi, ali naša skripta je prekinuta ubrzo nakon toga. To se događa jer smo zatvorili cijevi (čini se da PHP to radi tiho, u slučaju da smo zaboravili), budući da ova skripta pokušava napisati nešto u cijevi koja više ne postoji - dobiva pogrešku i izlazi.
Sada pokušajmo bez cijevi (dobro, hoće, ali će koristiti trenutni tty bez veze na PHP):
$proc = proc_open("top -b -n 10000", array(), $pipes); proc_close($proc);
Sada naša PHP skripta čeka da završi skripta ljuske. Možemo li to izbjeći? Srećom, PHP generira skripte ljuske pomoću
Sh -c "shell_script"
tako da možemo jednostavno ubiti sh proces i ostaviti našu skriptu da radi:
$proc = proc_open("top -b -n 10000", array(), $pipes); $proc_status=proc_get_status($proc); exec("kill -9 ".$proc_status["pid"]); proc_close($proc);
Naravno, mogli bismo pokrenuti ovaj proces u pozadini, ovako:
$proc = proc_open("top -b -n 10000 &", array(), $pipes); proc_close($proc);
i nema nikakvih problema, ali ova nas funkcija dovodi do najtežeg pitanja: možemo li započeti proces s proc_open(), pročitati neki izlaz, a zatim ponovno forsirati proces? Pa, na neki način, da.
Glavni problem ovdje su cijevi: ne možemo ih zatvoriti ili će naš proces umrijeti, ali trebaju nam za čitanje korisnih podataka iz tog procesa. Ispostavilo se da ovdje možemo upotrijebiti čarobni trik - gdb.
Najprije negdje stvorite datoteku (/usr/share/gdb_null_descr u mom primjeru) sa sljedećim sadržajem:
P dup2(otvori("/dev/null",0),1) p dup2(otvori("/dev/null",0),2)
Reći će gdb-u da promijeni deskriptore 1 i 2 (dobro, obično stdout i stderr) u nove rukovatelje datotekama (/dev/null u ovom primjeru, ali možete ga promijeniti).
Sada, zadnja stvar: provjerite može li se gdb povezati s drugim pokrenutim procesima - ovo se primjenjuje prema zadanim postavkama na nekim sustavima, ali na primjer na ubuntu 10.10 trebate postaviti /proc/sys/kernel/yama/ptrace _scope na 0 ako ne nemoj ga pokrenuti kao root.
$proc = proc_open("top -b -n 10000", array(array("pipe", "r"), array("pipe", "w"), array("pipe", "w")), $cijevi); //Obradi neke podatke koje ispisuje naša skripta, ali ne sve podatke echo fread($pipes,100); $proc_status=proc_get_status($proc); //Pronađi pravi pid našeg procesa (moramo se spustiti jedan korak u stablu procesa) $pid=trim(exec("ps h -o pid --ppid ".$proc_status["pid"])); //Ukini nadređeni sh proces exec("kill -s 9 ".$proc_status["pid"]); //Promjena stdin/stdout rukovatelja u našem procesu exec("gdb -p ".$pid." --batch -x /usr/share/gdb_null_descr"); array_map("fclose",$pipes); proc_close($proc);
edit: Zaboravio sam spomenuti da PHP ne pokreće vašu shell skriptu odmah, tako da morate malo pričekati prije izvršavanja drugih shell naredbi, ali to je obično dovoljno brzo (ili je PHP dovoljno spor), a ja sam previše lijen da dodam te provjere mojim primjerima.
16,5 tisućaZapravo, kako otvoriti php datoteku nije veliki problem. Može biti teže otvoriti bocu piva kada ste usred šume. Ali samo strastveni programeri razmišljaju na ovaj način. A za početnike ćemo vam reći o svim mogućnostima PHP-a za rad s datotekama:
php datoteke
Datoteke sa php proširenje sadrže kod napisan u istoimenom programskom jeziku. Za razliku od drugih jezika, php je programski jezik na strani poslužitelja. Odnosno, radi na strani poslužitelja. Stoga, za otklanjanje pogrešaka koda, lokalni poslužitelj mora biti instaliran na klijentskom računalu.
Za rad s php datotekama koristite posebne aplikacije– uređivači softvera. Najčešći su:
- Dreamweaver.
- PHPEdit.
- Eclipse PHP razvoj.
uključiti naziv datoteke
Primjer povezivanja:
Uključena datoteka:
Uključivanje datoteke također je moguće korištenjem zahtijevane konstrukcije. Za razliku od include, uključuje datoteku prije nego što se programski kod izvrši. Korištenjem zahtjeva u kodu, moguć je samo jedan poziv ove datoteke. Kada mu se ponovno pristupi, sustav će prikazati globalnu poruku o pogrešci i zaustaviti izvođenje programa.
Include konstrukcija uključuje samo izvor tijekom izvođenja programa. Podržava višestruko čitanje php datoteke. Ako dođe do pogreške, prikazat će se samo poruka upozorenja, a izvršavanje koda će se nastaviti od sljedećeg retka.
Otvaranje i zatvaranje datoteka
U php-u sve operacije s datotekama provode se u nekoliko faza:
- Otvaranje datoteke;
- Uređivanje sadržaja;
- Zatvaranje datoteke.
Funkcija fopen() koristi se za otvaranje datoteke. Njegova sintaksa je:
int fopen(string naziv datoteke, string mod [, int use_include_path])
Prihvaćeni argumenti:
- string naziv datoteke – naziv datoteke ili apsolutni put do nje. Ako put do datoteke nije naveden, ona će se pretraživati u trenutnom direktoriju. Ako datoteka koju tražite nedostaje, sustav će prikazati poruku o pogrešci. Primjer:
- način stringa – označava način otvaranja datoteke. Vrijednosti koje prihvaća argument:
- r – datoteka se otvara samo za čitanje, pokazivač datoteke se postavlja na početak;
- r+ – datoteka je otvorena za čitanje i pisanje;
- w – stvoreno nova datoteka samo za potrebe snimanja. Ako datoteka s istim nazivom već postoji, bit će automatsko uklanjanje svi podaci;
- w+ - stvara novu datoteku za pisanje i čitanje. Kada takva datoteka postoji, njezini su podaci potpuno prebrisani novima;
- a – datoteka je otvorena za pisanje. Pokazivač je postavljen na kraj. Odnosno ulazak u php datoteka neće započeti od početka, nego od kraja;
- a+ – otvorite datoteku u načinu čitanja i pisanja. Snimanje će početi od kraja;
- b – način rada s datotekom koja sadrži binarne podatke (in binarni sustav račun). Ovaj način je dostupan samo u operacijski sustav Windows.
Za zatvaranje pristupa datoteci koristite funkciju fclose(). Sintaksa:
int fclose (int datoteka) , gdje je int datoteka ručka za mjesto koje treba zatvoriti.
Nakon svakog čitanja ili pisanja, datoteka se mora zatvoriti ovom funkcijom. Inače, tok stvoren za datoteku ostaje otvoren. A to dovodi do nepotrebne potrošnje kapaciteta poslužitelja.
Primjer:
Čitanje i pisanje datoteka
Za jednostavno prikazivanje cijelog sadržaja datoteke idealna je funkcija readfile(). Njegova sintaksa je:
readfile (string filename) , gdje je string filename naziv datoteke niza (ne oznaka).
Ista se datoteka može pročitati pomoću funkcije fpassthru(). Čita podatke od krajnjeg položaja pokazivača do kraja datoteke. Njegova sintaksa je:
int fpassthru (int datoteka)
Funkcija zahtijeva otvaranje i zatvaranje datoteke. Primjer:
Rezultat je sličan prethodnom.
Funkcije za rad s datotekama u php-u omogućuju čitanje sadržaja red po red i znak po znak:
- string fgets (int datoteka, int duljina)– funkcija čita niz duljine length . Primjer:
- string fread (int datoteka, int duljina)– radnja je identična prethodnoj.
Za pisanje tekstualnih podataka u datoteku postoje dvije identične funkcije:
- int fputs (int datoteka, string string [, int duljina ])
- int fwrite(int datoteka, string string [, int duljina ])
Funkcije pišu u datoteku int file string string navedene duljine int length ( izborni argument). Primjer:
Stvaranje i brisanje datoteka
Za izradu php datoteke možete koristiti funkciju fopen() u načinu pristupa "w" ili "w+". Ili funkcija touch(). Postavlja vrijeme izmjene datoteke. Ako ne postoji element s traženim nazivom, on će biti kreiran. Njegova sintaksa.