Only process macros once per page.

This commit is contained in:
JT Smith 2003-03-02 21:15:56 +00:00
parent 0ebac2be41
commit 5f6313579f
12 changed files with 219 additions and 26 deletions

View file

@ -49,6 +49,11 @@ save you many hours of grief.
significantly. Macros written for versions prior to 5.2.0
are not compatible with this version or after.
* All discussions and user submission systems now have a property
for filtering content. This filter has been set to remove
javascript and macros, but you may wish to set these to one
of the other options.
5.1.0
--------------------------------------------------------------------

View file

@ -58,6 +58,11 @@ INSERT INTO international VALUES (4,'HttpProxy',2,'Timeout (Sekunden)',104039557
INSERT INTO international VALUES (3,'HttpProxy',2,'HTTP Proxy',1040395372);
INSERT INTO international VALUES (2,'HttpProxy',2,'HTTP Proxy ändern',1040395360);
INSERT INTO international VALUES (1,'HttpProxy',2,'URL',1040395344);
alter table wobject add column filterPost varchar(30) not null default 'javascript';
delete from settings where name='filterContributedHTML';
update international set namespace='Discussion' where internationalId=524 and namespace='WebGUI';
alter table wobject add column addEditStampToPosts int not null default 1;

View file

@ -210,8 +210,7 @@ sub formatHeader {
#-------------------------------------------------------------------
sub formatMessage {
my $output;
$output = $_[0];
$output = WebGUI::HTML::filter($output);
$output = WebGUI::HTML::filter($_[0],$_[1]);
unless ($output =~ /\<div\>/ig || $output =~ /\<br\>/ig || $output =~ /\<p\>/ig) {
$output =~ s/\n/\<br\>/g;
}
@ -244,7 +243,7 @@ sub post {
%message = getMessage($session{form}{replyTo});
$footer = formatHeader($message{subject},$message{userId},$message{username},$message{dateOfPost},$message{views},
'',$message{status})
.'<p>'.formatMessage($message{message});
.'<p>'.formatMessage($message{message},$_[0]->get("filterPost"));
$message{message} = $signature;
$message{subject} = "Re: ".$message{subject} unless ($message{subject} =~ /^Re:/);
$session{form}{mid} = "new";
@ -278,7 +277,7 @@ sub post {
%message = getMessage($session{form}{mid});
$footer = formatHeader($message{subject},$message{userId},$message{username},$message{dateOfPost},$message{views},
'',$message{status})
.'<p>'.formatMessage($message{message});
.'<p>'.formatMessage($message{message},$_[0]->get("filterPost"));
}
$f->hidden("func","postSave");
$f->hidden("wid",$session{form}{wid});
@ -347,7 +346,7 @@ sub postSave {
if ($session{form}{subscribe}) {
subscribeToThread($session{user}{userId},$rid);
}
} elsif ($session{setting}{addEditStampToPosts}) {
} elsif ($_[0]->get("addEditStampToPosts")) {
$session{form}{message} = "\n --- (Edited at ".epochToHuman(time())." by $session{user}{username}) --- \n\n"
.$session{form}{message};
}
@ -490,7 +489,7 @@ sub showMessage {
.WebGUI::International::get(364).'</a><br>';
$html .= $_[0];
$html .= '</tr><tr><td class="tableData">';
$html .= formatMessage($message{message}).'<p>';
$html .= formatMessage($message{message},$_[1]->get("filterPost")).'<p>';
$html .= '</td></tr></table>';
} else {
$html = WebGUI::International::get(402);
@ -544,7 +543,7 @@ sub showReplyTree {
if ($data{messageId} == $message{messageId}) {
$html .= 'class="highlight"';
}
$html .= '>'.formatMessage($data{message}).'<br/><br/></td></tr>';
$html .= '>'.formatMessage($data{message},$_[0]->get("filterPost")).'<br/><br/></td></tr>';
}
}
$sth->finish;
@ -598,7 +597,7 @@ sub showThreads {
if ($data{messageId} eq $session{form}{mid}) {
$html .= 'class="highlight"';
}
$html .= '>'.formatMessage($data{message}).'<br/><br/></td></tr>';
$html .= '>'.formatMessage($data{message},$_[0]->get("filterPost")).'<br/><br/></td></tr>';
}
}
$html .= '</table>';

View file

@ -134,7 +134,9 @@ sub fatalError {
print '<br>'.$WebGUI::Session::session{setting}{companyURL};
} else {
print "<h1>WebGUI Fatal Error</h1>Something unexpected happened that caused this system to fault.<p>";
print "<pre>".$data."</pre>";
my $formattedData = $data;
$formattedData =~ s/\n/\<br\>/g;
print $formattedData;
}
my $log = _log();
print $log $data;

View file

@ -443,6 +443,52 @@ sub file {
return '<input type="file" name="'.$_[0]->{name}.'" size="'.$size.'" '.$_[0]->{extras}.'>';
}
#-------------------------------------------------------------------
=head2 filterContent ( hashRef )
Returns a select list containing the content filter options. This is for use with WebGUI::HTML::filter().
=over
=item name
The name field for this form element. This defaults to "filterContent".
=item value
The default value for this form element.
=item extras
If you want to add anything special to this form element like javascript actions, or stylesheet information, you'd add it in here as follows:
'onChange="this.form.submit()"'
=back
=cut
sub filterContent {
my %filter;
tie %filter, 'Tie::IxHash';
%filter = (
'none'=>WebGUI::International::get(420),
'macros'=>WebGUI::International::get(891),
'javascript'=>WebGUI::International::get(526),
'most'=>WebGUI::International::get(421),
'all'=>WebGUI::International::get(419)
);
my $name = $_[0]->{name} || "filterContent";
return selectList({
name=>$name,
options=>\%filter,
value=>[$_[0]->{value}],
extras=>$_[0]->{extras}
});
}
#-------------------------------------------------------------------
=head2 formHeader ( hashRef )

View file

@ -16,6 +16,7 @@ package WebGUI::HTML;
use HTML::TagFilter;
use strict;
use WebGUI::Macro;
use WebGUI::Session;
=head1 NAME
@ -84,7 +85,7 @@ The HTML content you want filtered.
=item filter
Choose from all, none, javascript, or most. Defaults to most. All removes all HTML tags; none removes no HTML tags; javascript removes all references to javacript; and most removes all but simple formatting tags like bold and italics.
Choose from "all", "none", "macros", "javascript", or "most". Defaults to "most". "all" removes all HTML tags and macros; "none" removes no HTML tags; "javascript" removes all references to javacript and macros; "macros" removes all macros, but nothing else; and "most" removes all but simple formatting tags like bold and italics.
=back
@ -92,10 +93,11 @@ Choose from all, none, javascript, or most. Defaults to most. All removes all H
sub filter {
my ($filter, $html, $type);
$type = $_[1] || $session{setting}{filterContributedHTML};
$type = $_[1];
if ($type eq "all") {
$filter = HTML::TagFilter->new(allow=>{'none'},strip_comments=>1);
$html = $filter->filter($_[0]);
return WebGUI::Macro::filter($html);
} elsif ($type eq "javascript") {
$html = $_[0];
$html =~ s/\<script.*?\/script\>//ixsg;
@ -113,17 +115,19 @@ sub filter {
$html =~ s/onKeyDown/removed/ixsg;
$html =~ s/onSubmit/removed/ixsg;
$html =~ s/onReset/removed/ixsg;
$html = WebGUI::Macro::filter($html);
} elsif ($type eq "macros") {
return WebGUI::Macro::filter($_[0]);
} elsif ($type eq "none") {
$html = $_[0];
return $_[0];
} else {
$filter = HTML::TagFilter->new; # defaultly strips almost everything
$html = $filter->filter($_[0]);
return WebGUI::Macro::filter($html);
}
return $html;
}
1;

View file

@ -43,6 +43,7 @@ Package that makes HTML forms typed data and significantly reduces the code need
$f->email("emailAddress","Email Address");
$f->fieldType("dataType",\%supportedTypes,"Type of Field");
$f->file("image","Image to Upload");
$f->filterContent("filterThisContent","Filter This Content");
$f->group("groupToPost","Who can post?");
$f->hidden("wid","55");
$f->HTMLArea("description","Description");
@ -597,6 +598,69 @@ sub file {
$self->{_data} .= $output;
}
#-------------------------------------------------------------------
=head2 filterContent ( [ name, label, value, extras, subtext, uiLevel ] )
Adds a content filter select list to the form for use with the WebGUI::HTML::filter() function.
=over
=item name
The name field for this form element. Defaults to "filterContent".
=item label
The left column label for this form row. Defaults to "Filter Content" (internationalized).
=item value
The default value for this form element.
=item extras
If you want to add anything special to this form element like javascript actions, or stylesheet information, you'd add it in here
as follows:
'onChange="this.form.submit()"'
=item subtext
Extra text to describe this form element or to provide special instructions.
=item uiLevel
The UI level for this field. See the WebGUI developer's site for details. Defaults to "0".
=back
=cut
sub filterContent {
my ($output);
my ($self, @p) = @_;
my ($name, $label, $value, $extras, $subtext, $uiLevel) =
rearrange([qw(name label value extras subtext uiLevel)], @p);
if (_uiLevelChecksOut($uiLevel)) {
$label = WebGUI::International::get(418) if ($label eq "");
$output = WebGUI::Form::filterContent({
"name"=>$name,
"value"=>$value,
"extras"=>$extras
});
$output .= _subtext($subtext);
$output = $self->_tableFormRow($label,$output);
} else {
$output = WebGUI::Form::hidden({
"name"=>$name,
"value"=>$value
});
}
$self->{_data} .= $output;
}
#-------------------------------------------------------------------
=head2 group ( name [ label, value, size, multiple, extras, subtext, uiLevel, excludeGroups ] )

View file

@ -45,8 +45,8 @@ These functions are available from this package:
#-------------------------------------------------------------------
# Returns a complex regular expression for matching macro patterns.
sub _nestedMacro {
# This sub returns the regular expression for matching nested macro's.
# Regular expression for matching balanced parenthesis
my $parenthesis = qr /\( # Start with '(',
(?: # Followed by
@ -69,6 +69,32 @@ sub _nestedMacro {
#-------------------------------------------------------------------
=head2 filter ( html )
Removes all the macros from the HTML segment.
=over
=item html
The segment to be filtered.
=back
=cut
sub filter {
my $content = shift;
my $nestedMacro = _nestedMacro();
while ($content =~ /($nestedMacro)/gs) {
$content =~ s/\Q$1//gs;
}
return $content;
}
#-------------------------------------------------------------------
=head2 getParams ( parameterString )
@ -115,7 +141,7 @@ A string of HTML to be processed.
sub process {
my $content = shift;
my $nestedMacro = &_nestedMacro;
my $nestedMacro = _nestedMacro();
while ($content =~ /($nestedMacro)/gs) {
my ($macro, $searchString, $params) = ($1, $2, $3);
next if ($searchString =~ /^\d+$/); # don't process ^0; ^1; ^2; etc.

View file

@ -86,7 +86,7 @@ sub www_addInternationalMessage {
$f->hidden("lid",1);
$f->hidden("op","addInternationalMessageSave");
$f->combo("namespace",
WebGUI::SQL->buildHashRef("select namespace,namespace from international where language=1 order by namespace")
WebGUI::SQL->buildHashRef("select namespace,namespace from international where languageId=1 order by namespace")
,"Namespace",['WebGUI']);
$f->textarea("message","Message");
$f->submit;
@ -100,8 +100,9 @@ sub www_addInternationalMessageSave {
($nextId) = WebGUI::SQL->quickArray("select max(internationalId) from international where languageId=1
and namespace=".quote($session{form}{namespace}));
$nextId++;
my $namespace = $session{form}{namespace_new} || $session{form}{namespace};
WebGUI::SQL->write("insert into international (languageId, internationalId, namespace, message, lastUpdated) values
(1,$nextId,".quote($session{form}{namespace}).",".quote($session{form}{message}).",".time().")");
(1,$nextId,".quote($namespace).",".quote($session{form}{message}).",".time().")");
return "<b>Message was added with id $nextId.</b>".www_listInternationalMessages();
}

View file

@ -92,8 +92,6 @@ sub www_editContentSettings {
$f->select("defaultPage",$pages,WebGUI::International::get(527),[$session{setting}{defaultPage}]);
$f->select("notFoundPage",$pages,WebGUI::International::get(141),[$session{setting}{notFoundPage}]);
$f->text("docTypeDec",WebGUI::International::get(398),$session{setting}{docTypeDec});
$f->yesNo("addEditStampToPosts",WebGUI::International::get(524),$session{setting}{addEditStampToPosts});
$f->select("filterContributedHTML",\%htmlFilter,WebGUI::International::get(418),[$session{setting}{filterContributedHTML}]);
$f->integer("maxAttachmentSize",WebGUI::International::get(130),$session{setting}{maxAttachmentSize});
$f->integer("maxImageSize",WebGUI::International::get(583),$session{setting}{maxImageSize});
$f->integer("thumbnailSize",WebGUI::International::get(406),$session{setting}{thumbnailSize});

View file

@ -177,6 +177,13 @@ sub discussionProperties {
$editTimeout = $_[0]->get("editTimeout");
$moderationType = $_[0]->get("moderationType");
}
my $filterPost = $_[0]->get("filterPost") || "most";
$f->filterContent(
-name=>"filterPost",
-value=>$filterPost,
-label=>WebGUI::International::get(1,"Discussion"),
-uiLevel=>7
);
$groupToModerate = $_[0]->get("groupToModerate") || 4;
$f->group(
-name=>"groupToPost",
@ -210,6 +217,12 @@ sub discussionProperties {
-value=>[$moderationType],
-uiLevel=>7
);
$f->yesNo(
-name=>"addEditStampToPosts",
-label=>WebGUI::International::get(524,"Discussion"),
-value=>$_[0]->get("addEditStampToPosts"),
-uiLevel=>9
);
return $f->printRowsOnly;
}
@ -487,7 +500,7 @@ sub moveCollateralUp {
#-------------------------------------------------------------------
=head2 new ( properties )
=head2 new ( properties [, extendedProperties, allowDiscussion] )
Constructor.
@ -497,16 +510,46 @@ NOTE: This method should never need to be overridden or extended.
=item properties
A hash reference containing at minimum "wobjectId" and "namespace" and wobjectId may be set to "new" if you're creating a new instance. This hash reference should be the one created by WebGUI.pm and passed to the wobject subclass.
A hash reference containing at minimum "wobjectId" and "namespace". wobjectId may be set to "new" if you're creating a new instance. This hash reference should be the one created by WebGUI.pm and passed to the wobject subclass.
NOTE: It may seem a little weird that the initial data for the wobject instance is coming from WebGUI.pm, but this was done to lessen database traffic thus increasing the speed of all wobjects.
=item extendedProperties
An array reference containing a list of properties that extend the wobject class. This list should match the properties that are added to this wobject's namespace table in the database. So if this wobject has a namespace of "MyWobject" and a table definition that looks like this:
create MyWobject (
wobjectId int not null primary key,
something varchar(25),
foo int not null default 1,
bar int
);
Then the extended property list would be "[something, foo, bar]".
NOTE: This is used to define the wobject and should only be passed in by a wobject subclass.
=item allowDiscussion
Defaults to "0". If set to "1" this will add a discussion properties tab to this wobject to enable content managers to set the properties of a discussion attached to this wobject.
NOTE: This is used to define the wobject and should only be passed in by a wobject subclass.
=back
=cut
sub new {
bless {_property => $_[1]}, $_[0];
my $self = shift;
my $properties = shift;
my $extendedProperties = shift;
my $allowDiscussion = shift || 0;
bless({
_property=>$properties,
_extendedProperties=>$extendedProperties,
_allowDiscussion=>$allowDiscussion
},
$self);
}
#-------------------------------------------------------------------
@ -1224,7 +1267,7 @@ Displays a discussion message post form.
sub www_post {
if (WebGUI::Privilege::isInGroup($_[0]->get("groupToPost"))) {
return WebGUI::Discussion::post();
return WebGUI::Discussion::post($_[0]);
} else {
return WebGUI::Privilege::insufficient();
}
@ -1280,7 +1323,7 @@ sub www_showMessage {
($defaultMid) = WebGUI::SQL->quickArray("select min(messageId) from discussion where wobjectId=".$_[0]->get("wobjectId"));
$session{form}{mid} = $session{form}{mid} || $defaultMid || 0;
$output = WebGUI::Discussion::showMessage($_[1],$_[0]);
$output .= WebGUI::Discussion::showReplyTree();
$output .= WebGUI::Discussion::showReplyTree($_[0]);
return $output;
}

View file

@ -456,7 +456,7 @@ sub www_viewSubmission {
$var{"attachment.icon"} = $file->getIcon;
$var{"attachment.name"} = $file->getFilename;
}
$var{"replies"} = WebGUI::Discussion::showThreads();
$var{"replies"} = WebGUI::Discussion::showThreads($_[0]);
return WebGUI::Template::process(WebGUI::Template::get($_[0]->get("submissionTemplateId"),"USS/Submission"), \%var);
}