merging 7.4 changes

This commit is contained in:
Graham Knop 2008-01-23 23:48:35 +00:00
parent 5292426cc5
commit 1149fd54ed
19 changed files with 319 additions and 167 deletions

View file

@ -200,48 +200,53 @@ sub generateRecurringEvents {
}
# Get the distance between the event startDate and endDate
# Only days, since event recurrence only changes the Date the event occurs, not
# the time.
# Include the time, as recurrence can change it when crossing a daylight
# savings time border.
# TODO: Allow recurrence patterns of less than a single day.
my $duration_days = 0;
my $initialStart
= WebGUI::DateTime->new($session, $properties->{startDate} . " "
. ($properties->{startTime} || "00:00:00"));
my $initialEnd
= WebGUI::DateTime->new($session, $properties->{endDate} . " "
. ($properties->{endTime} || "00:00:00"));
my $duration = $initialEnd->subtract_datetime($initialStart);
my $event_start
= WebGUI::DateTime->new($session, $properties->{startDate}." 00:00:00");
my $event_end
= WebGUI::DateTime->new($session, $properties->{endDate}." 00:00:00");
$duration_days
= $event_end->subtract_datetime($event_start)->days;
my $eventTime;
my $localTime;
if ($properties->{startTime}) {
$eventTime = WebGUI::DateTime->new($session, $properties->{startDate} . " " . $properties->{startTime});
$eventTime = $eventTime->set_time_zone($properties->{timeZone})->toMysqlTime;
$localTime = $initialStart->clone->set_time_zone($properties->{timeZone})->toMysqlTime;
}
$properties->{feedUid} = undef;
my @dates = $self->getRecurrenceDates;
for my $date (@dates) {
my $dt;
if ($eventTime) {
$dt = WebGUI::DateTime->new($session, mysql => $date . " " . $eventTime, time_zone => $properties->{timeZone});
my $startDate;
if ($localTime) {
$startDate = WebGUI::DateTime->new($session,
mysql => $date . " " . $localTime,
time_zone => $properties->{timeZone},
);
}
else {
$dt = WebGUI::DateTime->new($session, $date." ". "00:00:00");
$startDate = WebGUI::DateTime->new($session, $date." 00:00:00");
}
my $startDate = $dt->toDatabaseDate;
my $endDate = $startDate->clone->add($duration);
my $dbDate = $startDate->toDatabaseDate;
# Only generate if the recurId does not exist on this day
my ($exists)
= $session->db->quickArray(
"select count(*) from Event where recurId=? and startDate=?",
[$properties->{recurId}, $startDate],
[$properties->{recurId}, $dbDate],
);
if (!$exists) {
$properties->{startDate} = $startDate;
$properties->{endDate}
= $dt->clone->add(days => $duration_days)->toDatabaseDate;
$properties->{startDate} = $dbDate;
$properties->{endDate} = $endDate->toDatabaseDate;
if ($localTime) {
$properties->{startTime} = $startDate->toDatabaseTime;
$properties->{endTime} = $endDate->toDatabaseTime;
}
my $newEvent = $parent->addChild($properties);
$newEvent->requestAutoCommit;
}
@ -1802,9 +1807,8 @@ Wrap update so that isHidden is always set to be a 1.
sub update {
my $self = shift;
my $properties = shift;
$properties->{isHidden} = 1;
return $self->SUPER::update($properties);
my $properties = shift;
return $self->SUPER::update({%$properties, isHidden => 1});
}

View file

@ -1041,8 +1041,7 @@ sub update {
view => $self->get("groupIdView"),
edit => $self->get("groupIdEdit")
);
$properties->{isHidden} = 1;
$self->SUPER::update($properties, @_);
$self->SUPER::update({%$properties, isHidden => 1});
if ($self->get("ownerUserId") ne $before{owner} || $self->get("groupIdEdit") ne $before{edit} || $self->get("groupIdView") ne $before{view}) {
my $storage = $self->getStorageLocation;
if (-d $storage->getPath) {

View file

@ -242,35 +242,40 @@ Returns a thread object for the next (newer) thread in the same forum.
=cut
sub getNextThread {
my $self = shift;
unless (defined $self->{_next}) {
my $self = shift;
unless (defined $self->{_next}) {
my $parent = $self->getParent;
my $sortBy = $parent->getSortBy;
my $sortByCompare = $sortBy eq 'assetData.revisionDate' ? $self->get('revisionDate') : $self->get($sortBy);
$sortBy = join('.', map { $self->session->db->dbh->quote_identifier($_) } split(/\./, $sortBy));
my $sortOrder = $parent->getSortOrder;
my ($id, $class, $version) = $self->session->dbSlave->quickArray("
select asset.assetId,asset.className,max(assetData.revisionDate)
from Thread
left join asset on asset.assetId=Thread.assetId
left join assetData on assetData.assetId=Thread.assetId and assetData.revisionDate=Thread.revisionDate
left join Post on Post.assetId=assetData.assetId and assetData.revisionDate=Post.revisionDate
where asset.parentId=".$self->session->db->quote($self->get("parentId"))."
and asset.state='published'
and asset.className='WebGUI::Asset::Post::Thread'
and ".$sortBy.($sortOrder eq 'asc' ? '>' : '<').$self->session->db->quote($self->get($sortBy))."
and (
assetData.status in ('approved','archived')
or assetData.tagId=".$self->session->db->quote($self->session->scratch->get("versionTag"))."
or (assetData.ownerUserId=".$self->session->db->quote($self->session->user->userId)." and assetData.ownerUserId<>'1')
)
group by assetData.assetId
order by ".$sortBy." ".$sortOrder."
");
if ($id) {
my $sortCompare = lc $sortOrder eq 'asc' ? '>=' : '<=';
my ($id, $class, $version) = $self->session->dbSlave->quickArray(<<END_SQL, [$self->get("parentId"), $self->getId, $sortByCompare, $self->session->scratch->get("versionTag"), $self->session->user->userId]);
select asset.assetId, asset.className, max(assetData.revisionDate)
from Thread
left join asset on asset.assetId=Thread.assetId
left join assetData on assetData.assetId=Thread.assetId and assetData.revisionDate=Thread.revisionDate
left join Post on Post.assetId=assetData.assetId and assetData.revisionDate=Post.revisionDate
where
asset.parentId=?,
and asset.assetId <> ?
and asset.state='published'
and asset.className='WebGUI::Asset::Post::Thread'
and $sortBy $sortCompare ?
and (
assetData.status in ('approved','archived')
or assetData.tagId=?
or (assetData.ownerUserId=? and assetData.ownerUserId<>'1')
)
group by assetData.assetId
order by $sortBy $sortOrder, assetData.revisionDate asc
limit 1
END_SQL
if ($id) {
$self->{_next} = WebGUI::Asset->new($self->session, $id, $class, $version);
}
# delete $self->{_next} unless ($self->{_next}->{_properties}{className} =~ /Thread/);
};
return $self->{_next};
};
return $self->{_next};
}
@ -297,37 +302,42 @@ Returns a thread object for the previous (older) thread in the same forum.
=cut
sub getPreviousThread {
my $self = shift;
my $self = shift;
unless (defined $self->{_previous}) {
my $parent = $self->getParent;
my $sortBy = $parent->getSortBy;
my $sortByCompare = $sortBy eq 'assetData.revisionDate' ? $self->get('revisionDate') : $self->get($sortBy);
$sortBy = join('.', map { $self->session->db->dbh->quote_identifier($_) } split(/\./, $sortBy));
my $sortOrder = lc($parent->getSortOrder) eq 'asc' ? 'desc' : 'asc';
my ($id, $class, $version) = $self->session->dbSlave->quickArray("
select asset.assetId,asset.className,max(assetData.revisionDate)
from Thread
left join asset on asset.assetId=Thread.assetId
left join assetData on assetData.assetId=Thread.assetId and assetData.revisionDate=Thread.revisionDate
left join Post on Post.assetId=assetData.assetId and assetData.revisionDate=Post.revisionDate
where asset.parentId=".$self->session->db->quote($self->get("parentId"))."
and asset.state='published'
and asset.className='WebGUI::Asset::Post::Thread'
and ".$sortBy.($sortOrder eq 'asc' ? '>' : '<').$self->session->db->quote($self->get($sortBy))."
and (
assetData.status in ('approved','archived')
or assetData.tagId=".$self->session->db->quote($self->session->scratch->get("versionTag"))."
or (assetData.ownerUserId=".$self->session->db->quote($self->session->user->userId)." and assetData.ownerUserId<>'1')
)
group by assetData.assetId
order by ".$sortBy." ".$sortOrder.", assetData.revisionDate desc ");
if($id) {
$self->{_previous} = WebGUI::Asset::Post::Thread->new($self->session, $id,$class,$version);
}
# delete $self->{_previous} unless ($self->{_previous}->{_properties}{className} =~ /Thread/);
}
return $self->{_previous};
my $sortCompare = lc $sortOrder eq 'asc' ? '>=' : '<=';
my ($id, $class, $version) = $self->session->dbSlave->quickArray(<<END_SQL, [$self->get("parentId"), $self->getId, $sortByCompare, $self->session->scratch->get("versionTag"), $self->session->user->userId]);
select asset.assetId, asset.className, max(assetData.revisionDate)
from Thread
left join asset on asset.assetId=Thread.assetId
left join assetData on assetData.assetId=Thread.assetId and assetData.revisionDate=Thread.revisionDate
left join Post on Post.assetId=assetData.assetId and assetData.revisionDate=Post.revisionDate
where
asset.parentId=?,
asset.assetId <> ?
and asset.state='published'
and asset.className='WebGUI::Asset::Post::Thread'
and $sortBy $sortCompare ?
and (
assetData.status in ('approved','archived')
or assetData.tagId=?
or (assetData.ownerUserId=? and assetData.ownerUserId<>'1')
)
group by assetData.assetId
order by $sortBy $sortOrder, assetData.revisionDate desc
limit 1
END_SQL
if ($id) {
$self->{_previous} = WebGUI::Asset->new($self->session, $id, $class, $version);
}
};
return $self->{_previous};
}
#-------------------------------------------------------------------
=head2 getStickUrl ( )

View file

@ -156,7 +156,12 @@ sub purgeCache {
sub view {
my $self = shift;
my $calledAsWebMethod = shift;
if (!$self->session->var->isAdminOn && $self->get("cacheTimeout") > 10) {
my $versionTag = WebGUI::VersionTag->getWorking($self->session, 1);
my $noCache =
$self->session->var->isAdminOn
|| $self->get("cacheTimeout") <= 10
|| ($versionTag && $versionTag->getId eq $self->get("tagId"));
unless ($noCache) {
my $out = WebGUI::Cache->new($self->session,"view_".$calledAsWebMethod."_".$self->getId)->get;
return $out if $out;
}
@ -166,7 +171,7 @@ sub view {
if ($self->getValue("processAsTemplate")) {
$output = WebGUI::Asset::Template->processRaw($self->session, $output, $self->get);
}
if (!$self->session->var->isAdminOn && $self->get("cacheTimeout") > 10) {
unless ($noCache) {
WebGUI::Cache->new($self->session,"view_".$calledAsWebMethod."_".$self->getId)->set($output,$self->get("cacheTimeout"));
}
return $output;

View file

@ -311,8 +311,7 @@ Wrap update to force isHidden to be on, all the time.
sub update {
my $self = shift;
my $properties = shift;
$properties->{isHidden} = 1;
$self->SUPER::update($properties, @_);
return $self->SUPER::update({%$properties, isHidden => 1});
}
#-------------------------------------------------------------------

View file

@ -225,39 +225,29 @@ sub definition {
return $class->SUPER::definition($session, $definition);
}
#-------------------------------------------------------------------
# strip all html tags from the given data structure. This is important to
# prevent cross site scripting attacks
#my $_stripped_html = {};
sub _strip_html {
#my ($data) = @_;
if (ref($_[0]) eq 'HASH') {
keys(%{$_[0]});
while (my ($name, $val) = each (%{$_[0]})) {
$_[0]->{$name} = _strip_html($val);
}
} elsif (ref($_[0]) eq 'ARRAY') {
for (my $i = 0; $i < @{$_[0]}; $i++) {
$_[0]->[$i] = _strip_html($_[0]->[$i]);
}
} else {
if ($_[0]) {
$_[0] =~ s/\&lt;/</g;
$_[0] =~ s/\&gt;/>/g;
$_[0] = WebGUI::HTML::filter($_[0], 'all');
##Unencode double encoded entities. This is usually done
##by passing XML::RSSLite an already encoded entity.
$_[0] =~ s/\&amp;(?=(#[0-9]+|#x[0-9a-fA-F]+|\w+);)/&/g;
}
unless (ref $_[0]) {
return $_[0] = WebGUI::HTML::Filter($_[0], 'all');
}
my $ref = shift;
if (ref $ref eq 'HASH') {
if (exists $ref->{description}) {
$ref->{description} = HTML::Entities::decode_entities($ref->{description});
}
return $_[0];
foreach my $value (values %$ref) {
_strip_html($value);
}
}
elsif (ref $ref eq 'ARRAY') {
foreach my $value (@$ref) {
_strip_html($value);
}
}
return $ref;
}
#-------------------------------------------------------------------
@ -399,7 +389,7 @@ sub _get_rss_data {
$rss->{items} = [];
}
_strip_html($rss);
_strip_html($rss);
$rss->{items} = [ $rss->{items} ] unless (ref $rss->{items} eq 'ARRAY');
_normalize_items($rss->{items});

View file

@ -296,8 +296,7 @@ sub www_editBranchSave {
$data{url} .= $descendant->get("url");
}
}
# copy of %data instead of reference so modifications don't propagate to the next asset
my $newRevision = $descendant->addRevision({%data}, undef, {skipAutoCommitWorkflows=>1});
my $newRevision = $descendant->addRevision(\%data, undef, {skipAutoCommitWorkflows=>1});
foreach my $form ($self->session->form->param) {
if ($form =~ /^metadata_(.*)$/) {
my $fieldName = $1;

View file

@ -322,7 +322,7 @@ sub www_manageTrash {
<script type=\"text/javascript\">
//<![CDATA[
var assetManager = new AssetManager();
assetManager.AddColumn('".WebGUI::Form::checkbox($self->session,{name=>"checkAllAssetIds", extras=>'onchange="toggleAssetListSelectAll(this.form);"'})."','','center','form');
assetManager.AddColumn('".WebGUI::Form::checkbox($self->session,{name=>"checkAllAssetIds", extras=>'onclick="toggleAssetListSelectAll(this.form);"'})."','','center','form');
assetManager.AddColumn('".$i18n->get("99")."','','left','');
assetManager.AddColumn('".$i18n->get("type")."','','left','');
assetManager.AddColumn('".$i18n->get("last updated")."','','center','');
@ -345,15 +345,20 @@ sub www_manageTrash {
."','".$child->get("revisionDate")."','".$child->get("assetSize")."');\n";
}
$output .= '
assetManager.AddButton("'.$i18n->get("restore").'","restoreList","manageTrash");
assetManager.AddButton("'.$i18n->get("purge").'","purgeList","manageTrash");
assetManager.Write();
var assetListSelectAllToggle = false;
function toggleAssetListSelectAll(form){
assetListSelectAllToggle = assetListSelectAllToggle ? false : true;
for(var i = 0; i < form.assetId.length; i++)
assetManager.AddButton("'.$i18n->get("restore").'","restoreList","manageTrash");
assetManager.AddButton("'.$i18n->get("purge").'","purgeList","manageTrash");
assetManager.Write();
var assetListSelectAllToggle = false;
function toggleAssetListSelectAll(form) {
assetListSelectAllToggle = assetListSelectAllToggle ? false : true;
if (typeof form.assetId.length == "undefined") {
form.assetId.checked = assetListSelectAllToggle;
}
else {
for (var i = 0; i < form.assetId.length; i++)
form.assetId[i].checked = assetListSelectAllToggle;
}
}
}
//]]>
</script> <div class="adminConsoleSpacer"> &nbsp;</div>';
return $ac->render($output, $header);

View file

@ -56,11 +56,11 @@ sub execute {
if ($operation->{$op}) {
$output = eval { WebGUI::Pluggable::run("WebGUI::Operation::".$operation->{$op}, 'www_'.$op, [ $session ] ) };
if ( $@ ) {
die $@ if ($@ =~ "^fatal:");
$session->errorHandler->error($@);
return;
}
}
else {
} else {
$session->errorHandler->security("execute an invalid operation: ".$op);
}
return $output;

View file

@ -17,6 +17,9 @@ package WebGUI::Pluggable;
use strict;
use Carp qw(croak);
# Carps should always bypass this package in error reporting
$Carp::Internal{ __PACKAGE__ }++;
=head1 NAME
Package WebGUI::Pluggable
@ -55,25 +58,21 @@ The name of the module you'd like to load like "WebGUI::Asset::Snippet";
sub instanciate {
my ($module, $sub, $params) = @_;
eval { load($module) };
if ($@) {
croak "Could not instanciate object using $sub on $module because $module could not be loaded.";
if ( ! eval { load($module); 1 } ) {
croak "Could not instanciate object using $sub on $module: $@";
}
else {
unless ($module->can($sub)) {
croak "Could not instanciate object using $sub on $module because $sub is not a valid method.";
}
my $object = eval{$module->$sub(@{$params})};
if ($@) {
croak "Could not instanciate object using $sub on $module because $@";
}
else {
unless (defined $object) {
croak "Could not instanciate object using $sub on $module. The result is undefined.";
}
return $object;
}
# Module loaded properly
unless ($module->can($sub)) {
croak "Could not instanciate object using $sub on $module because $sub is not a valid method.";
}
my $object;
if (! eval{$object = $module->$sub(@{$params}); 1}) {
croak "Could not instanciate object using $sub on $module because $@";
}
if (defined $object) {
return $object;
}
croak "Could not instanciate object using $sub on $module. The result is undefined.";
}
#-------------------------------------------------------------------
@ -88,12 +87,20 @@ The name of the module you'd like to load like "WebGUI::Asset::Snippet";
=cut
# Cache results of failures. Modules with compile errors will pass a require check if done a second time.
my %moduleError;
sub load {
my $module = shift;
my $modulePath = $module.".pm";
$modulePath =~ s{::}{/}g;
eval { require $modulePath };
if ($@) {
if ($moduleError{$module}) {
croak "Could not load $module because $moduleError{$module}";
}
my $modulePath = $module . ".pm";
$modulePath =~ s{::|'}{/}g;
if (eval { require $modulePath; 1 }) {
return 1;
}
else {
$moduleError{$module} = $@;
croak "Could not load $module because $@";
}
}
@ -120,21 +127,15 @@ An array reference of parameters to pass in to the sub routine.
sub run {
my ($module, $sub, $params) = @_;
eval { load($module) };
if ($@) {
croak "Could not run $sub on $module because $module could not be loaded.";
if (! eval { load($module); 1 }) {
croak "Unable to run $sub on $module: $@";
}
elsif (my $sub = $module->can($sub)) {
# Let any other errors propagate
return $sub->(@$params);
}
else {
my $command = $module."::".$sub;
no strict qw(refs);
my $out = eval { &$command(@{$params}) };
use strict;
if ($@) {
croak "Could not run $sub on $module because $@";
}
else {
return $out;
}
croak "Could not run $sub on $module because it does not exist";
}
}

View file

@ -19,6 +19,7 @@ use strict;
use Log::Log4perl;
use Apache2::RequestUtil;
use JSON;
use HTML::Entities;
=head1 NAME
@ -215,7 +216,7 @@ sub fatal {
elsif ($self->canShowDebug()) {
$self->session->output->print("<h1>WebGUI Fatal Error</h1><p>Something unexpected happened that caused this system to fault.</p>\n",1);
$self->session->output->print("<p>".$message."</p>\n",1);
$self->session->output->print($self->getStackTrace(), 1);
$self->session->output->print("<pre>" . encode_entities($self->getStackTrace) . "</pre>", 1);
$self->session->output->print($self->showDebug(),1);
}
else {
@ -228,7 +229,7 @@ sub fatal {
$self->session->output->print('<br />'.$self->session->setting->get("companyURL"),1);
}
$self->session->close();
exit;
die "fatal: " . $message;
}