Perl программа читает длину строки POST, но не читает строку - PullRequest
0 голосов
/ 03 марта 2020

Я недавно мигрировал с хоста IIS на хост Apache, и мой скрипт perl больше не работает. Я отступил к простой фиксированной строке POST. Сценарий perl будет читать правильное значение из $ ENV {\ 'CONTENT_LENGTH \'}, но не будет читать строковое значение.

Файл HTML имеет значение

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Mail Test</title>
        <meta charset="utf-8">
        <meta name="description" content="This is a simple mail test. So far the mailtest.pl program won't even read any input.">
        <meta name="keywords" content="">
    </head>
    <body>
        <h1>
            Email Us
        </h1>
        <!-- Starting out with a simple two value POST submit -->
        <form id="email_form" target="_blank" method="POST" action="cgi-bin/mailtest.pl">
            <input type="hidden" name="mytest" value="foo" >
            <input type="hidden" name="mytest2" value="bar" >
            <input type="submit" id="email_submit" value="Send Email" >
            <input type="reset" />
        </form>
    </body>
</html>

Файл perl, включающий в себя несколько операторов отладки:

#!/usr/bin/perl

use strict;
use warnings;

use CGI;
print CGI::header();
# If you don't output a header, apache will not work.


print "<DOCTYPE! html>\n<html lang=\"en\">\n";
print "<header>\n<title>\"Simple POST Test Result\"</title>\n";
print "<meta charset=\"utf-8\">\n</header>\n<body>\n";
print "<h1>Simple POST test.</h1>\n";

my $buffer = ''; # Raw POST data

print "<p>(1) Going to get the data.</p>\n";

&get_data;

print "<p>(8) Returned from get_data.</p>";
print "<p> I will only get this far if everything works</p>\n</body>\n</html>";

sub get_data {
 print '<p>(2) Getting the data.</p>';
 if ($ENV{'REQUEST_METHOD'} eq 'POST') {
   print "<p>(3) Verified: It's a POST request.</p>";
   print ("<p>(4) The length of the post data string as reported in ", '$ENV{\'CONTENT_LENGTH\'}', "is ", $ENV{'CONTENT_LENGTH'}, "</p>");
   print "<p>(5) The data should be \"mytest=foo&mytest2=bar\" so the length should be 22.";
   # Get the input
   print "<p>(6) If the POST data is read, it will be printed on the next line</p>";
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}) or die "POST data could not be read, why? Stopped ";
   print ("The buffer contained ", $buffer);
   print '<p>(7) Got the data.</p>';
  }
 else {
  print "<p3b> It wasn't a POST request so I will die soon.";
  die "The request method must be POST for this application. Stopped ";
  }

}

Ответ html:

Простой тест POST. (1) Получение данных.

(2) Получение данных.

(3) Проверено: это запрос POST.

(4) Длина строка данных поста, указанная в $ ENV {'CONTENT_LENGTH'}, равна 22 * ​​1018 *

(5). Данные должны быть "mytest = foo & mytest2 = bar", поэтому длина должна быть 22.

( 6) Если данные POST прочитаны, они будут напечатаны на следующей строке

Журнал ошибок не содержит ничего, кроме оператора d ie:

AH01215 : Данные POST не могут быть прочитаны, почему? Остановлено на mailtest.pl строка 33 .: /home/fffwweb/fffw.org/cgi-bin/mailtest.pl, реферер: https://fffw.org/mailtest.html

.htaccess файл во всех каталогах (при условии, что это перебор):

RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
AddHandler cgi-script .pl
Options +ExecCGI
AddType application/pdf pdf

Я подозреваю, что моя проблема очевидна, но я потратил три дня, пытаясь найти ее безрезультатно, в том числе в чате с техподдержкой веб-хостинга.

Любые предложения приветствуются. Спасибо, Рэнди Т

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Если вы закомментируете эти две строки:

# use CGI;
# print CGI::header();

и замените их написанным вручную заголовком:

# Note: Fixed line endings
print "Content-type: text/html\015\012\015\012";

Тогда все будет работать как положено. Но я не рекомендую это делать. Я рекомендую использовать CGI.pm, как он и ожидается, и использовать его механизмы для чтения входных параметров.

Проблема в том, что CGI.pm делает для вас слишком много. Просто загрузив его, он будет читать все ваши параметры - и это включает в себя чтение всех данных из STDIN. Поскольку CGI.pm прочитал данные из STDIN, для вашего кода больше не осталось данных для чтения. Переменная окружения CONTENT_LENGTH по-прежнему имеет исходное значение, но вы больше не можете ожидать, что найдете столько данных в дескрипторе файла.

Решение состоит в том, чтобы не пытаться перечитывать данные для себя , Вместо этого используйте метод param() для получения значений вашего ввода.

my $mytest  = CGI::param('mytest');
my $mytest2 = CGI::param('mytest2');
0 голосов
/ 03 марта 2020

Ну, я нахожу слишком трудным для чтения вашего кода. Я взял на себя некоторую свободу, чтобы очистить его.

Пожалуйста, посмотрите, если вы находите следующий стиль более подходящим

#!/usr/bin/perl

use strict;
use warnings;

use CGI;
print CGI::header();
# If you don't output a header, apache will not work.

my $buffer = ''; # Raw POST data

print 
'<DOCTYPE! html>
<html lang="en">
<header>
    <title>"Simple POST Test Result"</title>
    <meta charset="utf-8">
</header>
<body>
    <h1>Simple POST test.</h1>
    <p>(1) Going to get the data.</p>
';

&get_data;

print '
    <p>(8) Returned from get_data.</p>
    <p> I will only get this far if everything works</p>
</body>
</html>
';

sub get_data {
 print '<p>(2) Getting the data.</p>';
 if ($ENV{'REQUEST_METHOD'} eq 'POST') {
   read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'})
        or die 'POST data could not be read, why? Stopped';

   print '
        <p>(3) Verified: It\'s a POST request.</p>
        <p>(4) The length of the post data string as reported in $ENV{CONTENT_LENGTH} is '
        . $ENV{'CONTENT_LENGTH'} . '
        </p>
        <p>(5) The data should be "mytest=foo&mytest2=bar" so the length should be 22.
        <p>(6) If the POST data is read, it will be printed on the next line</p>
        The buffer contained '
        . $buffer . '
        <p>(7) Got the data.</p>
        ';
  }
 else {
      print '<p3b> It wasn\'t a POST request so I will die soon.';
      die 'The request method must be POST for this application. Stopped';
  }
}

Также, пожалуйста, смотрите следующую веб-страницу

Примечание: вы чрезмерно используете двойные кавычки без причины, они предназначены для интерполяции переменных. Используя двойные кавычки без причины, вы теряете циклы ЦП (perl все еще ищет переменные в таких строках, чтобы подставить их имена в их значения).

...