Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Funktio palauttaa PHP:n lähdekoodiin tekstinä

Sivun loppuun

Macro [06.12.2009 20:01:58]

#

<?php
function php($s) {
    return '<div style="font-size: 12px">' .
	highlight_string(html_entity_decode(stripslashes($s)), True)
	. '</div>';
}

function archive($var) {
    $var = file_get_contents($var);
    $search = array('/\[koodi\](.*?)\[\/koodi\]/ise');
    $replace = array("php('\\1')");

    $var = preg_replace($search, $replace, $var);
	echo $var;
}

Tuon näköisen systeemin onnistuin tekemään, mutta on yksi ongelma. Jos sivulla joka ajetaan archive-funktion läpi, on php-koodia, niin tämä tulostetaan sellaisenaan lähdekoodiin. Mitä tein väärin, että se tekee niin PHP:n ajamisen sijaan?

Metabolix [06.12.2009 21:50:30]

#

Mitä tarkoitat? Voisitko antaa esimerkin tiedostosta, toivomistasi käsittelyvaiheista ja tulosteesta?

Macro [07.12.2009 08:54:18]

#

Tulos on sama, kuin laittaisi PHP-koodia *.html sivulle jota ei ajeta PHP tulkin läpi. Eli, jos sivulla lukee

<?php
echo "Hello world!";
?>

niin archive-funktion läpiajettaessa PHP tulkitaan normaalina kielenä, eikä ajeta PHP-tulkin läpi. Ylläoleva tulostaa tyhjän sivun, jonka lähdekoodissa lukee tuo pätkä.

JoonasK [07.12.2009 09:15:23]

#

Käytät file_get_contents(); funktiota, joka ottaa tiedostosisällön stringii. Haluat varmaa käyttää include-funktiota, mutta jotta sen käyttäminen onnistuisi stringinä, tarvitset seuraavaa koodinpätkää:

<?php

function get_include_contents($file) {
	if(is_file($file)) {
		ob_start();
		include $file;
		$result = ob_get_contents();
		ob_end_clean();
		return $result;
	}
	return false;
}

?>

Ja sitten file_get_contentsin sijasta käytät get_include_contents.

Macro [07.12.2009 09:20:56]

#

Muuten hyvä, mutta kuten aikaisemmasta viestistä huomaat, niin [koodi]-tagien sisällä oleva koodi pitäisi tulostaa väritettynä. Nyt käy siten, että kaikki koodit suoritetaan.

Merri [07.12.2009 09:29:10]

#

Palataanpa vähän olennaisempiin asioihin, jotka jätit välistä. Onko tarkoituksesi tulostaa jonkin valitun PHP-tiedoston koodi väritettynä?

(Nyt yritetään neuvoa ennen kuin tiedetään mitä oikeastaan haet takaa.)

Macro [07.12.2009 09:31:46]

#

Ihan sama asia kuin Ohjelmointiputkassa: [ koodi]-tagien sisältö tulostetaan väritettyinä, ja jos sivulla on muuta PHP-koodia niin tämä ajetaan PHP-tulkin läpi. HTML:n kanssa menetellään normaalisti (Kuten file_get_contents() tekeekin).

JoonasK [07.12.2009 09:37:15]

#

Helpoin tapa varmistaa ettei koodia suoriteta on käyttää htmlentities('<?php echo 'koodi jotai ei suoriteta'; ?>');, mikäli siis mahdollista tilanteessasi.

Macro [07.12.2009 09:40:36]

#

En nyt ihan ymmärrä. Mitä pitäisi tehdä, että postittamasi funktio ei käsittelisi [koodi]-tagien välissä olevaa dataa "omakseen", vaan antaisi php() funktion suorittaa sen?

Merri [07.12.2009 09:44:07]

#

Todettakoon, että Putkassa on käytössä oma BBCode-systeeminsä. Viesti on siis kokonaan säilötty tekstinä, mm. (kai) htmlspecialchars suoritetaan kertaalleen koko viestille ja sen jälkeen muutetaan tagit HTML:ksi ja väritetään toki koodikin. Viestit on ymmärtääkseni säilötty tietokantaan. Tämän vuoksi file_get_contentsin ym. sotkeminen mukaan on hieman hämmentävää, ainakin jos tarkoituksena on tehdä oma BBCode-systeemi.

Suosittelen tutkimaan foorumijärjestelmien BBCode-koodia ja Geshi saattaa kiinnostaa myös.

JoonasK [07.12.2009 09:46:32]

#

Macro kirjoitti:

En nyt ihan ymmärrä. Mitä pitäisi tehdä, että postittamasi funktio ei käsittelisi [koodi]-tagien välissä olevaa dataa "omakseen", vaan antaisi php() funktion suorittaa sen?

Mistä koodi-tagien välissä oleva data ensinnäkin tulee? Uskoisin että pystyt vaikuttamaan siellä, lisäämällä koodi-tagien sisällä olevan koodin ympärillä htmlentities()-funktiot joka tekee merkeistä html-entiteettejä, jolloin koodia ei suoriteta.

Esim:

<?php

echo 'tämä koodi on tagien sisällä';

?>

Korvautuisi tällä:

<?php htmlentities("
<?php

echo 'tämä koodi on tagien sisällä';

?>
"); ?>

EDIT:
Jos tekstisi sisältö tulee tietokannasta kannattaa käyttää htmlentities()-funktiota jo tallentaessa sitä sinne.

Macro [07.12.2009 09:51:24]

#

Saisi sen varmaan näinkin, tosin vaikeamman kautta. arvhive-funktion paramentti $var ottaa arvokseen sivun osoitteen, jonka tämä sitten hakee.

-tagien välissä oleva data pitäisi ajaa php()-funktion läpi, ja muu tuon get_include_contents()-funktion läpi.

[koodi PHP]<?php
function php($s) {
    return '<div style="font-size: 12px">' .
	highlight_string(html_entity_decode(stripslashes($s)), true)
	. '</div>';
}

function archive($var) {
	$var = get_include_contents($var);
    $search = array('/\[koodi\](.*?)\[\/koodi\]/ise');
    $replace = array("php('\\1')");

    $var = preg_replace($search, $replace, $var);
	echo $var;
}

JoonasK [07.12.2009 09:56:41]

#

Macro kirjoitti:

Saisi sen varmaan näinkin, tosin vaikeamman kautta. arvhive-funktion paramentti $var ottaa arvokseen sivun osoitteen, jonka tämä sitten hakee. [koodi]-tagien välissä oleva data pitäisi ajaa php()-funktion läpi, ja muu tuon get_include_contents()-funktion läpi.

En usko että tämä lähestymistapa voisi toimia, saati sitten olla mahdollista. Et tietääkseni pysty mitenkään muokkaamaan dataa ensin muuttujassa ja sitten suorittamaan sitä, vaan sinun pitää muokata dataa jo ennen kuin se suoritetaan.

EDIT: Mikäköhän kirjoitustaitoani vaivaa...

Macro [07.12.2009 10:01:08]

#

En ymmärrä, että mitä koitat ajaa takaa tuolla. Miten siis suoritan kaiken muun paitsi [koodi]-tagien sisällön, jonka syntaxi-värityksen annan php() funktiolla? Jostain syystä ei tee mieli pyytää esimerkkiä, mutta se voisi nyt kyllä helpottaa.

Metabolix [07.12.2009 10:42:34]

#

Siis onko tavoitteesi tämä:

<?php
echo "Tuloste\n";
?>
[kooditagi]
<?php
echo "Väritys\n";
?>
[/kooditagi]
Tuloste
&lt;?php
echo &quot;Väritys\n&quot;;
?&gt;

Ensimmäinen PHP-osuus ajettiin ja se tulosti yhden sanan. Kooditagien sisältö on HTML-enkoodattu ja näkyy sivulla alkuperäisessä muodossaan. (Lisäksi sekaan tulisi väritystä varten tageja, mutta nyt en selkeyden vuoksi laittanut niitä.)

Entä miten tämän koodin pitäisi toimia:

<?php
for ($i = 0; $i < 10; ++$i) {
  ?>
  [kooditagi]
    <?php
      echo $i;
    ?>
  [/kooditagi]
  <?php
}

(Voit kokeilla tavallisella PHP-sivulla, mitä tuo tavallisesti tekee.)

Voit esimerkiksi poimia kooditagien välisen osuuden säännöllisellä lausekkeella ja enkoodata sen ennen koodin ajamista. Tämä tapa kuitenkin toimii aika omituisesti, jos kooditageja esiintyy muun PHP-koodin seassa. Mutkikkaammalla lausekkeella saisi paremman lopputuloksen, mutta sellaisen saat opetella itse kirjoittamaan. (Katso oppaan lisäksi vaikka koodivinkkiä C++-koodin värityksestä.)

<?php
function varita($osuma) {
	return htmlspecialchars($osuma[1]);
}
eval('?>'.preg_replace_callback('#\\[kooditagi\\](.*?)\\[/kooditagi\\]#ms', 'varita', file_get_contents('testi.php')));
?>

Edit: Esimerkki.

Macro [07.12.2009 16:32:47]

#

Kiitos Metabolix! Muistinkin, että PHP:ssä on eval() funktio, mutta en älynnyt/osannut käyttää.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta