所以我正在做一个超级简单的博客,它使用rss.reader的markdown格式来发布帖子。对于我想发帖的人来说,这是非常简单但又复杂的。所以我创建了一个简单的"文件创建者",如果你的遗嘱类型表单使用hallojs的话。它为hallowjs获取转换后的markdown代码,并根据用户输入将其写入一个文件(2014-04-08_markdownfile-test.md)。它由index.html和post.php组成。除了一个问题外,这一切都很顺利:
有三个特定的"网站",任何这些博客文章都可以在上面创建,所以我包含了一个选择选项,这意味着我的目录现在可以使用,很容易被恶意破解者选中。作为一种安全措施,我已经包含了必要的.htaccess,以"拒绝所有人"并防止任何人潜入,但根据表单,他们可以很容易地注入自己的文件并运行它们,所以我正在试图找到一种方法来防止这种情况。我的第一个想法是在php文件中声明目录,而不是简单地显示在index.html上。然而,我觉得我自己很困惑,现在我正在兜圈子。以下是我的资料来源:
index.htm
<article>
<div class="editable" contenteditable="true"> //hallojs user-input
<h1>Create new post</h1>
<p> Please edit your blog post! :D
</p>
</div>
</article>
<form name="form1" method="post" action="post.php">
<table width="100%" border="0" cellspacing="1" cellpadding="3">
<textarea id="source" id="textfield" name="textfield"></textarea> //markdown output
<tr>
<td width="16%">Date</td>
<td width="2%"></td>
<td width="82%">
<input name="date" type="text" id="date" size="50"></td>
</tr>
<tr>
<td>Title</td>
<td></td>
<td><input name="title" type="text" id="title" size="50"></td>
</tr>
<tr>
<td>Which Site?</td>
<td></td>
<td><select name="dir">
<option value="path/to/dir1">Site1</option>
<option value="path/to/dir2">Site2</option>
<option value="path/to/dir3">Site3</option>
</select></td></tr>
<td> </td>
<td> </td>
<td><input type="submit" name="Submit" value="Submit"></td>
</table></form>
post.php
<?php
$date = $_POST['date'];
$title = $_POST['title'];
$underscore = "_";
$dir = $_POST['dir'];
$myfile = fopen("$dir/$date$underscore$title.md", 'w');
if ($_SERVER['REQUEST_METHOD'] == "POST")
{
$myfile or die("Can't open file for writing.");
fwrite($myfile, $_POST['textfield']);
fclose($myfile);
echo "Content saved. ";
echo "Your file: <b>" ;
echo $date;
echo $underscore;
echo $title . ".md</b> ";
echo "was successfully created!";
}
// Print the form
?>
我想也许可以把下拉列表的值改为"dir1…dir2…dir3.",然后做这样的事情,但我只想确保它是安全的:
<?
$dir = $_POST['dir'];
if($dir == "dir1")
{
$dir == "path/to/dir1"
}elseif { $dir =="dir2")
{
$dir == "path/to/dir2"
}; // etc..
我认为仅仅从外观上看是行不通的。任何帮助都将不胜感激。哦,如果有人配置了我的$下划线问题,那就太棒了。文件名输出的日期后必须有下划线。无论我试着只放下划线,它都不起作用,否则我会收到诸如"$date_尚未设置"之类的错误,并且我的文件只以$title.md输入命名。真的很有趣。
Sooo。。。我想通了!以下是我所做的更改,以防有人出现同样的问题(这将是一个奇怪的问题):
<?php
$date = $_POST['date'];
$title = $_POST['title'];
$underscore = "_";
$dir = "";
if(!isset($_POST['dir'])) $_POST['dir']="";
switch($_POST['dir']) {
case "Site1": $dir = "path/to/site1"; break;
case "Site2": $dir = "path/to/site2"; break;
case "Site3": $dir = "path/to/site3"; break;
}
$myfile = fopen("$dir/$date$underscore$title.md", 'w');
if ($_SERVER['REQUEST_METHOD'] == "POST"){
$myfile or die("Can't open file for writing.");
fwrite($myfile, $_POST['textfield']);
fclose($myfile);
echo "Content saved. ";
echo "Your file: <b>" ;
echo $date;
echo $underscore;
echo $title . ".md</b> ";
echo "was successfully created to the website: <b>";
echo $_POST['dir'];
echo "</b>";
}
// Print the form
?>
我很惊讶它能起作用,因为我不知道我到底在做什么——这看起来很合乎逻辑,所以我这么做了。
有趣的是,我最初的想法奏效了,但其他地方看起来都非常丑陋,所以我决定使用switch语句,因为它们非常干净和脏。我还没有弄清楚$下划线的问题。。。但在大多数情况下,它现在更安全了!:}