如何编辑/保存包含哈希变量的文本文件



我使用的是一个perl脚本,它打开一个文本文件,并允许我在文本区域字段中编辑它。以下是摘录:

# Database Definition
# --------------------------------------------------------
# Definition of your database. Format is
#       field_name => ['position', 'field_type', 'form-length', 'maxlength', 'not_null', 'default', 'valid_expr']
%def = (
'RecordID'            => [ 0, 'numer',    -1,   255, 1, '',              ''],
'Userid'              => [ 1, 'alpha',    -1,   255, 1, '',              ''],
'Title'               => [ 2, 'alpha',    20,   255, 1, '',              ''],
'Category'            => [ 3, 'alpha',    20,   255, 1, '',              ''],
'Type'                => [ 4, 'alpha',    20,   255, 1, 'D2015',              ''],
'Client'              => [ 5, 'alpha',    20,   255, 0, '',              ''],
'Client_database'     => [ 6, 'alpha',    20,   255, 0, '',              ''],
'Installed'           => [ 7, 'alpha',    20,   255, 0, 'xxxxx',           ''],
'Description'         => [ 8, 'alpha',    0,   1500, 1, '',              ''],
'Called_by'           => [ 9, 'alpha',    20,   255, 0, '',              ''],
'Updated'             => [10, 'timestamp',     -1,   25, 0, &get_timestamp(),       ''],
'Display'             => [11, 'alpha',     -1,     4, 0, 'No',             ''],
'Files'               => [12,'alpha',20,255,0,'',''],
'Followup'            => [13, 'alpha',     -1,     4, 0, 'No',             ''],
'Status_public'       => [14, 'alpha',    20,   255, 0, '',              ''],
'Status_private'      => [15, 'alpha',    20,   255, 0, '',              ''],
'Reserved'           => [16, 'alpha',    -1,     5, 0, 'zzzzz',           '']
);

# Select fields. Field name => 'comma seperated list of drop down options'.
%select_fields   = ( 
);
# client is both radio and checkbox so checkbox can be used on search form
# Radio fields. Field name => comma seperated list of radio buttons.
%radio_fields    = ( 
'Type' => 'DBMan,Delicia,Client,D2015',
'Display' => 'Yes,No,Deleted',
'Followup' => 'Yes,No',
'Client' => 'delicia,dreydev,ohs1968,bhccwga,interiorsolutions,danaespa,knue,langford,kudzu,suwaneeday',
'Status_public' => 'n/a,Planning,Coding,Alpha,Beta,Complete',
'Status_private' => 'n/a,Planning,Coding,Alpha,Beta,Complete'
);
# Checkbox fields. Field name => Checkbox value.
%checkbox_fields = (
'Category' => 'Configuration,Variable,Flag,Subroutine,Field,FieldType,Problem,TroubleTip,File,Hack,ChangeLog,Other',
'Client' => 'delicia,dreydev,ohs1968,bhccwga,knue',
'Installed' => 'delicia,dreydev,ohs1968,bhccwga,knue'
);
#   
# delicia added from autogenerate enhancement
# Textarea fields. Field name => '[columns]x[rows]'.
%textarea_fields   = (
Description => '60x10'
);

我的问题是,当我保存编辑后的文件时,百分号会转换为不可打印的字符。我需要他们保持原样。例如:我可能想添加或删除单选字段列表中的项目。我的页眉包含以下内容:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">

以下是编辑后的文件的示例:

#
# Database Definition
# --------------------------------------------------------
# Definition of your database. Format is
#       field_name => ['position', 'field_type', 'form-length', 'maxlength', 'not_null', 'default', 'valid_expr']
Þf = (
'RecordID'            => [ 0, 'numer',    -1,   255, 1, '',              ''],
'Userid'              => [ 1, 'alpha',    -1,   255, 1, '',              ''],
'Title'               => [ 2, 'alpha',    20,   255, 1, '',              ''],

%def已更改为无法识别的内容,因此脚本无法运行。

编辑:这是读取文件的代码:

open (FILEEDIT, $edit_file_data) or &cgierr ("unable to open: $edit_file_data.nReason: $!");
if ($db_use_flock) {
flock(FILEEDIT, 1)  or &cgierr("unable to get exclusive lock on $edit_file_data.nReason: $!");
}
$out = join ("", <FILEEDIT>);
close (FILEEDIT);
... I'M OMITTING THE OTHER PARTS OF HTML PAGE
print qq|
<TEXTAREA NAME="file_data" COLS="66" ROWS="20" wrap=virtual>$out</TEXTAREA></td></tr>
<td class="text-center"><input type=submit value="$submit_button" class="btn btn-primary"></td></tr>
</table></form>
|;

现在是编写文件的代码:

my ($out, $write_file_data);
$write_file_data = $in{'write_file_data'};
$out = $in{'file_data'};
$out =~ s/r//g;
open (FILEDATA, ">$write_file_data") or &cgierr("unable to open: $write_file_data.nReason: $!");
if ($db_use_flock) {
flock(FILEDATA, 2)  or &cgierr("unable to get exclusive lock on $write_file_data.nReason: $!");
}
print FILEDATA $out; # write file.
close FILEDATA;

编辑:我认为问题在这里,但我不知道是什么

sub parse_form { 
# -------------------------------------------------------- 
my (%in); 
my ($buffer, $pair, $name, $value,$s); 
PAIR: foreach $name ($query->param()) { 
@value = $query->param("$name"); 
$value = join '~~', @value; 
$name =~ tr/+/ /; 
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; 

$value =~ tr/+/ /; 
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
if ($value eq "---") { next PAIR; } 
if ($value eq "http://") { next PAIR; }   # Removes default beginning of URLs
unless ($value) { next PAIR; } 
unless ( length ($value) ) { next PAIR; }
unless ($value =~ /S+/) { next PAIR; } # 01/29/2017

$in{$name} = $value; 
} 
return %in; 
}

我从几年前在网上发现的一个修改中得到了这个代码;它应该处理上传文件并允许多个选择项目;如果我使用原始脚本,我对%没有问题,但我需要这些技巧这是打开表单的标签:

<FORM ENCTYPE="multipart/form-data" action="$db_script_url" method="POST">

问题:

您的脚本对表单字段进行双重解码,不必要地导致数据损坏。

$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;

CCD_ 1是CCD_ 2的URL编码。

对已解码的表单数据调用pack会损坏它。

解决方案:

不要双重解码。

你说这是有充分理由的。如果是这样的话,一个最小的变通方法可能是只在那些真正需要它的字段上进行

my %is_double_decode_field = map { $_=>1 } qw(
name_of_field_containing_url
name_of_another_field_containing_url
...
);
sub parse_form { 
my (%in); 
my ($buffer, $pair, $name, $value, $s); 
PAIR: foreach $name ($query->param()) { 
@value = $query->param("$name"); 
$value = join '~~', @value; 
if ( $is_double_decode_field{ $name } ) {
$name =~ tr/+/ /; 
$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; 

$value =~ tr/+/ /; 
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
}
if ($value eq "---") { next PAIR; } 
if ($value eq "http://") { next PAIR; }   # Removes default beginning of URLs
unless ($value) { next PAIR; } 
unless ( length ($value) ) { next PAIR; }
unless ($value =~ /S+/) { next PAIR; } # 01/29/2017

$in{$name} = $value; 
} 
return %in; 
}

安全问题:

考虑:

$out = join ("", <FILEEDIT>);
# ...
print qq|
<TEXTAREA NAME="file_data" ...>$out</TEXTAREA>...
|;

您显示的从文件加载的代码在注入到html表单之前并没有对其进行消毒,也没有显示的将其写回的代码似乎这样做

如果您在某个地方用&amp;提交后加载网页,文本区域是包含&amp;还是仅包含&

如果附加:

</textarea><textarea name="file2_data">hello!

下次加载时是否会显示额外的表单字段?

检索表单数据的代码看起来也不安全。在列表上下文中使用param()是一个漏洞。建议使用multi_param()。请参阅CGI文档。

我预计还有更多的问题在潜伏。

最新更新