ugrás a tartalomhoz

sima file append de a meglévő fájl elejére!

Somnus · 2007. Május. 27. (V), 15.45
Sziasztok!
Hogy lehet azt megoldani hogy php file append-nél ne a txt végére fűzze az új szöveget, hanem az elejéhez csapja hozzá?
Először csináljak másolatot róla aztán írjam felül az egyiket az új adattal és vágjam egybe őket?
Ez elég barbár megoldás lenne sztem.
Valami ötlet?
Előre is kösz!
 
1

Seek

janoszen · 2007. Május. 27. (V), 16.36
Mivel egy fájlban szekvenciálisan írni és seekelni tudsz, ezért nem tudsz mást csinálni, mint hogy egy tempfájlba összevágod a dolgokat és utána kitörlöd az eredetit és átnevezed a temp fájlt.
2

+1 krédés

Somnus · 2007. Május. 27. (V), 17.51
Okés ezt akor így értem.
Akkor másfelől közelítem meg a dolgot: hogy lehet mondjuk egy fájlból a sorok olvasását a végétől kezdeni?
Szóval visszafelé.
Mert nem szeretném beolvastatni (több 100kbyteos fájlok) legelejétől, ha csak a végére vagyok kiváncsi :)
3

Végéről?

janoszen · 2007. Május. 27. (V), 18.25
Ezt meg minek? Egyébként úgy, hogy első műveletként a végére seek-elsz, majd pl 1 kB-os darabokban vissza. Természetesen az első seek és olvasás után már KÉT kb-ot kell visszafele lépned, mert az olvasással egyet haladtál.

De ez valeszeg hülyeség, ha így akarod megoldani, vagy baromira el van cseszve az adatstruktúra amit kitaláltál vagy valami eleve elcseszett helyzetbe csöppentél bele, amire viszont az első hozzászólásom a megoldás.
4

megvan!

Somnus · 2007. Május. 27. (V), 19.11
ezzel végétől az eleje felé olvasok, szal ami kellett
amúgy egy "saját csetet" próbálok összehozni ajaxal és php-jal.
ezt a php-t hivogatom 2-3 másodpercenként ami megvizsgálja hogy kell e hozáfűzni az ablakban lévő szöveghez vagy sem.
eleve így "terveztem", csak hogy nekelljen összes sort beolvasni ezért gondoltam ilyen megoldásra, mert azért ha haverok feljönnek, 2másodpercenként kérnek a szervertől, jobb ha minimálisat számol.

$file_name="logs/" . date('Y-m-d') . ".sc6";

$file = array_reverse( file( $file_name ) );
$limit = 30;

for ($i = 0; $i < $limit; $i++ )
{
if (strlen($file[$i])!=0)
{
echo $file[$i] . "<br>\n";
}
else
{
break;
}
}
5

Uh

janoszen · 2007. Május. 27. (V), 19.34
Saját chat adatbázis nélkül? Eléggé szuicid megoldásnak hangzik, mert ha többen rákattannak nagyon csúnya párhuzamos hozzáférési problémáid lesznek. Gondoltál már arra, hogy mi van ha ketten egyszerre próbálnak írni ugyanabba a fájlba? És PHP esetén még a flock sem megoldás.

Szerintem, sürgősen próbálj meg valami adatbázis hátteret varázsolni a dolognak, különben adott esetben szét fog esni az egész. Arról nem is beszélve, hogy nem igazán gazdaságos, ha minden alkalommal megfordítod az egész fájlt. Ez az inkább pazarló megoldás.

Ja, és remélem a mások által beküldött tartalmakat szűröd mindenféle injection szempontból, mert az is baj lehet.
6

array + serialize

krey · 2007. Május. 27. (V), 20.57
Nem olvastam végig a kódrészleteket, de mi lenne ha serializálna egy tömböt? Azzal már az injection-t is nagyjából szűrte, nem? Mi is kb. vmi ilyen csúnyaságot vittünk véghez egyszer mindenféle adatbáziskezelő-modul hiányában.

Igen az flock elég problémás szokott lenni, a végén úgyis írni kell egy daemon-t...

üdv. krey

ps. közben rájöttem, hogy gázos a serialize dolog, mert meg akarja spórolni az írás-olvasásokat...
7

Serialize

janoszen · 2007. Május. 27. (V), 21.50
Na igen, az SQL injectionöket. És mi van a content injectionökkel? Azzal is lehet csúnya dolgokat csinálni.
8

jogos

krey · 2007. Május. 27. (V), 22.24
Kettes típusú XSS-re gondolsz (vagy mi ennek a normál neve)? Az ellen outputolásnál kell védekezni...
Amúgy itt SQL-ről szó nincs, de ha lenne, akkor is védve van minden az injectionök ellen ;)

üdv. krey
9

JavaScript

janoszen · 2007. Május. 27. (V), 22.40
Amikor JavaScriptet tolunk bele a tartalomba? Az ellen itt semmi nincs védve és a bevitelkor kéne megszűrni, hogy mindjárt vissza is dobja. :)
10

és ha direkt azt akarok?

gex · 2007. Május. 27. (V), 23.46
miért kéne visszadobni? nem lehet pont javascript a téma? nem a js beírásával van a gond, hanem azzal hogy te hogyan adod vissza...
15

Mert...

janoszen · 2007. Május. 28. (H), 08.13
Mert fölösleges eltárolni nyilvánvalóan ártó szándékú kódokat. Ha valami JavaScript kódot tartalmaz végrehajtható módon az nem a témához tartozik, hanem valszeg ártó szándékú.
19

nyilvánvaló?

gex · 2007. Május. 28. (H), 09.27
ebben a szálban melyik hozzászólást ítélnéd nyilvánvalóan ártó szándékúnak?
a te scripted valószínűleg nem fogja tudni eldönteni, hogy mi vág a témába és mi nem, úgyhogy kénytelen leszel mindent eltárolni, amit kapsz. ilyen alapon a "</div></body></html>" sztring is nyilvánvalóan ártó szándékú, mert elronthatja a designt, persze csak ha html-ről van szó. úgyhogy akkor vegyük sorra mi lehet még ártó szándékú az rss-emre, a csv fájljaimra, az adatbázisomra, stb. persze most már nem csak a chat-ről van szó, de szerintem rossz a logikád. olyan, mintha letiltanám a ', " és ; jelek használatát, mert bezavarhat az adabázisban tárolásnál.
20

Nem erről van szó!

janoszen · 2007. Május. 28. (H), 09.41
Nem kódrészletekről van szó, hanem HTML kódról. Ha meg akarod jeleníteni a HTML kódot, escapelni kell. Ha nem escapeled, akkor forráskódként fog értelmeződni. Erről volt szó.
21

korábban még visszadobtad volna

gex · 2007. Május. 28. (H), 10.21
igen én pontosan erről beszéltem, hogy nem hibával kell visszadobni amit beírt, hanem rendesen le kell kezelni...
22

Chat

janoszen · 2007. Május. 28. (H), 14.40
Kérdés, hogy mit akar a t. kérdező. Ha csak sima szöveges bevitel, akkor vissza kell dobni, ha lehet szó szakmai dolgokról, akkor be kell kódolni... helyzetfüggő. Én csak annyit mondtam, hogy a nem megfelelő bevitelt szűrni kell és vissza kell dobni.
11

Más elképzelés

krey · 2007. Május. 28. (H), 00.08
Nem értem hogy lehetne javascriptet tolni bele a tartalomba :S Én így képzelem el:

<?php
function reader($last_mod_time, $last_message_id) {
    global $chatFile;
    if ($mod_time == filemtime($chatFile))
    return;
    return array_map("htmlspecialchars" ,array_slice(unserialize(file_get_contents($chatFile)), $last_message_id+1));
}
function writer($user,$message) {
   global $chatFile;
   if (empty($message))
   return;
   $messages = unserialize(file_get_contents($chatFile));
   $messages[] = array($user,$message, time());
   return $messages;
   //file_put_contents($chatFile, serialize($messages));
}
?>
Itt pl. nem vágom hol a content injection, de ha van szóljatok!
Amúgy a kód csak demonstráció...

Megjegyzem a kérdező kódja nem is lenne rossz, ha nem a teljes logon fordítana egyet, hanem csak az új üzeneteken.

Nem értem miért ilyen fontos a sebesség, mellesleg. Ha tényleg max. sebességet akarsz, akkor írj egy daemont. Elvileg phpban is lehet futtasd a szerveren és ha frissül valami akkor dobja vissza az összes kliensnek az új üziket (mondjuk 1mp-s minimum intervallal). Ezt flashben olyan jól meg lehet csinálni, nemtom ajaxban hogy kell, de érdekelne :) És ha már megy a daemon, akkor beleépítheted az adatbázis kezelést is!

üdv. krey
12

:)

Somnus · 2007. Május. 28. (H), 07.33
Sziasztok!
Nekem csak egy volt a lényeg, hogy az új üzenetek egyből előre kerüljenek ÉS előről olvasom be a sorokat VAGY a végére kerülnek az új üzenetek ÉS a végétől visszafelé olvasom be a sorokat.
Az utóbbit találtam célszerű(bb)nek.
Bocsi ha kontárkodok össze meg vissza, de én spec így tudok megtanulni valamit ha kipróbálom, nemrég kezdett el érdekelni a php meg ezek a webes dolgok.
Perpill csak a legutolsó sort frissíti le, de ez már csak phptól függ hogy meddig olvas vissza, majd azis meglesz idővel.
3 másodpercenként nézi meg hogy van e friss sor a fájlban, és ha van akkor hozzáteszi a meglévőkhöz.
pl.: http://sc6.somnusoft.com
Várom a hozzászólásokat ill. kritikákat!
UI: amit említettél daemont, azt hogy lehetne megvalósítani? (utánnaolvasok ígérem)
14

Daemon

janoszen · 2007. Május. 28. (H), 08.09
Nyilván, fájllal nem tudod okosabban megcsinálni, de akkor is...

Ami a daemont illeti, két fajta megoldás létezik: Mindkettő lényege az, hogy nem maga a PHP program intézi a chat kezelést, hanem egy harmadik valami, ami állandóan fut a háttérben.

1. Rendszerdaemon

Használhatsz pl IRC szervert vagy írhatsz egy sajátot. A probléma az, hogy ehhez rendszergazdai hozzáférés kell a szerverhet szal valszeg kilőve.

2. Adatbázis

Tulajdonképpen ez is egy daemon, csak a legtöbb helyen föl van telepítve. Az előnye az, hogy tudsz sorokat lekérni belőle és nem kell vacakolnod a fájlkezeléssel, mert ezt az adatbázis elintézi neked. Ajánlom figyelmedbe a MySQL dokumentációt.

Röviden így nézhet ki az adatbázis tábla:
CREATE TABLE chat
(
 id INT PRIMARY KEY AUTO_INCREMENT,
 nick VARCHAR(32) NOT NULL,
 arrived TIMESTAMP NOT NULL,
 comment MEDIUMTEXT NOT NULL
);
Ekkor egy adatbázis lekérés PHP-ból így nézhetne ki:
<?php
 $r = mysql_query("SELECT nick, arrived, comment FROM chat ORDER BY id LIMIT 30");
?>
Persze, lehet aztán a legutóbbi lekérés óta beérkezetteket lekérni meg minden ilyen finomság. A beszúrás pedig így nézhetne ki:
<?php
 $r = mysql_query
 (
  "INSERT INTO chat (nick, arrived, comment)
    VALUES ('" . mysql_real_escape_string($nick) . "',
    NOW(),
    '" . mysql_real_escape_string($comment) . "')
  "
 );
?>
Persze, nem szabad megfeledtkezni az előbb tárgyalt injection védelemről sem.
17

nagyon szépen köszönöm!

Somnus · 2007. Május. 28. (H), 08.25
nemgondoltam volna hogy ennyit segít valaki is :)
kösz szépen mégegyszer!
amúgy te voltál fent és kérdeztél rá a Cross Site Scripting-re?
elvileg minden < > stb... jelet átalakítok html kódra
na majd re, nagymamát viszem ügyeletre!
mégegyszer köszi szépen!
18

Menni fog

janoszen · 2007. Május. 28. (H), 08.33
Na, így már menni fog. Ha nem akarod lemezre írni / megőrizni a chatet, állítsd be az utolsó zárójel után a táblakreálásnál, hogy ENGINE=Memory és időközönként nyomj rá egy deletet, ami kivadássza a régi hozzászólásokat. Így gyorsabb lesz a dolog és nem is lesznek konkurencia problémáid.

Nagyinak meg jobbulást.
13

kezdek újat mert ott már nagyon tömör volt a sor

Somnus · 2007. Május. 28. (H), 08.01
Olyanra is gondoltam, hogy, mindenkinek csinálna a szerver egy fájlt (a fájlnév az az illető ipjének az md5-ös kódja lenne) és abba írkálná hogy kinek mi az utolsó sora, mert az a gond hogy amit eddig csináltam abba csak a phpból csak egy visszatérési értéket tud kiolvasni az ajax vagy nemtudommiez (úgy vagdostam össze xD)
(bocs a kontárkodás miatt)
és ez az egy visszatérési értékből kellene a phpba viszatöltenem az utolsó sort (akkor van gáz ha egyszerre több sort kapott) :S
mit szóltok hozzá?
amúgy én mindeképpen fájl alapút akarok, nem akarok sql ben tárolni az üziket se semmit, max a jelszavakat (talán)
hogy ne tudja mindeki használni, szépen teszek majd az egész subra egy htaccess fájlt ami jelszóval nézhető csak meg.
üdv: Somnus
16

Inkább

janoszen · 2007. Május. 28. (H), 08.20
Inkább olvasd el a 16-os hozzászólásomat... A fájllal mindenképpen konkurens hozzáférési problémáid lesznek, mert a PHP egész egyszerűen nem erre való. Használhatsz memory táblát is, akkor nem írja lemezre és törölgetheted rendszeresen a 30 másodpercnél régebbieket...
23

flock?

Hodicska Gergely · 2007. Május. 29. (K), 10.50
A fájllal mindenképpen konkurens hozzáférési problémáid lesznek, mert a PHP egész egyszerűen nem erre való.
Ez ma másodjára olvasom Tőled ("nem erre való"). Miért ne lehetne erre való? Szerinted a PHP alap (fájl alapú) session kezelése hogyan működik?


Üdv,
Felhő
24

Flock

janoszen · 2007. Május. 29. (K), 19.12
Ha megnézed, a flock egyáltalán nem thread safe. Ami pedig a fájl hozzáférést illeti, akkor pl nincs (akkora) gond, ha hozzászólás-modult valósítasz meg, mert ott nagyon kevés lesz az írás és sok az olvasás, úgyhogy valószínűtlen hogy lesznek ilyen problémák. Ami viszont a chatet illeti, ott bizony előfordulhat ilyen, látogatottság függvényében.

A session kezelés megint más, mert ott egy klienst szolgálsz ki egy sessionből. Egyébként ha megnézed a leírásokat, ott is van konkurens hozzáférési probléma csak a gyakorlatban ritkán jön elő, mert két oldalletöltés egy felhasználótól ritkán történik egy időben. Ergo ott sincs lekezelve.
25

strace

Hodicska Gergely · 2007. Május. 30. (Sze), 00.50
Ha megnézed, a flock egyáltalán nem thread safe.
Azt írja a manual, hogy bizonyos oprendszerek esetén nem threadsafe, tehát ez nem eleve elrendeltetett. Ugyanott találhatsz ilyen esetre is megoldást. Félre ne érts, nem azt mondom, hogy ez lenne az ajánlott megoldás, de kivitelezhető korrekt módon.

A session kezelés megint más, mert ott egy klienst szolgálsz ki egy sessionből.
Ki garantála ezt? Lásd AJAX alkalmazások, ma már azért ez erőteljesen jelen van, külön probléma is saját session kezelő írásakor, hogy legyen benne megfelelő lockolás versenyhelyzet esetén is megfelelő működés érdekében.

Ergo ott sincs lekezelve.
Ezt egyszerűen tudod ellenőrizni: strace php -r "session_start();". Ebben ezt találod:
open("/var/lib/php5/sess_71a9a825136647cf9adb6487cb1d7ec4", O_RDWR|O_CREAT, 0600) = 3
flock(3, LOCK_EX)
Tehát kezelve van.


Üdv,
Felhő
26

flock

janoszen · 2007. Május. 30. (Sze), 08.54
Igen, de mivel nem tudom, a tisztelt kérdező szervere min fut, úgyhogy abból kell kiindulni, hogy bizony nem thread safe.

AJAX: ott a pont. De azért nagyságrendileg több lekérés érkezik még így is egy többek által közösen használt erőforráshoz, mint egy egyetlen ember által használt session-höz. Ergo, valószínűbb, hogy megúszod versenyhelyzet nélkül. Arról nem is beszélve, hogy ha okos a JS lib, akkor tudja queue-ba tenni a szerverhívásokat és akkor nincs gond.

session_start: nem tudtam ellenőrizni, mert valamiért nem akar rajta fogni a grep, de biztos így van. De mint az előbb említettük, a flock nem (feltétlenül) thread safe.

Összegezve: szőrszálhasogatás helyett inkább azt mondanám, mivel az adatbázis thread safe és már megírtam az előbb elég sok mindent hozzá, inkább használja azt a t. kérdező.
27

re: flock

Hodicska Gergely · 2007. Május. 30. (Sze), 20.04
De azért nagyságrendileg több lekérés érkezik még így is egy többek által közösen használt erőforráshoz, mint egy egyetlen ember által használt session-höz. Ergo, valószínűbb, hogy megúszod versenyhelyzet nélkül.
Jaja, én se tenném fájlba, mert macerásabb, de csak arra reagáltam, hogy megoldható jó eséllyel.

Arról nem is beszélve, hogy ha okos a JS lib, akkor tudja queue-ba tenni a szerverhívásokat és akkor nincs gond.
Csak általában két kapcsolatot használnak a szerver fele, ezért lehetnek gondok az időzítéssel.

session_start: nem tudtam ellenőrizni, mert valamiért nem akar rajta fogni a grep, de biztos így van.
Ezt valamiért én se tudtam lesselni, de strace -o filename működik.

De mint az előbb említettük, a flock nem (feltétlenül) thread safe.
Ez az OS flockja, nem a PHP-é!

Összegezve: szőrszálhasogatás helyett inkább azt mondanám, mivel az adatbázis thread safe
Ehhez még érdekességként annyit, hogy pl. a session problémájára simán csak egy alapú session kezelő nem adna megoldást, ott is külön figyelned kell a lockra, amire egy master esetén (mysql) nagyon jó lehet a get_lock/release_lock páros.


Üdv,
Felhő
28

Sqlite?

vbence · 2007. Május. 31. (Cs), 15.57
Ha a fájlos megoldás szóba került, talán érdemes lenne pár percet szánnod az SQLite támogatásra, ami valahol félúton van a fájl és a mysql között. (Szerényebben kialakított webtárhelyen is működik, nem kell a szolgáltató biztosítson adatbázist, futtasson szervert stb, elég ha csak telepítve van a php-be ez a kiterjesztés).