【问题标题】:Writing post data to a file using CGI-perl使用 CGI-perl 将 post 数据写入文件
【发布时间】:2015-03-05 03:18:07
【问题描述】:

我正在开发纯 html/javascript 中的客户端程序,该程序能够将文件夹、文件及其内容作为参数发送到目标 cgi 脚本(即 saveFile.cgi )的发布请求中。

我能够从发布请求中检索数据,但我无法在脚本中使用这些表单数据创建文件/文件夹,但我可以使用 print 打印这些值。

另外,我可以使用我试图从发布请求中检索的确切字符串文字来创建文件/文件夹。我不明白我哪里出错了。

我在windows环境下编程:

客户代码:

var data = {
             "folder": variant,
             "file"  : "metadata.json",
             "content": response
           };

           $.post('../cgi-bin/demos/saveJSON.cgi', data, function(resp) {
                  // Do something with the request
           }, 'json');

服务器端/CGI 脚本:

#!C:\perl\bin\perl.exe -wT
    use CGI;
    use JSON;

    print "Content-type: text/html\n\n";

    $query = new CGI;

    $folder  = $query->param("folder");
    $file    = $query->param("file");
    $content = $query->param("content");

    #print "Folder " . $folder ."<br/>";
    #print "File " . $file ."<br/>";
    #print "Content " . $content ."<br/>";

    mkdir($folder, 0700) unless(-d $folder);
    open(OS,">$folder/$file") or die("Cannot write to file");
    print OS $content;
    close(OS);

【问题讨论】:

  • 为什么不用cgi方法param来检索数据呢?
  • @JE SUIS CHARLIE 它是检索数据的另一种选择,我知道,但即便如此也对我的情况没有帮助。
  • 你应该总是测试open的结果。
  • 添加了一个die语句,检查是否打开成功。 mkdir $folder 也不成功,但 mkdir "myFolder" 即使 $folder = query->param('folder') 也是如此。

标签: perl cgi server


【解决方案1】:

我无法在 脚本,但我可以使用 print 打印这些值

几乎可以肯定,问题在于您的网络服务器没有权限在您尝试创建文件的目录中创建文件。您可以通过改进 open() 调用的错误检查并查看 Web 服务器错误日志来检查该理论。

# $! contains the details of the error
open(OS,">$folder/$file") or die("Cannot write to file '$folder/$file': $!");

然后,您必须更改您的处理,以便写入您拥有正确权限的目录。

其他一些建议。

  • 始终包含use strictuse warnings
  • 使用my $query = CGI-&gt;new 而不是$query = new CGI
  • open() 使用词法文件句柄和三个参数
    • open my $os_fh, '&gt;', "$folder/$file" or die "..."
  • 考虑从 CGI 转移到现代解决方案,例如 Dancer

【讨论】:

  • 如果文件名/文件夹是字符串文字的一部分,则文件夹/文件会完美创建,但同样的事情不适用于 POST 参数。这些参数打印正确,但是当字符串文字方式有效时,我无法使用它们创建文件。我不明白这种虚伪。
  • 那么我只能重申我关于在调用open() 时增强错误日志记录的建议。试试这个,然后用你在错误日志中得到的详细信息更新你的帖子。您的参数中一定有一些奇怪的字符。
  • 成功了。这完全是由于为 perl 命令设置的“污点或 -T”标志。这阻止了它执行从表单数据接收到的变量。检查:stackoverflow.com/questions/4239076/t-option-in-perl
  • 那么,一旦您改进了错误日志记录,您就会立即发现问题所在?
  • 我总是检查 apache/logs/error.txt 但没有太注意 -T 标志的事情,因为错误不是很具体到这个问题和上面的链接,补充了理论关于“污​​点”。无论如何,谢谢:)你的帮助。
【解决方案2】:

我不知道你是否可以在你的服务器上安装模块。如果是,我肯定会建议您使用一些抽象层,例如 IO::All。

...
$folder  = $query->param("folder");
$file    = $query->param("file");
$content = $query->param("content");

# very minimal folder and filename sanitizing: allow only 
# alphanumeric characters. No slashes!
$folder =~ s{[^a-z0-9_\-.]}{}gi;
$file   =~ s{[^a-z0-9_\-.]}{}gi;

use IO::All;
io( $folder )->mkdir;
io( "$folder/$file" ) < $content; # yes, the < is like "put into"

IO::All 最酷的地方在于它隐藏了对文件句柄、缓冲区等的处理,并且在出现问题时会因错误而死 - 例如无法创建目录时。

见:IO::All on metacpan

消毒非常少,不允许子目录,但你不希望任何人写发送类似的东西

{ 
    folder:  "/var/www-data/.evil", 
    file:    "hacker.zip",
    content: "..someting really evil.."
}

将此上传到您的服务器。

无论如何,要安装 IO::All 使用任何一个

cpan IO::All

或在 Debian/Ubuntu 上

sudo apt-get install libio-all-perl

【讨论】:

  • 这些都无助于解决实际问题。这几乎可以肯定归结为文件权限。
猜你喜欢
  • 2013-12-29
  • 2019-05-14
  • 2021-02-13
  • 2011-06-12
  • 2010-12-27
  • 2017-02-22
  • 2011-07-10
  • 2013-09-26
  • 1970-01-01
相关资源
最近更新 更多