492 lines
18 KiB
Perl
492 lines
18 KiB
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
|
|
#-------------------------------------------------------------------
|
|
|
|
use FindBin;
|
|
use strict;
|
|
use lib "$FindBin::Bin/../lib";
|
|
|
|
use WebGUI::Test;
|
|
use WebGUI::PseudoRequest;
|
|
use WebGUI::Session;
|
|
use WebGUI::Asset;
|
|
|
|
my @getRefererUrlTests = (
|
|
{
|
|
input => undef,
|
|
output => undef,
|
|
comment => 'getRefererUrl returns undef unless there is a referrer',
|
|
},
|
|
{
|
|
input => 'http://www.domain.com/myUrl.html',
|
|
output => 'myUrl.html',
|
|
comment => 'getRefererUrl returns the url minus the gateway',
|
|
},
|
|
{
|
|
input => 'http://www.domain.com/myUrl.html?op=switchAdminOn',
|
|
output => 'myUrl.html',
|
|
comment => 'getRefererUrl returns the url minus the gateway',
|
|
},
|
|
{
|
|
input => 'https://www.site.com/myUrl.html',
|
|
output => 'myUrl.html',
|
|
comment => 'getRefererUrl handles SSL urls',
|
|
},
|
|
{
|
|
input => 'itunes://www.site.com/myUrl.html',
|
|
output => undef,
|
|
comment => 'getRefererUrl only handles HTTP protocols',
|
|
},
|
|
{
|
|
input => 'http://site/myUrl.html',
|
|
output => 'myUrl.html',
|
|
comment => 'getRefererUrl will also parse weird URLs',
|
|
},
|
|
);
|
|
|
|
use Test::More;
|
|
use Test::MockObject::Extends;
|
|
plan tests => 87 + scalar(@getRefererUrlTests);
|
|
|
|
my $session = WebGUI::Test->session;
|
|
|
|
my $pseudoRequest = WebGUI::PseudoRequest->new();
|
|
$session->{_request} = $pseudoRequest;
|
|
|
|
#disable caching
|
|
my $preventProxyCache = $session->setting->get('preventProxyCache');
|
|
|
|
$session->setting->set('preventProxyCache', 0);
|
|
|
|
#######################################
|
|
#
|
|
# append
|
|
#
|
|
#######################################
|
|
|
|
my $url = 'http://localhost.localdomain/foo';
|
|
my $url2;
|
|
|
|
$url2 = $session->url->append($url,'a=b');
|
|
is( $url2, $url.'?a=b', 'append first pair');
|
|
|
|
$url2 = $session->url->append($url2,'c=d');
|
|
is( $url2, $url.'?a=b;c=d', 'append second pair');
|
|
|
|
#######################################
|
|
#
|
|
# gateway
|
|
#
|
|
#######################################
|
|
|
|
WebGUI::Test->originalConfig('gateway');
|
|
$session->config->set('gateway', '/');
|
|
|
|
is( $session->config->get('gateway'), '/', 'Set gateway for downstream tests');
|
|
|
|
$url2 = $session->url->gateway;
|
|
is( $url2, '/', 'gateway: args');
|
|
|
|
$url2 = $session->url->gateway('/home');
|
|
is( $url2, '/home', 'gateway: with leading slash');
|
|
|
|
$url2 = $session->url->gateway('home');
|
|
is( $url2, '/home', 'gateway: without leading slash');
|
|
|
|
#Disable caching
|
|
$session->setting->set(preventProxyCache => 1);
|
|
|
|
is( 1, $session->setting->get('preventProxyCache'), 'gateway: disable proxy caching');
|
|
|
|
$url2 = $session->url->gateway('home');
|
|
like( $url2, qr{/home\?noCache=\d+:\d+$}, 'gateway: check proxy prevention setting');
|
|
|
|
$url2 = $session->url->gateway('home','',1);
|
|
is( $url2, '/home', 'gateway: skipPreventProxyCache');
|
|
|
|
#Enable caching
|
|
$session->setting->set(preventProxyCache => 0);
|
|
|
|
$url = '/home';
|
|
$url2 = $session->url->gateway($url,'a=b');
|
|
is( $url2, '/home?a=b', 'append one pair via gateway');
|
|
|
|
#Restore original proxy cache setting so downstream tests work with no surprises
|
|
$session->setting->set(preventProxyCache => $preventProxyCache );
|
|
|
|
#######################################
|
|
#
|
|
# setSiteUrl and getSiteUrl
|
|
#
|
|
#######################################
|
|
|
|
##Memorize the current setting and set up the default setting to start tests.
|
|
my $setting_hostToUse = $session->setting->get('hostToUse');
|
|
$session->setting->set('hostToUse', 'HTTP_HOST');
|
|
my $sitename = $session->config->get('sitename')->[0];
|
|
WebGUI::Test->originalConfig('webServerPort');
|
|
$session->config->delete('webServerPort');
|
|
is( $session->url->getSiteURL, 'http://'.$sitename, 'getSiteURL from config as http_host');
|
|
|
|
$session->url->setSiteURL('http://webgui.org');
|
|
is( $session->url->getSiteURL, 'http://webgui.org', 'override config setting with setSiteURL');
|
|
|
|
##Create a fake environment hash so we can muck with it.
|
|
my %mockEnv = %ENV;
|
|
my $env = $session->env;
|
|
$env = Test::MockObject::Extends->new($env);
|
|
$env->mock('get', sub { return $mockEnv{$_[1]} } );
|
|
|
|
$mockEnv{HTTPS} = "on";
|
|
$session->url->setSiteURL(undef);
|
|
is( $session->url->getSiteURL, 'https://'.$sitename, 'getSiteURL from config as http_host with SSL');
|
|
|
|
$mockEnv{HTTPS} = "";
|
|
$mockEnv{HTTP_HOST} = "devsite.com";
|
|
$session->url->setSiteURL(undef);
|
|
is( $session->url->getSiteURL, 'http://'.$sitename, 'getSiteURL where requested host is not a configured site');
|
|
|
|
WebGUI::Test->originalConfig('sitename');
|
|
$session->config->addToArray('sitename', 'devsite.com');
|
|
$session->url->setSiteURL(undef);
|
|
is( $session->url->getSiteURL, 'http://devsite.com', 'getSiteURL where requested host is not the first configured site');
|
|
|
|
$session->setting->set('hostToUse', 'sitename');
|
|
$session->url->setSiteURL(undef);
|
|
is( $session->url->getSiteURL, 'http://'.$sitename, 'getSiteURL where illegal host has been requested');
|
|
|
|
$session->config->set('webServerPort', 80);
|
|
$session->url->setSiteURL(undef);
|
|
is( $session->url->getSiteURL, 'http://'.$sitename.':80', 'getSiteURL with a port');
|
|
|
|
$session->config->set('webServerPort', 8880);
|
|
$session->url->setSiteURL(undef);
|
|
is( $session->url->getSiteURL, 'http://'.$sitename.':8880', 'getSiteURL with a non-standard port');
|
|
|
|
$session->url->setSiteURL('http://'.$sitename);
|
|
is( $session->url->getSiteURL, 'http://'.$sitename, 'restore config setting');
|
|
$session->setting->set('hostToUse', $setting_hostToUse);
|
|
|
|
#######################################
|
|
#
|
|
# makeCompliant
|
|
#
|
|
#######################################
|
|
|
|
$url = 'level1 /level2/level3 ';
|
|
$url2 = 'level1-/level2/level3';
|
|
is $session->url->makeCompliant($url), $url2, 'internal spaces encoded, trailing spaces removed';
|
|
is $session->url->makeCompliant('home/'), 'home', '... trailing slashes removed';
|
|
is $session->url->makeCompliant('home is where the heart is'), 'home-is-where-the-heart-is', '... makeCompliant translates spaces to dashes';
|
|
is $session->url->makeCompliant('/home'), 'home', '... removes initial slash';
|
|
is $session->url->makeCompliant('home -- here'), 'home-here', 'multiple dashes collapsed';
|
|
is $session->url->makeCompliant('home!@#$%^&*here'), 'home-here', 'non-word characters collapsed to single dash';
|
|
is $session->url->makeCompliant("home\x{2267}here"), 'home-here', 'non-word international characters removed';
|
|
is $session->url->makeCompliant("home\x{1EE9}here"), "home\x{1EE9}here", 'word international characters not removed';
|
|
my $character = "\x{00C0}";
|
|
utf8::upgrade($character);
|
|
is( $session->url->makeCompliant($character), $character, 'utf8 allowed in URLs');
|
|
|
|
|
|
#######################################
|
|
#
|
|
# getRequestedUrl
|
|
#
|
|
#######################################
|
|
|
|
my $originalRequest = $session->request; ##Save the original request object
|
|
$session->{_request} = undef;
|
|
|
|
is($session->url->getRequestedUrl, undef, 'getRequestedUrl returns undef unless it has a request object');
|
|
$session->{_request} = $originalRequest;
|
|
|
|
$pseudoRequest->uri('empty');
|
|
is($session->request->uri, 'empty', 'Validate Mock Object operation');
|
|
|
|
$pseudoRequest->uri('full');
|
|
is($session->request->uri, 'full', 'Validate Mock Object operation #2');
|
|
|
|
$pseudoRequest->uri('/path1/file1');
|
|
is($session->url->getRequestedUrl, 'path1/file1', 'getRequestedUrl, fetch');
|
|
|
|
$pseudoRequest->uri('/path2/file2');
|
|
is($session->url->getRequestedUrl, 'path1/file1', 'getRequestedUrl, check cache of previous result');
|
|
|
|
$session->url->{_requestedUrl} = undef; ##Manually clear cached value
|
|
$pseudoRequest->uri('/path2/file2?param1=one;param2=two');
|
|
is($session->url->getRequestedUrl, 'path2/file2', 'getRequestedUrl, does not return params');
|
|
|
|
$session->url->{_requestedUrl} = undef;
|
|
my $utf8_url = "Viel Spa\x{00DF}";
|
|
$pseudoRequest->uri($utf8_url);
|
|
use Encode;
|
|
my $decoded_url = decode_utf8($utf8_url);
|
|
is $session->url->getRequestedUrl(), $decoded_url, 'getRequestedUrl returns utf8 decoded data';
|
|
|
|
#######################################
|
|
#
|
|
# page
|
|
#
|
|
#######################################
|
|
|
|
my $sessionAsset = $session->asset;
|
|
$session->asset(undef);
|
|
|
|
$session->url->{_requestedUrl} = undef; ##Manually clear cached value
|
|
$pseudoRequest->uri('/path1/">file1');
|
|
is($session->url->page, '/path1/%22%3Efile1', 'page with no args returns getRequestedUrl through gateway, escaping the requested URL for safety');
|
|
|
|
is($session->url->page('op=viewHelpTOC;topic=Article'), '/path1/%22%3Efile1?op=viewHelpTOC;topic=Article', 'page: pairs are appended');
|
|
|
|
$url2 = 'http://'.$session->config->get('sitename')->[0].'/path1/%22%3Efile1';
|
|
is($session->url->page('',1), $url2, 'page: withFullUrl includes method and sitename');
|
|
|
|
$session->setting->set('preventProxyCache', 0);
|
|
|
|
is($session->url->page('','',1), '/path1/%22%3Efile1', 'page: skipPreventProxyCache is a no-op with preventProxyCache off in settings');
|
|
$session->setting->set('preventProxyCache', 1);
|
|
my $cacheableUrl = $session->url->page('','',1);
|
|
is($cacheableUrl, '/path1/%22%3Efile1', 'page: skipPreventProxyCache does not change url');
|
|
|
|
like($session->url->page('','',0), qr(^/path1/%22%3Efile1\?noCache=\d{0,4}:\d+$), 'page: noCache added');
|
|
|
|
##Restore original setting
|
|
$session->setting->set('preventProxyCache', $preventProxyCache);
|
|
|
|
my $defaultAsset = WebGUI::Asset->getDefault($session);
|
|
$session->asset($defaultAsset);
|
|
is($session->url->page, $session->url->gateway($defaultAsset->get('url')), 'page:session asset trumps requestedUrl');
|
|
$session->asset($sessionAsset);
|
|
#######################################
|
|
#
|
|
# getReferrerUrl
|
|
#
|
|
#######################################
|
|
|
|
$mockEnv{'HTTP_REFERER'} = 'test';
|
|
|
|
is($session->env->get('HTTP_REFERER'), 'test', 'testing overridden ENV');
|
|
|
|
foreach my $test (@getRefererUrlTests) {
|
|
$mockEnv{HTTP_REFERER} = $test->{input};
|
|
is($session->url->getRefererUrl, $test->{output}, $test->{comment});
|
|
}
|
|
|
|
#######################################
|
|
#
|
|
# makeAbsolute
|
|
#
|
|
#######################################
|
|
|
|
is($session->url->makeAbsolute('page1', '/layer1/layer2/'), '/layer1/layer2/page1', 'makeAbsolute: use a different root');
|
|
is($session->url->makeAbsolute('page1', '/layer1/page2'), '/layer1/page1', 'makeAbsolute: use a second root that is one level shallower');
|
|
is($session->url->makeAbsolute('page1'), '/page1', 'makeAbsolute: default baseUrl from session->asset');
|
|
|
|
#######################################
|
|
#
|
|
# extras
|
|
#
|
|
#######################################
|
|
|
|
my $extras = WebGUI::Test->originalConfig('extrasURL');
|
|
|
|
WebGUI::Test->originalConfig('cdn');
|
|
$session->config->delete('cdn');
|
|
|
|
is($session->url->extras, $extras.'/', 'extras method returns URL to extras with a trailing slash');
|
|
is($session->url->extras('foo.html'), join('/', $extras,'foo.html'), 'extras method appends to the extras url');
|
|
is($session->url->extras('/foo.html'), join('/', $extras,'foo.html'), 'extras method removes extra slashes');
|
|
is($session->url->extras('/dir1//foo.html'), join('/', $extras,'dir1/foo.html'), 'extras method removes extra slashes anywhere');
|
|
|
|
$extras = 'http://mydomain.com/';
|
|
$session->config->set('extrasURL', $extras);
|
|
|
|
is($session->url->extras('/foo.html'), join('', $extras,'foo.html'), 'extras method removes extra slashes');
|
|
is($session->url->extras('/dir1//foo.html'), join('', $extras,'dir1/foo.html'), 'extras method removes extra slashes anywhere');
|
|
|
|
$extras = 'https://mydomain.com/';
|
|
$session->config->set('extrasURL', $extras);
|
|
|
|
is($session->url->extras('/foo.html'), join('', $extras,'foo.html'), 'extras method removes extra slashes');
|
|
is($session->url->extras('/dir1//foo.html'), join('', $extras,'dir1/foo.html'), 'extras method removes extra slashes anywhere');
|
|
|
|
$extras = 'http://mydomain.com/';
|
|
$session->config->set('extrasURL', $extras);
|
|
|
|
my $cdnCfg = { "enabled" => 1,
|
|
"extrasCdn" => "http://extras.example.com/",
|
|
"extrasSsl" => "https://ssl.example.com/",
|
|
"extrasExclude" => ["^tiny"]
|
|
};
|
|
$session->config->set('cdn', $cdnCfg);
|
|
is($session->url->extras('/dir1/foo.html'), join('', $cdnCfg->{extrasCdn}, 'dir1/foo.html'),
|
|
'extras cleartext with CDN');
|
|
is($session->url->extras('tinymce'), join('', $extras, 'tinymce'),
|
|
'extras exclusion from CDN');
|
|
# Note: env is already mocked above.
|
|
$mockEnv{HTTPS} = 'on';
|
|
is($session->url->extras('/dir1/foo.html'), join('', $cdnCfg->{extrasSsl}, 'dir1/foo.html'),
|
|
'extras using extrasSsl with HTTPS');
|
|
$mockEnv{HTTPS} = undef;
|
|
$mockEnv{SSLPROXY} = 1;
|
|
is($session->url->extras('/dir1/foo.html'), join('', $cdnCfg->{extrasSsl}, 'dir1/foo.html'),
|
|
'extras using extrasSsl with SSLPROXY');
|
|
delete $mockEnv{SSLPROXY};
|
|
|
|
#######################################
|
|
#
|
|
# escape and unescape
|
|
# Our goal in this test is just to show that the calls to the URI module work,
|
|
# not to test the URI methods themselves
|
|
#
|
|
#######################################
|
|
|
|
my $escapeString = '10% is enough;';
|
|
my $escapedString = $session->url->escape($escapeString);
|
|
my $unEscapedString = $session->url->unescape($escapeString);
|
|
is($escapedString, '10%25%20is%20enough%3B', 'escape method');
|
|
is($unEscapedString, '10% is enough;', 'unescape method');
|
|
|
|
#######################################
|
|
#
|
|
# urlize
|
|
# part of urlize is calling makeCompliant, which is tested elsewhere.
|
|
# these tests will just make sure that it was called correctly and
|
|
# check other urlize behavior
|
|
#
|
|
#######################################
|
|
|
|
is($session->url->urlize('HOME/PATH1'), 'home/path1', 'urlize: urls are lower cased');
|
|
is $session->url->urlize('home/../out-of-bounds'), 'home/out-of-bounds', '... removes ../';
|
|
is $session->url->urlize('home/./here'), 'home/here', '... removes ./';
|
|
is $session->url->urlize('home/../../out-of-bounds'), 'home/out-of-bounds', '... removes multiple ../';
|
|
is $session->url->urlize('home/././here'), 'home/here', '... removes multiple ./';
|
|
|
|
#######################################
|
|
#
|
|
# getBackToSiteURL
|
|
#
|
|
#######################################
|
|
|
|
$sessionAsset = $session->asset;
|
|
$session->{_asset} = undef;
|
|
$session->url->{_requestedUrl} = undef; ##Manually clear cached value
|
|
$pseudoRequest->uri('/goBackToTheSite');
|
|
|
|
is($session->url->getBackToSiteURL, '/goBackToTheSite', 'getBackToSiteURL: when session asset is undefined, the method falls back to using page');
|
|
|
|
$session->asset($sessionAsset);
|
|
is($session->url->getBackToSiteURL, $session->asset->getUrl, q!getBackToSiteURL: for most regular old assets, it takes you back to the assets container!);
|
|
|
|
my $defaultAssetUrl = WebGUI::Asset->getDefault($session)->getUrl;
|
|
|
|
$session->asset( WebGUI::Asset->getImportNode($session) );
|
|
is(
|
|
$session->url->getBackToSiteURL,
|
|
$defaultAssetUrl,
|
|
q!getBackToSiteURL: importNode asset returns you to the default Asset!
|
|
);
|
|
|
|
$session->asset( WebGUI::Asset->getMedia($session) );
|
|
is(
|
|
$session->url->getBackToSiteURL,
|
|
$defaultAssetUrl,
|
|
q!getBackToSiteURL: Media Folder asset returns you to the default Asset!
|
|
);
|
|
|
|
$session->asset( WebGUI::Asset->getRoot($session) );
|
|
is(
|
|
$session->url->getBackToSiteURL,
|
|
$defaultAssetUrl,
|
|
q!getBackToSiteURL: Root returns you to the default Asset!
|
|
);
|
|
|
|
TODO: {
|
|
local $TODO = 'extra tests for getBackToSiteURL';
|
|
ok(0, 'test a child of the import node');
|
|
ok(0, 'test a child of the media folder');
|
|
}
|
|
|
|
my $versionTag = WebGUI::VersionTag->getWorking($session);
|
|
WebGUI::Test->addToCleanup($versionTag);
|
|
my $statefulAsset = WebGUI::Asset->getRoot($session)->addChild({ className => 'WebGUI::Asset::Snippet' });
|
|
$versionTag->commit;
|
|
$session->asset( $statefulAsset );
|
|
|
|
$statefulAsset->{_properties}{state} = 'published';
|
|
is(
|
|
$session->url->getBackToSiteURL,
|
|
WebGUI::Asset->getRoot($session)->getUrl,
|
|
q!getBackToSiteURL: When asset state is published, it returns you to the Assets container!
|
|
);
|
|
|
|
$statefulAsset->{_properties}{state} = 'trash';
|
|
is(
|
|
$session->url->getBackToSiteURL,
|
|
$defaultAssetUrl,
|
|
q!getBackToSiteURL: When asset state is trash, it returns you to the default Asset!
|
|
);
|
|
|
|
$statefulAsset->{_properties}{state} = 'clipboard';
|
|
is(
|
|
$session->url->getBackToSiteURL,
|
|
$defaultAssetUrl,
|
|
q!getBackToSiteURL: When asset state is clipboard, it returns you to the default Asset!
|
|
);
|
|
|
|
#######################################
|
|
#
|
|
# forceSecureConnection
|
|
#
|
|
#######################################
|
|
|
|
WebGUI::Test->originalConfig('sslEnabled');
|
|
|
|
##Test all the false cases, first
|
|
|
|
$session->config->set('sslEnabled', 0);
|
|
$mockEnv{HTTPS} = 'not on';
|
|
$mockEnv{SSLPROXY} = 0;
|
|
ok( ! $session->url->forceSecureConnection(), 'sslEnabled must be 1 to force SSL');
|
|
|
|
$session->config->set('sslEnabled', 1);
|
|
$mockEnv{HTTPS} = 'on';
|
|
$mockEnv{SSLPROXY} = 0;
|
|
ok( ! $session->url->forceSecureConnection(), 'HTTPS must not be "on" to force SSL');
|
|
|
|
$session->config->set('sslEnabled', 1);
|
|
$mockEnv{HTTPS} = 'not on';
|
|
$mockEnv{SSLPROXY} = 1;
|
|
ok( ! $session->url->forceSecureConnection(), 'SSLPROXY must not be true to force SSL');
|
|
ok( ! $session->url->forceSecureConnection('/test/url'), 'all conditions must be met, even if a URL is directly passed in');
|
|
|
|
##Validate the HTTP object state before we start
|
|
$session->http->setStatus('200', 'OK');
|
|
is($session->http->getStatus, 200, 'http status is okay, 200');
|
|
is($session->http->getRedirectLocation, undef, 'redirect location is empty');
|
|
|
|
$mockEnv{HTTPS} = 'not on';
|
|
$mockEnv{SSLPROXY} = 0;
|
|
|
|
my $secureUrl = $session->url->getSiteURL . '/foo/bar/baz/buz';
|
|
$secureUrl =~ s/http:/https:/;
|
|
|
|
ok($session->url->forceSecureConnection('/foo/bar/baz/buz'), 'forced secure connection');
|
|
is($session->http->getStatus, 302, 'http status set to redirect, 302');
|
|
is($session->http->getRedirectLocation, $secureUrl, 'redirect location set to proper passed in URL with SSL and sitename added');
|
|
|
|
$session->http->setStatus('200', 'OK');
|
|
$session->http->setRedirectLocation(undef);
|
|
|
|
$secureUrl = $session->url->getSiteURL . $session->url->page();
|
|
$secureUrl =~ s/http:/https:/;
|
|
ok($session->url->forceSecureConnection(), 'forced secure connection with no url param');
|
|
ok($session->http->isRedirect, '... and redirect status code was set');
|
|
is($session->http->getRedirectLocation, $secureUrl, '... and redirect status code was set');
|
|
|