2

设置:

我有一个标准的 .php 文件(index.php),其中包含两个包含,一个用于页眉(header.php),一个用于页脚(footer.php)。index.php 文件如下所示:

索引.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>

我正在编写一个 PHP 脚本,它允许您编辑页面上的任何“.editable”项目。我的问题是这些可编辑区域可能出现在任何包含的文件以及 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

您正在创建什么类型的系统?

如果它要被公众使用,你会有严重的安全问题。人们可以在提供的内容中包含他们自己的 PHP 代码或 JavaScript。

这根本不是创建动态内容的标准方式。大多数情况下,您希望创建一个模板,然后允许用户将他们的更改保存到数据库中。然后,您将信息从数据库中填写到模板中以供显示。

如果您允许它们包含 HTML,请使用html purifier之类的东西来清理它,使用PDO使用准备好的语句将数据插入到数据库中。我相信这里的人们会很乐意回答您关于使用数据库的任何问题。

于 2010-01-09T00:51:00.887 回答
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 回答
0

如果用户可以将内容提交到这些文件中,然后将它们包含在 PHP 文件中,那么您将遇到一些严重的麻烦。

您应该有简单的模板,其中包含很少或没有 PHP,这些模板会被解析——然后,只有这样,您才应该在正确清理 DOM 后将内容插入到 DOM 中。

解决“查找包含”问题的方法——你不需要,PHP 会为你做——也许使用ob_start等。然后包含模板文件。然后获取缓冲区内容(将是 HTML),然后使用 DOM 解析器解析已经组装好的模板。

请,请确保您对注入 DOM 的任何内容进行消毒。

否则,暴政和破坏肯定会降临到您的网站上(以及您,取决于您服务器上的其他内容)。

于 2010-01-09T01:04:21.527 回答
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>

等等。默认数组保存可编辑部分的标准内容,如果用户没有提供任何内容,则打印这些内容。如果有,则加载它,然后与默认数组合并。从文件加载的数据将覆盖 array_merge 部分中的默认数组信息(如果可用)。

于 2010-01-09T03:04:54.193 回答
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 回答