2010-01-09 12 views
2

La configuration:Enregistrement d'un fichier .php et sauver le comprend aussi (peut-être)

J'ai un fichier standard .php (index.php) qui contient deux comprend, pour un en-tête (header.php) et un pour footer (footer.php). Le fichier index.php ressemble à ceci:

index.php

<?php 
include header.php; 
?> 

<h2>Hello</h2> 
<p class="editable">Lorem ipsum dolar doo dah day</p> 

<?php 
include footer.php; 
?> 

header.php comme ceci:

<html> 
<head> 
<title>This is my page</title> 
</head> 
<body> 
<h1 class="editable">My Website rocks</h1> 

et pied de page .php comme ceci:

<p>The end of my page</p> 
</body> 

J'écris un script PHP qui vous permet de modifier l'un des éléments ".editable" sur une page. Mon problème est que ces régions modifiables pourraient apparaître dans tous les fichiers inclus ainsi que le corps principal de index.php.

Mon code php saisit le fichier index.php avec file_get_contents(); ce qui fonctionne bien. Je suis également capable d'éditer et de sauvegarder toutes les régions ".editable" dans index.php.

Ma question:

J'ai été incapable de trouver un moyen de « trouver » le comprend et analyser à travers ceux des régions « .editable » aussi bien. Je cherche des suggestions sur la façon dont je travaillerais à travers tous les inclus dans index.php - en les vérifiant pour les régions modifiables. Aurais-je besoin d'utiliser des expressions régulières pour trouver "include * .php"? Je ne suis pas sûr d'où commencer même ...

Pour ceux d'entre vous qui souhaitent voir mon code PHP. Je me sers de la classe PHP: [texte du lien] [1] qui me permet d'écrire du code comme:

// load the class and file 
$html = new simple_html_dom(); 
$html->load_file("index.php"); 

// find the first editable area and change its content to "edited" 
$html->find('*[class*=editable]', 0)->innertext = "Edited"; 

// save the file 
$html->save(index.php); 

[1]: http://simplehtmldom.sourceforge.net/manual_api.htmanalyseur simple dom php


UPDATE

J'ai joué avec des expressions régulières pour essayer de faire correspondre les inclusions. Je suis assez nul à regex mais je pense que je me rapproche. Voici ce que j'ai jusqu'à présent:

$findinclude = '/(?:include|include_once|require|require_once)\s*(?:[a-z]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?]|[^\?\>])*\?>)/i'; 

Cela correspond assez bien même si elle ne semble revenir l'impair) et «lors de l'utilisation preg_match. J'essaye d'ajouter un peu de sécurité dans la regex pour m'assurer qu'elle correspond seulement aux balises php - cette partie: (? = (?: [^ \ < \?] | [^ \?>]) * \?>) - mais il ne renvoie que le premier include sur une page. Des astuces pour améliorer cette expression régulière? (Je suis là depuis environ 6 heures)

+0

Ceci est un trou de sécurité sérieux. Laisser les gens éditer le code php réel qui fonctionnera sur votre serveur n'est pas intelligent. –

+0

@George Edison - Le code PHP n'est pas éditable. Seul le HTML autour du PHP. Dans mon esprit (à condition que toutes les données sauvegardées soient validées correctement), ce n'est pas différent d'un système qui édite des fichiers HMTL. – Scott

Répondre

0

Ok, je me suis finalement débrouillée. Si vous cherchez un include, include_once, require, require_once dans un fichier .php, vous pouvez utiliser l'expression régulière suivante avec une fonction php comme preg_match_all.

'/(?:include|include_once|require|require_once)\s*(?:[a-z]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?])*\?>)/i'; 

Ceci recherche toutes les inclusions dans les balises. Référant cela à mon exemple original. Mon code ressemble à ceci:

$html = new simple_html_dom(); 
$html->load_file("index.php"); 

$findinclude = '/(?:include|include_once|require|require_once)\s*(?:[a-z]|"|\(|\)|\'|_|\.|\s|\/)*(?=(?:[^\<\?])*\?>)/i'; 

if (preg_match_all($findinclude, $html,$includes)): 

    // shift the array to the left 
    $incfiles = $includes[0]; 
    $i = 0; 

    // then loop through the includes array and print our filename 
    foreach ($incfiles as $inc) { 
     print basename(preg_replace('/[^a-zA-Z0-9\s\.\_\/]/', '', $inc)."\n"); 
    } 
endif; 

Job done! Je peux maintenant travailler à travers ceci pour éditer chaque dossier comme requis.

1

Quel type de système créez-vous?

Si le système devait être utilisé par le public, vous auriez de graves problèmes de sécurité. Les utilisateurs peuvent inclure leur propre code PHP ou JavaScript dans le contenu fourni.

Ce n'est pas du tout la manière standard de créer du contenu dynamique. Dans la plupart des cas, vous souhaiterez créer un modèle unique, puis autoriser les utilisateurs à enregistrer leurs modifications dans une base de données. Vous devez ensuite remplir les informations dans le modèle de la base de données pour l'affichage.Si vous leur permettez d'inclure du code HTML, utilisez le html purifier pour le nettoyer, insérez les données dans votre base de données avec une instruction préparée en utilisant PDO. Je suis sûr que les gens ici seraient heureux de répondre à toutes les questions que vous pourriez avoir sur l'utilisation d'une base de données.

+0

J'espère que ce sera un système de gestion de contenu léger. Tous les utilisateurs/éditeurs du système devront être connectés pour apporter des modifications et tout le HTML sauvegardé sera validé avec quelque chose comme htmlpurifier.org (merci pour le lien). Dans ce cas, je ne souhaite pas utiliser de base de données pour le contenu. – Scott

+0

Je vois. Bien sûr, si toutes les personnes éditées sont dignes de confiance, il pourrait être acceptable de les faire modifier des fichiers potentiellement exécutables. Pourtant, je suggère de regarder la philosophie structurelle de la modélisation et l'utilisation d'une base de données. Je stocke le contenu modifiable séparément de la partie de présentation, que ce soit dans une base de données ou en tant que fichier. Puis récupérez-le dans le script et affichez-le si disponible, ou affichez le contenu par défaut s'il n'y a pas de modifications. Cela éliminerait le besoin de faire ce que votre question initiale a demandé, aussi. – JAL

0

Si les utilisateurs peuvent soumettre du contenu dans ceux-ci, puis ils sont inclus dans un fichier PHP, alors vous êtes dans un sérieux problème.

Vous devriez avoir des modèles simples qui contiennent peu ou pas de PHP, qui seront analysés - et alors seulement si vous insérez du contenu dans le DOM, après qu'il a été correctement nettoyé. Pour résoudre votre problème de "trouver les inclusions" - vous n'avez pas besoin de le faire, PHP le fait pour vous - peut-être utiliser ob_start et al. puis incluez le fichier de modèle. Ensuite, récupérez le contenu du tampon (qui sera HTML), puis analysez le modèle déjà assemblé avec l'analyseur DOM. S'il vous plaît, s'il vous plaît, assurez-vous de désinfecter tout ce que vous injectez dans le DOM. Sinon, la tyrannie et la destruction vont certainement pleuvoir sur votre site web (et vous, en fonction de ce qui est sur votre serveur).

+0

Merci pour vos commentaires. Tous les utilisateurs devront être connectés pour éditer les sections et toutes les données seront également fortement validées. Parce que les fichiers modèles peuvent contenir php je ne vois pas d'autre moyen de le faire - comme je dois préserver ce PHP et manipuler seulement le HTML dans/autour de lui. J'ai joué avec la bufferisation de sortie et je continuerai à ... jusqu'à maintenant cela ne m'a pas donné de moyen clair de faire ce travail. – Scott

+1

avez-vous pensé à stocker les parties modifiables dans une base de données? ou au moins un csv ou quelque chose? Donc, au moins, vous n'avez pas besoin d'analyser le DOM et d'essayer d'analyser PHP, vous n'avez qu'à faire comme ' –

1

Je vous ai mal compris, ignorez tout après le hr. Pour faire ce que vous voulez, je suppose que la façon la plus simple est de présenter la page au navigateur, de créer une sorte de javascript qui trouve et modifie les zones modifiables et de soumettre cela à un fichier PHP via AJAX.

Le fichier PHP recevrait alors le contenu et l'endroit où il devrait changer le contenu, je ne comprends toujours pas très bien comment le CMS statique le fait, mais il y a quelques projets open source, vérifiez here et here. Je vous suggère d'étudier leur code pour savoir comment ils le font.


qui est vraiment simple, au lieu de incluiding le fichier comme ceci:

file_get_contents('/path/to/file.php'); 

Vous devez faire comme ceci:

file_get_contents('http://your-host.com/path/to/file.php'); 

En outre, take a look at QueryPath, semble être beaucoup mieux que SimpleHTMLDom.

+0

Merci, j'ai jeté un coup d'oeil aux autres CMS sur lesquels vous m'avez montré et ils fonctionnent un peu différemment. Toute bonne recherche cependant. QueryPath semble décent aussi. – Scott

+0

@Scott: Etes-vous sûr? Avez-vous vu ** Orbis CMS ** et ** MechEdit **? –

+0

@Alix Axel - MechEdit fonctionne uniquement avec des fichiers HTML - il ne doit donc pas être respectueux du code PHP comme les inclusions etc. Orbis stocke ses données séparément des fichiers modèles et utilise ensuite du code PHP pour placer le contenu pertinent au bon endroit : par exemple "" - les deux ont des modèles similaires mais sont toujours légèrement différents. – Scott

0

Vous devez simplement stocker le texte entré par l'utilisateur quelque part et le charger dans, et le sortir avec, votre modèle PHP.

Je chercherais à apprendre à utiliser une base de données. Il n'y a rien de lourd ou de lent, et vraiment, c'est ce qu'ils sont pour. Si vous ne voulez pas utiliser une base de données, vous pouvez utiliser des fichiers à la place. Je suggère de stocker les données dans le fichier au format JSON pour lui donner une certaine structure.

Voici un système très simple pour utiliser des fichiers pour stocker et récupérer des données codées JSON.

Faire un tableau de ce que vous voulez sauvegarder après avoir modifié

$user_data=array('title'=>$user_supplied_info,'content'=>$user_supplied_words); 
$json_data=json_encode($user_data); 
file_put_contents('path_to/user_data/thisuser',$json_data); 

Puis, quand il est temps pour afficher la page

<?php 
$user_data=array('title'=>'My page rocks!','content'=>'lorems ipso diddy doo dah'); 

$file_data=file_get_contents('path_to/user_data/thisuser'); 
if(!$user_data){$no_data=true;}//file not found 
$data_array=json_decode($user_data,true); 
if(!is_array($data_array)) 
    { $no_data=true; }//maybe the json could not be parsed 
else 
    { $user_data=array_merge($user_data,$data_array); } 
?> 
<html> 
<head> 
<title>This is my page</title> 
</head> 
<body> 
<h1 class="editable"><?php echo $user_data['title']?></h1> 

Et ainsi de suite. Le tableau defaults contient le contenu standard des sections modifiables, qui sont imprimées si l'utilisateur n'en a pas fourni. Si c'est le cas, il est chargé, puis fusionné avec le tableau par défaut. Les données chargées à partir d'un fichier écraseront les informations du tableau par défaut, si elles sont disponibles, dans la partie array_merge.

1

Basé sur le regex que vous avez fourni, je l'ai optimisé un peu et fixé quelques bugs cruciaux:

~<[?].*?(?:include|require(?:_once)?)\s*?(?:[(]?['"])(.+?)(?:['"][)]?)\s*?;.*?(?:[?]>)?~is 

Et dans preg_match_all():

preg_match_all('~<[?].*?(?:include|require(?:_once)?)\s*?(?:[(]?[\'"])(.+?)(?:[\'"][)]?)\s*?;.*?(?:[?]>)?~is', $html, $includes); 

Il doit correspondre avec des chiffres, des noms de fichiers chiffres , tirets, traits de soulignement, barres obliques, espaces, points et ainsi de suite.

De plus, le nom de fichier est stocké dans la référence n ° 1 et la balise PHP de fin est facultative.

Il est à noter que le token_get_all() function est beaucoup plus fiable que les expressions régulières.

+0

Wow. Merci Alix. Je vais essayer ça :) – Scott