2

セットアップ:

ヘッダー用 (header.php) とフッター用 (footer.php) の 2 つのインクルードを含む標準の .php ファイル (index.php) があります。index.php ファイルは次のようになります。

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:

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

フッター .php は次のようになります。

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

ページ上の「.editable」アイテムを編集できるようにする PHP スクリプトを作成しています。私の問題は、これらの編集可能な領域が、index.php の本体だけでなく、含まれているファイルにも表示される可能性があることです。

私のphpコードは、file_get_contents()でindex.phpファイルを取得しています。これはうまく機能します。また、index.php の「.editable」領域を編集して保存することもできます。

私の問題:

インクルードを「見つける」方法を見つけられず、「.editable」領域のインクルードも解析できませんでした。index.phpのすべてのインクルードをどのように処理するかについての提案を探しています-編集可能な領域をチェックします。「include *.php」を見つけるために正規表現を使用する必要がありますか? どこから始めればいいのかわからない...

私の PHP コードを見たい人のために。私は PHP クラスを利用しています: [link text][1] これにより、次のようなコードを書くことができます:

// 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.htm シンプルな php dom パーサー


アップデート

インクルードを一致させるために、正規表現をいじってみました。私は正規表現でかなりゴミですが、近づいていると思います。これが私がこれまでに持っているものです:

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

preg_match を使用すると奇数の ) と ' が返されるように見えますが、これはかなりよく一致します。PHPタグ間でのみ一致するように、正規表現に少しのセキュリティを追加しようとしています-この部分: (?=(?:[^\<\?]|[^\?>])*\?>) - ただし、ページの最初のインクルードのみを返します。この正規表現を改善するためのヒントはありますか? (私は約6時間そこにいました)

4

6 に答える 6

1

私はあなたを誤解しました. の後のすべてを無視してくださいhr.

あなたが望むことをするための最も簡単な方法は、ページをブラウザーに表示し、編集可能な領域を見つけて編集するある種の JavaScript を作成し、それを AJAX 経由で PHP ファイルに送信することです。

次に、PHP ファイルはコンテンツとコンテンツを変更する場所を受け取ります。静的 CMS がどのようにそれを行うかはまだよくわかりませんが、いくつかのオープン ソース プロジェクトがあります。ここここを確認してください。彼らのコードを調べて、彼らがどのようにそれを行うかを調べることをお勧めします。


次のようにファイルを含める代わりに、それは本当に簡単です。

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

次のようにする必要があります。

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

また、QueryPath を見てください。SimpleHTMLDomよりもはるかに優れているようです。

于 2010-01-09T02:13:51.317 に答える
1

あなたが提供した正規表現に基づいて、少し最適化し、いくつかの重大なバグを修正しました。

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

そしてでpreg_match_all()

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

ファイル名は、数字、数字、ダッシュ、アンダースコア、スラッシュ、スペース、ドットなどと一致する必要があります。

また、ファイル名はリファレンス #1 に格納され、終了 PHP タグはオプションです。

token_get_all() 関数は、正規表現よりもはるかに信頼性が高いことに注意してください。

于 2010-01-14T13:57:20.080 に答える
1

どのようなシステムを作成していますか?

一般に使用される場合は、深刻なセキュリティ上の懸念があります。提供されたコンテンツに独自の PHP コードまたは JavaScript を含めることができます。

これは、動的コンテンツを作成するための標準的な方法ではありません。ほとんどの場合、単一のテンプレートを作成し、ユーザーが変更をデータベースに保存できるようにします。次に、データベースからテンプレートに情報を入力して表示します。

HTML を含めることを許可する場合は、html purifierなどを使用してクリーンアップし、 PDOを使用して準備済みステートメントを使用してデータベースにデータを挿入します。ここにいる人たちは、データベースの使用に関する質問に喜んで答えてくれると確信しています。

于 2010-01-09T00:51:00.887 に答える
0

ユーザーが入力したテキストをどこかに保存し、PHPテンプレートにロードして出力するだけです。

私はデータベースの使い方を学ぶことを検討したいと思います。それについて重いものや遅いものは何もありません、そして実際、これは彼らが求めているものです。データベースを使用したくない場合は、代わりにファイルを使用できます。構造を持たせるために、データをJSON形式でファイルに保存することをお勧めします。

これは、ファイルを使用してJSONエンコードされたデータを保存および取得するための非常に単純なシステムです。

編集後に保存したいものの配列を作成します

$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);

次に、ページを表示する時間になります

<?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>

等々。defaults配列は、編集可能なセクションの標準コンテンツを保持します。これは、ユーザーが何も指定しなかった場合に出力されます。ある場合は、ロードされてから、デフォルトの配列とマージされます。ファイルからロードされたデータは、array_merge部分にあるデフォルトの配列の情報(使用可能な場合)を上書きします。

于 2010-01-09T03:04:54.193 に答える
0

ユーザーがこれらにコンテンツを送信でき、それが PHP ファイルに含まれる場合、重大な問題が発生します。

PHP がほとんど、またはまったく含まれていない単純なテンプレートを使用して解析する必要があります。適切にサニタイズした後、コンテンツを DOM に挿入する必要があります。

「インクルードを見つける」問題を解決する方法-必要はありません。PHPがそれを行います-おそらくob_startなどを使用してください。次に、テンプレート ファイルをインクルードします。次に、バッファーの内容 (HTML になります) を取得し、DOM パーサーを使用して既にアセンブルされたテンプレートを解析します。

どうか、DOM に注入するものはすべてサニタイズしてください。

そうしないと、専制政治と破壊が確実にあなたの Web サイトに降り注ぎます (そして、あなたのサーバーに他に何があるかにもよりますが、あなたも)。

于 2010-01-09T01:04:21.527 に答える
0

わかりました、私はついにそれを解決しました。誰かが .php ファイルで include、include_once、require、require_once を見つけようとしている場合は、preg_match_all のような php 関数で次の正規表現を使用できます。

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

これは、タグ内のインクルードなどを探します。これを元の例に戻します。私のコードは次のようになります。

$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;

仕事終わり!これで、必要に応じて各ファイルを編集できます。

于 2010-01-09T23:34:37.070 に答える