Merge branch 'master' of git@github.com:plainblack/webgui

Conflicts:

	lib/WebGUI/i18n/English/Asset_EMSSubmission.pm
This commit is contained in:
daviddelikat 2009-12-01 18:50:27 -06:00
commit 60b04ff928
71 changed files with 686 additions and 176 deletions

View file

@ -1,7 +1,24 @@
7.8.7
- fixed #11278: Wrong test for Template::Toolkit in testEnvironment.pl
- fixed #11282: USPS Shipping Driver does not accept ZIP+4
- fixed #11284: Collaboration System Cron jobs for email
7.8.6
- fixed #11250: i18n Asset_EMSSubmissionForm::delete created items label help
- fixed #11251: perload.perl tries to load t/lib/WebGUI/Test.pm
- fixed #11249: Recaptcha https bug
- fixed #11200: Navigation in AssetProxy cached in browser
- fixed #11143: cancel button
- fixed #11259: Snippet content never cached
- fixed #11254: RTF files are streamed with the wrong content-type
- fixed #10932: code showing
- fixed #11265: typo i18n
- fixed #11263: CleanLoginHistory can cause workflow errors
- fixed #11185: Code editor broken in IE8 for SQLReport
- fixed #11177: Code editor steals focus on load
- fixed #10888: Final touches on map point bugs
- fixed #11274: Add attachment broken in template
- fixed #11272: Security issue with asset manager search
7.8.5
- added the EMS submission subsystem

File diff suppressed because one or more lines are too long

View file

@ -7,6 +7,10 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief.
7.8.6
--------------------------------------------------------------------
* WebGUI now requires LWP 5.833 or higher, to fix a bug in that module.
7.8.5
--------------------------------------------------------------------
* WebGUI now requires Locales 0.10 or higher, to replace the deprecated

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -31,6 +31,7 @@ my $quiet; # this line required
my $session = start(); # this line required
# upgrade functions go here
addMaxCacheOverrideSetting($session);
finish($session); # this line required
@ -60,6 +61,16 @@ ENDSQL
# print "DONE!\n" unless $quiet;
#}
#----------------------------------------------------------------------------
# Describe what our function does
sub addMaxCacheOverrideSetting {
my $session = shift;
print "\tAdding maximum cache timeout setting... " unless $quiet;
# and here's our code
$session->setting->add('maxCacheTimeout', 86400) unless $session->setting->has('maxCacheTimeout');
print "DONE!\n" unless $quiet;
}
# -------------- DO NOT EDIT BELOW THIS LINE --------------------------------

View file

@ -0,0 +1,174 @@
#!/usr/bin/env perl
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
our ($webguiRoot);
BEGIN {
$webguiRoot = "../..";
unshift (@INC, $webguiRoot."/lib");
}
use strict;
use Getopt::Long;
use WebGUI::Session;
use WebGUI::Storage;
use WebGUI::Asset;
use WebGUI::Workflow::Cron;
use WebGUI::Asset::Wobject::Collaboration;
my $toVersion = '7.8.7';
my $quiet; # this line required
my $session = start(); # this line required
# upgrade functions go here
clearOrphanedCSMailCronJobs($session);
deleteExtraCronJobsForCS($session);
finish($session); # this line required
#----------------------------------------------------------------------------
# Describe what our function does
#sub exampleFunction {
# my $session = shift;
# print "\tWe're doing some stuff here that you should know about... " unless $quiet;
# # and here's our code
# print "DONE!\n" unless $quiet;
#}
#----------------------------------------------------------------------------
# Describe what our function does
sub clearOrphanedCSMailCronJobs {
my $session = shift;
print "\tClear orphaned csworkflow000000000001 Cron Jobs with no CS attached... " unless $quiet;
my $crons = WebGUI::Workflow::Cron->getAllTasks($session);
##This section of code handles cron jobs created for CS'es where the revision of the
##CS with the cron has been deleted.
CRON: foreach my $cron (@{ $crons }) {
next CRON unless $cron->get('workflowId') eq 'csworkflow000000000001';
my $assetId = $cron->get('parameters');
my $asset = WebGUI::Asset->newByDynamicClass($session, $assetId);
next CRON if $asset;
print "\n\t\tDeleting ".$cron->get('title') unless $quiet;
$cron->delete;
}
print "\tDONE!\n" unless $quiet;
}
#----------------------------------------------------------------------------
# Describe what our function does
sub deleteExtraCronJobsForCS {
my $session = shift;
print "\tGuarantee that each CS has one and only one Cron job. Older jobs will be deleted... " unless $quiet;
my $cses = WebGUI::Asset::Wobject::Collaboration->getIsa($session);
CS: while( my $cs = $cses->() ) {
my @cronIds = $session->db->buildArray('select distinct(getMailCronId) from Collaboration where assetId=?',[$cs->getId]);
next CS unless @cronIds > 1;
my @oldCronIds = grep { $_ ne $cs->get('getMailCronId') } @cronIds;
CRON: foreach my $cronId (@oldCronIds) {
my $cron = WebGUI::Workflow::Cron->new($session, $cronId);
next CRON unless $cron;
print "\n\t\tDeleting ".$cron->get('title') unless $quiet;
$cron->delete;
}
$session->db->write('update Collaboration set getMailCronId=? where assetId=?', [$cs->get('getMailCronId'), $cs->getId]);
}
print "\tDONE!\n" unless $quiet;
}
# -------------- DO NOT EDIT BELOW THIS LINE --------------------------------
#----------------------------------------------------------------------------
# Add a package to the import node
sub addPackage {
my $session = shift;
my $file = shift;
# Make a storage location for the package
my $storage = WebGUI::Storage->createTemp( $session );
$storage->addFileFromFilesystem( $file );
# Import the package into the import node
my $package = eval { WebGUI::Asset->getImportNode($session)->importPackage( $storage, { overwriteLatest => 1 } ); };
if ($package eq 'corrupt') {
die "Corrupt package found in $file. Stopping upgrade.\n";
}
if ($@ || !defined $package) {
die "Error during package import on $file: $@\nStopping upgrade\n.";
}
# Turn off the package flag, and set the default flag for templates added
my $assetIds = $package->getLineage( ['self','descendants'] );
for my $assetId ( @{ $assetIds } ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId );
if ( !$asset ) {
print "Couldn't instantiate asset with ID '$assetId'. Please check package '$file' for corruption.\n";
next;
}
my $properties = { isPackage => 0 };
if ($asset->isa('WebGUI::Asset::Template')) {
$properties->{isDefault} = 1;
}
$asset->update( $properties );
}
return;
}
#-------------------------------------------------
sub start {
my $configFile;
$|=1; #disable output buffering
GetOptions(
'configFile=s'=>\$configFile,
'quiet'=>\$quiet
);
my $session = WebGUI::Session->open($webguiRoot,$configFile);
$session->user({userId=>3});
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->set({name=>"Upgrade to ".$toVersion});
return $session;
}
#-------------------------------------------------
sub finish {
my $session = shift;
updateTemplates($session);
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->commit;
$session->db->write("insert into webguiVersion values (".$session->db->quote($toVersion).",'upgrade',".time().")");
$session->close();
}
#-------------------------------------------------
sub updateTemplates {
my $session = shift;
return undef unless (-d "packages-".$toVersion);
print "\tUpdating packages.\n" unless ($quiet);
opendir(DIR,"packages-".$toVersion);
my @files = readdir(DIR);
closedir(DIR);
my $newFolder = undef;
foreach my $file (@files) {
next unless ($file =~ /\.wgpkg$/);
# Fix the filename to include a path
$file = "packages-" . $toVersion . "/" . $file;
addPackage( $session, $file );
}
}
#vim:ft=perl

View file

@ -1,7 +1,7 @@
package WebGUI;
our $VERSION = '7.8.6';
our $VERSION = '7.8.7';
our $STATUS = 'beta';

View file

@ -336,7 +336,7 @@ sub getInboxNotificationTemplateId {
#-------------------------------------------------------------------
=head2 getInboxSMSNotificationTemplateId ( )
=head2 getInboxSmsNotificationTemplateId ( )
This method returns the template ID for inbox SMS notifications.

View file

@ -1402,6 +1402,21 @@ sub getRoot {
}
#-------------------------------------------------------------------
=head2 getSearchUrl ( )
Returns the URL for the search screen of the asset manager.
=cut
sub getSearchUrl {
my $self = shift;
return $self->getUrl( 'op=assetManager;method=search' );
}
#-------------------------------------------------------------------
=head2 getSeparator
@ -2285,16 +2300,18 @@ sub processTemplate {
my $var = shift;
my $templateId = shift;
my $template = shift;
my $session = $self->session;
# Sanity checks
if (ref $var ne "HASH") {
$self->session->errorHandler->error("First argument to processTemplate() should be a hash reference.");
$session->errorHandler->error("First argument to processTemplate() should be a hash reference.");
return "Error: Can't process template for asset ".$self->getId." of type ".$self->get("className");
}
$template = WebGUI::Asset->new($self->session, $templateId,"WebGUI::Asset::Template") unless (defined $template);
$template = WebGUI::Asset->new($session, $templateId,"WebGUI::Asset::Template") unless (defined $template);
if (defined $template) {
$var = { %{ $var }, %{ $self->getMetaDataAsTemplateVariables } };
$var->{'controls'} = $self->getToolbar if $self->session->var->isAdminOn;
$var->{'controls'} = $self->getToolbar if $session->var->isAdminOn;
$var->{'assetIdHex'} = $session->id->toHex($self->getId);
my %vars = (
%{$self->{_properties}},
'title' => $self->getTitle,
@ -2304,7 +2321,7 @@ sub processTemplate {
return $template->process(\%vars);
}
else {
$self->session->errorHandler->error("Can't instantiate template $templateId for asset ".$self->getId);
$session->errorHandler->error("Can't instantiate template $templateId for asset ".$self->getId);
my $i18n = WebGUI::International->new($self->session, 'Asset');
return $i18n->get('Error: Cannot instantiate template').' '.$templateId;
}
@ -2889,8 +2906,7 @@ sub www_editSave {
=head2 www_manageAssets ( )
Redirect to the asset manager content handler (for backwards
compatibility)
Redirect to the asset manager content handler (for backwards compatibility)
=cut
@ -2902,6 +2918,21 @@ sub www_manageAssets {
#-------------------------------------------------------------------
=head2 www_searchAssets ( )
Redirect to the asset manager content handler (for backwards
compatibility)
=cut
sub www_searchAssets {
my $self = shift;
$self->session->http->setRedirect( $self->getSearchUrl );
return "redirect";
}
#-------------------------------------------------------------------
=head2 www_view ( )
Returns the view() method of the asset object if the requestor canView.

View file

@ -176,6 +176,30 @@ sub exportGetUrlAsPath {
#-------------------------------------------------------------------
=head2 getCache ( $calledAsWebMethod )
Overrides the base method to handle Snippet specific caching.
=head3 $calledAsWebMethod
If this is true, then change the cache key.
=cut
sub getCache {
my $self = shift;
my $calledAsWebMethod = shift;
my $session = $self->session;
my $cacheKey = "view_".$calledAsWebMethod.'_'.$self->getId;
if ($session->env->sslRequest) {
$cacheKey .= '_ssl';
}
my $cache = WebGUI::Cache->new($session, $cacheKey);
return $cache;
}
#-------------------------------------------------------------------
=head2 getToolbar ( )
Returns a toolbar with a set of icons that hyperlink to functions that delete, edit, promote, demote, cut, and copy.
@ -253,6 +277,8 @@ sub purgeCache {
WebGUI::Cache->new($self->session,"view__".$self->getId)->delete;
WebGUI::Cache->new($self->session,"view_1_".$self->getId)->delete;
WebGUI::Cache->new($self->session,"view__".$self->getId."_ssl")->delete;
WebGUI::Cache->new($self->session,"view_1_".$self->getId."_ssl")->delete;
$self->SUPER::purgeCache();
}
@ -270,16 +296,16 @@ toolbar if in adminMode.
=cut
sub view {
my $self = shift;
my $self = shift;
my $calledAsWebMethod = shift;
my $session = $self->session;
my $session = $self->session;
my $versionTag = WebGUI::VersionTag->getWorking($session, 1);
my $noCache =
$session->var->isAdminOn
|| $self->get("cacheTimeout") <= 10
|| ($versionTag && $versionTag->getId eq $self->get("tagId"));
unless ($noCache) {
my $cache = $self->getCache;
my $cache = $self->getCache($calledAsWebMethod);
my $out = $cache->get if defined $cache;
return $out if $out;
}
@ -293,7 +319,8 @@ sub view {
}
WebGUI::Macro::process($session,\$output);
unless ($noCache) {
WebGUI::Cache->new($session,"view_".$calledAsWebMethod."_".$self->getId)->set($output,$self->get("cacheTimeout"));
my $cache = $self->getCache($calledAsWebMethod);
$cache->set($output,$self->get("cacheTimeout"));
}
return $output;
}

View file

@ -946,6 +946,16 @@ sub duplicate {
my $self = shift;
my $newAsset = $self->next::method(@_);
$newAsset->createSubscriptionGroup;
my $i18n = WebGUI::International->new($self->session, "Asset_Collaboration");
my $newCron = WebGUI::Workflow::Cron->create($self->session, {
title=>$self->getTitle." ".$i18n->get("mail"),
minuteOfHour=>"*/".($self->get("getMailInterval")/60),
className=>(ref $self),
methodName=>"new",
parameters=>$self->getId,
workflowId=>"csworkflow000000000001"
});
$self->update({getMailCronId=>$newCron->getId});
return $newAsset;
}

View file

@ -112,7 +112,9 @@ sub handler {
my $asset = getAsset($session, getRequestedAssetUrl($session));
# display from cache if page hasn't been modified.
if ($var->get("userId") eq "1" && defined $asset && !$http->ifModifiedSince($asset->getContentLastModified)) {
if ($var->get("userId") eq "1"
&& defined $asset
&& !$http->ifModifiedSince($asset->getContentLastModified, $session->setting->get('maxCacheTimeout'))) {
$http->setStatus("304","Content Not Modified");
$http->sendHeader;
$session->close;

View file

@ -19,17 +19,20 @@ Gets a select box to choose a class name.
sub getClassSelectBox {
my $session = shift;
my $i18n = WebGUI::International->new($session, 'Asset');
tie my %classes, "Tie::IxHash", (
"" => "Any Class",
"" => $i18n->get("Any Class"),
$session->db->buildHash("select distinct(className) from asset"),
);
delete $classes{"WebGUI::Asset"}; # don't want to search for the root asset
my $className = $session->scratch->get('assetManagerSearchClassName') || $session->form->process("class","className");
$session->scratch->set('assetManagerSearchClassName', $className);
return WebGUI::Form::selectBox( $session, {
name => "class",
value => $session->form->process("class","className"),
defaultValue => "",
name => "class",
value => $className,
defaultValue => "",
options => \%classes,
});
}
@ -142,8 +145,10 @@ sub getSearchPaginator {
$queryString .= ';class=' . $class;
}
my $p = $s->getPaginatorResultSet( $session->url->page( $queryString ) );
my $pageNumber = $session->scratch->get('assetManagerSearchPageNumber') || $session->form->get('pn');
my $p = $s->getPaginatorResultSet( $session->url->page( $queryString ), undef, $pageNumber );
$session->scratch->set('assetManagerSearchPageNumber', $pageNumber);
return $p;
}
@ -533,64 +538,36 @@ sub www_search {
$session->style->setScript( $session->url->extras( 'yui/build/yahoo-dom-event/yahoo-dom-event.js' ) );
$session->style->setScript( $session->url->extras( 'yui-webgui/build/assetManager/assetManager.js' ) );
$session->style->setScript( $session->url->extras( 'yui-webgui/build/form/form.js' ) );
my $keywords = $session->scratch->get('assetManagerSearchKeywords') || $session->form->get('keywords');
### Show the form
$output .= q{<form method="post" enctype="multipart/form-data" action="} . $currentAsset->getUrl . q{"><p>}
. q{<input type="hidden" name="op" value="assetManager" />}
. q{<input type="hidden" name="method" value="search" />}
. q{<input type="text" size="45" name="keywords" value="} . $session->form->get('keywords') . q{" />}
. q{<input type="text" size="45" name="keywords" value="} . $keywords . q{" />}
. getClassSelectBox( $session )
. q{<input type="submit" name="action" value="}.$i18n->get( "search" ).q{" />}
. q{</p></form>}
;
### Actions
if ( my $action = lc $session->form->get( 'action' ) ) {
my @assetIds = $session->form->get( 'assetId' );
if ( $action eq "delete" ) { ##aka trash
for my $assetId ( @assetIds ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId );
next unless $asset;
$asset->trash;
}
}
elsif ( $action eq "cut" ) {
for my $assetId ( @assetIds ) {
my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId );
next unless $asset;
$asset->cut;
}
}
elsif ( $action eq "copy" ) {
for my $assetId ( @assetIds ) {
# Copy == Duplicate + Cut
my $asset = WebGUI::Asset->newByDynamicClass( $session, $assetId);
my $newAsset = $asset->duplicate( { skipAutoCommitWorkflows => 1 } );
$newAsset->update( { title => $newAsset->getTitle . ' (copy)' } );
$newAsset->cut;
}
}
}
### Run the search
if ( $session->form->get( 'keywords' ) || $session->form->get( 'class' ) ) {
my $keywords = $session->form->get( 'keywords' );
my @classes = $session->form->get( 'class' );
if ( $keywords || $session->form->get( 'class' ) ) {
my @classes = $session->form->get( 'class' );
my $keywordsScrubbed = $keywords;
# Detect a helper word key
my @assetIds = ($keywords =~ /assetid:\s*([^\s]+)/gi);
# purge helper word keys
if (@assetIds) {
$keywords =~ s/\bassetid:\s*[^\s]+//gi;
$keywordsScrubbed =~ s/\bassetid:\s*[^\s]+//gi;
}
$keywords =~ s/^\s+//g;
$keywords =~ s/\s+$//g;
$keywordsScrubbed =~ s/^\s+//g;
$keywordsScrubbed =~ s/\s+$//g;
my $p = getSearchPaginator( $session, {
assetIds => \@assetIds,
keywords => $keywords,
keywords => $keywordsScrubbed,
classes => \@classes,
orderByColumn => $session->form->get( 'orderByColumn' ),
orderByDirection => $session->form->get( 'orderByDirection' ),
@ -601,9 +578,10 @@ sub www_search {
}
else {
### Display the search results
$output .= q{<form method="post" enctype="multipart/form-data">}
. q{<input type="hidden" name="op" value="assetManager" />}
. q{<input type="hidden" name="method" value="search" />}
$output .= q{<form method="post" enctype="multipart/form-data" action="}.$currentAsset->getUrl.q{">}
. q{<input type="hidden" name="func" value="searchAssets" />}
. q{<input type="hidden" name="proceed" value="searchAssets" />}
. WebGUI::Form::CsrfToken->new($session)->toHtml
. q{<input type="hidden" name="pn" value="} . $session->form->get('pn') . q{" />}
. q{<input type="hidden" name="keywords" value="} . $keywords . q{" />}
;
@ -707,9 +685,9 @@ sub www_search {
$output .= q{</tbody>}
. q{</table>}
. q{<p class="actions">} . $i18n->get( 'with selected' )
. q{<input type="submit" name="action" value="}.$i18n->get( 'delete' ) . q{" />}
. q{<input type="submit" name="action" value="}.$i18n->get( "cut" ) . q{" />}
. q{<input type="submit" name="action" value="}.$i18n->get( "Copy" ) .q{" />}
. q{<input type="submit" name="action" value="}.$i18n->get( 'delete' ) . q[" onclick="if(confirm('].$i18n->get('43').q[')){this.form.func.value='deleteList'; this.form.submit();}{ return false; }" />]
. q{<input type="submit" name="action" value="}.$i18n->get( "cut" ) . q{" onclick="this.form.func.value='cutList'; this.form.submit();" />}
. q{<input type="submit" name="action" value="}.$i18n->get( "Copy" ) .q{" onclick="this.form.func.value='copyList'; this.form.submit();" />}
. q{</p>}
. q{</form>}
;
@ -730,6 +708,7 @@ sub www_search {
$output .= '</div>';
$session->scratch->set('assetManagerSearchKeywords', $keywords);
return $ac->render( $output );
}

View file

@ -60,6 +60,15 @@ use Exception::Class (
},
);
sub WebGUI::Error::full_message {
my $self = shift;
my $message = $self->message ? $self->message : $self->description;
my @fields = map { defined $self->$_ ? ($_ . ': ' . $self->$_) : () } $self->Fields;
if (@fields) {
$message .= ' (' . join( q{, }, @fields ) . ')';
}
return $message;
}
=head1 NAME

View file

@ -60,16 +60,9 @@ time - time component formatted as HH:MM:SS
sub process {
my ( $session, $toTZ, $format, $date, $time ) = @_;
my $uTZ = 'UTC';
my $uFormat = '%F %T';
my $uTZ = $session->user->profileField("timeZone");
my $uFormat = $session->user->profileField("dateFormat");
# Change defaults only if we have a user defined and they have these set.
eval { $session->user };
unless ($@) {
$uTZ = $session->user->profileField("timeZone");
$uFormat = $session->user->profileField("dateFormat");
}
$toTZ ||= $uTZ;
$format ||= $uFormat;

View file

@ -35,8 +35,8 @@ sub process {
my $i18n = WebGUI::International->new($session, "Macro_SpectreCheck");
if (defined $status) {
return $i18n->get('success') if($status eq 'success');
return $i18n->get('subnet') if($status eq 'subnet');
return $i18n->get('spectre') if($status eq 'spectre');
return $i18n->get('subnet') if($status eq 'subnet');
return $i18n->get('spectre');
}
else {
return $i18n->get('spectre');

View file

@ -204,6 +204,14 @@ sub definition {
hoverHelp=>$i18n->get("Enable Metadata description"),
defaultValue=>$setting->get("metaDataEnabled")
});
push(@fields, {
tab=>"content",
fieldType=>"interval",
name=>"maxCacheTimeout",
label=>$i18n->get("Maximum cache timeout"),
hoverHelp=>$i18n->get("Maximum cache timeout description"),
defaultValue=>$setting->get("maxCacheTimeout")
});
# user interface settings
push(@fields, {
tab=>"ui",

View file

@ -205,19 +205,36 @@ sub getStreamedFile {
#-------------------------------------------------------------------
=head2 ifModifiedSince ( epoch )
=head2 ifModifiedSince ( epoch [, maxCacheTimeout] )
Returns 1 if the epoch is greater than the modified date check.
=head3 epoch
The date that the requested content was last modified in epoch format.
=head3 maxCacheTimeout
A modifier to the epoch, that allows us to set a maximum timeout where content will appear to
have changed and a new page request will be allowed to be processed.
=cut
sub ifModifiedSince {
my $self = shift;
my $epoch = shift;
my $self = shift;
my $epoch = shift;
my $maxCacheTimeout = shift;
require APR::Date;
my $modified = $self->session->request->headers_in->{'If-Modified-Since'};
return 1 if ($modified eq "");
$modified = APR::Date::parse_http($modified);
##Implement a step function that increments the epoch time in integer multiples of
##the maximum cache time. Used to handle the case where layouts containing macros
##(like assetproxied Navigations) can be periodically updated.
if ($maxCacheTimeout) {
my $delta = time() - $epoch;
$epoch += $delta - ($delta % $maxCacheTimeout);
}
return ($epoch > $modified);
}

View file

@ -54,9 +54,12 @@ sub buildXML {
$xmlTop->{Package} = [];
##Do a request for each package.
my $packageIndex;
my $shipType = $self->get('shipType');
my $service = $shipType eq 'PRIORITY VARIABLE' ? 'PRIORITY'
: $shipType;
my $shipType = $self->get('shipType');
my $service = $shipType eq 'PRIORITY VARIABLE'
? 'PRIORITY'
: $shipType;
my $sourceZip = $self->get('sourceZip');
$sourceZip =~ s/^(\d{5}).*$/$1/;
PACKAGE: for(my $packageIndex = 0; $packageIndex < scalar @packages; $packageIndex++) {
my $package = $packages[$packageIndex];
next PACKAGE unless scalar @{ $package };
@ -79,6 +82,7 @@ sub buildXML {
}
my $destination = $package->[0]->getShippingAddress;
my $destZipCode = $destination->get('code');
$destZipCode =~ s/^(\d{5}).*$/$1/;
$packageData{ID} = $packageIndex;
$packageData{Service} = [ $service ];
$packageData{ZipOrigination} = [ $self->get('sourceZip') ];

View file

@ -197,7 +197,6 @@ sub new {
my $session = shift;
my $startingTabs = shift;
my $css = shift || $session->url->extras('tabs/tabs.css');
my $cancelUrl = shift || $session->url->page();
my %tabs;
tie %tabs, 'Tie::IxHash';
foreach my $key (keys %{$startingTabs}) {
@ -206,9 +205,13 @@ sub new {
$tabs{$key}{uiLevel} = $startingTabs->{$key}->{uiLevel};
}
my $i18n = WebGUI::International->new($session);
my $cancelJS = 'history.go(-1);';
if (my $cancelURL = $session->env->get('HTTP_REFERER')) {
$cancelJS = sprintf q{window.location.href='%s';}, $cancelURL;
}
my $cancel = WebGUI::Form::button($session,{
value=>$i18n->get('cancel'),
extras=>q|onclick="history.go(-1);" class="backwardButton"|
extras=>sprintf(q|onclick="%s" class="backwardButton"|, $cancelJS),
});
bless { _session=>$session, _cancel=>$cancel, _submit=>WebGUI::Form::submit($session),
_form=>WebGUI::Form::formHeader($session), _hidden=>"", _tab=>\%tabs, _css=>$css }, $class;

View file

@ -115,7 +115,7 @@ sub execute {
# Stop if there are no records preceding ageToDelete
next USERLOOP unless @deleteTimes;
my $inTimes = WebGUI::SQL::quoteAndJoin( \@deleteTimes );
my $inTimes = $db->quoteAndJoin( \@deleteTimes );
$db->write( "DELETE FROM userLoginLog WHERE userId = ? AND timeStamp IN ($inTimes)", [$userId] );
} ## end while ( my (@userIdData) ...
} ## end else [ if ( not $self->get("retainLastAlways"...

View file

@ -1392,6 +1392,12 @@ Couldn't open %-s because %-s <br />
context => q{},
},
'Any Class' => {
message => q{Any Class},
lastUpdated => 0,
context => q{Class, as in name of class, or type of asset},
},
};
1;

View file

@ -4660,6 +4660,16 @@ Users may override this setting in their profile.
lastUpdated => 0,
},
'Maximum cache timeout' => {
message => 'Maximum cache timeout',
lastUpdated => 0,
},
'Maximum cache timeout description' => {
message => 'This timeout will override the content check that is done before generating a page. It can help with caching problems for macros and Navigations. Setting it to 0 will disable the timeout. A setting of several hours is recommended.',
lastUpdated => 0,
},
};
1;

View file

@ -2,7 +2,9 @@ use strict;
my $webguiRoot = '/data/WebGUI';
@INC = "$webguiRoot/lib", grep { $_ ne q{.} } @INC;
@INC = grep { $_ ne q{.} } @INC;
unshift @INC, "$webguiRoot/lib";
# add custom lib directories to library search path
unshift @INC, grep {

View file

@ -60,10 +60,10 @@ if ($] >= 5.008) {
##Doing this as a global is not nice, but it works
my $missingModule = 0;
checkModule("LWP", 5.824 );
checkModule("LWP", 5.833 );
checkModule("HTTP::Request", 1.40 );
checkModule("HTTP::Headers", 1.61 );
checkModule("Test::More", 0.61, 2 );
checkModule("Test::More", 0.82, 2 );
checkModule("Test::MockObject", 1.02, 2 );
checkModule("Test::Deep", 0.095, 2 );
checkModule("Test::Exception", 0.27, 2 );
@ -95,7 +95,7 @@ checkModule("HTML::Highlight", 0.20 );
checkModule("HTML::TagFilter", 1.03 );
checkModule("HTML::Template", 2.9 );
checkModule("HTML::Template::Expr", 0.07, 2 );
checkModule("Template::Toolkit", 2.20, 2 );
checkModule("Template", 2.20, 2 );
checkModule("XML::FeedPP", 0.40 );
checkModule("JSON", 2.12 );
checkModule("Config::JSON", "1.3.1" );

View file

@ -16,14 +16,14 @@ use lib "$FindBin::Bin/../lib";
use WebGUI::Test;
use WebGUI::Session;
use Test::More tests => 16; # increment this value for each test you create
use Test::More tests => 18; # increment this value for each test you create
use WebGUI::Asset::Snippet;
my $session = WebGUI::Test->session;
my $node = WebGUI::Asset->getImportNode($session);
my $versionTag = WebGUI::VersionTag->getWorking($session);
$versionTag->set({name=>"Snippet Test"});
WebGUI::Test->tagsToRollback($versionTag);
addToCleanup($versionTag);
my $snippet = $node->addChild({className=>'WebGUI::Asset::Snippet'});
# Test for a sane object type
@ -86,6 +86,21 @@ is($snippet->view(), 'WebGUI', 'Interpolating macros in works with template in t
my $empty = $node->addChild( { className => 'WebGUI::Asset::Snippet', } );
is($empty->www_view, 'empty', 'www_view: snippet with no content returns "empty"');
#----------------------------------------------------------------------
#Check caching
##Set up the snippet to do caching
$snippet->update({
cacheTimeout => 100,
snippet => 'Cache test: ^#;',
});
$versionTag->commit;
is $snippet->view, 'Cache test: 1', 'validate snippet content and set cache';
$session->user({userId => 3});
is $snippet->view(1), 'Cache test: 3', 'receive uncached content since view was passed the webMethod flag';
TODO: {
local $TODO = "Tests to make later";
ok(0, 'Test indexContent method');

View file

@ -8,19 +8,6 @@
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
# XXX I (chrisn) started this file to test the features I added to the
# Collaboration / Post system for 7.5, but didn't have the time available to me
# to do a full test suite for the Collaboration Wobject. This means that this
# test suite is *largely incomplete* and should be finished. What is here *is*
# the following:
#
#
# 1. The basic framework for a test suite for the Collaboration Wobject.
# Includes setup, cleanup, boilerplate, etc. Basically the really boring,
# repetitive parts of the test that you don't want to write yourself.
# 2. The tests for the features I've implemented; namely, the groupToEditPost
# functionality.
use FindBin;
use strict;
use lib "$FindBin::Bin/../../lib";
@ -32,7 +19,7 @@ use WebGUI::Asset::Wobject::Collaboration;
use WebGUI::Asset::Post;
use WebGUI::Asset::Wobject::Layout;
use Data::Dumper;
use Test::More tests => 10; # increment this value for each test you create
use Test::More tests => 13; # increment this value for each test you create
my $session = WebGUI::Test->session;
@ -41,6 +28,7 @@ my $node = WebGUI::Asset->getImportNode($session);
# grab a named version tag
my $versionTag = WebGUI::VersionTag->getWorking($session);
addToCleanup($versionTag);
$versionTag->set({name => 'Collaboration => groupToEditPost test'});
# place the collab system under a layout to ensure we're using the inherited groupIdEdit value
@ -55,6 +43,10 @@ my $collab = $layout->addChild({
url => 'collab',
});
$versionTag->commit;
$collab = $collab->cloneFromDb;
ok($session->id->valid($collab->get('getMailCronId')), 'commited CS has a cron job created for it');
# Test for a sane object type
isa_ok($collab, 'WebGUI::Asset::Wobject::Collaboration');
@ -99,12 +91,13 @@ is($collab->getRssFeedUrl, '/collab?func=viewRss', 'getRssFeedUrl');
is($collab->getRdfFeedUrl, '/collab?func=viewRdf', 'getRdfFeedUrl');
is($collab->getAtomFeedUrl, '/collab?func=viewAtom', 'getAtomFeedUrl');
note "Mail Cron job tests";
my $dupedCollab = $collab->duplicate();
addToCleanup(WebGUI::VersionTag->new($session, $dupedCollab->get('tagId')));
ok($dupedCollab->get('getMailCronId'), 'Duplicated CS has a cron job');
isnt($dupedCollab->get('getMailCronId'), $collab->get('getMailCronId'), '... and it is different from its source asset');
TODO: {
local $TODO = "Tests to make later";
ok(0, 'A whole lot more work to do here');
}
END {
# Clean up after thyself
$versionTag->rollback();
}

View file

@ -298,6 +298,7 @@ $templateMock->mock('process', sub { $templateVars = $_[1]; } );
'ownerUserId' => ignore(),
'extraHeadTags' => ignore(),
'assetId' => ignore(),
'assetIdHex' => ignore(),
'url' => 'test-ems',
'isHidden' => ignore(),
'isPrototype' => ignore(),

24
t/Macro/BackToSite.t Normal file
View file

@ -0,0 +1,24 @@
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use FindBin;
use strict;
use lib "$FindBin::Bin/../lib";
use WebGUI::Test;
use WebGUI::Macro::BackToSite;
use Test::More; # increment this value for each test you create
my $session = WebGUI::Test->session;
plan tests => 1;
my $output = WebGUI::Macro::BackToSite::process($session);
is($output, $session->url->getBackToSiteURL, 'fetching current url');

View file

@ -0,0 +1,66 @@
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2008 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use FindBin;
use strict;
use lib "$FindBin::Bin/../lib";
use WebGUI::Test;
use WebGUI::Session;
use Test::More;
use WebGUI::Macro::DeactivateAccount;
my $session = WebGUI::Test->session;
plan tests => 7;
my $defaultText = 'Please deactivate my account permanently.';
my $testText = 'Deactivate account';
# Test 1: User is admin: return nothing
$session->user({userId => 3});
my $out1 = WebGUI::Macro::DeactivateAccount::process($session);
is( $out1, '', "User is admin: return nothing" );
# Test 2: User is not admin, but can't self-deactivate: return nothing
$session->user({userId => 1});
$session->setting->set("selfDeactivation", 0);
my $out2 = WebGUI::Macro::DeactivateAccount::process($session);
is( $out2, '', "User can't self-deactivate: return nothing" );
# Test 3: linkonly
$session->setting->set("selfDeactivation", 1);
my $out3 = WebGUI::Macro::DeactivateAccount::process($session, $testText, 1);
# my ($url3, $text3) = simpleHTMLParser($out3);
is( $out3, '/?op=auth;method=deactivateAccount', 'Link only - URL check');
# Test 4: full deactivation link with default text
my $out4 = WebGUI::Macro::DeactivateAccount::process($session);
my ($url4, $text4) = simpleHTMLParser($out4);
is( $url4, '/?op=auth;method=deactivateAccount', 'Full test - URL check');
is( $text4, $defaultText, 'Full test - text check');
# Test 5: full deactivation link with custom text
my $out5 = WebGUI::Macro::DeactivateAccount::process($session, $testText);
my ($url5, $text5) = simpleHTMLParser($out5);
is( $url5, '/?op=auth;method=deactivateAccount', 'Full test with custom text - URL check');
is( $text5, $testText, 'Full test with custom text - text check');
sub simpleHTMLParser {
my ($text) = @_;
my $p = HTML::TokeParser->new(\$text);
my $token = $p->get_tag("a");
my $url = $token->[1]{href} || "-";
my $label = $p->get_trimmed_text("/a");
return ($url, $label);
}

View file

@ -41,6 +41,11 @@ my @testSets = (
output => 'application/octet-stream',
comment => q|Null path returns application/octet-stream|,
},
{
input => 'foo.rtf',
output => 'application/rtf',
comment => q|RTF file|, ##Added test due to a bug on some operating systems.
},
{
input => undef,
output => undef,

44
t/Macro/SpectreCheck.t Normal file
View file

@ -0,0 +1,44 @@
#-------------------------------------------------------------------
# WebGUI is Copyright 2001-2009 Plain Black Corporation.
#-------------------------------------------------------------------
# Please read the legal notices (docs/legal.txt) and the license
# (docs/license.txt) that came with this distribution before using
# this software.
#-------------------------------------------------------------------
# http://www.plainblack.com info@plainblack.com
#-------------------------------------------------------------------
use FindBin;
use strict;
use lib "$FindBin::Bin/../lib";
use WebGUI::Test;
use WebGUI::Session;
use WebGUI::Operation::Spectre;
my $original_spectreCheck = \&WebGUI::Operation::Spectre::spectreTest;
my $spectreStatus;
*WebGUI::Operation::Spectre::spectreTest = sub {
return $spectreStatus;
};
use WebGUI::Macro::SpectreCheck;
use Test::More; # increment this value for each test you create
my $session = WebGUI::Test->session;
plan tests => 4;
my $i18n = WebGUI::International->new($session, 'Macro_SpectreCheck');
is WebGUI::Macro::SpectreCheck::process($session), $i18n->get('spectre'), 'with no status, get an i18n message for a bad spectre';
$spectreStatus = 'success';
is WebGUI::Macro::SpectreCheck::process($session), $i18n->get('success'), 'good status';
$spectreStatus = 'subnet';
is WebGUI::Macro::SpectreCheck::process($session), $i18n->get('subnet'), 'bad subnet';
$spectreStatus = 'spectre';
is WebGUI::Macro::SpectreCheck::process($session), $i18n->get('spectre'), 'bad spectre';
*WebGUI::Operation::Spectre::spectreTest = $original_spectreCheck;

View file

@ -23,9 +23,7 @@ use Data::Dumper;
use Test::More; # increment this value for each test you create
use Test::Deep;
my $num_tests = 53;
plan tests => $num_tests;
plan tests => 57;
my $session = WebGUI::Test->session;
@ -401,6 +399,22 @@ is_deeply(
$session->user({userId => 1});
####################################################
#
# ifModifiedSince
#
####################################################
##Clear request object to run a new set of requests
$request = WebGUI::PseudoRequest->new();
$session->{_request} = $request;
$request->headers_in->{'If-Modified-Since'} = '';
ok $session->http->ifModifiedSince(0), 'ifModifiedSince: empty header always returns true';
$request->headers_in->{'If-Modified-Since'} = $session->datetime->epochToHttp(WebGUI::Test->webguiBirthday);
ok $session->http->ifModifiedSince(WebGUI::Test->webguiBirthday + 5), '... epoch check, true';
ok !$session->http->ifModifiedSince(WebGUI::Test->webguiBirthday - 5), '... epoch check, false';
ok $session->http->ifModifiedSince(WebGUI::Test->webguiBirthday - 5, 3600), '... epoch check, made true by maxCacheTimeout';
####################################################
#
# Utility functions
@ -428,7 +442,3 @@ sub deltaHttpTimes {
my $dt2 = $httpParser->parse_datetime($http2);
my $delta_time = $dt1-$dt2;
}
END {
}

View file

@ -25,7 +25,7 @@ use WebGUI::Test; # Must use this before any other WebGUI modules
use WebGUI::Session;
use WebGUI::Shop::ShipDriver::USPS;
plan tests => 66;
plan tests => 69;
#----------------------------------------------------------------------------
# Init
@ -232,6 +232,13 @@ my $wucAddress = $addressBook->addAddress({
city => 'Madison', state => 'WI', code => '53703',
country => 'United States',
});
my $zip4Address = $addressBook->addAddress({
label => 'work-zip4',
organization => 'Plain Black Corporation',
address1 => '1360 Regent St. #145',
city => 'Madison', state => 'WI', code => '53715-1255',
country => 'United States',
});
$cart->update({shippingAddressId => $workAddress->getId});
cmp_deeply(
@ -826,6 +833,48 @@ SKIP: {
}
#######################################################################
#
# Test ZIP+4 format domestic code
#
#######################################################################
$cart->update({shippingAddressId => $zip4Address->getId});
my $xmlData = XMLin($driver->buildXML($cart, @shippableUnits),
KeepRoot => 1,
ForceArray => ['Package'],
);
cmp_deeply(
$xmlData,
{
RateV3Request => {
USERID => $userId,
Package => [
{
ID => 0,
ZipDestination => '53715', ZipOrigination => '97123',
Pounds => '1', Ounces => '8.0',
Size => 'REGULAR', Service => 'PRIORITY',
Machinable => 'true',# Container => 'VARIABLE',
},
],
}
},
'buildXML: removed plus4 part of zipcode'
);
SKIP: {
skip 'No userId for testing', 2 unless $hasRealUserId;
my $cost = eval { $driver->calculate($cart); };
my $e = Exception::Class->caught();
ok( ! ref $e, 'no exception thrown for zip+4 address');
cmp_deeply($cost, num(10,9.99), 'zip+4 address returns a valid cost');
}
$cart->update({shippingAddressId => $workAddress->getId});
#######################################################################
#
# Check for throwing an exception

View file

@ -48,7 +48,7 @@ is_deeply($wf->getCrons, [], 'workflow has no crons');
isa_ok(WebGUI::Workflow->getList($session), 'HASH', 'getList returns a hashref');
ok(!isIn($wfId, keys %{WebGUI::Workflow->getList($session)}), 'workflow not in enabled list');
is(scalar keys %{WebGUI::Workflow->getList($session)}, 12, 'There are twelve default workflows, of all types, shipped with WebGUI');
is(scalar keys %{WebGUI::Workflow->getList($session)}, 11, 'There are eleven enabled, default workflows, of all types, shipped with WebGUI');
$wf->set({enabled => 1});
ok($wf->get('enabled'), 'workflow is enabled');

View file

@ -7,20 +7,6 @@ if ( typeof WebGUI == "undefined" ) {
if ( typeof WebGUI.TemplateAttachments == "undefined" ) {
WebGUI.TemplateAttachments = {};
}
if ( typeof WebGUI.TemplateAttachments.i18n == "undefined" ) {
WebGUI.TemplateAttachments.i18n = new WebGUI.i18n( {
namespaces : {
'Asset_Template' : [
"attachment header remove",
"Already attached!",
"No url!"
]
},
onpreload : {
fn : function(){}
}
} );
}
var addClick = (function() {
var uniqueId = 1;
@ -181,7 +167,21 @@ var addClick = (function() {
addAnchor.appendChild(tr);
}
init();
if ( typeof WebGUI.TemplateAttachments.i18n == "undefined" ) {
WebGUI.TemplateAttachments.i18n = new WebGUI.i18n( {
namespaces : {
'Asset_Template' : [
"attachment header remove",
"Already attached!",
"No url!"
]
},
onpreload : {
fn : init
}
} );
}
return function() {
var d = {
index: nodes.index.value,

View file

@ -42,38 +42,28 @@
link.href = this.get('css_url');
this._getDoc().getElementsByTagName('head')[0].appendChild(link);
// Highlight the initial value
if ( !this.browser.ie ) { // IE puts "!!CURSOR HERE!!" in the main doc, not the iframe...
this.highlight(false);
if ( this.getEditorText() != this.old_text ) {
Lang.later(10, this, function () { this.highlight(true) } );
if ( this.status ) {
Lang.later(100, this, this._writeStatus);
}
this.old_text = this.getEditorText();
}
// Setup resize
if ( this.status ) {
this._writeStatus();
this._setupResize();
}
}, this, true);
this.on('editorKeyUp', function(ev) {
// Don't highlight arrows or modifiers
if ( ( ev.ev.keyCode > 36 && ev.ev.keyCode < 41 )
|| ev.ev.keyCode == 16 || ev.ev.keyCode == 17
|| ev.ev.keyCode == 18 || ev.ev.keyCode == 91 // Safari "command"
|| ev.ev.keyCode == 224 // Firefox "command"
) {
return;
// Highlight only if content has changed
if ( this.getEditorText() != this.old_text ) {
Lang.later(10, this, this.highlight);
if ( this.status ) {
Lang.later(100, this, this._writeStatus);
}
this.old_text = this.getEditorText();
}
// TODO: Don't re-highlight if there is a selection
// That is the problem we're trying to avoid with disabling
// highlighting for arrows and modifiers
// Don't highlight Ctrl, Alt, or Meta key combinations
if ( ev.ev.ctrlKey || ev.ev.altKey || ev.ev.metaKey ) {
return;
}
// Highlight every keypress
Lang.later(10, this, this.highlight);
Lang.later(100, this, this._writeStatus);
}, this, true);
//Borrowed this from CodePress: http://codepress.sourceforge.net
@ -107,10 +97,14 @@
str = str.replace(/{/gi, 'RIGHT_BRACKET');
str = str.replace(/}/gi, 'LEFT_BRACKET');
// &nbsp; before <br> for IE7 so lines show up correctly
if ( this.browser.ie && this.browser.ie <= 7 ) {
// &nbsp; before <br> for IE8 so lines show up correctly
if ( this.browser.ie && this.browser.ie <= 8 ) {
str = str.replace(/\r?\n/g, "&nbsp;<br>");
}
// Fix tabs into softtabs
str = str.replace(/\t/g, '&nbsp;&nbsp;&nbsp;&nbsp;'); // TODO: Make softtabs configurable
return str;
};
@ -167,6 +161,7 @@
if (!html) {
html = this.getEditorHTML();
}
html = html.replace(/(&nbsp;){4}/g,"\t"); // TODO: make softtabs configurable
html = html.replace(/&nbsp;/g," ");
html = html.replace(/ ?<br>/gi,'\n');
html = html.replace(/<[^>]+>/g,'');
@ -211,7 +206,7 @@
this._getSelection().getRangeAt(0).insertNode(this._getDoc().createTextNode(this.cc));
} else if (this.browser.webkit || this.browser.ie || this.browser.opera) {
try {
this.execCommand('inserthtml', '!!CURSOR_HERE!!');
this.execCommand('inserthtml', '<span class="cursor_here"></span>');
}
catch (e) {}
}
@ -236,18 +231,18 @@
}
YAHOO.log(html);
// &nbsp; before <br> for IE7
html = html.replace(/(&nbsp;|!!CURSOR_HERE!!)?<br[^>]*>/gi,'$1\n');
html = html.replace(/(&nbsp;|<span class="cursor_here"><\/span>)?<br[^>]*>/gi,'$1\n');
html = html.replace(/<[^>]*>/g,'');
html = html.replace(/\r?\n/g,'<br>');
// &nbsp; between <br> for IE6
html = html.replace(/<br[^>]*>(!!CURSOR_HERE!!)?<br[^>]*>/gi, '<br>$1&nbsp;<br>');
html = html.replace(/<br[^>]*>(<span class="cursor_here"><\/span>)?<br[^>]*>/gi, '<br>$1&nbsp;<br>');
YAHOO.log(html);
}
for (var i = 0; i < this.keywords.length; i++) {
html = html.replace(this.keywords[i].code, this.keywords[i].tag);
}
YAHOO.log("AFTER HIGHLIGHT:" + html);
html = html.replace('!!CURSOR_HERE!!', '<span id="cur">|</span>');
html = html.replace('<span class="cursor_here"></span>', '<span id="cur">|</span>');
this._getDoc().body.innerHTML = html;
if (!focus) {

View file

@ -46,6 +46,7 @@ WebGUI.Map.editPoint
marker = new GMarker( map.getCenter(), { draggable: true } );
marker.infoWin = document.createElement("div");
marker.bindInfoWindow( marker.infoWin );
marker.map = map;
mgr.addMarker( marker, 0 );
mgr.refresh();
assetId = "new";